From d36c2458b802f10e615665d87bec94380a9e93d7 Mon Sep 17 00:00:00 2001 From: Sagittaeri Date: Sat, 21 Jan 2017 12:52:14 +1100 Subject: [PATCH] ui stuff --- IronToad_UnityProject/Assets/BansheeGz.meta | 9 + .../Assets/BansheeGz/BGCurve.meta | 9 + .../Assets/BansheeGz/BGCurve/Examples.meta | 9 + .../BGCurve/Examples/Animations.meta | 9 + .../BGAnimatedObjectsForPoints.controller | Bin 0 -> 7080 bytes ...BGAnimatedObjectsForPoints.controller.meta | 8 + .../Examples/Animations/BGAnimationTest.anim | Bin 0 -> 13736 bytes .../Animations/BGAnimationTest.anim.meta | 8 + .../Animations/BGComponentTest.controller | Bin 0 -> 7056 bytes .../BGComponentTest.controller.meta | 8 + .../BGCurveSnappingAdaptiveMath.controller | Bin 0 -> 7064 bytes ...GCurveSnappingAdaptiveMath.controller.meta | 8 + .../BGCurveSnappingBaseMath.controller | Bin 0 -> 7064 bytes .../BGCurveSnappingBaseMath.controller.meta | 8 + .../Examples/Animations/BGLeafs.controller | Bin 0 -> 7048 bytes .../Animations/BGLeafs.controller.meta | 8 + .../Examples/Animations/BGMoomin.controller | Bin 0 -> 7040 bytes .../Animations/BGMoomin.controller.meta | 8 + .../Animations/BGMoominAnimation.anim | Bin 0 -> 27028 bytes .../Animations/BGMoominAnimation.anim.meta | 8 + .../Examples/Animations/BGMoon.controller | Bin 0 -> 8928 bytes .../Animations/BGMoon.controller.meta | 8 + .../Examples/Animations/BGMoonAnimation.anim | Bin 0 -> 12760 bytes .../Animations/BGMoonAnimation.anim.meta | 8 + .../Animations/BGMoonIdleAnimation.anim | Bin 0 -> 10092 bytes .../Animations/BGMoonIdleAnimation.anim.meta | 8 + .../BGPointTransformsAnimation.anim | Bin 0 -> 14120 bytes .../BGPointTransformsAnimation.anim.meta | 8 + .../BGPointsModeSphereAnimation.anim | Bin 0 -> 12512 bytes .../BGPointsModeSphereAnimation.anim.meta | 8 + .../Examples/Animations/BGSnap1Animation.anim | Bin 0 -> 12832 bytes .../Animations/BGSnap1Animation.anim.meta | 8 + .../Examples/Animations/BGSnap2Animation.anim | Bin 0 -> 11928 bytes .../Animations/BGSnap2Animation.anim.meta | 8 + .../Examples/Animations/BGSnufkin.controller | Bin 0 -> 7048 bytes .../Animations/BGSnufkin.controller.meta | 8 + .../Animations/BGSnufkinAnimation.anim | Bin 0 -> 25364 bytes .../Animations/BGSnufkinAnimation.anim.meta | 8 + .../Examples/Animations/BGSphere.controller | Bin 0 -> 7064 bytes .../Animations/BGSphere.controller.meta | 8 + .../Animations/BGStarProjectile.controller | Bin 0 -> 7072 bytes .../BGStarProjectile.controller.meta | 8 + .../Animations/BGStarProjectileAnimation.anim | Bin 0 -> 14076 bytes .../BGStarProjectileAnimation.anim.meta | 8 + .../Examples/Animations/BGSun.controller | Bin 0 -> 7048 bytes .../Examples/Animations/BGSun.controller.meta | 8 + .../Examples/Animations/BGSunAnimation.anim | Bin 0 -> 20440 bytes .../Animations/BGSunAnimation.anim.meta | 8 + .../Examples/Animations/BGTreeAnimation.anim | Bin 0 -> 13832 bytes .../Animations/BGTreeAnimation.anim.meta | 8 + .../BGCurve/Examples/BGCurveDemo.unity | Bin 0 -> 179201 bytes .../BGCurve/Examples/BGCurveDemo.unity.meta | 8 + .../BGCurve/Examples/BGCurveDemo2.unity | Bin 0 -> 120313 bytes .../BGCurve/Examples/BGCurveDemo2.unity.meta | 8 + .../BGCurve/Examples/BGCurveMainMenu.unity | Bin 0 -> 58705 bytes .../Examples/BGCurveMainMenu.unity.meta | 8 + .../BGCurveTestCcChangeCursorLinear.unity | Bin 0 -> 152601 bytes ...BGCurveTestCcChangeCursorLinear.unity.meta | 8 + .../Examples/BGCurveTestClosestPoint.unity | Bin 0 -> 19729 bytes .../BGCurveTestClosestPoint.unity.meta | 8 + .../Examples/BGCurveTestComponents.unity | Bin 0 -> 67881 bytes .../Examples/BGCurveTestComponents.unity.meta | 8 + .../Examples/BGCurveTestCustomFields.unity | Bin 0 -> 43217 bytes .../BGCurveTestCustomFields.unity.meta | 8 + .../BGCurve/Examples/BGCurveTestMath.unity | Bin 0 -> 26569 bytes .../Examples/BGCurveTestMath.unity.meta | 8 + .../Examples/BGCurveTestPerformance.unity | Bin 0 -> 34785 bytes .../BGCurveTestPerformance.unity.meta | 8 + .../Examples/BGCurveTestPointsMode.unity | Bin 0 -> 61697 bytes .../Examples/BGCurveTestPointsMode.unity.meta | 8 + .../BGCurveTestPointsTransforms.unity | Bin 0 -> 37412 bytes .../BGCurveTestPointsTransforms.unity.meta | 8 + .../BGCurve/Examples/BGCurveTestRuntime.unity | Bin 0 -> 72881 bytes .../Examples/BGCurveTestRuntime.unity.meta | 8 + .../BGCurveTestRuntimeCustomFields.unity | Bin 0 -> 57985 bytes .../BGCurveTestRuntimeCustomFields.unity.meta | 8 + .../Examples/BGCurveTestSnapping.unity | Bin 0 -> 40593 bytes .../Examples/BGCurveTestSnapping.unity.meta | 8 + .../BansheeGz/BGCurve/Examples/Materials.meta | 9 + .../Examples/Materials/BGTestCheckerBoard.png | Bin 0 -> 1533 bytes .../Materials/BGTestCheckerBoard.png.meta | 57 + .../Materials/BGTestCheckerBoardMaterial.mat | 138 + .../BGTestCheckerBoardMaterial.mat.meta | 8 + .../Examples/Materials/BGTestGrass.png | Bin 0 -> 165984 bytes .../Examples/Materials/BGTestGrass.png.meta | 57 + .../Examples/Materials/BGTestLineRenderer.mat | 146 + .../Materials/BGTestLineRenderer.mat.meta | 8 + .../BGTestLineRendererCheckerBox.mat | Bin 0 -> 4960 bytes .../BGTestLineRendererCheckerBox.mat.meta | 8 + .../Examples/Materials/BGTestMoonMaterial.mat | Bin 0 -> 4916 bytes .../Materials/BGTestMoonMaterial.mat.meta | 8 + .../Examples/Materials/BGTestSunMaterial.mat | Bin 0 -> 4964 bytes .../Materials/BGTestSunMaterial.mat.meta | 8 + .../Materials/BGTestTrailRenderer.mat | 147 + .../Materials/BGTestTrailRenderer.mat.meta | 8 + .../Materials/BGTestTreeLeafsMaterial.mat | Bin 0 -> 4908 bytes .../BGTestTreeLeafsMaterial.mat.meta | 8 + .../Materials/BGTestTreeTrunkMaterial.mat | Bin 0 -> 4908 bytes .../BGTestTreeTrunkMaterial.mat.meta | 8 + .../Examples/Materials/BGTestTrunk.mat | Bin 0 -> 4896 bytes .../Examples/Materials/BGTestTrunk.mat.meta | 8 + .../Examples/Materials/BGTestTrunk.png | Bin 0 -> 101397 bytes .../Examples/Materials/BGTestTrunk.png.meta | 57 + .../BansheeGz/BGCurve/Examples/Scripts.meta | 9 + .../BGCurve/Examples/Scripts/BGTestCamera.cs | 33 + .../Examples/Scripts/BGTestCamera.cs.meta | 12 + .../Scripts/BGTestCcChangeCursorLinear.cs | 489 ++ .../BGTestCcChangeCursorLinear.cs.meta | 12 + .../Examples/Scripts/BGTestCurveChange.cs | 32 + .../Scripts/BGTestCurveChange.cs.meta | 12 + .../Scripts/BGTestCurveClosestPoint.cs | 321 + .../Scripts/BGTestCurveClosestPoint.cs.meta | 12 + .../Examples/Scripts/BGTestCurveDynamic.cs | 77 + .../Scripts/BGTestCurveDynamic.cs.meta | 12 + .../Examples/Scripts/BGTestCurveMath.cs | 324 + .../Examples/Scripts/BGTestCurveMath.cs.meta | 12 + .../Examples/Scripts/BGTestCurveRuntime.cs | 120 + .../Scripts/BGTestCurveRuntime.cs.meta | 12 + .../Scripts/BGTestCurveRuntimeCustomFields.cs | 65 + .../BGTestCurveRuntimeCustomFields.cs.meta | 12 + .../Examples/Scripts/BGTestCurveShowcase.cs | 416 + .../Scripts/BGTestCurveShowcase.cs.meta | 12 + .../Examples/Scripts/BGTestCurveStatic.cs | 70 + .../Scripts/BGTestCurveStatic.cs.meta | 12 + .../Examples/Scripts/BGTestDirector.cs | 96 + .../Examples/Scripts/BGTestDirector.cs.meta | 12 + .../Examples/Scripts/BGTestMainMenu.cs | 24 + .../Examples/Scripts/BGTestMainMenu.cs.meta | 12 + .../Examples/Scripts/BGTestPerformance.cs | 166 + .../Scripts/BGTestPerformance.cs.meta | 12 + .../BansheeGz/BGCurve/Examples/Terrain.meta | 9 + .../Examples/Terrain/BGTestDemoTerrain.asset | Bin 0 -> 11040 bytes .../Terrain/BGTestDemoTerrain.asset.meta | 8 + .../Terrain/BGTestSnappingTerrain.asset | Bin 0 -> 8020 bytes .../Terrain/BGTestSnappingTerrain.asset.meta | 8 + .../Assets/BansheeGz/BGCurve/Icons.meta | 9 + .../BansheeGz/BGCurve/Icons/BGAdd123.png | Bin 0 -> 459 bytes .../BansheeGz/BGCurve/Icons/BGAdd123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGBoxWhite123.png | Bin 0 -> 214 bytes .../BGCurve/Icons/BGBoxWhite123.png.meta | 57 + .../BGCurve/Icons/BGBoxWithBorder123.png | Bin 0 -> 250 bytes .../BGCurve/Icons/BGBoxWithBorder123.png.meta | 57 + .../BGCurve/Icons/BGCcEditName123.png | Bin 0 -> 368 bytes .../BGCurve/Icons/BGCcEditName123.png.meta | 57 + .../BGCurve/Icons/BGCcNoImage123.png | Bin 0 -> 824 bytes .../BGCurve/Icons/BGCcNoImage123.png.meta | 57 + .../BGCurve/Icons/BGCollapseAll123.png | Bin 0 -> 464 bytes .../BGCurve/Icons/BGCollapseAll123.png.meta | 57 + .../BGCurve/Icons/BGCollapsed123.png | Bin 0 -> 379 bytes .../BGCurve/Icons/BGCollapsed123.png.meta | 57 + .../BGCurve/Icons/BGComponents123.png | Bin 0 -> 810 bytes .../BGCurve/Icons/BGComponents123.png.meta | 57 + .../BGCurve/Icons/BGControlAbsent123.png | Bin 0 -> 662 bytes .../BGCurve/Icons/BGControlAbsent123.png.meta | 57 + .../Icons/BGControlBezierIndependent123.png | Bin 0 -> 987 bytes .../BGControlBezierIndependent123.png.meta | 57 + .../Icons/BGControlBezierSymmetrical123.png | Bin 0 -> 983 bytes .../BGControlBezierSymmetrical123.png.meta | 57 + .../BGCurve/Icons/BGConvertAll123.png | Bin 0 -> 1025 bytes .../BGCurve/Icons/BGConvertAll123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGCopy123.png | Bin 0 -> 519 bytes .../BGCurve/Icons/BGCopy123.png.meta | 57 + .../BGCurve/Icons/BGCurveComponents123.png | Bin 0 -> 6834 bytes .../Icons/BGCurveComponents123.png.meta | 57 + .../BGCurve/Icons/BGCurveLogo123.png | Bin 0 -> 7586 bytes .../BGCurve/Icons/BGCurveLogo123.png.meta | 57 + .../BGCurve/Icons/BGDeSelectAll123.png | Bin 0 -> 828 bytes .../BGCurve/Icons/BGDeSelectAll123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGDelete123.png | Bin 0 -> 321 bytes .../BGCurve/Icons/BGDelete123.png.meta | 57 + .../BGCurve/Icons/BGExpandAll123.png | Bin 0 -> 491 bytes .../BGCurve/Icons/BGExpandAll123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGExpanded123.png | Bin 0 -> 254 bytes .../BGCurve/Icons/BGExpanded123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGFields123.png | Bin 0 -> 464 bytes .../BGCurve/Icons/BGFields123.png.meta | 57 + .../BGCurve/Icons/BGHandlesOff123.png | Bin 0 -> 420 bytes .../BGCurve/Icons/BGHandlesOff123.png.meta | 57 + .../BGCurve/Icons/BGHandlesOn123.png | Bin 0 -> 399 bytes .../BGCurve/Icons/BGHandlesOn123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGHelp123.png | Bin 0 -> 456 bytes .../BGCurve/Icons/BGHelp123.png.meta | 57 + .../BGCurve/Icons/BGHierarchyErrorIcon123.png | Bin 0 -> 885 bytes .../Icons/BGHierarchyErrorIcon123.png.meta | 57 + .../Icons/BGHierarchyErrorSelectedIcon123.png | Bin 0 -> 884 bytes .../BGHierarchyErrorSelectedIcon123.png.meta | 57 + .../BGCurve/Icons/BGHierarchyIcon123.png | Bin 0 -> 840 bytes .../BGCurve/Icons/BGHierarchyIcon123.png.meta | 57 + .../Icons/BGHierarchySelectedIcon123.png | Bin 0 -> 846 bytes .../Icons/BGHierarchySelectedIcon123.png.meta | 57 + .../Icons/BGHierarchyWarningIcon123.png | Bin 0 -> 878 bytes .../Icons/BGHierarchyWarningIcon123.png.meta | 57 + .../BGHierarchyWarningSelectedIcon123.png | Bin 0 -> 887 bytes ...BGHierarchyWarningSelectedIcon123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGLockOff123.png | Bin 0 -> 391 bytes .../BGCurve/Icons/BGLockOff123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGLockOn123.png | Bin 0 -> 406 bytes .../BGCurve/Icons/BGLockOn123.png.meta | 57 + .../BGCurve/Icons/BGMenuItemBackground123.png | Bin 0 -> 277 bytes .../Icons/BGMenuItemBackground123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGMoveDown123.png | Bin 0 -> 487 bytes .../BGCurve/Icons/BGMoveDown123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGMoveUp123.png | Bin 0 -> 467 bytes .../BGCurve/Icons/BGMoveUp123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGOff123.png | Bin 0 -> 396 bytes .../BansheeGz/BGCurve/Icons/BGOff123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGOn123.png | Bin 0 -> 414 bytes .../BansheeGz/BGCurve/Icons/BGOn123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGPaste123.png | Bin 0 -> 460 bytes .../BGCurve/Icons/BGPaste123.png.meta | 57 + .../BGCurve/Icons/BGPointControlBS123.png | Bin 0 -> 3652 bytes .../Icons/BGPointControlBS123.png.meta | 57 + .../BGCurve/Icons/BGPointDelete123.png | Bin 0 -> 235 bytes .../BGCurve/Icons/BGPointDelete123.png.meta | 57 + .../BGCurve/Icons/BGPointInsertAfter123.png | Bin 0 -> 555 bytes .../Icons/BGPointInsertAfter123.png.meta | 57 + .../BGCurve/Icons/BGPointInsertBefore123.png | Bin 0 -> 579 bytes .../Icons/BGPointInsertBefore123.png.meta | 57 + .../BGCurve/Icons/BGPointSelected123.png | Bin 0 -> 394 bytes .../BGCurve/Icons/BGPointSelected123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGPoints123.png | Bin 0 -> 484 bytes .../BGCurve/Icons/BGPoints123.png.meta | 57 + .../BGCurve/Icons/BGSelectAll123.png | Bin 0 -> 877 bytes .../BGCurve/Icons/BGSelectAll123.png.meta | 57 + .../BGCurve/Icons/BGSelectionAdd123.png | Bin 0 -> 877 bytes .../BGCurve/Icons/BGSelectionAdd123.png.meta | 57 + .../BGCurve/Icons/BGSelectionRemove123.png | Bin 0 -> 820 bytes .../Icons/BGSelectionRemove123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGSettings123.png | Bin 0 -> 600 bytes .../BGCurve/Icons/BGSettings123.png.meta | 57 + .../BGCurve/Icons/BGSettingsIcon123.png | Bin 0 -> 1683 bytes .../BGCurve/Icons/BGSettingsIcon123.png.meta | 57 + .../BGCurve/Icons/BGTableCell123.png | Bin 0 -> 228 bytes .../BGCurve/Icons/BGTableCell123.png.meta | 57 + .../BGCurve/Icons/BGTableHeader123.png | Bin 0 -> 228 bytes .../BGCurve/Icons/BGTableHeader123.png.meta | 57 + .../BGCurve/Icons/BGTableTitle123.png | Bin 0 -> 1113 bytes .../BGCurve/Icons/BGTableTitle123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGTickNo123.png | Bin 0 -> 727 bytes .../BGCurve/Icons/BGTickNo123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/BGTickYes123.png | Bin 0 -> 716 bytes .../BGCurve/Icons/BGTickYes123.png.meta | 57 + .../BansheeGz/BGCurve/Icons/Components.meta | 9 + .../Icons/Components/BGCcCursor123.png | Bin 0 -> 1747 bytes .../Icons/Components/BGCcCursor123.png.meta | 57 + .../Components/BGCcCursorChangeLinear123.png | Bin 0 -> 1959 bytes .../BGCcCursorChangeLinear123.png.meta | 57 + .../Components/BGCcCursorObjectRotate123.png | Bin 0 -> 2278 bytes .../BGCcCursorObjectRotate123.png.meta | 57 + .../Components/BGCcCursorObjectScale123.png | Bin 0 -> 1766 bytes .../BGCcCursorObjectScale123.png.meta | 57 + .../BGCcCursorObjectTranslate123.png | Bin 0 -> 1548 bytes .../BGCcCursorObjectTranslate123.png.meta | 57 + .../BGCurve/Icons/Components/BGCcMath123.png | Bin 0 -> 1803 bytes .../Icons/Components/BGCcMath123.png.meta | 57 + .../Components/BGCcSplitterPolyline123.png | Bin 0 -> 2138 bytes .../BGCcSplitterPolyline123.png.meta | 57 + .../Icons/Components/BGCcTriangulate2D123.png | Bin 0 -> 2300 bytes .../Components/BGCcTriangulate2D123.png.meta | 57 + .../BGCcVisualizationLineRenderer123.png | Bin 0 -> 4215 bytes .../BGCcVisualizationLineRenderer123.png.meta | 57 + .../Assets/BansheeGz/BGCurve/Scripts.meta | 9 + .../Assets/BansheeGz/BGCurve/Scripts/Cc.meta | 9 + .../BGCurve/Scripts/Cc/BGCcCursor.cs | 102 + .../BGCurve/Scripts/Cc/BGCcCursor.cs.meta | 12 + .../Scripts/Cc/BGCcCursorChangeLinear.cs | 551 ++ .../Scripts/Cc/BGCcCursorChangeLinear.cs.meta | 12 + .../Scripts/Cc/BGCcCursorObjectRotate.cs | 387 + .../Scripts/Cc/BGCcCursorObjectRotate.cs.meta | 12 + .../Scripts/Cc/BGCcCursorObjectScale.cs | 74 + .../Scripts/Cc/BGCcCursorObjectScale.cs.meta | 12 + .../Scripts/Cc/BGCcCursorObjectTranslate.cs | 54 + .../Cc/BGCcCursorObjectTranslate.cs.meta | 12 + .../BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs | 696 ++ .../BGCurve/Scripts/Cc/BGCcMath.cs.meta | 12 + .../Scripts/Cc/BGCcSplitterPolyline.cs | 567 ++ .../Scripts/Cc/BGCcSplitterPolyline.cs.meta | 12 + .../BGCurve/Scripts/Cc/BGCcTriangulate2D.cs | 404 + .../Scripts/Cc/BGCcTriangulate2D.cs.meta | 12 + .../Cc/BGCcVisualizationLineRenderer.cs | 200 + .../Cc/BGCcVisualizationLineRenderer.cs.meta | 12 + .../BGCurve/Scripts/Cc/BGCcWithCursor.cs | 97 + .../BGCurve/Scripts/Cc/BGCcWithCursor.cs.meta | 12 + .../Scripts/Cc/BGCcWithCursorObject.cs | 33 + .../Scripts/Cc/BGCcWithCursorObject.cs.meta | 12 + .../BGCurve/Scripts/Cc/BGCcWithMath.cs | 33 + .../BGCurve/Scripts/Cc/BGCcWithMath.cs.meta | 12 + .../BansheeGz/BGCurve/Scripts/Curve.meta | 9 + .../BansheeGz/BGCurve/Scripts/Curve/BGCc.cs | 287 + .../BGCurve/Scripts/Curve/BGCc.cs.meta | 12 + .../BGCurve/Scripts/Curve/BGCurve.cs | 2063 +++++ .../BGCurve/Scripts/Curve/BGCurve.cs.meta | 12 + .../Scripts/Curve/BGCurveAdaptiveMath.cs | 421 + .../Scripts/Curve/BGCurveAdaptiveMath.cs.meta | 12 + .../BGCurve/Scripts/Curve/BGCurveBaseMath.cs | 1587 ++++ .../Scripts/Curve/BGCurveBaseMath.cs.meta | 12 + .../Curve/BGCurveCalculatorClosestPoint.cs | 656 ++ .../BGCurveCalculatorClosestPoint.cs.meta | 12 + .../Scripts/Curve/BGCurveChangedArgs.cs | 179 + .../Scripts/Curve/BGCurveChangedArgs.cs.meta | 12 + .../Scripts/Curve/BGCurveFormulaMath.cs | 290 + .../Scripts/Curve/BGCurveFormulaMath.cs.meta | 12 + .../BGCurve/Scripts/Curve/BGCurveFormulas.cs | 52 + .../Scripts/Curve/BGCurveFormulas.cs.meta | 12 + .../BGCurve/Scripts/Curve/BGCurveMathI.cs | 129 + .../Scripts/Curve/BGCurveMathI.cs.meta | 12 + .../BGCurve/Scripts/Curve/BGCurvePoint.cs | 817 ++ .../Scripts/Curve/BGCurvePoint.cs.meta | 12 + .../Scripts/Curve/BGCurvePointComponent.cs | 191 + .../Curve/BGCurvePointComponent.cs.meta | 12 + .../Scripts/Curve/BGCurvePointField.cs | 152 + .../Scripts/Curve/BGCurvePointField.cs.meta | 12 + .../BGCurve/Scripts/Curve/BGCurvePointGO.cs | 649 ++ .../Scripts/Curve/BGCurvePointGO.cs.meta | 12 + .../BGCurve/Scripts/Curve/BGCurvePointI.cs | 103 + .../Scripts/Curve/BGCurvePointI.cs.meta | 12 + .../Scripts/Curve/BGCurveReferenceToPoint.cs | 60 + .../Curve/BGCurveReferenceToPoint.cs.meta | 12 + .../BGCurve/Scripts/Curve/BGCurveSettings.cs | 366 + .../Scripts/Curve/BGCurveSettings.cs.meta | 12 + .../Scripts/Curve/BGReflectionAdapter.cs | 71 + .../Scripts/Curve/BGReflectionAdapter.cs.meta | 12 + .../BansheeGz/BGCurve/Scripts/Editor.meta | 9 + .../BansheeGz/BGCurve/Scripts/Editor/Cc.meta | 9 + .../Editor/Cc/BGCcCursorChangeLinearEditor.cs | 55 + .../Cc/BGCcCursorChangeLinearEditor.cs.meta | 12 + .../Scripts/Editor/Cc/BGCcCursorDrawer.cs | 11 + .../Editor/Cc/BGCcCursorDrawer.cs.meta | 12 + .../Scripts/Editor/Cc/BGCcCursorEditor.cs | 48 + .../Editor/Cc/BGCcCursorEditor.cs.meta | 12 + .../Editor/Cc/BGCcCursorObjectEditor.cs | 13 + .../Editor/Cc/BGCcCursorObjectEditor.cs.meta | 12 + .../Editor/Cc/BGCcCursorObjectRotateEditor.cs | 133 + .../Cc/BGCcCursorObjectRotateEditor.cs.meta | 12 + .../Editor/Cc/BGCcCursorObjectScaleEditor.cs | 31 + .../Cc/BGCcCursorObjectScaleEditor.cs.meta | 12 + .../Cc/BGCcCursorObjectTranslateEditor.cs | 10 + .../BGCcCursorObjectTranslateEditor.cs.meta | 12 + .../Scripts/Editor/Cc/BGCcMathEditor.cs | 117 + .../Scripts/Editor/Cc/BGCcMathEditor.cs.meta | 12 + .../Editor/Cc/BGCcSplitterPolylineEditor.cs | 101 + .../Cc/BGCcSplitterPolylineEditor.cs.meta | 12 + .../Editor/Cc/BGCcTriangulate2DEditor.cs | 46 + .../Editor/Cc/BGCcTriangulate2DEditor.cs.meta | 12 + .../Cc/BGCcVisualizationLineRendererEditor.cs | 33 + ...GCcVisualizationLineRendererEditor.cs.meta | 12 + .../BGCurve/Scripts/Editor/Curve.meta | 9 + .../Scripts/Editor/Curve/BGCcEditor.cs | 173 + .../Scripts/Editor/Curve/BGCcEditor.cs.meta | 12 + .../Scripts/Editor/Curve/BGCurveEditor.cs | 520 ++ .../Editor/Curve/BGCurveEditor.cs.meta | 12 + .../Editor/Curve/BGCurveEditorComponents.cs | 661 ++ .../Curve/BGCurveEditorComponents.cs.meta | 12 + .../Editor/Curve/BGCurveEditorFields.cs | 982 +++ .../Editor/Curve/BGCurveEditorFields.cs.meta | 12 + .../Editor/Curve/BGCurveEditorPoint.cs | 526 ++ .../Editor/Curve/BGCurveEditorPoint.cs.meta | 12 + .../Editor/Curve/BGCurveEditorPoints.cs | 538 ++ .../Editor/Curve/BGCurveEditorPoints.cs.meta | 12 + .../Curve/BGCurveEditorPointsSelection.cs | 617 ++ .../BGCurveEditorPointsSelection.cs.meta | 12 + .../Editor/Curve/BGCurveEditorSettings.cs | 166 + .../Curve/BGCurveEditorSettings.cs.meta | 12 + .../Scripts/Editor/Curve/BGCurveEditorTab.cs | 79 + .../Editor/Curve/BGCurveEditorTab.cs.meta | 12 + .../Curve/BGCurvePointComponentDrawer.cs | 49 + .../Curve/BGCurvePointComponentDrawer.cs.meta | 12 + .../Editor/Curve/BGCurvePointGOEditor.cs | 80 + .../Editor/Curve/BGCurvePointGOEditor.cs.meta | 12 + .../Curve/BGCurveReferenceToPointEditor.cs | 87 + .../BGCurveReferenceToPointEditor.cs.meta | 12 + .../Editor/Curve/BGNewPointPositionManager.cs | 189 + .../Curve/BGNewPointPositionManager.cs.meta | 12 + .../Editor/Curve/BGRectangularSelection.cs | 174 + .../Curve/BGRectangularSelection.cs.meta | 12 + .../BGCurve/Scripts/Editor/Infra.meta | 9 + .../Scripts/Editor/Infra/BGCcAddWindow.cs | 340 + .../Editor/Infra/BGCcAddWindow.cs.meta | 12 + .../Editor/Infra/BGCcChangeNameWindow.cs | 54 + .../Editor/Infra/BGCcChangeNameWindow.cs.meta | 12 + .../Scripts/Editor/Infra/BGCcChoseDrawer.cs | 53 + .../Editor/Infra/BGCcChoseDrawer.cs.meta | 12 + .../Scripts/Editor/Infra/BGCcChoseWindow.cs | 60 + .../Editor/Infra/BGCcChoseWindow.cs.meta | 12 + .../Editor/Infra/BGChoseComponentWindow.cs | 54 + .../Infra/BGChoseComponentWindow.cs.meta | 12 + .../Editor/Infra/BGCurveChosePointWindow.cs | 43 + .../Infra/BGCurveChosePointWindow.cs.meta | 12 + .../Editor/Infra/BGCurvePainterGizmo.cs | 82 + .../Editor/Infra/BGCurvePainterGizmo.cs.meta | 12 + .../Editor/Infra/BGCurvePainterHandles.cs | 42 + .../Infra/BGCurvePainterHandles.cs.meta | 12 + .../Editor/Infra/BGHandlesSettingsDrawer.cs | 70 + .../Infra/BGHandlesSettingsDrawer.cs.meta | 12 + .../Scripts/Editor/Infra/BGPropertyDrawer.cs | 102 + .../Editor/Infra/BGPropertyDrawer.cs.meta | 12 + .../Editor/Infra/BGTransformMonitor.cs | 77 + .../Editor/Infra/BGTransformMonitor.cs.meta | 12 + .../BGCurve/Scripts/Editor/Overlay.meta | 9 + .../Editor/Overlay/BGOverlayMessage.cs | 52 + .../Editor/Overlay/BGOverlayMessage.cs.meta | 12 + .../Scripts/Editor/Overlay/BGPopupMenu.cs | 226 + .../Editor/Overlay/BGPopupMenu.cs.meta | 12 + .../Editor/Overlay/BGSceneViewOverlay.cs | 143 + .../Editor/Overlay/BGSceneViewOverlay.cs.meta | 12 + .../Editor/Overlay/BGSceneViewOverlayMenu.cs | 131 + .../Overlay/BGSceneViewOverlayMenu.cs.meta | 12 + .../Overlay/BGSceneViewOverlayMenuPoint.cs | 146 + .../BGSceneViewOverlayMenuPoint.cs.meta | 12 + .../BGSceneViewOverlayMenuSelection.cs | 105 + .../BGSceneViewOverlayMenuSelection.cs.meta | 12 + .../Overlay/BGSceneViewOverlayPointAdd.cs | 166 + .../BGSceneViewOverlayPointAdd.cs.meta | 12 + .../BGSceneViewOverlayPointAddAtDistance.cs | 74 + ...SceneViewOverlayPointAddAtDistance.cs.meta | 12 + .../BGSceneViewOverlayPointAddSnap2D.cs | 75 + .../BGSceneViewOverlayPointAddSnap2D.cs.meta | 12 + .../BGSceneViewOverlayPointAddSnap3D.cs | 51 + .../BGSceneViewOverlayPointAddSnap3D.cs.meta | 12 + .../BGCurve/Scripts/Editor/Settings.meta | 9 + .../Settings/BGCurveSettingsForEditor.cs | 248 + .../Settings/BGCurveSettingsForEditor.cs.meta | 12 + .../BGCurveSettingsForEditorWindow.cs | 117 + .../BGCurveSettingsForEditorWindow.cs.meta | 12 + .../Settings/BGCurveSettingsOperations.cs | 144 + .../BGCurveSettingsOperations.cs.meta | 12 + .../Editor/Settings/BGCurveSettingsSO.cs | 12 + .../Editor/Settings/BGCurveSettingsSO.cs.meta | 12 + .../BGCurve/Scripts/Editor/Utils.meta | 9 + .../Scripts/Editor/Utils/BGEditorUtility.cs | 1207 +++ .../Editor/Utils/BGEditorUtility.cs.meta | 12 + .../Scripts/Editor/Utils/BGPrivateField.cs | 113 + .../Editor/Utils/BGPrivateField.cs.meta | 12 + .../BGCurve/Scripts/Editor/Utils/BGStartUp.cs | 69 + .../Scripts/Editor/Utils/BGStartUp.cs.meta | 12 + .../Scripts/Editor/Utils/BGTransition.cs | 84 + .../Scripts/Editor/Utils/BGTransition.cs.meta | 12 + .../Scripts/Editor/Utils/BGTreeView.cs | 275 + .../Scripts/Editor/Utils/BGTreeView.cs.meta | 12 + .../Assets/BansheeGz/BGCurve/readme.txt | 62 + .../Assets/BansheeGz/BGCurve/readme.txt.meta | 8 + IronToad_UnityProject/Assets/Fonts.meta | 9 + .../Assets/Fonts/Gang of Three.ttf | Bin 0 -> 21872 bytes .../Assets/Fonts/Gang of Three.ttf.meta | 21 + IronToad_UnityProject/Assets/LeanTween.meta | 2 + .../Assets/LeanTween/Documentation.meta | 2 + .../LeanTween/Documentation/assets.meta | 2 + .../LeanTween/Documentation/assets/css.meta | 2 + .../Documentation/assets/css/main.css | 836 ++ .../Documentation/assets/css/main.css.meta | 2 + .../Documentation/assets/favicon.ico | Bin 0 -> 5430 bytes .../Documentation/assets/favicon.ico.meta | 8 + .../LeanTween/Documentation/assets/index.html | 10 + .../Documentation/assets/index.html.meta | 2 + .../LeanTween/Documentation/classes.meta | 2 + .../Documentation/classes/LTBezierPath.html | 720 ++ .../classes/LTBezierPath.html.meta | 2 + .../Documentation/classes/LTDescr.html | 2705 ++++++ .../Documentation/classes/LTDescr.html.meta | 2 + .../Documentation/classes/LTEvent.html | 237 + .../Documentation/classes/LTEvent.html.meta | 2 + .../Documentation/classes/LTRect.html | 359 + .../Documentation/classes/LTRect.html.meta | 2 + .../Documentation/classes/LTSpline.html | 796 ++ .../Documentation/classes/LTSpline.html.meta | 2 + .../Documentation/classes/LeanAudio.html | 332 + .../Documentation/classes/LeanAudio.html.meta | 2 + .../classes/LeanAudioOptions.html | 383 + .../classes/LeanAudioOptions.html.meta | 2 + .../Documentation/classes/LeanTween.html | 7474 +++++++++++++++++ .../Documentation/classes/LeanTween.html.meta | 2 + .../Documentation/classes/LeanTweenType.html | 1090 +++ .../classes/LeanTweenType.html.meta | 2 + .../Documentation/classes/index.html | 10 + .../Documentation/classes/index.html.meta | 2 + .../LeanTween/Documentation/elements.meta | 9 + .../Documentation/elements/index.html | 10 + .../Documentation/elements/index.html.meta | 8 + .../Assets/LeanTween/Documentation/index.html | 165 + .../LeanTween/Documentation/index.html.meta | 2 + .../Assets/LeanTween/Editor.meta | 9 + .../Editor/LeanTweenDocumentationEditor.cs | 59 + .../LeanTweenDocumentationEditor.cs.meta | 7 + .../Assets/LeanTween/Examples.meta | 2 + .../Assets/LeanTween/Examples/Archived.meta | 9 + .../Examples/Archived/2dUnlitWithFade.shader | 30 + .../Archived/2dUnlitWithFade.shader.meta | 2 + .../Examples/Archived/GrumpyCat.jpeg | Bin 0 -> 9414 bytes .../Examples/Archived/GrumpyCat.jpeg.meta | 33 + .../Examples/Archived/OldGUIExamplesCS.cs | 84 + .../Archived/OldGUIExamplesCS.cs.meta | 7 + .../Examples/Archived/OldGUIExamplesCS.unity | Bin 0 -> 13352 bytes .../Archived/OldGUIExamplesCS.unity.meta | 2 + .../Examples/Archived/OldGUIExamplesJS.js | 71 + .../Archived/OldGUIExamplesJS.js.meta | 7 + .../Examples/Archived/OldGUIExamplesJS.unity | Bin 0 -> 14472 bytes .../Archived/OldGUIExamplesJS.unity.meta | 2 + .../Examples/Archived/OldGUISlideImageIn.js | 16 + .../Archived/OldGUISlideImageIn.js.meta | 7 + .../Archived/OldGUISlideImageIn.unity | Bin 0 -> 13120 bytes .../Archived/OldGUISlideImageIn.unity.meta | 2 + .../Examples/Archived/SoBeautiful.gif | Bin 0 -> 4052 bytes .../Examples/Archived/SoBeautiful.gif.meta | 33 + .../Examples/Archived/TestingPunch.cs | 182 + .../Examples/Archived/TestingPunch.cs.meta | 7 + .../Examples/Archived/TestingPunch.unity | Bin 0 -> 25488 bytes .../Examples/Archived/TestingPunch.unity.meta | 2 + .../Examples/Archived/TestingRigidbodyCS.cs | 21 + .../Archived/TestingRigidbodyCS.cs.meta | 7 + .../Archived/TestingRigidbodyCS.unity | Bin 0 -> 28432 bytes .../Archived/TestingRigidbodyCS.unity.meta | 2 + .../Assets/LeanTween/Examples/Material.meta | 2 + .../LeanTween/Examples/Material/AlphBumps.mat | Bin 0 -> 4252 bytes .../Examples/Material/AlphBumps.mat.meta | 2 + .../Examples/Material/AlphaReadyMaterial.mat | Bin 0 -> 4312 bytes .../Material/AlphaReadyMaterial.mat.meta | 2 + .../Material/FrictionLess.physicMaterial | Bin 0 -> 4172 bytes .../Material/FrictionLess.physicMaterial.meta | 2 + .../Material/Futoro_PersonSprites.jpg | Bin 0 -> 19092 bytes .../Material/Futoro_PersonSprites.jpg.meta | 91 + .../Material/Futoro_PlanetMaterial.mat | Bin 0 -> 4488 bytes .../Material/Futoro_PlanetMaterial.mat.meta | 4 + .../Examples/Material/Futoro_Ring.psd | Bin 0 -> 151543 bytes .../Examples/Material/Futoro_Ring.psd.meta | 47 + .../Examples/Material/Futoro_SineWave.mat | Bin 0 -> 4356 bytes .../Material/Futoro_SineWave.mat.meta | 4 + .../Examples/Material/Futuro_Bar.psd | Bin 0 -> 36154 bytes .../Examples/Material/Futuro_Bar.psd.meta | 47 + .../Examples/Material/Futuro_ButtonBack.psd | Bin 0 -> 53787 bytes .../Material/Futuro_ButtonBack.psd.meta | 47 + .../Examples/Material/Futuro_SineWave.psd | Bin 0 -> 34895 bytes .../Material/Futuro_SineWave.psd.meta | 58 + .../Examples/Material/Futuro_WindowBack.psd | Bin 0 -> 141963 bytes .../Material/Futuro_WindowBack.psd.meta | 47 + .../LeanTween/Examples/Material/Graph.mat | Bin 0 -> 4260 bytes .../Examples/Material/Graph.mat.meta | 2 + .../LeanTween/Examples/Material/GridLines.mat | Bin 0 -> 4428 bytes .../Examples/Material/GridLines.mat.meta | 2 + .../LeanTween/Examples/Material/Ground.mat | Bin 0 -> 4212 bytes .../Examples/Material/Ground.mat.meta | 2 + .../Examples/Material/LineGlowMaterial.mat | Bin 0 -> 4340 bytes .../Material/LineGlowMaterial.mat.meta | 2 + .../LeanTween/Examples/Material/Mock2d.mat | Bin 0 -> 4212 bytes .../Examples/Material/Mock2d.mat.meta | 2 + .../Examples/Material/ParticleGlow.mat | Bin 0 -> 4896 bytes .../Examples/Material/ParticleGlow.mat.meta | 8 + .../LeanTween/Examples/Material/PointMark.mat | Bin 0 -> 4216 bytes .../Examples/Material/PointMark.mat.meta | 2 + .../LeanTween/Examples/Material/TrackCar.mat | Bin 0 -> 4892 bytes .../Examples/Material/TrackCar.mat.meta | 8 + .../Examples/Material/TrackFollowMaterial.mat | Bin 0 -> 4304 bytes .../Material/TrackFollowMaterial.mat.meta | 8 + .../Examples/Material/TrackGlowMaterial.mat | Bin 0 -> 4344 bytes .../Material/TrackGlowMaterial.mat.meta | 8 + .../Examples/Material/TrackLines.mat | Bin 0 -> 4912 bytes .../Examples/Material/TrackLines.mat.meta | 8 + .../Examples/Material/TrailFollowMaterial.mat | Bin 0 -> 4304 bytes .../Material/TrailFollowMaterial.mat.meta | 2 + .../Examples/Material/WalkingStick.mat | Bin 0 -> 4216 bytes .../Examples/Material/WalkingStick.mat.meta | 2 + .../Assets/LeanTween/Examples/Models.meta | 2 + .../LeanTween/Examples/Models/2dText.fbx | Bin 0 -> 14492 bytes .../LeanTween/Examples/Models/2dText.fbx.meta | 75 + .../Examples/Models/AdvancedExamplesText.fbx | Bin 0 -> 35436 bytes .../Models/AdvancedExamplesText.fbx.meta | 91 + .../Examples/Models/BasicExamplesText.fbx | Bin 0 -> 64044 bytes .../Models/BasicExamplesText.fbx.meta | 104 + .../Examples/Models/CameraShakeText.fbx | Bin 0 -> 37372 bytes .../Examples/Models/CameraShakeText.fbx.meta | 55 + .../Examples/Models/CurvePathsText.fbx | Bin 0 -> 32684 bytes .../Examples/Models/CurvePathsText.fbx.meta | 55 + .../Examples/Models/EndlessDrivingText.fbx | Bin 0 -> 25500 bytes .../Models/EndlessDrivingText.fbx.meta | 76 + .../LeanTween/Examples/Models/ExampleCar.fbx | Bin 0 -> 15820 bytes .../Examples/Models/ExampleCar.fbx.meta | 76 + .../Examples/Models/ExampleFirTree.fbx | Bin 0 -> 12988 bytes .../Examples/Models/ExampleFirTree.fbx.meta | 84 + .../Assets/LeanTween/Examples/Models/Grid.fbx | Bin 0 -> 23804 bytes .../LeanTween/Examples/Models/Grid.fbx.meta | 75 + .../Examples/Models/LeanTween-Icon.blend.zip | Bin 0 -> 73922 bytes .../Models/LeanTween-Icon.blend.zip.meta | 2 + .../Examples/Models/LeanTween-Icon.fbx | 584 ++ .../Examples/Models/LeanTween-Icon.fbx.meta | 77 + .../Examples/Models/LeanTween.prefab | Bin 0 -> 8064 bytes .../Examples/Models/LeanTween.prefab.meta | 2 + .../Examples/Models/LeanTweenHD-Icon.fbx | Bin 0 -> 105260 bytes .../Examples/Models/LeanTweenHD-Icon.fbx.meta | 90 + .../LeanTween/Examples/Models/Materials.meta | 2 + .../Examples/Models/Materials/LMaterial.mat | Bin 0 -> 4216 bytes .../Models/Materials/LMaterial.mat.meta | 2 + .../Models/Materials/LineMaterial.mat | Bin 0 -> 4216 bytes .../Models/Materials/LineMaterial.mat.meta | 2 + .../Models/Materials/Material.001.mat | Bin 0 -> 4216 bytes .../Models/Materials/Material.001.mat.meta | 2 + .../Examples/Models/Materials/Material.mat | Bin 0 -> 4212 bytes .../Models/Materials/Material.mat.meta | 2 + .../Models/Materials/Material_001.mat | Bin 0 -> 4216 bytes .../Models/Materials/Material_001.mat.meta | 2 + .../Examples/Models/Materials/No Name.mat | Bin 0 -> 4244 bytes .../Models/Materials/No Name.mat.meta | 2 + .../Materials/SimpleAvatarAlphaBlue.mat | Bin 0 -> 4280 bytes .../Materials/SimpleAvatarAlphaBlue.mat.meta | 2 + .../Models/Materials/SimpleAvatarBlue.mat | Bin 0 -> 4220 bytes .../Materials/SimpleAvatarBlue.mat.meta | 2 + .../Models/Materials/SimpleAvatarHat.mat | Bin 0 -> 4372 bytes .../Models/Materials/SimpleAvatarHat.mat.meta | 2 + .../Models/Materials/SimpleAvatarMat.mat | Bin 0 -> 4220 bytes .../Models/Materials/SimpleAvatarMat.mat.meta | 2 + .../Models/Materials/SubTitleText.mat | Bin 0 -> 4216 bytes .../Models/Materials/SubTitleText.mat.meta | 2 + .../Examples/Models/Materials/eanTween.mat | Bin 0 -> 4472 bytes .../Models/Materials/eanTween.mat.meta | 2 + .../Examples/Models/SimpleAvatar.fbx | Bin 0 -> 28876 bytes .../Examples/Models/SimpleAvatar.fbx.meta | 57 + .../Examples/Models/SimpleAvatarPieces.fbx | Bin 0 -> 123852 bytes .../Models/SimpleAvatarPieces.fbx.meta | 312 + .../Assets/LeanTween/Examples/Prefabs.meta | 2 + .../Examples/Prefabs/Avatar2dParticles.prefab | Bin 0 -> 45320 bytes .../Prefabs/Avatar2dParticles.prefab.meta | 2 + .../Examples/Prefabs/AvatarAlpha.prefab | Bin 0 -> 27104 bytes .../Examples/Prefabs/AvatarAlpha.prefab.meta | 2 + .../Examples/Prefabs/AvatarDiffuse.prefab | Bin 0 -> 7312 bytes .../Prefabs/AvatarDiffuse.prefab.meta | 2 + .../Examples/Prefabs/AvatarEventsCS.prefab | Bin 0 -> 10336 bytes .../Prefabs/AvatarEventsCS.prefab.meta | 2 + .../Examples/Prefabs/AvatarEventsJS.prefab | Bin 0 -> 10336 bytes .../Prefabs/AvatarEventsJS.prefab.meta | 2 + .../Examples/Prefabs/AvatarSparkles.prefab | Bin 0 -> 51520 bytes .../Prefabs/AvatarSparkles.prefab.meta | 2 + .../Examples/Prefabs/BasicExamplesText.prefab | Bin 0 -> 8728 bytes .../Prefabs/BasicExamplesText.prefab.meta | 2 + .../Examples/Prefabs/EndlessPiece.prefab | Bin 0 -> 13992 bytes .../Examples/Prefabs/EndlessPiece.prefab.meta | 2 + .../Examples/Prefabs/GridLine.prefab | Bin 0 -> 7192 bytes .../Examples/Prefabs/GridLine.prefab.meta | 2 + .../LeanTween/Examples/Prefabs/Grids.prefab | Bin 0 -> 46568 bytes .../Examples/Prefabs/Grids.prefab.meta | 2 + .../Assets/LeanTween/Examples/Scenes.meta | 2 + .../Scenes/GeneralAdvancedTechniques.unity | Bin 0 -> 58364 bytes .../GeneralAdvancedTechniques.unity.meta | 8 + .../Examples/Scenes/GeneralBasicCS.unity | Bin 0 -> 123804 bytes .../Examples/Scenes/GeneralBasicCS.unity.meta | 2 + .../Examples/Scenes/GeneralBasicJS.unity | Bin 0 -> 123908 bytes .../Examples/Scenes/GeneralBasicJS.unity.meta | 2 + .../Examples/Scenes/GeneralBasics2dCS.unity | Bin 0 -> 71724 bytes .../Scenes/GeneralBasics2dCS.unity.meta | 2 + .../Examples/Scenes/GeneralBasics2dJS.unity | Bin 0 -> 71724 bytes .../Scenes/GeneralBasics2dJS.unity.meta | 2 + .../Examples/Scenes/GeneralCameraShake.unity | Bin 0 -> 75328 bytes .../Scenes/GeneralCameraShake.unity.meta | 2 + .../Examples/Scenes/GeneralEasingTypes.unity | Bin 0 -> 67408 bytes .../Scenes/GeneralEasingTypes.unity.meta | 8 + .../Examples/Scenes/GeneralEventsCS.unity | Bin 0 -> 102728 bytes .../Scenes/GeneralEventsCS.unity.meta | 2 + .../Examples/Scenes/GeneralEventsJS.unity | Bin 0 -> 103880 bytes .../Scenes/GeneralEventsJS.unity.meta | 2 + .../Examples/Scenes/GeneralSimpleUiCS.unity | Bin 0 -> 30144 bytes .../Scenes/GeneralSimpleUiCS.unity.meta | 2 + .../Examples/Scenes/GeneralSimpleUiJS.unity | Bin 0 -> 30880 bytes .../Scenes/GeneralSimpleUiJS.unity.meta | 2 + .../Examples/Scenes/GeneralUISpaceCS.unity | Bin 0 -> 107624 bytes .../Scenes/GeneralUISpaceCS.unity.meta | 4 + .../Examples/Scenes/LogoCinematic.unity | Bin 0 -> 28004 bytes .../Examples/Scenes/LogoCinematic.unity.meta | 2 + .../Examples/Scenes/PathBezier.unity | Bin 0 -> 113292 bytes .../Examples/Scenes/PathBezier.unity.meta | 2 + .../Examples/Scenes/PathMoveLocalJS.unity | Bin 0 -> 29864 bytes .../Scenes/PathMoveLocalJS.unity.meta | 2 + .../Examples/Scenes/PathSpline2d.unity | Bin 0 -> 26152 bytes .../Examples/Scenes/PathSpline2d.unity.meta | 2 + .../Examples/Scenes/PathSplineEndlessCS.unity | Bin 0 -> 88360 bytes .../Scenes/PathSplineEndlessCS.unity.meta | 8 + .../Scenes/PathSplinePerformanceCS.unity | Bin 0 -> 93588 bytes .../Scenes/PathSplinePerformanceCS.unity.meta | 8 + .../Examples/Scenes/PathSplineTrackCS.unity | Bin 0 -> 84244 bytes .../Scenes/PathSplineTrackCS.unity.meta | 8 + .../Examples/Scenes/PathSplines.unity | Bin 0 -> 112476 bytes .../Examples/Scenes/PathSplines.unity.meta | 2 + .../Examples/Scenes/TestingAllCS.unity | Bin 0 -> 30112 bytes .../Examples/Scenes/TestingAllCS.unity.meta | 2 + .../Examples/Scenes/TestingAllJS.unity | Bin 0 -> 30712 bytes .../Examples/Scenes/TestingAllJS.unity.meta | 2 + .../Examples/Scenes/TestingUnitTests.unity | Bin 0 -> 26656 bytes .../Scenes/TestingUnitTests.unity.meta | 2 + .../Assets/LeanTween/Examples/Scripts.meta | 2 + .../LeanTween/Examples/Scripts/Archive.zip | Bin 0 -> 2436 bytes .../Examples/Scripts/Archive.zip.meta | 2 + .../Scripts/GeneralAdvancedTechniques.cs | 60 + .../Scripts/GeneralAdvancedTechniques.cs.meta | 12 + .../Examples/Scripts/GeneralBasicCS.cs | 82 + .../Examples/Scripts/GeneralBasicCS.cs.meta | 7 + .../Examples/Scripts/GeneralBasicJS.js | 78 + .../Examples/Scripts/GeneralBasicJS.js.meta | 7 + .../Examples/Scripts/GeneralBasics2dCS.cs | 102 + .../Scripts/GeneralBasics2dCS.cs.meta | 7 + .../Examples/Scripts/GeneralBasics2dJS.js | 98 + .../Scripts/GeneralBasics2dJS.js.meta | 7 + .../Examples/Scripts/GeneralBasicsJS.js | 78 + .../Examples/Scripts/GeneralBasicsJS.js.meta | 10 + .../Examples/Scripts/GeneralCameraShake.cs | 82 + .../Scripts/GeneralCameraShake.cs.meta | 7 + .../Examples/Scripts/GeneralEasingTypes.cs | 70 + .../Scripts/GeneralEasingTypes.cs.meta | 12 + .../Scripts/GeneralEventsListenersCS.cs | 83 + .../Scripts/GeneralEventsListenersCS.cs.meta | 7 + .../Scripts/GeneralEventsListenersJS.js | 77 + .../Scripts/GeneralEventsListenersJS.js.meta | 7 + .../Examples/Scripts/GeneralSimpleUiCS.cs | 56 + .../Scripts/GeneralSimpleUiCS.cs.meta | 7 + .../Examples/Scripts/GeneralSimpleUiJS.js | 48 + .../Scripts/GeneralSimpleUiJS.js.meta | 7 + .../Examples/Scripts/GeneralUISpaceCS.cs | 89 + .../Examples/Scripts/GeneralUISpaceCS.cs.meta | 8 + .../Examples/Scripts/LogoCinematic.cs | 44 + .../Examples/Scripts/LogoCinematic.cs.meta | 7 + .../LeanTween/Examples/Scripts/PathBezier.cs | 48 + .../Examples/Scripts/PathBezier.cs.meta | 7 + .../Examples/Scripts/PathLocalCurveJS.js | 32 + .../Examples/Scripts/PathLocalCurveJS.js.meta | 7 + .../LeanTween/Examples/Scripts/PathSpline.cs | 38 + .../Examples/Scripts/PathSpline.cs.meta | 7 + .../Examples/Scripts/PathSpline2d.cs | 43 + .../Examples/Scripts/PathSpline2d.cs.meta | 7 + .../Examples/Scripts/PathSplineEndlessCS.cs | 125 + .../Scripts/PathSplineEndlessCS.cs.meta | 12 + .../Scripts/PathSplinePerformanceCS.cs | 93 + .../Scripts/PathSplinePerformanceCS.cs.meta | 12 + .../Examples/Scripts/PathSplineTrackCS.cs | 68 + .../Scripts/PathSplineTrackCS.cs.meta | 12 + .../LeanTween/Examples/Scripts/PathSplines.cs | 46 + .../Examples/Scripts/PathSplines.cs.meta | 7 + .../Examples/Scripts/TestingAllJS.js | 186 + .../Examples/Scripts/TestingAllJS.js.meta | 7 + .../Examples/Scripts/TestingUnitTests.cs | 521 ++ .../Examples/Scripts/TestingUnitTests.cs.meta | 7 + .../Assets/LeanTween/Examples/Textures.meta | 2 + .../Textures/DefaultParticleReplacement.jpg | Bin 0 -> 5405 bytes .../DefaultParticleReplacement.jpg.meta | 33 + .../LeanTween/Examples/Textures/Dude2d.png | Bin 0 -> 9921 bytes .../Examples/Textures/Dude2d.png.meta | 56 + .../Examples/Textures/HorizontalGradient.jpg | Bin 0 -> 4974 bytes .../Textures/HorizontalGradient.jpg.meta | 33 + .../Assets/LeanTween/License.txt | 31 + .../Assets/LeanTween/License.txt.meta | 8 + .../Assets/LeanTween/ReadMe.txt | 9 + .../Assets/LeanTween/ReadMe.txt.meta | 2 + IronToad_UnityProject/Assets/M_Lighthouse.FBX | Bin 0 -> 20080 bytes .../Assets/M_Lighthouse.FBX.meta | 81 + .../Assets/Materials/No Name.mat | Bin 0 -> 5008 bytes .../Assets/Materials/No Name.mat.meta | 8 + IronToad_UnityProject/Assets/Plugins.meta | 2 + .../Assets/Plugins/LeanTween.meta | 9 + .../Assets/Plugins/LeanTween/LTDescr.cs | 2246 +++++ .../Assets/Plugins/LeanTween/LTDescr.cs.meta | 12 + .../Plugins/LeanTween/LTDescrOptional.cs | 88 + .../Plugins/LeanTween/LTDescrOptional.cs.meta | 12 + .../Assets/Plugins/LeanTween/LeanAudio.cs | 418 + .../Plugins/LeanTween/LeanAudio.cs.meta | 12 + .../Assets/Plugins/LeanTween/LeanTest.cs | 123 + .../Assets/Plugins/LeanTween/LeanTest.cs.meta | 12 + .../Assets/Plugins/LeanTween/LeanTween.cs | 3615 ++++++++ .../Plugins/LeanTween/LeanTween.cs.meta | 12 + .../Plugins/LeanTween/LeanTween.dll.zip | Bin 0 -> 30942 bytes .../Plugins/LeanTween/LeanTween.dll.zip.meta | 8 + .../Assets/Scripts/NotificationServer.cs | 71 + .../Assets/Scripts/NotificationServer.cs.meta | 12 + .../Assets/Scripts/UIPanel.cs | 158 + .../Assets/Scripts/UIPanel.cs.meta | 12 + IronToad_UnityProject/Assets/ThirdParty.txt | 2 + .../Assets/ThirdParty.txt.meta | 8 + IronToad_UnityProject/Assets/UIArt.meta | 9 + .../Assets/UIArt/Icon_4-512.png | Bin 0 -> 49901 bytes .../Assets/UIArt/Icon_4-512.png.meta | 124 + .../Assets/_Scenes/UITestScene.unity | Bin 0 -> 64324 bytes .../Assets/_Scenes/UITestScene.unity.meta | 8 + 775 files changed, 57142 insertions(+) create mode 100644 IronToad_UnityProject/Assets/BansheeGz.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimatedObjectsForPoints.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimatedObjectsForPoints.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimationTest.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimationTest.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGComponentTest.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGComponentTest.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingAdaptiveMath.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingAdaptiveMath.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingBaseMath.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingBaseMath.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGLeafs.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGLeafs.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoomin.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoomin.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoominAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoominAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoon.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoon.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonIdleAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonIdleAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointTransformsAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointTransformsAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointsModeSphereAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointsModeSphereAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap1Animation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap1Animation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap2Animation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap2Animation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnufkin.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnufkin.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnufkinAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnufkinAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSphere.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSphere.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectile.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectile.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectileAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectileAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSun.controller create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSun.controller.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSunAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSunAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGTreeAnimation.anim create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGTreeAnimation.anim.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo2.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo2.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveMainMenu.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveMainMenu.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCcChangeCursorLinear.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCcChangeCursorLinear.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestClosestPoint.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestClosestPoint.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestComponents.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestComponents.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCustomFields.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCustomFields.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestMath.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestMath.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPerformance.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPerformance.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsMode.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsMode.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsTransforms.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsTransforms.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntime.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntime.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntimeCustomFields.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntimeCustomFields.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestSnapping.unity create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestSnapping.unity.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestCheckerBoard.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestCheckerBoard.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestCheckerBoardMaterial.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestCheckerBoardMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestGrass.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestGrass.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestLineRenderer.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestLineRenderer.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestLineRendererCheckerBox.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestLineRendererCheckerBox.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestMoonMaterial.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestMoonMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestSunMaterial.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestSunMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTrailRenderer.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTrailRenderer.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeLeafsMaterial.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeLeafsMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeTrunkMaterial.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeTrunkMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTrunk.mat create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTrunk.mat.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTrunk.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTrunk.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCamera.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCamera.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCcChangeCursorLinear.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCcChangeCursorLinear.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveChange.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveChange.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveClosestPoint.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveClosestPoint.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveDynamic.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveDynamic.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveMath.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveMath.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntime.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntime.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntimeCustomFields.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntimeCustomFields.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveShowcase.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveShowcase.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveStatic.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveStatic.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestDirector.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestDirector.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestMainMenu.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestMainMenu.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestPerformance.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestPerformance.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestDemoTerrain.asset create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestDemoTerrain.asset.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestSnappingTerrain.asset create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestSnappingTerrain.asset.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGAdd123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGAdd123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWhite123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWhite123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWithBorder123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWithBorder123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcEditName123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcEditName123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcNoImage123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcNoImage123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapseAll123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapseAll123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapsed123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapsed123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGComponents123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGComponents123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlAbsent123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlAbsent123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierIndependent123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierIndependent123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierSymmetrical123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierSymmetrical123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGConvertAll123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGConvertAll123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCopy123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCopy123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveComponents123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveComponents123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveLogo123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveLogo123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGDeSelectAll123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGDeSelectAll123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGDelete123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGDelete123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGExpandAll123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGExpandAll123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGExpanded123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGExpanded123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGFields123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGFields123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHandlesOff123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHandlesOff123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHandlesOn123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHandlesOn123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHelp123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHelp123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorIcon123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorIcon123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorSelectedIcon123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorSelectedIcon123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyIcon123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyIcon123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchySelectedIcon123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchySelectedIcon123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyWarningIcon123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyWarningIcon123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyWarningSelectedIcon123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyWarningSelectedIcon123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOff123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOff123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOn123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOn123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGMenuItemBackground123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGMenuItemBackground123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGMoveDown123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGMoveDown123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGMoveUp123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGMoveUp123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOff123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOff123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOn123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOn123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPaste123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPaste123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointControlBS123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointControlBS123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointDelete123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointDelete123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertAfter123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertAfter123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertBefore123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertBefore123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointSelected123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointSelected123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPoints123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPoints123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectAll123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectAll123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionAdd123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionAdd123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionRemove123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionRemove123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettings123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettings123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettingsIcon123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettingsIcon123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableCell123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableCell123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableHeader123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableHeader123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableTitle123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableTitle123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickNo123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickNo123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickYes123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickYes123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursor123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursor123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorChangeLinear123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorChangeLinear123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectRotate123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectRotate123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectScale123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectScale123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectTranslate123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectTranslate123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcMath123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcMath123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcSplitterPolyline123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcSplitterPolyline123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcTriangulate2D123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcTriangulate2D123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcVisualizationLineRenderer123.png create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcVisualizationLineRenderer123.png.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorChangeLinear.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorChangeLinear.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectRotate.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectRotate.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectScale.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectScale.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectTranslate.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectTranslate.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcSplitterPolyline.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcSplitterPolyline.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcTriangulate2D.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcTriangulate2D.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcVisualizationLineRenderer.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcVisualizationLineRenderer.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursorObject.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursorObject.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithMath.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithMath.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCc.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCc.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurve.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurve.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveAdaptiveMath.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveAdaptiveMath.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveBaseMath.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveBaseMath.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveCalculatorClosestPoint.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveCalculatorClosestPoint.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveChangedArgs.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveChangedArgs.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulaMath.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulaMath.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulas.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulas.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveMathI.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveMathI.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePoint.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePoint.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointComponent.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointComponent.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointField.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointField.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointGO.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointGO.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointI.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointI.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveReferenceToPoint.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveReferenceToPoint.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveSettings.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveSettings.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGReflectionAdapter.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGReflectionAdapter.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorChangeLinearEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorChangeLinearEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorDrawer.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorDrawer.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectRotateEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectRotateEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectScaleEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectScaleEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectTranslateEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectTranslateEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcMathEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcMathEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcSplitterPolylineEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcSplitterPolylineEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcTriangulate2DEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcTriangulate2DEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcVisualizationLineRendererEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcVisualizationLineRendererEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCcEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCcEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorComponents.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorComponents.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorFields.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorFields.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoint.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoint.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoints.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoints.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPointsSelection.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPointsSelection.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorSettings.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorSettings.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorTab.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorTab.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointComponentDrawer.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointComponentDrawer.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointGOEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointGOEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveReferenceToPointEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveReferenceToPointEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGNewPointPositionManager.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGNewPointPositionManager.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGRectangularSelection.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGRectangularSelection.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcAddWindow.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcAddWindow.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChangeNameWindow.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChangeNameWindow.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseDrawer.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseDrawer.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseWindow.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseWindow.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGChoseComponentWindow.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGChoseComponentWindow.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurveChosePointWindow.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurveChosePointWindow.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterGizmo.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterGizmo.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterHandles.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterHandles.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGHandlesSettingsDrawer.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGHandlesSettingsDrawer.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGPropertyDrawer.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGPropertyDrawer.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGTransformMonitor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGTransformMonitor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGOverlayMessage.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGOverlayMessage.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGPopupMenu.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGPopupMenu.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlay.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlay.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenu.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenu.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuPoint.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuPoint.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuSelection.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuSelection.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAdd.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAdd.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddAtDistance.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddAtDistance.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap2D.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap2D.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap3D.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap3D.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditor.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditorWindow.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditorWindow.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsOperations.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsOperations.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsSO.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsSO.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGEditorUtility.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGEditorUtility.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGPrivateField.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGPrivateField.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGStartUp.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGStartUp.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTransition.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTransition.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTreeView.cs create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTreeView.cs.meta create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/readme.txt create mode 100644 IronToad_UnityProject/Assets/BansheeGz/BGCurve/readme.txt.meta create mode 100644 IronToad_UnityProject/Assets/Fonts.meta create mode 100755 IronToad_UnityProject/Assets/Fonts/Gang of Three.ttf create mode 100644 IronToad_UnityProject/Assets/Fonts/Gang of Three.ttf.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/assets.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/assets/css.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/assets/css/main.css create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/assets/css/main.css.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/assets/favicon.ico create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/assets/favicon.ico.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/assets/index.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/assets/index.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTBezierPath.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTBezierPath.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTDescr.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTDescr.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTEvent.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTEvent.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTRect.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTRect.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTSpline.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LTSpline.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LeanAudio.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LeanAudio.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LeanAudioOptions.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LeanAudioOptions.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LeanTween.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LeanTween.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LeanTweenType.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/LeanTweenType.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/index.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/classes/index.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/elements.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/elements/index.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/elements/index.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/index.html create mode 100644 IronToad_UnityProject/Assets/LeanTween/Documentation/index.html.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Editor.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Editor/LeanTweenDocumentationEditor.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Editor/LeanTweenDocumentationEditor.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/2dUnlitWithFade.shader create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/2dUnlitWithFade.shader.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/GrumpyCat.jpeg create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/GrumpyCat.jpeg.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUIExamplesCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUIExamplesCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUIExamplesCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUIExamplesCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUIExamplesJS.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUIExamplesJS.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUIExamplesJS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUIExamplesJS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUISlideImageIn.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUISlideImageIn.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUISlideImageIn.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/OldGUISlideImageIn.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/SoBeautiful.gif create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/SoBeautiful.gif.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/TestingPunch.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/TestingPunch.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/TestingPunch.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/TestingPunch.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/TestingRigidbodyCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/TestingRigidbodyCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/TestingRigidbodyCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Archived/TestingRigidbodyCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/AlphBumps.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/AlphBumps.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/AlphaReadyMaterial.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/AlphaReadyMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/FrictionLess.physicMaterial create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/FrictionLess.physicMaterial.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futoro_PersonSprites.jpg create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futoro_PersonSprites.jpg.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futoro_PlanetMaterial.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futoro_PlanetMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futoro_Ring.psd create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futoro_Ring.psd.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futoro_SineWave.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futoro_SineWave.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futuro_Bar.psd create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futuro_Bar.psd.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futuro_ButtonBack.psd create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futuro_ButtonBack.psd.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futuro_SineWave.psd create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futuro_SineWave.psd.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futuro_WindowBack.psd create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Futuro_WindowBack.psd.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Graph.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Graph.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/GridLines.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/GridLines.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Ground.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Ground.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/LineGlowMaterial.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/LineGlowMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Mock2d.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/Mock2d.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/ParticleGlow.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/ParticleGlow.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/PointMark.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/PointMark.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrackCar.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrackCar.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrackFollowMaterial.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrackFollowMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrackGlowMaterial.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrackGlowMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrackLines.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrackLines.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrailFollowMaterial.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/TrailFollowMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/WalkingStick.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Material/WalkingStick.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/2dText.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/2dText.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/AdvancedExamplesText.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/AdvancedExamplesText.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/BasicExamplesText.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/BasicExamplesText.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/CameraShakeText.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/CameraShakeText.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/CurvePathsText.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/CurvePathsText.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/EndlessDrivingText.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/EndlessDrivingText.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/ExampleCar.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/ExampleCar.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/ExampleFirTree.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/ExampleFirTree.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Grid.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Grid.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/LeanTween-Icon.blend.zip create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/LeanTween-Icon.blend.zip.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/LeanTween-Icon.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/LeanTween-Icon.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/LeanTween.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/LeanTween.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/LeanTweenHD-Icon.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/LeanTweenHD-Icon.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/LMaterial.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/LMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/LineMaterial.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/LineMaterial.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/Material.001.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/Material.001.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/Material.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/Material.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/Material_001.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/Material_001.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/No Name.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/No Name.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SimpleAvatarAlphaBlue.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SimpleAvatarAlphaBlue.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SimpleAvatarBlue.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SimpleAvatarBlue.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SimpleAvatarHat.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SimpleAvatarHat.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SimpleAvatarMat.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SimpleAvatarMat.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SubTitleText.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/SubTitleText.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/eanTween.mat create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/Materials/eanTween.mat.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/SimpleAvatar.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/SimpleAvatar.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/SimpleAvatarPieces.fbx create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Models/SimpleAvatarPieces.fbx.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/Avatar2dParticles.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/Avatar2dParticles.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarAlpha.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarAlpha.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarDiffuse.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarDiffuse.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarEventsCS.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarEventsCS.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarEventsJS.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarEventsJS.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarSparkles.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/AvatarSparkles.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/BasicExamplesText.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/BasicExamplesText.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/EndlessPiece.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/EndlessPiece.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/GridLine.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/GridLine.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/Grids.prefab create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Prefabs/Grids.prefab.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralAdvancedTechniques.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralAdvancedTechniques.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralBasicCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralBasicCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralBasicJS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralBasicJS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralBasics2dCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralBasics2dCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralBasics2dJS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralBasics2dJS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralCameraShake.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralCameraShake.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralEasingTypes.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralEasingTypes.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralEventsCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralEventsCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralEventsJS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralEventsJS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralSimpleUiCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralSimpleUiCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralSimpleUiJS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralSimpleUiJS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralUISpaceCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/GeneralUISpaceCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/LogoCinematic.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/LogoCinematic.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathBezier.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathBezier.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathMoveLocalJS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathMoveLocalJS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSpline2d.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSpline2d.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSplineEndlessCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSplineEndlessCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSplinePerformanceCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSplinePerformanceCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSplineTrackCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSplineTrackCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSplines.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/PathSplines.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/TestingAllCS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/TestingAllCS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/TestingAllJS.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/TestingAllJS.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/TestingUnitTests.unity create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scenes/TestingUnitTests.unity.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/Archive.zip create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/Archive.zip.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralAdvancedTechniques.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralAdvancedTechniques.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasicCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasicCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasicJS.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasicJS.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasics2dCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasics2dCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasics2dJS.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasics2dJS.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasicsJS.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralBasicsJS.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralCameraShake.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralCameraShake.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralEasingTypes.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralEasingTypes.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralEventsListenersCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralEventsListenersCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralEventsListenersJS.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralEventsListenersJS.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralSimpleUiCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralSimpleUiCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralSimpleUiJS.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralSimpleUiJS.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralUISpaceCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/GeneralUISpaceCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/LogoCinematic.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/LogoCinematic.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathBezier.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathBezier.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathLocalCurveJS.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathLocalCurveJS.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSpline.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSpline.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSpline2d.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSpline2d.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSplineEndlessCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSplineEndlessCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSplinePerformanceCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSplinePerformanceCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSplineTrackCS.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSplineTrackCS.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSplines.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/PathSplines.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/TestingAllJS.js create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/TestingAllJS.js.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/TestingUnitTests.cs create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Scripts/TestingUnitTests.cs.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Textures.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Textures/DefaultParticleReplacement.jpg create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Textures/DefaultParticleReplacement.jpg.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Textures/Dude2d.png create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Textures/Dude2d.png.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Textures/HorizontalGradient.jpg create mode 100644 IronToad_UnityProject/Assets/LeanTween/Examples/Textures/HorizontalGradient.jpg.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/License.txt create mode 100644 IronToad_UnityProject/Assets/LeanTween/License.txt.meta create mode 100644 IronToad_UnityProject/Assets/LeanTween/ReadMe.txt create mode 100644 IronToad_UnityProject/Assets/LeanTween/ReadMe.txt.meta create mode 100644 IronToad_UnityProject/Assets/M_Lighthouse.FBX create mode 100644 IronToad_UnityProject/Assets/M_Lighthouse.FBX.meta create mode 100644 IronToad_UnityProject/Assets/Materials/No Name.mat create mode 100644 IronToad_UnityProject/Assets/Materials/No Name.mat.meta create mode 100644 IronToad_UnityProject/Assets/Plugins.meta create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween.meta create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LTDescr.cs create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LTDescr.cs.meta create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LTDescrOptional.cs create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LTDescrOptional.cs.meta create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LeanAudio.cs create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LeanAudio.cs.meta create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LeanTest.cs create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LeanTest.cs.meta create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LeanTween.cs create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LeanTween.cs.meta create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LeanTween.dll.zip create mode 100644 IronToad_UnityProject/Assets/Plugins/LeanTween/LeanTween.dll.zip.meta create mode 100644 IronToad_UnityProject/Assets/Scripts/NotificationServer.cs create mode 100644 IronToad_UnityProject/Assets/Scripts/NotificationServer.cs.meta create mode 100644 IronToad_UnityProject/Assets/Scripts/UIPanel.cs create mode 100644 IronToad_UnityProject/Assets/Scripts/UIPanel.cs.meta create mode 100644 IronToad_UnityProject/Assets/ThirdParty.txt create mode 100644 IronToad_UnityProject/Assets/ThirdParty.txt.meta create mode 100644 IronToad_UnityProject/Assets/UIArt.meta create mode 100644 IronToad_UnityProject/Assets/UIArt/Icon_4-512.png create mode 100644 IronToad_UnityProject/Assets/UIArt/Icon_4-512.png.meta create mode 100644 IronToad_UnityProject/Assets/_Scenes/UITestScene.unity create mode 100644 IronToad_UnityProject/Assets/_Scenes/UITestScene.unity.meta diff --git a/IronToad_UnityProject/Assets/BansheeGz.meta b/IronToad_UnityProject/Assets/BansheeGz.meta new file mode 100644 index 0000000..32380ef --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4c2a3a5b1b8384d5c8af8ee8bae092aa +folderAsset: yes +timeCreated: 1484953020 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve.meta new file mode 100644 index 0000000..a842f22 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 57191a445dbf4436eb022e58a93c378b +folderAsset: yes +timeCreated: 1484953020 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples.meta new file mode 100644 index 0000000..0d210bb --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 3f6e9929ec3d4d143b1fbea21cc0d3ff +folderAsset: yes +timeCreated: 1458400496 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations.meta new file mode 100644 index 0000000..e411cd6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 758f9f59418c8c54da21525f0f062516 +folderAsset: yes +timeCreated: 1476657327 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimatedObjectsForPoints.controller b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimatedObjectsForPoints.controller new file mode 100644 index 0000000000000000000000000000000000000000..896944ebdf65e79043209b8871eaac2bfea3f635 GIT binary patch literal 7080 zcmchcZH!$-8ONWq_ilG-#Uk=jsK6GgD23HpD=%Wbci*~eyY0nYX(ADG+&$a9c=uj% z@7cPG##~8I#DqvjzFdJ!gJ1=ReOpbIv@^xfQwU6_MTF6_K4HSK}mdaQwjdftCI8uk+{6Cl!EuP;PyG z$42`^dhofY9)05J@jw4~7OXNPGK@2iTSfZlf8JF3A_@L{ry~6yB+{<}CcY%{R$QM0 ze-qA-FntqTy#$SSq0assmm1{b(0MQFqqa?XB3~Gi{_|FccDVkb&bEMuIwPJZG7J5u zphNpPM$)I&P_iHPu#jIwUL&spYt-5n*?%dyDcd6Zxkk#XrvC_h z&G}vy@UyU`g*y4=0jK{zWBC;UKMMY^tzXG=jbl{hYqYpf-}iYQ&-Y-!`_ORD&-*=(=ZpQ)+Y|0rw*@@3^LEci z%({Hl+IffPqtW}${YK|?QS`pw8Sq8C)3lTR|DfmFBmW-?cxcauJlFl<8Q8;ppoW4= z6y?uauC^#Yi!py``9#qFDERNe@mD5G{1wZm$ZM(-?ir)m*rn8)-LP%kr$- z6Nd^t--tV>vXykbmCv*~XJh*9ycVDwDO)y^oNF&<8$i~@C$i?rRl0TVNF(j_ z;=c8jm24^REjHI6CCBjG{_5v1Y(DzKe_a01jvt+QarDW9d_C9j$PMGn<3iFKhV0i% zZ@7K)HL0MubcK&4x4#QXZ=6m!y>U8kWO{QJuPwJZ&Wl?K56+F8+Xwl@ggD5V4&hZd z+bn%mGdvE{OmCFOVVdcU;~&Gd+rF6IDA#Sr`G@IE9fjLb=x3%k%GI6?)Vb|5y{Vy; z(*~wD%42)32za=iGQH9Mu{{idgY02?5cM4xXpeWwFKo_VjNr-@@LGo2-6!Ljz4Fv1taR=_%AHqQ{sQL{Q44q z&2pwUQd9jaVaQ$-&X?=PgY$g}_OMR-i}Xf62i$XBq&J$z-vS-3Bhwq{8=WXDn)Ied z9EF!0wXOQJS9N0jBE3=lDXY))W{^J9n?d?aZwBcz zy-}|EcUyg?H-q$<-VD-bdNW9$?>%`G0CeB~pCahO{aLn*&3STjsg)gHS?OimvlqK5 zqOQgp6OAMJqSZ$l8_uFo(dejzY{;fOU?Rcs_Dp65IMHq9nT-^8r>*sj0b;({?RL7j zFh=>XU0=$Zrx}QrApy(jlmnL2c_RZB0}%6FZWP>f z>Sk_n0Aj#W9&Z#3SdJgTH3JYgbp|ZuRk;_}T@-3FU@6zU)cJt{%W(!K=Z7$0F%Udp zbu?g&!T-Z15Ih9Vb-B#w6#R>pb4}|~@Gn`;fTdgm-57)1gwgj z!M)B83|OjDm7n7J918uwfaT`PjotZy0n72w4-8mNC-egYRyZ%`2L`N=J3ow-xbwpv z&(#lqLY;nKz|wJJKiuGX?1#MpXK-@~2?Lh1Kb$WEmgC`k8L*VAJ-ZUMhXG4@Y!3sL z^4J~*EXVgj!`VZBE7yd?`JVyH@z5RyEai#3iuH1Vi2+M_Y!3sL^4Ol@d%Pmo+3!vI znE}g<%je`97=zCV1D5jmeF?tDO(N&s7oMFC-|Out)Mvo5I#B|^fTcYCerLk(c<8s= zJRdO$iSt|dJs$e)4&Ptb@!mw&k>BGrlyYLp?{Vd^-?%?H9wwHDJdf8g{2mYOp@z;Y z5xz&ChCTGNGVTwWSi1LU0&R&D+`UJWCGOs%DbH2^5vxD#d8|KE;!gi?i97vS&sG0% zt3T&?tpDK>clt+4-02_nT=k!{`tzR0`o~J#=^rm~r{C~AF>&DqtA7`G-Lz?<>z=ER z1Uy{F1g`Q4dXeh&2G~}#QeqlE;A|GCbVJcl9n{pwT9urqv`@B7gYZBUofTzJk*|rs#jEeD3>?F>?~~&!X@*i(^%7+qHh$ zv|WNn>+5J^dbnWQ@Gj$c`u1z~ou2so^iR^AXIty9y*fnrUyrNNW8$!`ShjrpllSpA zlbKGp(P_5xp59LR?d+HKvN8R!$uu~dwAa>uxkZQ6&E1$AHU!sdj~U&p*-EFo)>HHF z%aq9Dr%!Wt431gsW-K_YFi*9=+;7mJfBw_><$1ckZf&qK*d=Q^-XL*f%bB`1(XPMR PzO&dx!)w<^#A*K<3}nIy literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimatedObjectsForPoints.controller.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimatedObjectsForPoints.controller.meta new file mode 100644 index 0000000..41e5f35 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimatedObjectsForPoints.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: db3da87b26ed5d0448acc48198ffa770 +timeCreated: 1477969440 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimationTest.anim b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGAnimationTest.anim new file mode 100644 index 0000000000000000000000000000000000000000..2771716685d95d7183a251f9e7003573ffb9c256 GIT binary patch literal 13736 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGComponentTest.controller.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGComponentTest.controller.meta new file mode 100644 index 0000000..c9f5f89 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGComponentTest.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 87d06f2350ef4e94daec3edf4dd97b72 +timeCreated: 1476658635 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingAdaptiveMath.controller b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingAdaptiveMath.controller new file mode 100644 index 0000000000000000000000000000000000000000..709c6c310b75aeb0c6d3d08fd50920d87d284fc5 GIT binary patch literal 7064 zcmchcU2I%O701u@u46Z$^n-q+1X`yJE%d`Q4WXr!u(H zH^DAEtSXg{R;q|VD6|MUs6r~GLV`-5st>fP$^%3Qp-9k&f)G_Jo&X^vKoI`_IWu!- zuD3vV=uIZ~&Tr=a@0l}q=A63`x$1S1U8h9kB9XV_B(i^W-{`*Oz4EVf=guW1fcsEx ze{sip^Ju#Ng{K~U;=7}-{cswrG$1mFGmqOvdgy=7RC*!_{(QS6z3(T|D+4CJB=R;~ zp9Oyl&X6#D6I{IljrX9={(LSq$VZ`b8|uThO?e`pACTUQR)==D{-MscfQLFmo+mO5 z{imQq`}vHdN3DTmFYI9!acNeJGm((xd(keg~Iv{&l5R|z8^%LIvjKI zW8M?%Ur62~kM-Y5Zc0gNI8&cGm@V7C9NB-d=Yx^`mylPewJoy$QgTzaMfP)!l$TBa zA^4i(y)59TVM_yb^2-BG|9{r9AyyxKZCRL^VPn8?B{DdkNrGCUZGa(=iTI{ z#D2ck^Rm2(Yj&a^uJb(h!=8YLet4JXWw{6%BUa~n&tsh%0v_tT+w-z{Z*PDO{mFHS zOO$xLH+mkA_a@5+;D^1qk^bb|-t7AiNfrE~C>-xCo)1U!J{s`Q&i8sgBp;`~)wvbC zYT9BQtYgnZ9qudIU&q^l4#&IC^LV`P^E@8!{($$O;ohJ3dmfJ$`=z%h+^_BkcxdMb zJRdUi@>Of+ot_Uz>z(_Jj_ZPGz26n^1*~b>N&kPy^X-xU4+K24=fj@s{_r&H;XY77 z!6l0F=PXxSl%K{ke{T6$(0>;EH{kdy;|2b@dlOTVcqsTk#^JeT-y0G+j-`x)rB8AqTNlUme#GeoE@goi>jL5Xq3!d&>G8D z(i8R8arn#Jk=Ko6Y*XIII~!SZsop#`*ILR@o!@9KW=m#}GtH%J9mu-)XjVVALbuKw zs->My+_$>CoGo@c3-wh<$zi;=zj*$ojYog*kINt0@yzC#;V1WVd9LD>8^oE%`J^`t z*>9BIaQo&mDWSM@g|8*Izw=3NoK7*laXN2idUG1fmfIZ1#jS(~$41WWgZx559OO)g zu++^qOJ7wCkHa+68|87BW_siJ$8hboFQzxjb=z_NVR}hZ?u1G4?|!-dzjuhdtQZqPNGgNCCRr_c1JpFY!@ ze)>#rl&k)|R-frjKYgY*{q&jM^wa0MCyxSv?)(2!1f5^YvL$TJ;~R^O?8x$RC*z*I z&`uF`HQtzL9LeXcKGN857KMshOC@AoHsk>l363cL8aXe#yn5(zj ztu`)%VRu|AQtFJOs{pxyG zR!KH-uk!-~mg<-`rOzL*LfcMVNbvr++0G!faUBD$IF1_csO1LEahs?&P45Dz)~LD z!+@ncwub@B@tdIG?4iGvYeM4u&w%B4Xb%IH@Ay z?@jud0n0s?@5$qM2Hz6~EamZf3BJcoBIni%&rXNydOHgB8L+HQlmIYbDUZM3neaOv z`t1(ShfG4^{1$$Xhkm=$_t$y6Khb&Q_jm=Rm{{_ATzTv_?oW<~iRA&$<9Q6f$3uIl zq2o$~>*zDEhkjPZ{Xr8;w~ofpmPpRsIvOuezpS1dOp2zx!3*6}+DR8G>^E@$e;U%ko4|vtIX`<`i ztB(XcoX2^~qfE%AJ?D{cjjz-jOXi!qBj!5Nv!DO=Cy~O(Jbw2mW>mSFwWObDWMuR> z+fvNpkoHuY8|LYGs@LgbTi!~EN&JAbk)y&5c|-AWd5ig#Aoz78N++F3-U;@JVST;c z4XQ{6vu4+f!;Um)w8^JwHOZC8Z(n{GldQ*=ak|eG{V$d8{PiR=Cm~-$;cpg)%i8v% zm%nb>ux{lP+L#{B+cq+M&HY7wa;md=*p0biLvVdDuE!42l-u+* z!tYUMem2V;F*v5NgR$VSVmwv;K(B2*{?qe{<8po7T!?%QyJF?}t*VYxs_sf{`lH$< O)7Uk`>rLO!Y5yA+(!uip literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingAdaptiveMath.controller.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingAdaptiveMath.controller.meta new file mode 100644 index 0000000..90e2a90 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingAdaptiveMath.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a4a9c0fd6deb9f8418329c54a11468e6 +timeCreated: 1476936696 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingBaseMath.controller b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingBaseMath.controller new file mode 100644 index 0000000000000000000000000000000000000000..cbc59e2a2f64bfc78c7e5fe973a6e5e04f153d01 GIT binary patch literal 7064 zcmchcZH!$-8ONWq_ilG-MG$!@R$&WOl$X_7D~MR{-S@S-?c%O9u>o?jd$xP^?!C>u zr*#+oa66_r{HE4Vcb@u0TsX;ypoll}ZY}=G4a{qwzUa>l~!}Sk!wgo)Y8S*@l8R$O; z9oo-lBt2>kBzs{G3;6})HS&tFa~JNRo!iMxsmSf<`xO+{cX*!2S@iuZ>eS(wlb3i; ztbZYSk380YFS#idS-_e4)WK}o{?*9-i#;EV?0+A5jau6x`!69kWm{xF=SX?g^dEw+ zIo?YHej2tkQ76AF;Pn63Ex$bAbKu{y^(%O;@flTl4A(zIp>KAg=yM07_uPidYZR8 zt|5++v>Q*?hXZ z)@WrE4C}V%$uv(p^J(|1Z0DJ$b`C#uMZ25ILfWw2a(0+TFRE&Kqfs(e0wEBb#b$`oUNEa&bC&v4It~{BU$6v8r?d3a3Sq> zjPbrZ=atY`M*GT--`{aBSqdT(=$PAEq~T6mCbMpPAk$S9>;4=eE!EriM~Z z8<^fGkL|fU;Nf=4^hW!~_AmtYvxn)8v*!)?=MmKDOU=kfXpiydlVJ2G(;Jb3KZP1O z)0>c=LXDj1jq*ge%|4A5YC4xc9tBZ#0d+2|AodrZ>_vI#F0O=}nD1 zp2s4+iPQM&Ap=Pi)!%3Jncno%zma`wTlHzL>csj*dZYRiR-frjKYgY*{q&jM^wVd0 zqg?gxu=-4I`sp*h>8H>1rk_67J$V!Wbl?ALZN}XHlqFXsd*5$fn$5BEjL-RAwG^3O{S-us*3zuo)m13RBd zf4ltF5+(sb=l=>=+}z$NVDUxAg--3(X^K+Jc!QE=0# zo3X_KhyhD^yiqV% zs~=uRoqk}z(&xs0xYqO74|@X6;N}t%1}tZPI9>)U$HVb5U@2F7b|z{M1D5jG9tJGs zu{{h}j^6+cXAk|YToV%Ke+DeaLwgvolqd36%$EyH3|Puzdl;~k$MzK8;}yBues9vx z3|Q{Dd{4fIXYf5?z)~Ksm*9KcByw)O@a%NBuD7F5p8?D2LQ8ze>ra)q)1NMJr$6Jl>VMbj z&w3u~f1$*k{=pJ=`g5ME{DPJ!zJ$Y7d%f)TzJ*$-ws|kZJOx1_v(uQ z59e{w@+cFsY0r7&TjOhu=8E~|?uxmN^z7%q{Yj+sF^}Ip${AImW-aL_8W|Zq&bE}Z zIHW!G)~0!Sk?M8(*jBVsViG^#Y!;|=L(x!vT+w2FB?x{UiPA}Dl6QiAVp!j3=?Y#br+9fmCHN$Jy IN5pCW8}56&q5uE@ literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingBaseMath.controller.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingBaseMath.controller.meta new file mode 100644 index 0000000..02bcf56 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGCurveSnappingBaseMath.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 516ff215bfef74c4ebe1b3b634c7f489 +timeCreated: 1476936686 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGLeafs.controller b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGLeafs.controller new file mode 100644 index 0000000000000000000000000000000000000000..a8032dcdf134fcbeebdccdaffaf4751ef9dcb4da GIT binary patch literal 7048 zcmchcUyNK;9mjunXSTbvB7*!WR$&VTgu-gA1w(rpw;kM-CK55%-Mih<*_mc$ zT6d9$2??l>kYEfUg^<<|6M~J2l3)xEN(e8|5Mr7D4`_@8;u9KQ)M)*F&+nXb&$&CO z^?}=--g7?Z-0%6F-@W(zes?Nz`FkSUzAqvdhLU} zOIy~OhtfSSKKsbiKOKGd`Dw7yfXE=uJZ=%`Vf(SD(ZV(hn2*xurKB4;r6i)d4aYfgU6 zYhwNL$$R9n{zu78DM<}y>Qe`I%Z@Kc_J7Rt!N~p#$t%>_6xn|fxhb0>`+1L)m(BPg z_?qjzIN&E?O9O54O9D>+f7kL$13nARCylz7@myiOERUi7GZgw}D~irL7(EY{2Ryuw zd}MXJ`uPR4>7Q-nJ@&8dNgXo8=J&*mcBjBMQuJODq7eHgg>Rju2taDw!L!D21UN+C|b%GbI;po1P20XO$GoBC0*QsxHJ_}wo zeX$PSW6wh!?khT8*V};(*Sp*Ec)g$ZJYMgffcK!`o}ZgNkJpR+(%Td6SGNW{wDSv| z51IS&BWvevo)1UwJNFx1*Ll(VetWEt=qnRa;XkFxz^2^oqDUeS6064QikUIdUG*bGK-vPE@f*#*2Rai`r#G2b!LAp z?R4U?)#c@EvD;awuR=-=;JJPMH!rV0@{505^1znoPMjWoW)EM_RXlQoIP*A{^oAk( zgVGyr-+WCFg8Bj@%(em)@%a;8Ig z)y+0bUsVi`!!*+y<#Cv1dgJ)lPg!}|rLN^UcsTx|sS9S*!|_)v-(KK7h5 z|GVW(Z=|C7m%)%7C|ob^8xOAcZP>#$?a$L2{Ty)5d7j>A8h;aXcpsVGNYCg*VbP>F z74rB#=IKqG#@_%LNTR6zZmZAqrl0Grj4j&-A9B zKGPfJs(+W&XL{35pXp6MeWo}4^!eVCM*%?h{r@R~&L7FLC2Y>)>x+%-;PP@O+U3(%5hog^F5BC1g$3 z8x>=e58KtnZv7a8jrMQkf$hakV|BIRd|Bk57wy0Qjp4uC|J%J= zpHAOg{M!O<0)o!}6|lIueNe#SgO2I&y6{HxkG_C>P|hV_Ih|s_aylPoz+wPmzRQh* zn@-iNEe=2oSjyv#f&t6%{irhlaZ_i&QeKvOP;aA9n*mF?=B3UL3|NjcFgZVj0gHj) zUaO-4YXtruG=bm&aNd`TjZV(LXF2a_RdW6V%NekgYv6krZTf)$OYMpMkO!>T4|%{U z$q8KR{J?;vI%WA4>Ss{s2L>#+UT*Bp4-8n2hkjtdayp?O7_h>1IX^I9h1~gJq`;jY zwtKFA_#@i%0|S=M8~fpE&tpIA2sneAOGp^7oc-Z?8L%7=*UNyVT)?tS6e>F~YYj6!_|EUObG01Q~l1d92G9eJBrigJ?2+};Mb8TopdI7C)gRo_FBCg zG?5Hu&8}I8U1`v1lTXuYk}Hwlzx5DqvL5&0bhjz`Un;*W{g9cH^iYnV@HdMCW$kMm zKW_To2Y(!e>EXQX!@G>*)XsOGzd8Hs#G~Il`Pi-pAHHUQ@V_2I7%{eQHcOW~W-O&P zlck+(M1NQ^+|6$qeg5Hg9O7`D#=NjIs57M++qclpGJR_B^OKx@^;PbG!7+^;iv@=j yu3hioLD~MQT_N}|L+YatZqeRTj?%nR_>`XH= zt-I)lkpy2bAt50Ig_x~D5`x4;2_}RONC(Xr)y@~?B}&Lt&)J5X+T zVcS~sSi1lDC+>UnhogV|=?qwDKx7bS9yf^e(EpsN^h6T;d8{P8A1Bf)117#C@@`z8 z0e=V1kT87{T)hg7524Qf9G4p8qtN*%>ch58c_LpQklqVchjzIBq0W|ohdM)^Co%*5 zC!j<7IY!c>)-Pohp8&N+FG z_r&@alK04C{dba^Qj!|Z)Ta(s%l0ov_P@*X!N~rL$t%>_64`$VxhY#B`?*HS%clPj ze9ie@8t~JwrGYy6WdW!Ezhe320Y41>OU_ZSSm)Y+hdLkhylkG^YoSAb^1Z|* zN<81|Jdfvlz2yV&!#>Vb6!;^VGLG9|5nL zwpa)6vFD)<_Z980^X))~^Bwa%p6|yzkLSBT;5}%#=jY>|$MeO0>Fo*ks~ZCz+W863 zhs?S>VC}rg^Wo@y=YFH}x*&SrZw~kZ-f7xN|9{H!t&#r^1U$6o7SDBmcoOz-AE=<< z5=Hs5ma8qwPh-rVTRtB2KMejFIR45+fuFT}lDwii;l45D`^V4ubihOV4_aPr)>qSR zt3ATENpjJH}1HDR+9t;mH@aa|6l>-`5e4YAyOH|=I~ z>EcSgnNcvT+n%S=ZrYwpJ6~cu&pfrd@IyzmyQ$RDy7iW`!!&wPRnr@dlDP|7&?Y%$xL##xsc>~;*4aa~ zw9|?ER+pEv#cpSzz6vQhg6H-ZKYMZgzMuT#vU|2YweiaELUHK|A4_h3=ab$zonm_9bl%SN<}_YgZgZR$w-O$l8#%WR@(T%ZkTV^^ zt8TVg`l@1h9HyDxD38N5(;LS>hikWeF}+c)+m7=O)0-*^x1-R{OmCE{J!`0Q+h=-H zK`EvUOmCFO_FNwDa64ssqy1xh7y|p*!}P}4^E&)}_m*E> z;D5KA>5WuW{|Xqg8-?@by7AzAUxhua)BZfY(a!<*oagC{rty2B!*yhOBR!)Ng+-Iz zRLJ9X%+s4VjlT{ukVH}aF{{t?rl0;E_N{Ezr@g8Z>*wi>>Q7pIrZ@fcncno%XL{35 zpXrTq)xX{9Grj4j&-A9BKGU0i`h4%nqX3}${{Iv~=TBtW5;o_F^~FYZba}axanD|8 zr--^5Z%j0f2%)LPf2m60#=ia+iq&N1M}`8Q@sE-py>JxIJy0%orf%>g{%` zjSFLx58KtnZv7O4jka&*f$hacV|BIRd|Bk5mmIqLSHo}K{mTQ} zA5DL~__qZt0)o!}6|lIuy;Z>CgO1_wx^SWSM_)ibDCZNfoK7)dIi0sNU@-tO-{nTZ zO{Z$+76%{(EamY=!GPuXAzU*6aZ_i&QeKujaot9tHUpM&%}bph7_b~?U~+y40~Q0p zT~T4|%{U z$p-Fqeqg{-ow7WG>oX|y0|S$1Lq9NJIi1iC3|Qg3oF5plLhk%9QsB-H zyF6Dv`~h|PfdNa$js0+q=dmAl2b{spB_s@3&i-(|3|Nkb^JTzNuJ&wC)E)*b<*_{s zSjuC27_c0_9vaRb`dhgsB+mZ~SdNGGFkmT9IUm&%_v?q}vCJ(Lv`{$_EctZjSF ze#f+(1%C*I>EXO>!@G>*vAth=dTjTp@gIEluebc}rJb)05dPO=7(K=h&b3S#W&eNC|HU`)6_&x4$!7+oKiUo%i;i>Yc69yIk`A_2% n=j8f2pNl+*-S32sRTMUL+Obj9CSL!=_MO4*7+$+RB2N3?yLGjQ literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoomin.controller.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoomin.controller.meta new file mode 100644 index 0000000..bbb5b64 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoomin.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: eb3c033f1dfe7964dac7eeddac8b1a56 +timeCreated: 1476944185 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoominAnimation.anim b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoominAnimation.anim new file mode 100644 index 0000000000000000000000000000000000000000..5320eec6faf2a9ec5db8a62f00e12d6288cfb366 GIT binary patch literal 27028 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoon.controller.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoon.controller.meta new file mode 100644 index 0000000..06b3265 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoon.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 38aa8bab7803d794ca7285b4bf017945 +timeCreated: 1476807795 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonAnimation.anim b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonAnimation.anim new file mode 100644 index 0000000000000000000000000000000000000000..f3fc0be24580210b7252da3bb731e242cf4d3850 GIT binary patch literal 12760 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonAnimation.anim.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonAnimation.anim.meta new file mode 100644 index 0000000..1cb0ae9 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonAnimation.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f91122ae46f42fb4e88dd5ecad9a7403 +timeCreated: 1476807795 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonIdleAnimation.anim b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonIdleAnimation.anim new file mode 100644 index 0000000000000000000000000000000000000000..c7696ef3cf80b3fa4699be4f4d495838f73de1d8 GIT binary patch literal 10092 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 H4I6wDtU0F) literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonIdleAnimation.anim.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonIdleAnimation.anim.meta new file mode 100644 index 0000000..90f03c9 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGMoonIdleAnimation.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c65020880747fa241bf235f7e6e29b16 +timeCreated: 1476808692 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointTransformsAnimation.anim b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointTransformsAnimation.anim new file mode 100644 index 0000000000000000000000000000000000000000..d429c8756579700cf9c39779a89e69e8e2218537 GIT binary patch literal 14120 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointTransformsAnimation.anim.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointTransformsAnimation.anim.meta new file mode 100644 index 0000000..31c4f07 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointTransformsAnimation.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ca93d1b2992418548b16f01ac657af1f +timeCreated: 1477969440 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointsModeSphereAnimation.anim b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGPointsModeSphereAnimation.anim new file mode 100644 index 0000000000000000000000000000000000000000..20a8efb16f021ae4d31fa38d1fb17c5ac8547c10 GIT binary patch literal 12512 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 jzvlSb+^)HoLCwmCd3>f?wb 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap1Animation.anim.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap1Animation.anim.meta new file mode 100644 index 0000000..67391cf --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap1Animation.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 55f60c7466992b3468cf6475c8f54eb5 +timeCreated: 1476936686 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap2Animation.anim b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSnap2Animation.anim new file mode 100644 index 0000000000000000000000000000000000000000..89328a288e3ab9a537c517f4c78166ef35b0a987 GIT binary patch literal 11928 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 K*RGF<)BZR8Ex;cD literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectile.controller.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectile.controller.meta new file mode 100644 index 0000000..4b4b56e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectile.controller.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4381832d97e48b343ab2c1cc3d0d1cf9 +timeCreated: 1476924217 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectileAnimation.anim b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectileAnimation.anim new file mode 100644 index 0000000000000000000000000000000000000000..cf431f24d0cddb77f04e760beedda6792c50d6bb GIT binary patch literal 14076 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectileAnimation.anim.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectileAnimation.anim.meta new file mode 100644 index 0000000..00a8807 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGStarProjectileAnimation.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b161154b027eb8347bef0a765e6bb3dd +timeCreated: 1476924217 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSun.controller b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGSun.controller new file mode 100644 index 0000000000000000000000000000000000000000..acf4a97a63e9071ae51246662b57527890bc1feb GIT binary patch literal 7048 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGTreeAnimation.anim.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGTreeAnimation.anim.meta new file mode 100644 index 0000000..c502a16 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Animations/BGTreeAnimation.anim.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dab27e7b63564f4419261a691368b852 +timeCreated: 1476838167 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo.unity new file mode 100644 index 0000000000000000000000000000000000000000..83a0f48459146c5cb2ece5b504ae9350becffa99 GIT binary patch literal 179201 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo2.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo2.unity.meta new file mode 100644 index 0000000..fa21037 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveDemo2.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f9c119faa3d242b45ba786dfe2e3f8a8 +timeCreated: 1476650409 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveMainMenu.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveMainMenu.unity new file mode 100644 index 0000000000000000000000000000000000000000..42a82bea11e747439efe2f9fbcd20a2264e989a2 GIT binary patch literal 58705 zcmeHw3z$^ZmF_9tU{rjDJd{E)pdx}s1tZWepiz*P2E+$K(S7JHsjh0Ps-auW*tt3p z^K|aj8x7Hc#6+SdI?+ULl8G2i)WqbPi6-W0PofE$I2tqNn&^c4|9h`>&OWEAn!=Qy zWSRrJ&)NUlXYJS8Yp?w{yF72xZ$0nXb3D&G(DQn6^So20pFI8K^)tP{?%K60aTtLA zhlkkI8(F3YUNzo$&fk z^Spk%whLZ75l?uZ8}9Xg3A7P_7|uHW^}Hv6zYX_ca15Kk(=YMn;qWv3a0j0bJ`>>| zBQzU6;eBwJ*Z+|48R>*~`HXUKm(S<`Pk8SIpN+zYanzSd&sYa{`HTzjgtryxTn#?V z;eK$5dYdFai@E&#-lCr^q;uK1Ue}rh>5RXq2@fr)VkaJ6MIIjg*}{)){$EoM zoxb`LGtT+mJr7^BZOezQeDtOpM{Zv8z^zBuwNM`K7QXvr(zcR)GD-Q1%KYwRk|nnb zZIklE_C#Gr<)dx$BzW0&-VwuR3;xa+UN88&V)#PA-yPry(>7ZKKO%;w1V1u{=LDyY zwCPNEKS!Ir%zC|~!ILKa+t9v02tU(5DTZ$r{HOr8d_Dv}vhN)o;KMwZ&*T`ce2xil zo3HEOXT0w*ILp)G;AQYBf>)~(s2tkc)7cKFiN*fX40 zGo5L#&!juDU4EAI)?zAOY|Q1eeqMd`z3Bpj`k72?`cfaAV;@P~sWux!V=h}L=2L0& ze&}h;^#J)Z)YBc`AE>)@%abdfZ2R!(GmiaA+wb0W!}HI6^xbFt;zuveZ(TO3fz^2l zTmo*NdfKO+-e{M}lA8({IvtMYL|i?o2}SjkK)a>da!m)SCyQH?JyqK*O}NPmQ(gYjbr<_>McbX{3&mDH1FzqXW>xUB?PsSpraMwabolc(qE)i- zHRV$s%RBRap);3h_x^%L^?x^?{>uCVZqNRcP_^t$tfB zOU1U#@Agy0CO?y+^{^n9Z}XSr+IuoS!*2Aw*HCtMe0IdnSAOwwa&daf)x}*CKepfS z8y~v&o=-I$c0Up>=D#AFHlqp# zT99hPWQH4TnP13ddZ;RNP|=q6{p^xdv8_{Bn&)%V?ZwWe`DR}RF)f{a1u7)rz95y! ztV^|RXfwku5?>8ZLdS^tUYVgnOokqZNE?McmC3| z>#zIDr)SQ2=AtLAc;~@iJE4E)mwvgN)t83br*`(4QtaaY7PZ5!nQDi!WYiA2W^MlU zz^IN??F<9u3^emr!9%q(%uFG#6Wp3ob$igoFY3tV^8PY^qn|JM?F;j%?#^@@#~BTo zT-yc=>+Jx=MV6!r8yFys@yLIn5C#spC4K+B-YK)juKw;VSD!QI{p}|mym%wE0(i5os_U!xg^a;P^|yl?#RM#mp)FtgzP)|BoS(4cp)rwkP7C;q ziLASv5a6Rs_!r@4y-bI*w$CW448R;6D-kOa~{Q z-v}S-8|6N6f2a~W9Nd9TA;=cV9Zmg;Lu6^hGK z`3}G6HTGaezlb**J5$*Xzun9>BGl4soZ`WhFQf}thAcM1*j|{=^>7&>iWXv_7(W67 z=2GV5aL!YrM@s!-XAaYyT^u|ZgTFrC(ZiL9##CD;LG{xTu?!R`0qP3{ziVBlZ+Tz0 zFDw^ji%#$bnOw^Cw-)oTbesSUxm?EaGV!K(5LLj`=EV*xSlIRn4=tFS_46D3`a(D6 zasgnWHq(f#n1vL2Y;J{8-({9ZBp9u(P3Z!2%#cg->5g>P>^r#bw9%ja+< zSiSN3E4O_1nwE|^PdxbeZ*JYbc+B<7uYkCmI^2rvz9|uQs{72WL>=WJIt@$p2n}O! zcRRz|1Kh5iuv=pn7EX!S?I(4>sOEHRLNkRb@;o@I<8W+Z<5hJWPV)|rbgS0PVtOne zPH&Qroe~MtuY8UK&2|q_KGw_%`EY85e3Echtw+-{32-?+G_x#j({mO4JfbUza==$ENh0^@DB@a%q)k`qk>Nh!rORh`Y~RbS>@uTndS1=cxh(2xW-E} z%f&TbYi1=)y)(b)`b@kuv&zLwd35<`yvEFO@}==wGmHFfIcU7627GLOUx1(awPscr zUdx$gR=Id-X1Tb=Ys@SsJsPhyv&i303H}$}XFbx)QuBrNcwoZf#>^5qITF}$aFn&V zPWV~C7Qj(HjhSV_N9D5)v~qG@AK=40@;P7l(99~=UK)e&Q8{l4aLean;WNJiADUU^ z(z7tY6W(Ru@liOM?`#{^e6(ieHo+GKc+{+3NfKPN7oDOh146B2m<$N)m z&DSXJdc^q|iFX6>&8)l8CSP|-zA{1h=rFhoxXo8|7@Q68(Po&pL-^;&$MBC1gS#2t zwB8 zaNV_wdINm4*}gh{IK$ZK8Y};{{3iluIxmG&`Dc2L2TpmujJPSEsJ^-!aJlyWe&QxQ z(f0Tcf>%2%4EK;=OcC*zah42Y%)XP|DMpm5C2Wo3WmQy=R@+`eI3T7=0Yjie8w#;v0~Sj$>1K3X=E5#nx-5g$o&1VIa80-W{?u4TlLwAJ)c z%ZMXsizm#8un~TaR5+5hBP2VLpk>RR$Bv|vNRP#7!4f|L&W=ekujVWDRDcJ zCLe3@8OsxR5>73?Hazyhu{}*9ZhE$T3l_G%qL$hTC?1RNTd+_IZYVBTY=yGmED77O zwikSq1-05dduQ=gX%Ki)Jq&mOF2gto{T<2VZ`-$IFgR)bB?50{?%IC z*22`qmwgK{Z}LLS0_;$2N)@@P6+GH1pqItZyWGroD;8-j_Q9OSMi#$NTwpe*ElFpE zz9iKvPwpo%=DDG7p`YvWi+S!|U6yX^T<-Uhd$?J4DK^ur&*U}%)D5!^v^bsh!%t?+ z%WNcHK62E(=N~Zj^Dn>LkiU4=p--?A<`AC^?hXh$rYHL;)bQeo!u$90_2`pm^iz>+ zrXTG{zaEV=%CP|+HL}Jz_(ZJKVtS*WM$mo%Zl~e40B2cIk=C2i8R1Pv_;HAv*!}@- zr-5`@>Hr6KKLI%~z->8mnwk6=H!qeyJ2CyL^dN%$#G_w*9?Y?JFLnAcGpGK&SH{pE)w{%MG1_sTUfdo>zx=5*|8={)adHrz!qVjIc}KhSc0!)G{mBUY%gaezA&NV;TLaidh*l_I}SPf{Ue_~3YeL1!M%vg zL>e2gzo*7lt53C`g>bOZYGZRp930WG9NDm3{B*(D*j$`K%4PXD1SS0(RfW`b8wB9jm_n+@v^bG{9E89e>OHZyz)1VtqgxQ3OBs+XJb?T zRCcT3Wus+dv&tx{6xi4-9#sl#Y>IzhlpWK_#%6J=?6h&Ru_^90PBu1+Cp_}$gr9uO zh|fr~wYZdz8Sx43@=4;Ig#4prcnSQh$4Lg?lSaEZhh5ssa@b>{d%Q38*g+b+B_~sc z;x{|VK{Vf_VjDRg7vLLr)6$paa>b?jc09B49)Drif(MVUd*`2q?Raq0KYsAQlOgn``P3V;1Lw4|M1!qI%rQ!b>&kS#RO$Y$-#o+S=6Gk>c)P>={D&fu4jR|ApeN1pR zWL~<_`w2XgKkJzn%YnV@ukcLVHsm@JFB|4_g0ms>VtW3J`~GMPtlK0UFYVn`ekK{r z;%xXT&+HKKDxBTCa0EPz_h>j?ik~3(WD6Ud$h!=74?*oqi-mwP7kQzJ3@~J&BA~Jp|zaW$9Fgx4v$p|OIv$DDnZj-Y! z`1sbneP!C;)RM~=mvK)QKYZWBPf@&1`z1;i+>&jXba%2llgj$u`j|KEXWEmw^~sIk z;(<$NuETD%k9d*=epSy;R=U9&`VZUkurbZuaL>=@ve15jdF+SHv4uF4=*gP}9J?eS z02o<678Z~?4qL2$ejg)iZd!)FOWWEqJv>=N;sn%+MF&5J&-gK%>EO3K0oLkwr(~T) zgDpwt^SQiPQKD=$F6#Wl?EIM9Pk6fd+1p#{4`F-z0UYa$SH!^TxAjW-E_W6VJ5=f$ zcBn?LoAA*Nm3rCAQ?x^+O!1=iy%l^odSDtx8q~&1{%qgmPrb|w?IbcfpRPcW7_97V9b}*%OUMh^L4EA_8}l+-Xev{1 zUI_%-lID5=(2&~TMqM5+V6ifT2?9f<)uBLh4wDD`)@*&M%@04wzYrO`^U5_#xBvOc zD+||+`sO=!+;cSx?j$%?FfR(fDlV^|c;%ry1*Vcwk_3%~A2&+Kn?gkzdGp_3MoCh_ z#*Gr?Q>{^=e8z%by@}NtCCZ0+v3Pl-q`~jRc?Y?keARlq6C7Xv@$gB1x!|!^QcsR< zJJCP<#FK$>CRCd;OZ&^f%+)`5X)i`tW5OV?Q8mprJWV2sESrl_HDi*Iqa!8KpD{KD{>FRN;Z+tn64Qq{P)#>;xMxQ+K}_!+M?0h6Fb>yaj)%SZFeF2cn%UYdX|uJLj#r}47BJ_SGX z<(hyr-R>0Jn1FSBC*jS9Dg3X%StsmHZGG7>+xOumA7cVSD42e#?jPG=vU+FvFx~+P zpTwOP`4fK;&*U?SATGss;h8w|&5JlEiuALY&;*R8XR-;)@X_?p1WY)5xR;UnVma|* zc$S0aYl^{2`LG=*ABI039;WkHI9^OA@kYUqvv7c?1V7%vw;_Cw;L{xZ!@zEYV>(YD zF6Hc|b2?zVDih7`i2%?W?wn`i*Z zx6*iO;z4mm8he~@hOL{!3>i*za)J5gJcjzNb!p6|wQlIsy*7f(zoaLH@3dp6Ybaye zi+!0pR5U(;Bq?CKF4wDzAxwBlzulb5<;Hz(sTd}!OY zcIR+RRc=GtTF&NU?`8gao}&YER#G7!frq&B!8uK84c>r3K$}lXB*enJ85^XrXPw`b z>ZS?O*i*paSz$=qZ!P9NCX!owvfkyW-F^0e_WN(PJ#Z6Bd((@*-F54KyfEk4f15k< zcX$7E(nMfq4U5_X?ZC{{Z}mo{p$FSL`zPudurQbE8SNKz=)s{o+w2@T_APwJ>$mNC z8=lS-EF5~+erJ{7qj2X%{lM^9Jd+3Q0bYtzqKF%NKyar2M!}6eAoybNx!XM3p$8rf zAL8E;+}Hzkv}+RHGr(ShV?L<+I5DE}9tu6icC9tioU-ljd^hTkCJ-J!?jz^;d5+QXrT9U|Q(;jKMD{&qF}Zs06S)*03+ zOnzBDUk8r=G9?t^KM>qZ3DsGg`PEf(+5?(S;;$e)%Z>Jc#S`BC5T;|`m`-aCgnTre zv=!hhv83oPKfQ0pDu4YsAFWKYVcV;`eP|z-IeLI7pqjIJ}~|FjqfCv;1I|>XGl#96Son zyx(udej9k40*qp8)TtNZ^@5XzVBlia;}XHGIt}rtIt}qQ32)VDh!+I6>eS+F{?`CU z%eBL+x-k3}32%m1PI^8sxKXEqlh2og51YDY_$0gs@c2VGVpg3pE^7w=JFpRORHuxe zIGg|TcxD=@PKnF%W+40GZ|K1>o&ku>4G}*oHCtSkYESnRJo79fZk}5+xo+RW*go8~ z&ckl&4!(+*l>OHdu^4^xu6$(LfNVT+^of!;xV2 zw9u|pwg-wqy+$-8)s##&631JnbwHbXk6rQU#VfX)dBKMltemps{t+E4Zit{M65Pz( z%2YncRY@F)vnVUgtx!x^4HQR))oP&C&uSpe;)BnvC?EFj<@it>mCs-cKFWu^d%bzX ziiM_!;z%54ux(5gbe^p0iIk`D`Uy9kddlY}eEjwUe)NGaT=m;?UStRNGdQ=UH^XnP zew*w{h7+?@sc6}Ol`C2f2=}CDl~25Al~1)rt9;@`t9-O*SxsBf63d-m&W@e~KjzD{ zble&K4BQt9W?DKjs4ZRNH7#9mwseixv~+{p0sAuWA%AN)S^m^8>wr-sSi>pAFA>}t zP9gq31hK?*^XtGU8`f~L_$k1@3ykTp6DeGqp-5IO zitNg`!eJ}}JK{2nJ7&OTmwC_wbCo4fLGbgKF&sj$-hOe9MH(MR2^NA=Q@Q^tpT-ap z^TX)$pj;G*y(t0At`T#%x&U^`SyxVUC1n8F{QbPt^N0Rv)y~iC*x0vW^ThjR0{ade zi+~q9NKWNjpDm_J&4!{-so6{hjnxp>NGAZ>lV+oQ;>||+RNHKnPrTVEAGg_XFUhG$ zCq>tEkYkdj8Eiw@EC9xQnP%hQ&4Sxz6NW!iaF&(bb72hvGzG(l&Bo$(FUi^PlDBC# z4u6f;G#dxkculi$aE;eA8-rW^7YTpUY@G1QpUuWir}AgBadG9(W~1rnQqTr?DL+)l zqWL3BQygztJh~KA?OqbCM~*ivAGR569bzQ=KWF zWPsao%N6jm-X|H{zQZHgKMX(R`6xKg3+r9W^XM3^<;nPMczYD%C*UI=_MGMTyeEb$ zpD6)u`FsX`@|haoR^Bu{$Hs8wb6kL1K3{>Ke2x$BD4%IDT=}s4+!5 z8**{wGedALU@zxadh78e-X3V>H(>`4znW|7#IiAtI0>Fpy}`5J?(7WWeq0(fp$t=Ak3fqd!tRMz67D{@PU9?%dX(2waKy>&CV7u?$*T^`XW{;k zarV72ANjo@_k#9*;EW$XhG60wD>Qx&{Sn{;##!1pq47K58KARG=Z!XpP88aGNYqrk zgKihjzW43h4j2iqHvk&vc-;6N7Fs`2bOXZ}XWx57XcO>u5^?gkYx1%x_NdTiLD_R& zpU3#+4QKRSLTesVnwHMj=dtN~-Jr$uo)+3mpvCikvC#U*qC8`H-ypR6#+Am`KK}n0 zbv^)EJU(A&Ytf;^<6AGZmq3fh*CDj2=vd-q{k3zyXw-5GXxAg3Zdrd_XgfiRm-W92 zjr$b%6@y#W-w@hXbU^X4zF%l}p%aRy<+3ZMnJJ^EK-(5e%jH7rM<*3e%lm~k0Ug!U zSX%x;Xm#k6;%T`;Xe}s#cv{Zf*<{kv3)(-$(sGv2#-rnE0gdOV=4FG$Vxg@Cts68R z?VOhx%_Ty69JI4Qd)hcFyJrh6Il=Sp0zP1zr5$tFbra$B9tSNh6YmjP3p&NPOiU5l z0BCWUm@2dhn2d|(J@MWzoA~NLi|2iq(4GP~Q1poqNb*Q^3ZX z3R+wSR|)NL(BgSNPiUP-4mM?j0$`*T8T zMrz~r{=Cqh0xe$ezZ2ScbmH;&9!_3&GV?wQw133iE$c^wwga@QK;zFa@<;cOlKVcRLE!|RQKfe?@HWuaXQT0DP$6k2kc=dDE| z5gp>Qz1x2ZjYe2Jf4{!$t7kC2?V!cW^BJK{g^>}D?^&VU2ilBSe7_OeP8cEa`2KwN z0rMH(_!*_~{Y7Zkf)-Q&+D*8-_17r0si@(& z>^2E)2Wa?!B%;gb3vK5qrLwy~Xs@1HnwHe7@0wUzb_(q-(0F9!0O$iE z6VD0lzFGE{==c*~dC+fO%@ z?Gey=kq5W_ZWUTxV`+Rx+%@7n1ot{Yi}yK43XO$%1Hud#XLZO#q1^!5gjn8_Lc0qC zm$=@YB(xo9G4Xc$(-*E&ZgvUxM{92$HKqjuG19Xrb}EpY*MfS;qG&XmJ@l zS!g$)rN#69UZKrsDV4!fgx0dGH1DShZEb65TJ}HZTir~{X3*ko`T(JgSzem=1BG@2 zXzz{XeZ0^fUr`$0xswkvs^(SD;_-Gym+ny?o z@5Yb5wu$jQ4qCh&eNt$v)|JM$MQA%gi?^ds32hb>dAuE6v;QN#jBhPy@%(*AXak_d z^Y>w)VO^?3c0VGt?dwb9`{e4MUT*RS+VyyV7{b{)+9I^hj#63rl+ZXK5Ff|gB(&tk zrFDC=&}M8XP0MQ+tiFP2Sp`~Lu3s10tDqtK5qof#(AH)=ZyIRK(B+Z`??TJ-TA@LN zy$gkw5ZVsVsINIMc_?XP@xX$>^~(0cucQv7_lx(P|8M&I++W}JGkyNeYjcdf%`l%h z__R9Q%*mrv#UPVB)ii1a1f?az56 zu{w^O!rZIntv>9kQ$K$A?1t@^eP!hLKK;X9rXaiy3?IGVCChBhI;@UjJzx#KoWR#3 zm9DLIp4Sg+g1va;ng^e_{&~#6xE~*Vh7Iw*8?Qe6yt#MfJLi6G%T;){f8LY5&&>gC z?v$BhjQ`*(>*jnbIb+VT7aj<_AAIOaF2U>STnghlXiA9mlLIG+ebn@5+IiPDTM`(+qmMMtRmXbO_bvmCKcCY#KZ~QL{pl+fP3H$k z+>aw?iX9(61l%mEO-n}KnwG?22i&kSXXf-7{5LI$_xMH9oUGr2_LZ5IZ0T8tbI8u} z`s_2nwVThK@JtzTuZi%ut;v4*6lq~W z@Wb%bu&}WQC(Or1%!Hv%&cV6-(5CIVfX9~}4;YCBt^bX-V-xuxf6B>++8*U!i`Kc8 z>07O@Sa&xX%P7=IOq&Cs@y0W;AkKIsgo7P29_{cBDvm}fGG(9R0ybq;*?_lKD^m~n&T!H;xOD>JGP6%|Oos=8*QaK87or`iq)k5AhJ^!8LjblQ+*k250 zXEAJ(-<3;Zzd&;4^qEO)r84`Hl|hBOmRkj~fvKkkB!I53s=VpisLGqJqpDxmTq%EV zgJYX$&8E7$vA?SpwwA61OY-Cv%9{m3IaK-3`3%z4&Qcpzm{ht|r2{ox8XxaN&CXI; z&@!l{ouzek2+Gy5vsAQ9-R-S5786%aK8CWLrR8BNuEHNz59!_t)kC^3LiLXBp-{i> zx1b)H0B4NyHv2NzAO z-E*aW-JeDML>ZFp_%)l4(!F6S^StXCfg~}QyW`q|VwLXY`03h0^c~K}Q|~o5;Ufe% zd)Yar9iY+0^`eFf@A3FT3ZD>%W-Lmm=u>{t0F~3Bb7H#3hwtfLE@$*Y{{9(R>9-4CyR-8)a2dpjKEP7h`<=M633VWNea$)WD? zm*mQ=vK(rC>Yi=BpmNA{&MK~|`aMmT#>e|m>-SVPvFJM zo@f#)>m3cJdx6z&?^>r(6uzo-4d2rAs66og_df31ll@c&A;0Wv?0Rw`$@3Rz@9gf< zavLlh<<0i9_`X!Wfl~R>@1@kQ-&TsL|99;N& zKGx>L?zUpOEtR3(Z0%Xsgo4Pt&92$opV=#O;gttna3a9N^aX`5G z=gr37hK1Psi4AH=v*E3fYeqR|)=kDb)_`WOhBHxR@YXVd)mzo}}FWv`}OWiBX z``#*-d(yvgY-0L1oJHFiDckZMEwA!ai@I{A;~|wZ{WewQOuu8TwVdg9wb69OWkuyD z#C2R+`d%2up;awsnx3I5XFMpu$eE0!#@SPXlQL{~inRQrmS1_QMX7rSB!GU)ta7K{ zA*_ybI;(%qtiXD>yR7`rKRR6qvShax#?X6|_89HkB^7Kh(CX zdPmPPP(7vR7myeGaq6K$av@IX!{K|mo|=5KMc#V$0-wXHvL50Xg_nN+!)MnfbN99D zIRp%&`&aqwe)FaK$%wmi7pk|3yM3{)OK969-P(TfG#f%yI*%c>9F#Bb`W>j@gg?x? z>vWFL(vyw&I=jJ+bIn-Sv|oL<(p}@NL?`abjqX!ZIni?`RF3qFidx%IdS*s6o$)dc z`zsCS)~{lATVF%TUOxhbY3!)Rwxr!nnS?3D{gg?&p)xG&L7%i72Mff0NXN5! zCW*?M_Kkd>`^?Rdc1bFWGn4bR*n6O7r)WJhE&Ba5~^B#Eq?M**A%5Qvn zzvhQRxs1zocvfEY{ix5iJ5~2-JJs`3wA}Qp74_@6ENr*@CfnGZII$I{5SnAvYf+X= zZE$W3J;4>vZ`h8t-1VFVzM_2>^->jARXSMHrSb7T)a*``2`vL{TebK;QtRq)l&foZ zIwEGOa&NUc%gM)3wl}pr25Wz=-JpA~RNv^?ORAsryd~8?=9{L_+^osk0@JEzMMcwH zS^rQTdFg&QKD*zt>Hbe`Go*)l-1?lqRp}yz*K{gh-gjpYI`QC<`$)Dnz|~t&%k0mvrl0^!zsU7^)GrhS2V?y>sQNH=b`zY_Ag3{ z@+$FFRi~OR<;nX{>t9qBv8av%qH)x{Yp8x7|Q*MmPbh|a{yQWs4iCh zqvzA9zR|Pn)UW5>ss53D$}?-FfAl;)C%Jgsz5dbfx%r;c#ZcBiS{^K$N|$Tb>baJxfAqXc)i-*! zCG`zuq{%O|<Dv@kTE*55zxJ$Nu<7uiHn=*(?uOBMWNu<2sGpW?Aw z)ok7ZFD*}vuiV}34|V=q6A#>KFB_)@b_U@e|m>lalfvZ8Q=XioNPhF( zX*#v-@jjS*aehJ_hD0x<&bG(-{hv#cnA5TCVzh|NHrN4cl z@>MIlUVn=tn$CEg)345k)cr7}@5SFWA*$-b7*f-t^1%C0vg>uuD9N99*3Cku2nYY8 zM*+RezHun%=nVsLX}9?iUT;D-DD7`3J&z*6`i% zozf>wPqlIvwg(%(zV}w^FV?Ys$F?W)tjFLzv;R=$S-bPOjraxeWFgn(CpV@GJ*iBx z$UV!YMOPNl@+?af(3M9$M^@!gfA2=+QGXk!*7{F>t0$VyxXhHwn7jWud{@JTh&)xT z|1>=+PrMH${kK2zYveF;0&PiomH=9AB?Jd>$CtWiUFA)G(@5n_fB#7R`ddk=51B^& zDUMp$dHNepPIB>BSq@b`^!H)-o{lS-#wxC=WKz?m@$o*?#+51yS_ZWoS881yjB<76 z^HsD=HSVorN+zzHd<!B9sk!X3CimUL4ddQ9^@cYs7yJy;0>+hNIH_pr@ zzi-ChL*u2tlg4M-WlK`&Y_c)c<>ME<_$>?l;$@JMOJ%r(5Cimg+@f%0eH0B>y-(xW z({#O&@O)?U)l=rF+qQM9{C*kJYy0j`-gx6&``c&T4K|Lgb)enPvs`&Gq=U)2{RY$8owk&Xe@xILG!I)Nj!20nT?jcI?R7p8(q_b4TtgS9Yws z}J4CI$fghET@^|Jd^0)3U{X?t59DX z^e~p-xGr3?=%JGMe$0ILBsh|-hrJX`!%e=_dQm#XME^db1O0acJgn+x4Iq8u0DN!2 zUBKHbJs(8pK%RX7S4VqiBGo;c4wSn`;aLvo4`TW~01xAwb{_is0`3CtrH}TEM;~?u zcu7fP{YfLss~T(TN6v2y)ihMq)(msz&KOly9U3!&G9|&rO3M6~uHlea|0p_VlY7zF0hq?9h3E3;}f8Y*P11NapThmRCEKF=P6ORmUBDHIf39JC;G)c6xT0 z>xG@4q2T`ZI+Nh0{>2ZUWx=JrW>|1(ubEM}Zm%+KmmtB-_G)7IECUWXFJ(E)0FPt; z(7`(e549`1>KjQNP}Tf6VX(3;rp?8>4Vd|8u6_6oq@~&$Hk{|6B_$^yf$6nm)M| zCI5mb+)MvF3oi7}x8Oqmf+)O$)17GdX8IQ@IN28I2YzEeDnma%r6Wt}v!i3qiBx>V zdLBeHhBKWo)z|v>(pi{*&Y~#11Li)?6gtqpi$Q0ZlE*XmSrUbJ^31I+23*P0$uaF@ zX|#T4=T)+YSxo;Dz@GvAY!7{6$@agShyHTFcSHT%RGc7lw@agNO@A)azYK6CkC*=C zQMi{r;!0g#!$BYVzcLEf^v`AbS4H7o`YWPvFa4_xIQ**6|5+5S=`Uvb*8r~c@1=ij z6z-+}^C+F&)EpM{(T>+e>v!?!`Fet96+@r9d-S{#aHY51J#*w6qHrze3YHUbcRW4c z6oq@`yxD-mKR{0Shg%dpK=O3)_=jIuaOq#ST5#!K%~80P^A{{9={&BSw?*MzId3=M zlvQ%}q|7g)@Gi=~-AD8x{~Zbr`FHoof2Rc(`R}seBLCe{xTgOI)4wMQ_tL-Df(!lo zEV$6WKML3SS;zYMm4d?_y!Q6%DBP=`2MjpIO|&D%_tgp>YsWQIMn8Ix4n1z__9Y*o z;15}F88;uc;4*GL5`}B|pJDmIC!QTX8ijl12Y>1B@6+0p$iG&>WAe*51-W!Qpyd}m zKW@QA&yd%w{|3nkJvSSFuWc4!|tSe$dCRWiPrC;{O!@a zmbH=K+^;=;;I~ou9v(mNI|KeD$q4#A2=-JIzNfPDulc%uZ^3sk{Aml`k(2;E{K10n z$?#1ET#bVar=f!7@1o>9l;MB0;Q0)H)`Ax>{JAJx>wf~lp||G=9?yPWh{C=4f6;)? zBpT2U{J`cYT+1or_)7%W`tRZy$NvteTcU6+&owO1>rpyhdESV^z4H9UfFnK;{roiw_sa7o!Q;t8Ho$N#&nlMZ?I<0u zJX@o1uRQM<@O6fM{uYIM<$0Ij@#J|g3fJ)1CIA84f3xaETI(Y1PTNJM4 z*^lMm+1;eSx zeyp9kC)LF8EP`icyM)&CFJO4PXnj3@yoTTawa1?^$m{yIbNvoRefZ~JF}$M%U(4`L z3~%kdkKv<>n(F6;CWjgut7nejvl5xRVq3Q;w8b9V`Xkksnmu`=ZH zb(1hqu9KC@MWqcdD5?Q3IL3+z^3^D_(2Wq|%a^E{FLq*SeXyosc5VIKQB|SpawkOU zf&n^n$&3b$aLTG{8|aeRI+Z0kbuhsO`q4TXS4--3<~s|V^TawvRn<2%YB&o_=2Kf! zu0g6x^o}wfrU^#N`gUP&W;x6$L%(p8cnwp7)lH=J*^pHVvubOr8BTIZjq2K<53RJkJ_-deh`;t)i%{c3C*2RL>(hkPd6mhZOTTv9O?~R^_-?4;cCc&8E~!>tf`tC zgiWh1$l$S|1+(jebE!*J(Vuw`*r}?STwO~Yrnae3XSnaFzDl=0>qBE|W>?izH7>x- z(AtJZqd2LyQSq2iUrwS`5akK8&ZdiCc3PREqhQik?cBQB8oClsjUs^#b7obT@^VQv zZM2f-RI~A;HKJtHiK8bZJY)0(Zs3OKxv(9WP)urRQg7QU(yHNyISn@PJLBHMW}uZ8aAk$q6XIv50=dt6)Yob3e6*Bsix3k zsVsGgvQQEEr;1Sd$Y_PHDPn%_vh^!I_&jjLUx!?GOx~AYU;1U2rR#oM@|SH7&6zi9 zuRF?DPNo6mxORFpX}d$+c87XjvWF}e_TY`I5K$sX0DK}v6o{-)-aiW0kx4F>u?i!R z$uX35>A=kE06O#x&ii!Dfdtl(SUXRodQcRupZXY0Wy}N*rr&rgz z7vR|%Zpwd16s{wvQ>ctcFF=QuQ^TiF5%3%feip+IHQ>#(Vm61$(9dCjbA+~v(`TP3Jj=l>4>Jnr z^Ci~joouH^6NS$Xast>4Kx zk!X*h1J{)wt>0O#B*=_r0KxTjb@tfFz$m>_XLSeR9imVFol$h?exdchjew97{y@vw zPU+_xmWNcp^0fD~J9RCVN6!SsK2HW*$dt8of_Ed( zcm)rT%JoH&ggknNwA&*mfAWB8fiKT{TgUWKvzKgsz=w?Hq{|U^*|dOZ<#8fGJ)~nUvC|+;(@=? zV0}fXkuu{$jg__KN+DFhjJ2@7qG_(;QdSwF8d7ecye1$JAE2V=H3CD{R z0Y8=c2S%nGI?NHGoQfDB4ps2j2yqUTQ6G__IYKlrytf5!VmKm2v;MgZN2CaNW=Dc@ zS;V7BCRX?KDis&Jp5+^ICRwL__2v`jY@W0I;}e#TKJ)c!HvYWyixXZxW8KC3Hmv;O zqS+fUe7-@Rg#NcV6Vd|yVcO94VDzpx?S#{a=S} z5$t`2o72w!5DYgcP(P3IdYX~BY3E)<`(Qe7UEg=wc{t0tv!9ecx$kIn&=+)6R>DKCa89Ll2sI+IbDb3k^7?owu_*!vS9gyUpyh^AVy? z|9#WW-w_aU+SAS#S)SskJeiqxW_A#7s0-2U5xOZ=Kf9W4#p!!4PO$v!riRAh3rcD2 zzIt4!rlPSj$;viJs8w#KJXB40)YM-MP%Ge*LP44n=~ZaGa_)h6=U%(;4DDO;W&;Z9 zPkU&^(GQ$5;1}Oq`Of>tH_n~Zsn=E8_jlhoxcT(K2V4v-FZ6O*SV8?VhNG7Y9CIWrprB8wxe(8h0Kbyqz3EqOwXGsL*HaPnF&7d# zQwjb{Dq`VA&xHa+Q!n8^NHEmLT*zFAd6?n37JLoE`&jVD7>>D+rlXhkf5UJ!7b5Q^ zYXncD9vx~fMAwyBuhvjkUB%BAV3l75g}5uw*g&D1JXcj-drEENgt+VfwCb-PoJnyB zTHg*RY^0^^`bIU^>(~A16XtckeaHAqdX3usmA7|%cWBeIgNNNd<=51JkPH1@ z%DQOtn{9sc`}j@R66Vy1E_%`tFSDB46 z>3ikg^N)WFuRnWmk5{1ODmtL?`$=nLC1JEK6)6Xe|G%@X3|{Snr9*x)DA`uVbAx=h zDBNqET@3gk#;Z8HN8$R0`c0%2=n6flP-&-w)0^sdA>M%P8HIaaeca1{o3BuIjl#8_ z@!$sN!*Y?Jf2;_}b~Aee7zW(i>-Iri7jW-&bq8D>-d@)u3fJ_p@&&!Y%fzFP2RY)= z-yd*wcxjdvvH=fngjJN?EtkCzXDL;lDqNSfxg7e0Q z8Y-p6n1(`nu#ujTg)pD>toXwhzZmiAadRTwPr0z;+X&$TGf7qf?mmg+4l)(1)`-lZxoH z=xo{+(UtnhkInmiP-1{C0I-9`F&WX;Z;aLvoR8kpqbZ5&_`h3fY zb#e?gfI`nEoj??>Lx6LrjCRaX@Kidjip}LIZGH~^Ty$VO7cYwv!rTla8gLq(d^0wo(&d>@W_A=@6sAu+jPKjx2LzbYyexi4Fxi=*T7A&=_F3a;-vh8eCpvH@Sg zaCBrOw9P8g&#jaP9W`o_0RTRZ;J;FJc;hQKR{wFXuVQmmN7H$Z;poUn^1{|Dlm~sZ zGZORwyZsyG0oNVbReaHrKVmpKG7{wZFa7RGeF1G7paThXP+#mPN5M249bfDa10tPD zhwk`4p#u1-H4Ovam*Kq$h9r8xy+NF>)-()w0mH$^adrJwBo7{&1$`Bp(=X@%jz?Po z$3TQ6^cN7E{yTjX)NzXFslobSDnUebC|EzLI!G^((R&c|mIH1H)s%amD4`&N-uVeu z)5C`4Q>*Y=S$*RqdK6LluXC%)>4sHh2#+ArJ7>ZAKv{KFU7!vxP&u=$B3{J_)Xomf zBPtG2sjRK257t#ym3az*2E1i9cgBcN9g!yg*Hld}j#Zd%Ys{UYA6FzW_5;*ctU;xr z`HfBWq1YpY3?M@KkwSV8grvjUGrBx-0hkq!m_&akl$BLCVaq}0NubH}GDxVF?$*(L zJ9-C>o~#tu5wkza-nO5~SekFXEhFN0qyep%?)ep%?W)-MYk+b;_p(=U&sEB8Ei z<7z!LQ$IYGZlCez%Mg><<~?`_+^2caw5PII?(?jE-Sz60;m1mH3SD=@ymcCkh+&(;A{G2 z_*3Dl{W9q2@mTbu11wE{71dwM^aJ!u6C^tH`0+b6S@hQMn40n`ywwJeMvkm(c(Ado5}_qQrqD_iFRN==*#I ztgxm6Z|~w!auI=^mZwpXuDk(5f*(r2$;6RH5;aFwd(1LG2iP$3qA`_U4yn(+ukYK% z@84Ha*c~18B{UWtNU1n-I4U?OI0iI2*&osII)?UuyMTKgLkGYq0p84x0Wx${P{6h0 zfkOa&IC3PLJ{&ocO&@~=65ue>vq?G_J{&nxmZKfv5XwWAE()gMa4^HE3>ugzLoShL zEaf2&Xd&71r~q5Rz1JIa6<{kmddCHkM+Mjlp5-7YUQP#O(E)ZC z@~A*-6~S;_aO8C9QTRht0$c~!G57|C>i|3KOfC!6#NNxN&M|fJh+t!oY>aaH)r5w^ z`g)2!l#NOskGH|GIt8H?by(w+XoR9s!<;B!cyNx%IzGIC;y8MKxKUy8lCS`Z>BSLe z7Da%w={?udO6s(gwe*g64qf0Yx4ixA!j%J;|K{dTH+*};mOr6UM$&->MuPDlqqFKS z8a+`I1H(uZ#ef%-4C4n4GzyFghL}neBXsO2M(DIQiV-??6eD!HkX(f<=^)AvqXR~T zYt*wyJxT~2;PjmY?{&fW0f*P8ZLY~xwc6(^E5doOApF8-2LBI7dKqn>9+?& z9=Qb9GLU7XA7yt4iBt;f>rP~M=v;{$MSyVe90h2n;wXfU?I?s!YaNBqu^olbF&za) zZLteAN|Id+4^;-|Rn<1NzR_mWl@6F%+T)}PUeDURaq)`hZ@uqs#3_%_0rzGF-F`Q4 zi=YiV=m{CUa)ftbC)WkbD5xiFbaGNyT~$$o7e@(L8l1(IN6~}WX0~wwMM5-vsw%5g zjFeocq@pzX1w*~{QN^sFQ%RzK^IH3yuTOvOU%^*9m-P?r*B{Zqdb%cn{eE>jDqzY)XFU^BgJzrn_RSet=-$i>|2a>*;~;)dOyyMPy{2s*v!FeBR6bT##CjD~BzTM3T(0XmRGo-Zg5 zcn*M+1ipjvfaAK60LNYWZdqEM!!($nUU_<}x~Q)MB#}q2^Tg=jgA2GW=n2WDbEJa# z>7XCbsdQ+)(Z-=l&OQV~5_l2AkJ8{MJjn2)4fra@2{$o3&wyV>up8)roP7aT{my&6 z{RkXS|NW!zEa!frv6kuNgAOJ8dIu<&hGWJhdPD!FQ)$mM>9Ht8c2@0tiEbgd^)Vq@{ts5y(xVgl^&6^CO&c-TrK@uv#b8htnMxy(kxh z#jZ__Mnz4tLbSSu0jY>y9;%%itEq=kwaf+dIXuou6q>_>pyy(Q0uAYj=z$nLfYb2gcZh`!c*UdB z+F()WV1z1+BM(L>4NrWB7(owhJQ9ZN=#4U>VFZC5;mI*VnIrOXR7Cx~=rBj#!3xSiQyQbG+cYsVGPFzg#;a~B6&`xJou_$(HN;GF zTrcS0O*p!@G5AD=s}YLoE60;UC~uD+F-J!(5gY2khmm*H3;PJX;bm30u5WA@gHr5HhsU!T zZhUxE5H}(8?FT8)z@)bOgfor$@cJO_&r@BiuSAUoD*DH;K=t%^$bLQU?Px=&N1Vif?`dq~NRPLMg z3Ac3(!C^aan@F&qwj0S|pPu2qGkGH!dWJpYp%eHAv>OlGo(B<>`=$M_ zCsNO*w%mh2m|*B|r-K^KF;PML=3DTa7>)^sS^pM>V}haKS|G^bcVfHUxk?2*X5v46A=-IQdI8agzG)FdX4oy!u19KJ*DY$CuUU zzk{$13DX(5nU~7w*LK5xC)}{7JEy$ebOS$Pi{^j*d{fls46>LMCK5_k>e0Y@~1B=8F;4>&Z41US6c z4U`8Q(GU{g@J0`-ywheGd~Hx?Va$C-k0FmV z2m8wKtVHTGsPgDBp1MXs&rIZ113VB`PtRgaXlksZ{pay87rDN|>RF-kTH5%sLESkC z;SsGMeE|WVHK3)c*wZ5LlJlzSYt>B_B>_!;SfG(L!CBQIJfu<{l}))-fN7JOYV3g@ z!$?kl3fvGlA;L5110N577wg2obFo-Iw@jBf!TUs6NwBsVb5Y3@{ruijWKM7P-|P3oS9dt%%$I-Hd)$e4k3zToiVm_m zl`y$fff`C-m}Y!;iZu&ca~EfDz6BQsIRS)ju4!GaueBmS$%CoL-Ya5U>SW^ zgPsSWWsX!I~y=3{q64$x_2I(MgP=GJASjbOdGa z6hCFKrlE96KPtgR!X5sErY``9O$I2xmX1nwXq>hy$JxSggbKItdC)hKOAH3n?^Ei~ z=WU-h1t@1e;X?GQWze|)GHxpYuO%GlbYPlA&65<%`6SeZ)_Efsx1Dh1)_EftH4lT=VS9e#JkxPI7MQ~Hj+Zh+2&QeD>Q_f#9ZUx~GT3{kr zPrpcaFs>WLCd;V&ox*{#ROv^qXw>tgt@kl*3w6po(#?MrP6t%EA6=@t zb~be=yB+#4ZW-Yqr>U2t7`KgZc01%T4!7d%b~yQf6IEAVOE{a~SjG(|M`-gK$GB#~ z+5ApnTt3A{Hox^ZELHp}31{=$z_ptPik@U;e@mO*&i7<^Dw`?Jj=MvgtP7C zImVUr_S?(zjN3vu+g@H^-0H*q_VOa*dLH4om(7e@d8FT7USeE!uHRn%#JJo(etWs- z(x3H&UZ&;w+ab)jErhe}Wg+9-zW#Pt%(%^jv+d;?n=ajOXzCLzsn5AwIeos4TH zT!79q$CbMn7a^tC{dVsWPpcW-HVT04{;&_@>L{47+o3z-wh+$l5BoB%a)`ejx;#*- zW{S;(v-`vDj9W=7j<)~YgK^m>`rBbo#w{b9-41&(uG>lecIe8uEri4Mnf|jIcdnf4fg++~8t=+mu=j>jN3}M zfYrxNV;sKDQcdx&8M{q>uaP`1(VIXoG0}PEwU;t(eu@9ur!ekA!r8uOD&s0A`t@=u zxmf^c?!IG1tVPWRjAe8$ZuoZTPJV_fzbe*64p>?Xy}C7eAzd@Hy!{cZFe z<5m;SZlfKH%RkHCM$S0RZ!O_ovf3z%aVuu{+o&Dmwi7OF*=~Er%@6w9r~~6ZBwT>b zGslOHjLR6S?%w)Fa9BLG_HM1jo$`0Gj3X~-v(b|T!e78 z4Zh5{5*pxaA9+N-BE@eR;l3ok)J$|}zk4L(@Hj7_9n&Z0GHx5;Y#Z#uxVn0OI~>Kh z?S!*!@My+uZt%B59^(c#`rDx|U8^O5MgtPVe@$j-^!S6%D z+5A3XT;*avzfT#rnQ->?ea^Uv^%C-%7@X31{=Wk#XIY z`uPR=x{6;h;X=gM^bo$GA;|v)kbt#^sYEx8?kf zaS_7V?XYOmYl`1?!r6LR%((f>{rr|NZY$wzeoGlwcd4J>_&s|Kqsw*fCYD zDdRR><@cXc7&mx@-+xYJ+_bCx{`0dD6AExO%g7*Xd-e@^!g z$jD4P%V%8Ob^h}PFm5a1Y<&(Cn%DdFIf!u|67EgnYsRg|FmBUIzdny;T>cGyeICcS z)i?U}c|79+H~IBBm~rmS{%1!%x9JXl`(4Sn;=BCqcNOE-5-vc3m@(}N#%;OVAJ<(i zH1G49&cR>IkF-B!k}UG2ZVcNiCV(BBS!V_fq?{&skmaoryFx5Imk z%YVf0mrnWfLZz3PkNItP0^_z44(-rE9eNxqVO;TAzwJ(9+!n&ww!2}_Q;J`=-}w1O z7`K9OHouLG+fFzd20Zt&e#f|FkNf#OllSf^RNaXX&Yt)Gk#U=z@VEQ3j2rx z+*-ofr97a12OT$uWix#qZ;aZbeF?k_Q}j&OGW`xE0 zdU=>}TL~Ao^zsPfX8zHymo<#rOt=7@XZoc_8Mp0Ozh8R1ZjVx2`^*>o_VNVdDqr+p z`;&~@LO5HW>lim}vtKXk8Ml>iwx8I*xV40^{a}P~fj{~6vXODkFZ=cKTgG*J#jls& zF)sgAzr8%gxb0i~*Vl1Xjndit*Zn%{#JKPqew}q@+&045I?HBU-Cz7V+l_JC31{o9 z3*$Eb)vvSN88?`W+P0-V7`OH|pH}^X2O+|Ud*w7-M{LlL1)?jbewZ6ovmkF zm~hmU9J&lTw9neWxRQT4SiX0*tGPvI$~n&B1*NCscO~KM_<9NB?*6yG9WG{E&;R(Z zeW}nSoIO5V!nnY8zwIt#+;+m**S?%_Gs#$NeO}7AtzY}~c^TtM{^xJ^%NbYqjo)^! zVBBCQ%hxxH{?_*l=xir8O^ZAgmjGIrmfYn#VF>WPo`Dd@Ck7wM>-Tl{hYTiJl zv#o@?n)sRheH!ED?~&z;ZBAoc_MWsqJ)P&OL)-Oq#+4B67=q`hL*q_o+%m$!mdySz zcH=2ZmTiP1v-ij{j&UE-XCn^I!X7#%(3sOGMio$CfZ|ZEydzU(C3`;r?r1%DCnu{MUX7V>*Y&*+mT+ckeovrQ^R{Tl`XU~BiWZbmAeqBGr zxJ`t+fb?mu$vw=tV%o~ow!udjx0!ITYqK5JFm82!e>*(NxSsj`c6f|&D+l=7VJ+jb z={*6v9e%^O+(CYS{W#;c(M!tq^)2}LE~T@&q5p=4)N=H5#zQH&X#2{=m7x2(wDANFbfMA6(v zxC`kVb4=~dxVjPk^Lj9D3*qd3v>)RtNBaBG$HxX{5gVtOa9>*dK4IL-QU135lyTXk z{cZah$HhSeoI`4j#8Mlo(R;h-0@ zZ;obMPul*zk#Musq3x`gaVrRC%W}dKV?tEb2~76$JCSkCgtPgb#JKEIKh0r`TS++k z`uYbSglNuY!o5Skrd{VVZtWDmoef}I?o_`m4P@ME!r6Xe5aX7e>bIq17`KgZVG_h# zmpYblb*K4l={Ux1C0u~cGuK~^XPk4oe{8(y^l$~Py^h}C3tHD6X51FS*?#xJv)(>i zop+YMZ~l~Vl{5T0yNGdH2xt4DTAgj9W`MTc01EI1-_kQ&Qz0$39|Q@!5WT ze$2SFgtPVe3F8LO@$2(b#zhEc>+>_lEvxqH^K-^+Bb;rYUoft&#;?z9jN3{$+djW! zoKxr5=Oc&SaSrs7-{AKJYZ$khaJDaalyN;9{k~u=_bY)z(^Zf15 zjd5YZ+3m15xtEclUGEd4zk1GUS@*&|^TD zack)U?0LsR#^o;b>ueF@Ruj(lt&17AY>{7QOBlC}aKzH%TQ6o@-4egfmNITD;R1A? z>02*hoU_#LTOV4pN?m*1GQaIU%(!iYvu*bg#!Xx9x7|k>_aWhI+g;Ro(E{i?aH*f) zV#YNS&gQp-aoLyo`7LGKO2XOvb|2GlKKN}WoV}*Hhu|*vx9y&cbFc9CmAx1jA)MV; zx-zc#N`Jd|V_e`Wf4lF^xMhU1+kGF#Wnb-Y_wJ0FPdK~XdoXV0&-{Jmf2W^GPZ`k~ z-_Nt0d+67+`EM9E|2ls=e9O44gd0KU>2=d=kaBh~F86xkM`if>3%DOSXJ~%Y7?buYUXw1Wn=l^Tqz>99z z&^di)?*GQ(&&EG6@Q80GKYUMj4gKl1x{q#qv|!Yg3)fWq>y!QV(9nDO1z&u(xZ{{x z=RYy))QNfj)X)>3Ie10(s##+fz5d7*b6$M3n}#Yu=+9n~q2KDNS@psC1^t_9Xm7+o zx!x@>K(7MR2GH2|&pC77CC6R0-;m*VpZ{pb=Wlx%uNNArtC5eMq>0U#MX!R=mn>$` z{r8Py+(4IXx)ii@_aMu$oP!BtPvtF zb0XyBK2U39f^7*Od5<;+L@3GovHRvIXpEqJ$pFn2%kGzu&ezAnUVkYrBx}AWL_mYv9cQRr3 z@G;4f@I!ke;aA2@1>irTcZ|d3A$;ym(~jAXDPv5oRQaR6&0l1bwq}vk_9eZfpnhX| zao9(fd+>=1rXHlA1*uFag6$hC5NxS|uxi5TV#8Z?M}yw`sTPM`1huR;fS$;+?6 zOq!aWmxrc}zd~R8Zup%TOyh0ZQr2{}47d(CH0>BasRz2Beln+EVHh7o)_jE)&VkQD zn%JY$M)*ioh{}gjcmw|MK|ir1<5Y~7=vb~VR=1_xRW&;z@XM&T&)+6SB72msr)-$= zF6HCeabo^0ar5I}T61dzV*xOqpLo)SjyK*-Hlp$cl!p#{DG7hqSGg4c(WCffoT6cY zLX1hRAmOWm_T@1$8n@(dE!ihU;&Iti1!$a;sd!xWcwx5u6E2vZ_hjVj()V2eBo;S) zmc*lcLW@7b2Rf6u;)jgKMV?gRakIT-KN@K-*=I)DOZKFJVlvrYvPX_r;o*XPY5sI+ zlKGRo@9sS>aY^|6SlUbENw>XZKObo?*{4U^OZN1EMl#u6vd55D)8T?Ai|>nUzU4p{ z@Ob@8p2hT@m$)Q+ek|=J@}$yUkX`(t?1zLa#=1jkWmP?vXELz{0h+QG6Y{YXE;zr( zFc)RaK^!&K>Tz4-l6!%uBhNq}FZW!Lm-qgVm-U&J;!4yt=lim+lgz(mA0#Quo=H-c z{gtFFdof8__HB~+zU=WNc-aq1%CdJ9MS~$Q_kew4kgylvh+;+YljG-B_8y`HAc`3i`1WE_m(s9)&0; znxDwNlBi?eGnMz805{ieWPSphYAKoPAF^+$*sJVED)uUSmx5*{?N#c7BoKMQWuQI=reNv??d#XxV_Ft8c=K+9=-ZMR)wE06`o4?2=Z4G&lGC7|#OKYX z2OqFkWMZ!u72K?o?tId`F6b=Td{X)j>LHmnm8u=VcP45_FQ4T1lcoQO4J4dT9;-z5 z{MnV}lXg2Nn@^hkDBby_&97}f=`lUW)=%4f^83#x)4884rMOJD<@?F<{(tP8F3JxZMML(V5fo^<1LnYT&2Ec@q6S@znOvh2$*W!b}D%Cg_T z#OLyD0Kv<51f(qA9Dvq;LWhpekBi;!QIB{A^fR7>&qRz4Uh<6u_6kiTi_6V^lWtsY^J|OCz4mA8r!6i|FD{2x;j@s^xz8ixl=u(O(Rq6e z1txh)=RQwj{>gd8!*0It<_N|D;947(C*kkLKzLf=jv1I!ae>^Vl6XG0+$6*64#Z|&j_c7hq;>F{l_e{s*Hh;)#^B38qt#OS= znT*FxIi%n0%y>NTlM4#+^QNg7eD%Lq7u>x1ewDxR{Hxu6zE`61>BQsabwEeS;&JIK zsE1_QP^xy5EFSmraU+UZf`L*t-OkD4akJl~8;{%k+TwAq{n`3y zi^sozJl^qd9X7&8YE7GCVB+VlWSkQJfpc}2JF(-$vkN} zgbS|w*MpJ!-`(y45HB8=Z#VJ@E&d1}=uF~@A2J>nc~XhT5ko-tNb;RfX)pQyr?i)R zD-?Az*Hg1jis)9?%%E~i`awASI`#bwhRNL zqVc;c%~$MpPBvdL`%Sv@6`Nn%e8n(4%G&yAo3H#Z^A#D7rFGJobJ#S}nK#%pL>~NV z-I5BdnuzqU9E)*4H;e%j)w^x`P=dx;U!c|KakFYzB}A??dBwzh5# z7i(3=N#_~q#4><#Bx2HUO@7j~zm8z6K;2RK2dp1a@;3G!Mt&IO*CB7G%+^qB;y1sm}7`;_rx)(obMyd0J|T9UQ2OOLtRL1Pz>5JyNj(g z(X~eRNlC;PaC3e2+(AnZ2P_AFD4oY;Szn#cW#G_XGW8zvJcBN1>l7~dh@MY*BFXb9 z-;Uj+=ed8SY9t>=urT!`Wq@Uq8 zUjG#RBQDD1{=hbW$ZPW#*`&>>ib|QB$Cz?R|JhmVzVI*GJ}OqvsbKEX^UUkjb1KMB ze`%R}`}3!$d5l>n-rNOBNVR>F&0nMsDdo~1)2348lWhLt<&!*ykbWpOkZ}GIXCZi3 zS_d}m7wwm9{$lo{bmuQNzfQz6QNM*elF*Jg(07q=Z&By`e=j1?|Ev22+xlsnzob8Z zfzLup=eZRbx5R&dj?UX-Dlo}YI%~*@`6uTU5Bqu78zUGSfNSk@D@ph(I-r$G5>ax@=;utxUY|e&*d_BU@oBIyklao z2kI~{GkZaT#}NiUly$OgF*er`eMbg8HCAey-*{+3lPxzB2n!y786GuPwgvTA!_-w)pD%$5-jRrzhjHv`#wj z+WBatu`i-cL*&8l_l-}?b;Qko2pkQXIru~AWiHD);!9ixE|cqsFB)_~Tc>bApL<`A zymd>5LX_h@r};$P9;IBlRX@T9I+Jnwhg?S#dD2}+JhESrYA=Z&`&;FHR=KZL&a=u# zb6Miaqbz(MtDMVaD8DBi`ngRNU>eUsjO&w$XCT1i2!kKWI<*{M7A~la4)L--9Ac6d z;}Yhl`Nb2^A7`})*m~6mx^z#c1{-Gn*Av4_}1dr7T?C~4msPewZ*sJKfXQZtWF!@ zGqtA8F){IbZ!&I)|G>FAZ=SCyw)D3u%h?D&je4zp?=3O^mbm%xj}$elu>qLYt{-NS zKlq9s#V^NT>8~G}@%f~j8}mRj2Y)C{;j+Z%ler9BCgbyo23^qBspaqgn%~-yvy%M^ zALvoyj2|*S7kN^N&&~F#y7XuLalO)B)m)bLI-AR=lgaj~H0Xl1PT_(jPp*r+F=vg7 za=iJ}!h5&P1g^D7`21MfOXNwny=2c{X|KN@fBzupLfY$nE(4ay_IlT#3)(t`3zq-o z$%qqt&qX<2d&&Obx_--lh0l+ry+odL+e`L>llD6H)K5L_HHgd5OeWiFfI&B=^>D#~ zz1Bo#fAB#8VDZ{Z_KS?2lRPJUek|=J@}%2dGG~(Z8o~2&>0iT*d3q+>%Qfi6G~Tj5 zl=YR^ImvUv=f~1sB2T*Q^~vxuwX?Xi*XLZ8_WG2|&`KuT>tlm%Oyl8#`zLlA)?9O{ z3mDD$hshyz&e-GgDUxr^ukiV?w3o<}ZhKunu`7L(I2Lc*$Yp7-m0U)hOt#l`23^qB zspb8H&2KKsS;>Bd&yS_OM4nXI3$jD^NI897)n3Ts`OuM76_x6PG?dT8nrXnG4<0(< zdzrHek;nVjj`58vk<0v!X{S{+(KYrz=DmB0rr|i|+Pi#@2J`rqk{KWW@9Fs-d;N~f zVz1wD88kC#uU{Kc7BY%lr7 zVh&&W(oL_a_LKHn!eyW{*Zx%<29RZ-Uq-kP%-89^(yu zDC=aeWudGOv@?>7o5;&IjA8dJt?LUvp@U!h{tRe}-ZOoF$mXBy{*bgaRVWb--jiT?l{owvtOV3MbF-i1xfKRK^>*q7Gas>TA~T6;ezll;L~^eBEg z221~b5NOIg?eh^6)LJ9xB1Rll9||=zE~pMsfR~B+<7Wna@X*P&1%EtcuEWUO5b`8T zkYBDVzwGrw)Rj1OuvI?ZDj#Q+kG0Cja9QHkK^A_XRUTlKhj1A(A#T#|ORDc+>ixXs zeMz9O^F7~X&^ZZw?jkwq+5BW2n*{#sM<_eXc`1;<3^6sQrKi;!X zskU>nI9K|XQZoH9Z7Wqi$>LluA2%ZW@N4!zl%;=)ohFKN2ddR;oDoaA(sNIy9YX`j z;#{*or5oqk{MzE&nB5^~>!&TwO)t(xzn54co%beX{1X3xw$Z)}W2@Kq0M}AV=iSM~ zGPrI!`@a0S|Gg266_E9_GkUH6V(pu1-xtacqkPjL@vB_G;@$6(d06b6H-FO@)cJ3XIz%~_q7)O8ZJY|ed$p1>-^Yz>bO&s%Kq;y z`R~h_pXdeGZToM*$+bZ?iVa-#)50G)SLP-5`^Nck&Od};Q);Rj7mTc_sHzF|n=tF_ zP+4PMz<~MA!gXFrN6Y(&kVYG7>x(LbH5H+8L_S!5w7Jpv$a$d};#Jtt5SlxydO_c! z$(6zSy1c;DP<=yHZOzd9e(GOdps1<3v8g^Zv?kQlSRbs;3zRg?s;(*<8(L6WJ10~# zw5F-LT4E`mxKV(u|77zLu{E5W?!3h2*ETPSHigRA`e~b&q&F{tGG+Zeo%fB!&r0j0 z^S-f7Bc1Pa+B8HS{A%BpICeJcCd!MwdGU$IKk=s$@8Uf9{s!`?`uk+-U0#1r9^Z(e zQ{{vDiN+Pvui+Xpxqd17h2A7S-z3gO~kCkZ=Fsi|X63$j4i!#C0c1=5s86 zJ+PhHA4cMj_pI`}R{3vM`5mjgmCF*3ylvs%vdV9A8L}QkhklM_kbl3#ahcgm=Pw4o zn0{LBAB#ILS|Ii1J!jZJOLi;#q@Ur}wp-8@y=Qve-{zmJ-$+|S9;8h68&i&*-ERM4+pX6(9 z(*MLhC9d|p=d9lT5XtrLt`t|B_KT}e7FV17DBZZ)=GPWidu`9wPg`7_UR;fSFL8A` z>-{oriT^+=>AXFrdfP8vDV??c#QfuNNDfP9jXjh6A)V+^{BjJI{=5L~E9*}a{=87d zdpRIXX%d%ZowS6@z~P)st!tlR&;@OsT7D06xB9mlq;_k5g%9*7amEk1elGH)vQBEY zm+bW??e#m}&r#ZIqp`nZCfjR+K{uv%dcUQG?|aHVoUwC~=Y-FXrM*O+RN4!5rGLqL zJTjm96TjCZ<(I7TW~=<7RepiXGM{?h!arw~pS8*_a~Z9003B+6HApQ0N8c0RN2@aO zT-!4SKk(Ga9t%*`2ihHJ&7pUkqjPl6jo+<8Ox#jjEc}EHe&fxrq#ZInzq0v5UYozj zCT%a*naTN;DTnyIowY6jTklc*n2SA8u>R2dh^JiaPlEjD!?O!t{8YauaLyNd7v6E_ zZ3*8QfF4q9U--sE`jx%}x=5x?rOF4_*g8JmeWc9(1{tJ3iVY;1Uk!?L<6>8uUzzp` zy(ODpnf)l;`IXJDZGHu<$C9m|w)s_h^DAgnVuN({k&7$b1jbw?hs-nnawdY+2%!zds3d8))Rgh2;KN~y=m%@K@EIH|So zFeH`%{OuSAlv_^ixQdJuD4Ju4Zui7_^IkMS$rurDf%?qFjYRu;!7_dZ+t1d?O$ngi7)NvVg}kL zP#U#1^l!e=3+6JN?WtSLB7I`N@RBc0gF zrXlj+SNpcaF_2j|Ufx`vlf88$4*4DLb1&uJTIG#aIbxMJa9QGz^%j1eResVcKgDIp zeIOlrea^d&hyL1qX5y8{4Sq3QwH&X=_X}{2tk1#jS{nC+pNvoVwc{1gly=DU`kc)_ zS-d1|4|$L>884Y~?Cf|6u|=t~R(JyJOQ4Hn+El81lEqJ6KHhyj%>D)$q(6#%O8jI$|1fA5-`B&mU+67a{ABi{ z$2UxJWv$=*O|`w-;wNZ5mhARui=WbupJaV5oqauI+!FtR7SgtjG1ZO4TC8=sboTa0 zEQ9N&^S)#8ZtEf#BOvk5X?^b7JN5b;<%dx|?)qF}8Nwuk6QLuel+GR_iDhtH@;w_; z5`Zh~wv3Gv0GnfoZui8oshppPx809Huci1XQ|ohPTr7K0N*ufw?@cM?J+1N{R(W@; z+=a^$7w=}_v#oMxtK5~#(A&Xu==HlHvFC#I7I!K%&cr%iM}r@D>eO;vJbTIJGN~WI8Uk`9oftzsM$SFV~sLxY(5A|3+N=Y5C)7KM=&f|LpY# zwI2xbr%v9pa6!*&)xGL-`t4Wv&-Y5c*L`dAx}djYak2Cz(XVM!soGJpxY*0bJ2sj9 z4RT0-6dOns7Y`gFQpbLGrFBKSos-4IW{FII#?_n^s)B=$;712wcnRZ*tbpo%x2kZ%z4Ol#d%1Czc@$IuSZj zN3I0liIr}b*NR+oJxBVveAfc?%{>(L`HBAuKcN%PZ}ZtM>fq?Xzkm-K1V0D)Vu#QI zUc+?`d7@A_aa;81lFdIdr`kKP?ZS;et;;nNzSZ z9Hu?uf%nouUqIbU&p1BP{J`-WfWK~82X}LIJLJQZk5FEn2b`J2zGJ*hzYTwpS~_{k zK9RQ?3)Ok=zEZNj>wEhvc_=@O@+ryy{;s0cS}AZHXABwVPVJz-J#f^1Yd75g`nBL2 zrhEbAl{_}R#Cib#FdeN=?WpR!>(6%YetodwReV_I$QgY)xuEd*%-!7P{kNnj1Nb+q z^FgDvsb=I61-)RIM~+@HUFC0{J16pogU(d>iyy3x zmoC!%~APp`kxcI`L=UZKDh9l$Y(|KRsJ_8o)alO=^~Zy zIHNA|;mE}*Kk}2BNd5trsQiMh)sgl+FH`v^I#xu+th`3$pMT-3$Zwv$S>=CyVrgXZ z?RTpDTh8D}=ZYs)9=<#D?khUKQch4tYSNZL49OmY~{%4h6bMrv=qo$Wte&OD(d&1Q(syzI4 z&e6}R{7s!o-PfP`gUa7mFx{Q7{3(^cBWs46*SJyT_j!A!d&j>wsQm3!v)ug`u2=bQ zep%-JXP&)8#7PW!Vt-tiH=tzUB`@+_NWN ztn&ZpdZIhgU8wS_e>&8i_x1vn-o~_AU*O?n{ERn0!8u*B<`qypQ80ggPxUKf($3&t z9;yyv6ARD=AI&RV(6{gSg8Y3OzZd^x>y9$#A(oVyUG>9%%yAzei3vmxiPjwl4K%6f z{2}yX?CJIY^*&$bxQVNWecARWIyB>(xAuG2g}vEFs`i#_J=@#fj$_UVA#0)p8RTB9 z>}@aeYOw>Hix^7Hd+E*KOx*hc&2|5(n}%O+(sQdAET%W?p@SsPZX^HSX|Ycv%D0XH zm;GXppIY%$SNtMfz3IGKopT)7OCDvpkA!?Gb7<6;B-bN006p3EA$1e|n)e6gyLHkY zmoF$i9p_2;GOK*4RbFnDmvLFvQ7*CYORe(7R{07pLx!Kwq3;h4_HJyL7Z{PrcU!@0 zvB4K*of6xL=zqfvOYs`IN@n}E)bE6!(7|uKc9iyjA4ufqHFx}ty@!x0f7G}6i)>;8 z!Y7q^l$?|3*VMz#o+rQu{rS-i?v~m+3vh4n?{&|)|Ew-m_XFS9XOF_o6MCuqHLrFr zyrTcDs*c1EJ2;6>Qq^xVzbbu7bY$98s(g}-*IquZEBx?l_B)iNU&{50pSGW$8#oxX zy=hk(uTA@f7LtwEW>i%@VVvvoEKNTQOcT_ktW=-y_l_`%PzG z&%`o-e}sr{UvQ-{qm5aG7@$qO2KguePw94bT45<-^>G=4VSbV&bzN=Ma@QrEA zww;)+MbGlRYMf)vg<5KV;U{zwwZF7SrsHFqKjgLTPh=At5WQqFJ~rjp+3_)SSXc5J z6(3_C&4pc_R`D_NT^`%3u<_9D>bqJly>k2>on*9%D>7QZ?3FG8rP}`e!r8wENV`w2+oNV@|`5)G~X6z#QRNK2PPWIZK z-5zama(d6xq2GU>I9bLo@gHafaCs}-yaya@su-AN#;qVR(Y~jo@A9LTICWh%e-lVg+IkAkLNOEi0+R$ zK;1`(?vI(DH-f%CkQtjBYw!b4oxJ*u={7bGJ@JV#Fng8c9uj*CqYx+&P_X})( zZSx@MHTu`qPun~wy?GF{37>_O&VEHQPKo~j9i6wwP+*d$boM$*%s)A=c-VCINlL=s zjmM)UnCMabGU{ts;<-jkG||2i?+144aVF~L@JWYpS>pX1E(48oGWETILkzmints9s z6IN}DOq%|d3s}7GvOd@;JQKLqCgB5}NnG(m&L2b`#Qkrya;|{6l(g4jJMK9P*Dmq+ zQC7K+RnE1_M_T10xGeGb;TFC(m%+0;9qK-X`uvyd(;3LfT<=hW4|wTh`wW!zA^jqJ z>CbvfZF$xU_T5taB>aRJx2{C>|1<6n&a)m@1!Saj%z;cb_TYZU2frNZf1h(>cgKfy%qm z`oC$fP(`x1*X%dx#=SPbwz$`8fVO_x;@L(gEMW@0ilW~YC$IgyJFlNhs;du6- zJ?|He{NLxj9O-+{t?Ky%vrfEc5}=1v^_wg%5gQf#nr)gYpJZ`~mrwHbIFUu{BT-y( zoK!S^ccr+*v|p$oSzKcFqjcjEn_pX8Vi+D}ZT+;xCF#W_==bnhNa?J{$+)a3q_=;# zP2-WGX62(nv$gl+Z5kpEezk8)KQ4iOWPPOXx&<>qGY5Yt<#Soqv-)uvIGmHI^{hOD zE@w8jOYn30f%8y#*HC&cB@(~OFuvLD@DnHI;v_Fw zvTloW)^kWV~z2A^m7)t-C>o zzwY>;`W_=<-1QsQsqZl&Kk1#$g@>(vLdCl^8}=%c*w?HdFZNBfos-4A(x;S?>5pk! zsq#q{_j>tw<6g7hK@RDcVha-Y`rccM6Zq~*aj$8|&|9*&*X&Q5&OE}EwRH10)%I?S zd!hAMvfHCA?oB`Lm6$G_xL3w6@gHa*ZQB@IT{qTZt;?lzFFLUd;2%j@hEI3=DuS^B z5HS)4w2=Xl@^ZC<-_imes`Z6C_ zZk3l=|FQ>okVsnde8KHz~&Em?S3Y*Nn6WxW^z7Y%CWQO1L#BfhYe8A zpJEQMWx-|Y`BUVty=9Rra{#kWyg2~$kZSuTn+HhW5&fDrl`0=xW1@ES^6}0Cgtz=k z{}UTXI1d;oXT*Ntly;TV29nJK%zl*i`ZxP2X_vNnK+Nutv)iL>9+3V#;QOq9 z%eW zOb?=dHJ{X(%P8(m$B3%>P+4PDZB4K`Fs`bivXNk!h`Ty5A6$#Ro^Zjx{@GaY+MlOJ zV=Y=4D|DP~bOZ_^Gq#dK97gNf7gkoze;jOQM3PNwds z>|@Z4$s8_N`sBLE8*|pUfW^C?BG0A7&PkpVK3P;v;=Uj9eu~JG%Ka2`zVyklfmyg> znJ;~1mH%OtzqHERtnwFJmif}>7XCA<{3(|qLr*%?b2`4yg5_uASsn2B*x-k7C!*knCGvskUdb`H}P$rA+!` z+EA)|;42fgo0pFp5q|N0rN2p=%lycGZh1(YlXs>0k!i0`MY8#k*>BRFAKCoc=0{!w zwDr?AKT29z%gip3?aSSYrOkdBww~^X;un@`p^KNAb%s zSo-rLw6DbD^6kkS5T;bc-#3+byu$e2X(r?GkU>{-#@}$k2km|x*)r$nE=uv@artg7 z@U2P02YQsa;)jgKMV|lD-nGU?RYc({e|+#L4>g7uY&C=*679o^D6$udJS2h!5=}so z4Hl@8g0!fJ(xv4Q5)Hn70LD-vXrf}YJfZ=@Vxl1=V8RcL(O|Isfui_`7^4!s-<|o` zxuG`hYbA6Cu?vjS4^5*)c=JMd0 zUfH~CX}Y;SeERVG(|{-WWPFwfJ)1$<)MiS2oP66c}#r%FkiP@sy>i=5CR!= zOjgn2zD<4e42KF`#6*2A2=za~I41;rld_lZHp>SEA%ouznX`h<);P}v2_9@yD_toM*JnpMSd`sua>_ekI5B>YhJg)!ena>5eK_~g- z%eIPq2&PVp)gzv`XFD#earCP{*{f2|Hhb0VN3Qm&ZlSc3k$^$};Ld*dC72D6^;gS!5Zk53XwNbGP^Kd*T!G-9*3yQ~x6>EjTgCq~Fvk~~=gE(F4OcnOqYjjN(*I{j{x-Zw zU86n-N#aGb9(|1$(Fb;R?9TH1!Pow5&+`1i-7N#My*Yo-d=ALSh7Z|SkPpFZL&dfm z8$OKkvHN?mzp*{?{|veBqpDKX+5GNL_)zNEh7Zkt$Zmew}WOht=5^n3p0<7W}N#GKwrJ$R1?#QZ!r!R3MRhg z{%_*jU-f=)(!U7$XF;D6^iP^5zWq_$KP%`TG>tl6JYT!}YdQgO6T!G=41PH|$-b#< z4Rbw``})IrYJVNX3*i*`w*4&PGlN#k3|--d6gYdjZ1lK9rF$ECox-!0yi<@-5L z?%tB+`#JAFasIIFot(w$(}r)^SClk8&ul}*^0DFDC?DS^zql*=8`~rCt@PKqE9S@j z3E!IS6{4`=TeIJ|;#@4!rwKWaxga$L@(x#L^RNn9u0ck`|%QDz0cg7A^1=?}19)3}Gr89;|8N@j>GLKtW%lX-NOZ;1jMlSM$K_$bRGUB-Wg-GWda~3UVyzj>l(zvG(Gc zKW#X)`$D*i{Mhesjl<)Vd(wDZ@<)9of7Xq5$B59+ zllXR{pf?D5y`a|#x=qu>yRG8>T1}&luz^B+TMPf!x>XCGsHY2TB5Tdy(PHoet%B@} z-SO@4DW8pGZu-BX-4wzlGLwBgGrA3sZewkz8Q@ughI1eQ;G{ zn>#+km`;4cJqs0@!G66jh3lt#jeRQkO;YQp9Y(pDb#Td~Hhq0C>!rJVq{XeDaz7F7 z_au-HWX5^=a;~4UKE#rhPZFLS+{elEoS*J{5P(jx>tT+qV=Jyg@g|7GI-5J3;t zG^7rH2esZE`d6C2+_(-)5Ik=co@tl71*=JviR=<+``Oswo9O6xbqNJKsye4+Zh@FK_ZUX4}Jb zGmooXVm=pSX0uD!hma4!Y*WRyBb!|k<>UJyvpiqyhisp;OS-Ll_jA8%sb`yAV)i3f zyF~IU*(K2iEag+OOL}jYxcH@T-s1QHEvdMiQ=|Heqg?z_^7D`5U{5Q1aBCKG19J7$ z9o9 z+XI8o1L=mw^1AfW`W5ML9UZhLbqUc6pD&u)o%&nzd1rIOy@v+vx#yLe+76t0wIy}U zm$w|Msd?9*etPN=*k!qoDud^k6q--Tk$hM$VB|P_#{BuNvYdSRnBJTGtSigf(cV6R uamr)c)~ypg@91RDTONE6+Wp|(VVtvq5GEO4z%9UKUU0_gBjfi@@csjeKFme{ literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCcChangeCursorLinear.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCcChangeCursorLinear.unity.meta new file mode 100644 index 0000000..e802144 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCcChangeCursorLinear.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 033171da8db1994499ead13b8ec05dc0 +timeCreated: 1477542088 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestClosestPoint.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestClosestPoint.unity new file mode 100644 index 0000000000000000000000000000000000000000..02c9992221af65ca3c169a41f22d5f39b55e1365 GIT binary patch literal 19729 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

QxSRu*chvOV82E*mz^hNdeC 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 the position on the curve by the distance from the start. + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcCursor")] + [ + CcDescriptor( + Description = "Identify location on the curve by distance.", + Name = "Cursor", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursor123.png") + ] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcCursor")] + public class BGCcCursor : BGCcWithMath + { + //=============================================================================================== + // Fields + //=============================================================================================== + + [SerializeField] [Tooltip("Distance from start of the curve.")] private float distance; + + /// Distance from the start + public float Distance + { + get { return distance; } + set + { + distance = Math.ClampDistance(value); + FireChangedParams(); + } + } + + /// Normalized distance from the start [Range(0,1)] + public float DistanceRatio + { + get { return Mathf.Clamp01(distance/Math.GetDistance()); } + set + { + distance = Math.GetDistance()*Mathf.Clamp01(value); + FireChangedParams(); + } + } + + public override bool SupportHandles + { + get { return true; } + } + + public override bool SupportHandlesSettings + { + get { return true; } + } + +#if UNITY_EDITOR + [Range(.5f, 1.5f)] [SerializeField] private float handlesScale = 1; + [SerializeField] private Color handlesColor = Color.white; + + public float HandlesScale + { + get { return handlesScale; } + set { handlesScale = value; } + } + + public Color HandlesColor + { + get { return handlesColor; } + set { handlesColor = value; } + } +#endif + + //=============================================================================================== + // Public functions + //=============================================================================================== + /// Calculates tangent by current distance + public Vector3 CalculateTangent() + { + return Math.CalcByDistance(BGCurveBaseMath.Field.Tangent, distance); + } + + /// Calculates position by current distance + public Vector3 CalculatePosition() + { + return Math.CalcByDistance(BGCurveBaseMath.Field.Position, distance); + } + + /// Calculates section's index by current distance + public int CalculateSectionIndex() + { + return Math.CalcSectionIndexByDistance(distance); + } + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + public override void Start() + { + //clamp + Distance = distance; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursor.cs.meta new file mode 100644 index 0000000..f82c3f3 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 924df4c68ad59e943b47b75f2323f73a +timeCreated: 1471831265 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorChangeLinear.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorChangeLinear.cs new file mode 100644 index 0000000..cc8712a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorChangeLinear.cs @@ -0,0 +1,551 @@ +using System; +using UnityEngine; +using UnityEngine.Events; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + /// Change cursor position linearly + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcCursorChangeLinear")] + [ + CcDescriptor( + Description = "Change cursor position linearly", + Name = "Cursor Change Linear", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorChangeLinear123.png") + ] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcCursorChangeLinear")] + + //idea.. refactor it.. the whole class looks like a nightmare + public class BGCcCursorChangeLinear : BGCcWithCursor + { + //=============================================================================================== + // Static & Enums + //=============================================================================================== + /// Speed, that is so small, that it can be ignored + public const float SpeedThreshold = 0.00001f; + + /// What to do, then cursor reaches first or last points + public enum OverflowControlEnum + { + /// Cycle in the same direction. For example, if it reaches the end point, start from the first point again + Cycle = 0, + + /// Change speed to -speed, and go in opposite direction + PingPong = 1, + + /// Stop + Stop = 2, + } + + //=============================================================================================== + // Events (Not persistent) + //=============================================================================================== + /// point was reached + public event EventHandler PointReached; + + //=============================================================================================== + // Fields (persistent) + //=============================================================================================== + + + [SerializeField] [Tooltip("Constant movement speed along the curve (Speed * Time.deltaTime)." + + "You can override this value for each point with speedField")] private float speed = 5; + + [SerializeField] [Tooltip("How to change speed, then curve's end reached.")] private OverflowControlEnum overflowControl; + + [SerializeField] [Tooltip("If curve's length changed, " + + "cursor position be adjusted with curve's length to ensure visually constant speed along the curve. ")] private bool adjustByTotalLength; + + [SerializeField] [Tooltip("Field to store the speed between each point. It should be a float field.")] private BGCurvePointField speedField; + + + [SerializeField] [Tooltip("Delay at each point. You can override this value for each point with delayField")] private float delay; + + [SerializeField] [Tooltip("Field to store the delays at points. It should be a float field.")] private BGCurvePointField delayField; + + [SerializeField] [Tooltip("Event is fired, then point is reached")] private PointReachedEvent pointReachedEvent = new PointReachedEvent(); + + + /// What to do, then cursor reaches first or last points + public OverflowControlEnum OverflowControl + { + get { return overflowControl; } + set + { + if (ParamChanged(ref overflowControl, value)) Stopped = false; + } + } + + /// Speed. It can be overriden for each point by SpeedField. The result speed is calculated as Speed * Time.deltaTime + public float Speed + { + get { return speed; } + set { ParamChanged(ref speed, value); } + } + + /// Should we adjust cursor position by the total length of the curve + public bool AdjustByTotalLength + { + get { return adjustByTotalLength; } + set { ParamChanged(ref adjustByTotalLength, value); } + } + + /// Custom field to get speed value. It should be a float field. If it's null, "Speed" property is used. The result speed is calculated as Speed * Time.deltaTime + public BGCurvePointField SpeedField + { + get { return speedField; } + set { ParamChanged(ref speedField, value); } + } + + /// Delay at each point. It can be overriden for each point by DelayField. + public float Delay + { + get { return delay; } + set { ParamChanged(ref delay, value); } + } + + /// Custom field to get delay value. It should be a float field. If it's null, "Delay" property is used. + public BGCurvePointField DelayField + { + get { return delayField; } + set { ParamChanged(ref delayField, value); } + } + + //=============================================================================================== + // Fields (Not persistent) + //=============================================================================================== + //curve's length at last calculation (only if adjustByTotalLength=true) + private float oldLength; + //is speed is reversed (if speed field is present) + private bool speedReversed; + //current section index (it's calculated only if it's required) + private int currentSectionIndex; + //delay started time + private float delayStarted = -1; + //if speed was positive while delay occured + private bool speedWasPositiveWhileDelayed; + //this is a part of overall nightmare, this class is. + private bool skipZeroPoint; + + + /// If it's stopped or moving + public bool Stopped { get; set; } + + /// If speed field is present and actual speed is reversed at the moment. It can be the case if PingPong is used. + public bool SpeedReversed + { + get { return speedReversed; } + } + + /// Speed at current cursor position + public float CurrentSpeed + { + get + { + if (Curve.PointsCount < 2) return 0; + + //no field + if (speedField == null) return speed; + + //by field + var speedAtPoint = Curve[Cursor.CalculateSectionIndex()].GetFloat(speedField.FieldName); + return speedReversed ? -speedAtPoint : speedAtPoint; + } + } + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + public override void Start() + { + oldLength = Cursor.Math.GetDistance(); + if (Application.isPlaying && Curve.PointsCount > 1 && (delay > 0 || delayField != null || pointReachedEvent.GetPersistentEventCount() > 0 || PointReached != null)) + currentSectionIndex = Cursor.Math.Math.CalcSectionIndexByDistance(Cursor.Distance); + } + + // Update is called once per frame + private void Update() + { + if (Stopped || (speedField == null && Mathf.Abs(speed) < SpeedThreshold)) return; + + var pointsCount = Curve.PointsCount; + if (pointsCount < 2) return; + + var cursor = Cursor; + var math = cursor.Math.Math; + var isPlaying = Application.isPlaying; + + //===================================================== cursor is delayed at point + if (isPlaying && delayStarted >= 0 && !CheckIfDelayIsOver(math, cursor)) return; + + //we are delayed so no need to process movement- return + if (delayStarted >= 0) return; + + + //===================================================== cursor is moving + //calculate adjustment if needed + var distance = cursor.Distance; + var newLength = 0f; + if (adjustByTotalLength) + { + newLength = math.GetDistance(); + if (Math.Abs(newLength) > BGCurve.Epsilon && Math.Abs(oldLength) > BGCurve.Epsilon && Math.Abs(newLength - oldLength) > BGCurve.Epsilon) distance = distance*newLength/oldLength; + } + + //-------------------------------- Check for new Delay + var newSectionIndex = -1; + + //check for new delays (and fire events) + var firingEvents = pointReachedEvent.GetPersistentEventCount() > 0 || PointReached != null; + var checkDelay = isPlaying && (delay > 0 || delayField != null); + if ((checkDelay || firingEvents) && CheckForNewDelay(math, distance, ref newSectionIndex, checkDelay, firingEvents)) return; + + //-------------------------------- calculate speed + var currentSpeed = speed; + if (speedField != null) + { + //we need to retrieve speed from a field value + if (newSectionIndex == -1) newSectionIndex = math.CalcSectionIndexByDistance(distance); + currentSpeed = Curve[newSectionIndex].GetFloat(speedField.FieldName); + if (speedReversed) currentSpeed = -currentSpeed; + } + + //-------------------------------- change distance + var newDistance = distance + currentSpeed*Time.deltaTime; + + + //-------------------------------- Check Overflows + if (newDistance < 0 || newDistance > math.GetDistance()) Overflow(math, ref newDistance, currentSpeed >= 0, checkDelay, firingEvents); + + //assign new value + cursor.Distance = newDistance; + oldLength = newLength; + } + + //=============================================================================================== + // Public functions + //=============================================================================================== + /// Delay at specified point + public float GetDelayAtPoint(int point) + { + return delayField == null ? delay : Curve[point].GetFloat(delayField.FieldName); + } + + /// Speed at specified point + public float GetSpeedAtPoint(int point) + { + return speedField == null ? speed : Curve[point].GetFloat(speedField.FieldName); + } + + //=============================================================================================== + // Private functions + //=============================================================================================== + //if delay required at given point + private bool IsDelayRequired(int pointIndex) + { + var hasDelayField = delayField != null; + return (!hasDelayField && delay > 0) || (hasDelayField && Curve[pointIndex].GetFloat(delayField.FieldName) > BGCurve.Epsilon); + } + + //start delay at current point + private void StartDelay(bool speedIsPositive) + { + delayStarted = Time.time; + speedWasPositiveWhileDelayed = speedIsPositive; + } + + //checks if cursor passed a point (current section is changed) and if new delay occured. Also fires events if needed + private bool CheckForNewDelay(BGCurveBaseMath math, float distance, ref int newSectionIndex, bool checkDelay, bool firingEvents) + { + if (currentSectionIndex == 0 && skipZeroPoint) return false; + if (!math.Curve.Closed && currentSectionIndex == math.Curve.PointsCount - 1) return false; + + newSectionIndex = math.CalcSectionIndexByDistance(distance); + if (currentSectionIndex != newSectionIndex) + { + //section is changed (there could be several points between) + + //if speed was positive or negative? + bool speedPositive; + if (speedField == null) speedPositive = speed > 0; + else + { + speedPositive = Curve[currentSectionIndex].GetFloat(speedField.FieldName) > 0; + if (speedReversed) speedPositive = !speedPositive; + } + + if (CheckDelayAtSectionChanged(newSectionIndex, checkDelay, firingEvents, speedPositive)) return true; + } + //no delay + delayStarted = -1; + + return false; + } + + //section is changed- check if delay required + private bool CheckDelayAtSectionChanged(int newSectionIndex, bool checkDelay, bool firingEvents, bool speedPositive) + { + var cursor = Cursor; + var math = cursor.Math.Math; + + var lastPointIndex = Curve.PointsCount - 1; + + //now we need to iterate all passed points + if (speedPositive) + { + //check for infinite loop (just in case) + if (newSectionIndex > currentSectionIndex) + { + for (var i = currentSectionIndex + 1; i <= newSectionIndex; i++) + { + if (firingEvents) FirePointReachedEvent(i); + + if (checkDelay && CheckDelayAtPoint(math, cursor, i, speedPositive)) return true; + } + } + } + else + { + //if speed is negative, the processing is slightly different + + if (currentSectionIndex == 0 && !Curve.Closed) currentSectionIndex = lastPointIndex; + + //check for infinite loop (just in case) + if (newSectionIndex < currentSectionIndex) + { + for (var i = currentSectionIndex; i > newSectionIndex; i--) + { + if (firingEvents) FirePointReachedEvent(i); + + if (checkDelay && CheckDelayAtPoint(math, cursor, i, speedPositive)) return true; + } + } + } + + currentSectionIndex = newSectionIndex; + return false; + } + + //points was passed and we check if delay is required at this point + private bool CheckDelayAtPoint(BGCurveBaseMath math, BGCcCursor cursor, int pointIndex, bool speedPositive) + { + if (IsDelayRequired(pointIndex)) + { + //we gotta delay at this point + currentSectionIndex = pointIndex; + //move cursor straight to the point + cursor.Distance = Curve.PointsCount - 1 == pointIndex && !Curve.Closed ? math.GetDistance() : math[pointIndex].DistanceFromStartToOrigin; + + // !!!!!!! start delay + StartDelay(speedPositive); + //we does not need to process movement (it will be ignored at any rate, cause we stick to the particular point) + return true; + } + return false; + } + + // overflow occurred + private void Overflow(BGCurveBaseMath math, ref float newDistance, bool currentSpeedPositive, bool checkDelay, bool firingEvents) + { + var lessThanZero = newDistance < 0; + var totalDistance = math.GetDistance(); + var lastPointIndex = Curve.PointsCount - 1; + + //we need to check delays. (all points up to boundary point) + if (checkDelay || firingEvents) + { + if (currentSpeedPositive) + { + //process all passed points +// var lastPointIndexToCheck = Curve.Closed ? lastPointIndex : lastPointIndex - 1; + var lastPointIndexToCheck = lastPointIndex; + if (currentSectionIndex != lastPointIndexToCheck) if (CheckDelayAtSectionChanged(lastPointIndexToCheck, checkDelay, firingEvents, true)) return; + } + else + { + if (currentSectionIndex > 0) + { + if (CheckDelayAtSectionChanged(0, checkDelay, firingEvents, false)) return; + } + + //this needs to be refactored + if (!skipZeroPoint) + { + if (checkDelay && CheckDelayAtPoint(math, Cursor, 0, false)) + { + if (firingEvents) FirePointReachedEvent(0); + skipZeroPoint = true; + return; + } + } + } + } + + + //overflow + switch (overflowControl) + { + case OverflowControlEnum.Stop: + newDistance = lessThanZero ? 0 : totalDistance; + Stopped = true; + break; + + case OverflowControlEnum.Cycle: + newDistance = lessThanZero ? totalDistance + newDistance : newDistance - totalDistance; + break; + + case OverflowControlEnum.PingPong: + if (speedField == null) speed = -speed; + speedReversed = !speedReversed; + currentSpeedPositive = !currentSpeedPositive; + newDistance = lessThanZero ? -newDistance : totalDistance*2 - newDistance; + break; + } + + if (newDistance < 0) newDistance = 0; + else if (newDistance > totalDistance) newDistance = totalDistance; + + + //ok, we need to check delays.. once again. (single boundary point) + if (checkDelay || firingEvents) + { + if (Curve.Closed) + { + if (skipZeroPoint) + { + skipZeroPoint = false; + } + else + { + if (firingEvents) FirePointReachedEvent(0); + + currentSectionIndex = currentSpeedPositive ? 0 : lastPointIndex; + + if (checkDelay && CheckDelayAtPoint(math, Cursor, 0, currentSpeedPositive)) return; + } + } + else + { + if (lessThanZero) + { + //original speed was negative + if (skipZeroPoint) + { + skipZeroPoint = false; + } + else + { + currentSectionIndex = 0; + if (firingEvents) FirePointReachedEvent(0); + if (checkDelay && CheckDelayAtPoint(math, Cursor, 0, currentSpeedPositive)) return; + } + } + else + { + //original speed was positive + if (!Curve.Closed) + { + if (currentSpeedPositive) + { + //last->first + currentSectionIndex = 0; + if (firingEvents) FirePointReachedEvent(0); + if (checkDelay && CheckDelayAtPoint(math, Cursor, 0, currentSpeedPositive)) return; + } + else + { + //last->last (pingpong) + currentSectionIndex = lastPointIndex - 1; + } + } + } + } + } + } + + //check if delay is over + private bool CheckIfDelayIsOver(BGCurveBaseMath math, BGCcCursor cursor) + { + var pointsCountMinusOne = Curve.PointsCount - 1; + + if (adjustByTotalLength) oldLength = math.GetDistance(); + + //curve is not closed and delayed at last point + var delayAtLastPoint = !Curve.Closed && currentSectionIndex == pointsCountMinusOne; + + //curve may be changing, so we need to adjust a position anyway + cursor.Distance = delayAtLastPoint ? math.GetDistance() : math[currentSectionIndex].DistanceFromStartToOrigin; + var delayValue = GetDelayAtPoint(currentSectionIndex); + + // we are still delayed + if (!(Time.time - delayStarted > delayValue)) return false; + + + // delay is over, start moving + delayStarted = -1; + if (speedWasPositiveWhileDelayed) + { + // if (delayAtLastPoint) cursor.Distance = 0; + // else cursor.Distance += BGCurve.Epsilon; + cursor.Distance += BGCurve.Epsilon; + } + else + { + if (currentSectionIndex > 0) + { + currentSectionIndex--; + cursor.Distance -= BGCurve.Epsilon; + } + else + { + if (!skipZeroPoint) + { + currentSectionIndex = pointsCountMinusOne; + cursor.Distance = math.GetDistance() - BGCurve.Epsilon; + } + } + } + return true; + } + + //fire "point is reached" event + private void FirePointReachedEvent(int pointIndex) + { + if (PointReached != null) PointReached(this, PointReachedArgs.GetInstance(pointIndex)); + + //probably we could skip pointPassed.GetPersistentEventCount() check + if (pointReachedEvent.GetPersistentEventCount() > 0) pointReachedEvent.Invoke(pointIndex); + } + + //=============================================================================================== + // Unity Persistent event + //=============================================================================================== + /// Fired when cursor reaches a point + [Serializable] + public class PointReachedEvent : UnityEvent + { + } + + //=============================================================================================== + // C# not persistent event + //=============================================================================================== + /// Fired when cursor reaches a point + public class PointReachedArgs : EventArgs + { + private static readonly PointReachedArgs Instance = new PointReachedArgs(); + + //point's index + public int PointIndex { get; private set; } + + private PointReachedArgs() + { + } + + public static PointReachedArgs GetInstance(int index) + { + Instance.PointIndex = index; + return Instance; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorChangeLinear.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorChangeLinear.cs.meta new file mode 100644 index 0000000..adabe67 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorChangeLinear.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 535a3a5d00075854a98f71fdd486b248 +timeCreated: 1472620386 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectRotate.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectRotate.cs new file mode 100644 index 0000000..95d60f7 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectRotate.cs @@ -0,0 +1,387 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + /// + /// Rotates an object. + /// if no rotation field is defined, object rotation is based on the curve's tangent at current Cursor position. + /// If rotation field is used, 2 rotation values, taken from boundary points, are lerped by current Cursor position. + /// + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcCursorObjectRotate")] + [ + CcDescriptor( + Description = "Align the object's rotation with curve's tangent or 'rotation' field values at the point, the Cursor provides.", + Name = "Rotate Object By Cursor", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectRotate123.png") + ] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcRotateObject")] + [ExecuteInEditMode] + public class BGCcCursorObjectRotate : BGCcWithCursorObject + { + //=============================================================================================== + // Enums + //=============================================================================================== + /// Rotation interpolation between current rotation and target rotation + public enum RotationInterpolationEnum + { + None = 0, + Lerp = 1, + Slerp = 2, + } + + /// Up direction for target rotation. It's used only if rotationField is not assigned. + public enum RotationUpEnum + { + WorldUp = 0, + WorldCustom = 1, + + LocalUp = 2, + LocalCustom = 3, + + TargetParentUp = 4, + TargetParentUpCustom = 5, + } + + //=============================================================================================== + // Events + //=============================================================================================== + + /// object was rotated + public event EventHandler ChangedObjectRotation; + + + //=============================================================================================== + // Fields (persistent) + //=============================================================================================== + + //============================================= Common + [SerializeField] [Tooltip("Rotation interpolation mode.")] private RotationInterpolationEnum rotationInterpolation; + + [SerializeField] [Tooltip("Rotation Lerp rotationSpeed. (Quaternion.Lerp(from,to, lerpSpeed * Time.deltaTime)) ")] private float lerpSpeed = 5; + + [SerializeField] [Tooltip("Rotation Slerp rotationSpeed. (Quaternion.Slerp(from,to, slerpSpeed * Time.deltaTime)) ")] private float slerpSpeed = 5; + + [SerializeField] [Tooltip("Angle to add to final result.")] private Vector3 offsetAngle; + + //============================================= Tangent rotation + [SerializeField] [Tooltip("Up mode for tangent Quaternion.LookRotation. It's used only if rotationField is not assigned." + + "\r\n1) WorldUp - use Vector.up in world coordinates" + + "\r\n2) WorldCustom - use custom Vector in world coordinates" + + "\r\n3) LocalUp - use Vector.up in local coordinates " + + "\r\n4) LocalCustom - use custom Vector in local coordinates" + + "\r\n5) TargetParentUp - use Vector.up in target object parent's local coordinates" + + "\r\n6) TargetParentUpCustom- use custom Vector in target object parent's local coordinates" + )] private RotationUpEnum upMode = RotationUpEnum.WorldUp; + + [SerializeField] [Tooltip("Custom Up vector for tangent Quaternion.LookRotation. It's used only if rotationField is not assigned.")] private Vector3 upCustom = Vector3.up; + + //============================================= By field rotation + [SerializeField] [Tooltip("Field to store the rotation between each point. It should be a Quaternion field.")] private BGCurvePointField rotationField; + + [SerializeField] [Tooltip("Additional 360 degree revolutions around tangent. It's used only if rotationField is assigned. " + + "It can be overriden with 'int' revolutionsAroundTangentField field.")] private int revolutionsAroundTangent; + + [SerializeField] [Tooltip("Field to store additional 360 degree revolutions around tangent for each point. It's used only if rotationField is assigned. " + + "It should be an int field.")] private BGCurvePointField revolutionsAroundTangentField; + + [SerializeField] [Tooltip("By default revolutions around tangent is counter-clockwise. Set it to true to reverse direction. It's used only if rotationField is assigned." + + "It can be overriden with bool field")] private bool revolutionsClockwise; + + [SerializeField] [Tooltip("Field to store direction for revolutions around tangent. It should be an bool field. It's used only if rotationField is assigned.")] private BGCurvePointField + revolutionsClockwiseField; + + + /// Rotation interpolation between current rotation and target rotation + public RotationInterpolationEnum RotationInterpolation + { + get { return rotationInterpolation; } + set { ParamChanged(ref rotationInterpolation, value); } + } + + /// Rotation speed for Lerp rotation interpolation + public float LerpSpeed + { + get { return lerpSpeed; } + set { ParamChanged(ref lerpSpeed, value); } + } + + /// Rotation speed for Slerp rotation interpolation + public float SlerpSpeed + { + get { return slerpSpeed; } + set { ParamChanged(ref slerpSpeed, value); } + } + + /// Custom Up Vector(direction) for target rotaion + public Vector3 UpCustom + { + get { return upCustom; } + set { ParamChanged(ref upCustom, value); } + } + + /// Up mode for tangent rotation. It's used only if rotationField is not assigned. + public RotationUpEnum UpMode + { + get { return upMode; } + set { ParamChanged(ref upMode, value); } + } + + /// Rotation field to get rotation values from. It should be a Quaternion field + public BGCurvePointField RotationField + { + get { return rotationField; } + set { ParamChanged(ref rotationField, value); } + } + + /// Field for a number of full turnovers around tangent. It's used only if rotationField is assigned. It should be an int field + public BGCurvePointField RevolutionsAroundTangentField + { + get { return revolutionsAroundTangentField; } + set { ParamChanged(ref revolutionsAroundTangentField, value); } + } + + /// Number of full turnovers around tangent for each section.It's used only if rotationField is assigned. It can be overriden with RevolutionsAroundTangentField + public int RevolutionsAroundTangent + { + get { return revolutionsAroundTangent; } + set { ParamChanged(ref revolutionsAroundTangent, value); } + } + + /// Field for identifying if RevolutionsAroundTangent should be clockwise or counter clockwise.It's used only if rotationField is assigned. It should be an bool field + public BGCurvePointField RevolutionsClockwiseField + { + get { return revolutionsClockwiseField; } + set { ParamChanged(ref revolutionsClockwiseField, value); } + } + + /// Should RevolutionsAroundTangent be clockwise or counter clockwise. It's used only if rotationField is assigned. It can be overriden by RevolutionsClockwiseField + public bool RevolutionsClockwise + { + get { return revolutionsClockwise; } + set { ParamChanged(ref revolutionsClockwise, value); } + } + + /// offset to apply to final rotation + public Vector3 OffsetAngle + { + get { return offsetAngle; } + set { ParamChanged(ref offsetAngle, value); } + } + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + public override string Error + { + get + { + return ChoseMessage(base.Error, + () => + { + if (!Cursor.Math.IsCalculated(BGCurveBaseMath.Field.Tangent)) + { + if (rotationField == null) return "Math should calculate tangents if rotation field is null."; + + if (RevolutionsAroundTangent != 0 || RevolutionsAroundTangentField != null) return "Math should calculate tangents if revolutions are used."; + } + + return null; + }); + } + } + + public override string Warning + { + get + { + return rotationField == null && (upMode == RotationUpEnum.TargetParentUp || upMode == RotationUpEnum.TargetParentUpCustom) + && ObjectToManipulate != null && ObjectToManipulate.parent == null + ? "Up Mode is set to " + upMode + ", however object's parent is null" + : null; + } + } + + public override bool SupportHandles + { + get { return true; } + } + + public override bool SupportHandlesSettings + { + get { return true; } + } + +#if UNITY_EDITOR + [Range(.5f, 1.5f)] [SerializeField] private float handlesScale = 1; + [SerializeField] private Color handlesColor = Color.white; + + public float HandlesScale + { + get { return handlesScale; } + set { handlesScale = value; } + } + + public Color HandlesColor + { + get { return handlesColor; } + set { handlesColor = value; } + } +#endif + + //=============================================================================================== + // Fields (Not persistent) + //=============================================================================================== + //latest successfull rotation that was used + private Quaternion rotation = Quaternion.identity; + + /// latest successfull rotation that was used + public Quaternion Rotation + { + get { return rotation; } + } + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + // Update is called once per frame + private void Update() + { + if (Curve.PointsCount == 0) return; + + var targetTransform = ObjectToManipulate; + if (targetTransform == null) return; + + if (!TryToCalculateRotation(ref rotation)) return; + + targetTransform.rotation = rotation; + + if (ChangedObjectRotation != null) ChangedObjectRotation(this, null); + } + + //=============================================================================================== + // Public Functions + //=============================================================================================== + /// Try to calculate target rotation at current Cursor positon + /// true if result was actually calculated and changed, false if calculation is failed + public bool TryToCalculateRotation(ref Quaternion result) + { + var pointsCount = Curve.PointsCount; + if (pointsCount == 0) return false; + + var cursor = Cursor; + var math = cursor.Math; + + if (rotationField == null) + { + // =============================================== By tangent + if (math == null || !math.IsCalculated(BGCurveBaseMath.Field.Tangent)) return false; + + if (pointsCount == 1) result = Quaternion.identity; + else + { + var tangent = cursor.CalculateTangent(); + if (Vector3.SqrMagnitude(tangent) < 0.01) return false; + + // up vector + Vector3 upwards; + switch (upMode) + { + case RotationUpEnum.WorldUp: + upwards = Vector3.up; + break; + case RotationUpEnum.WorldCustom: + upwards = upCustom; + break; + case RotationUpEnum.LocalUp: + upwards = transform.InverseTransformDirection(Vector3.up); + break; + case RotationUpEnum.LocalCustom: + upwards = transform.InverseTransformDirection(upCustom); + break; + default: + //TargetParentUp or TargetParentUpCustom + var targetTransform = ObjectToManipulate; + if (targetTransform.parent != null) + { + upwards = targetTransform.parent.InverseTransformDirection(upMode == RotationUpEnum.TargetParentUp ? Vector3.up : upCustom); + } + else + { + upwards = upMode == RotationUpEnum.TargetParentUp ? Vector3.up : upCustom; + } + break; + } + result = Quaternion.LookRotation(tangent, upwards); + } + } + else + { + // =============================================== By field + if (pointsCount == 1) result = Curve[0].GetQuaternion(rotationField.FieldName); + else + { + if (revolutionsAroundTangentField == null && revolutionsAroundTangent == 0) result = LerpQuaternion(rotationField.FieldName); //no compications + else + { + // there is possible revolutions involved- we need to check field if it exists + + //we need currentSection only if field is present + var currentSection = revolutionsAroundTangentField != null || revolutionsClockwiseField != null ? cursor.CalculateSectionIndex() : -1; + //rotaion without revolutoins + result = LerpQuaternion(rotationField.FieldName, currentSection); + + //do we have revolutions? + var additionalRevolutions = Mathf.Clamp( + revolutionsAroundTangentField != null + ? Curve[currentSection].GetInt(revolutionsAroundTangentField.FieldName) + : revolutionsAroundTangent + , 0, int.MaxValue); + + if (additionalRevolutions > 0 && math.IsCalculated(BGCurveBaseMath.Field.Tangent)) + { + //additional rotation around tangent is needed + var tangent = cursor.CalculateTangent(); + + if (Vector3.SqrMagnitude(tangent) > 0.01) + { + // targetAngle- target angle at t=1 + var targetAngle = 360*additionalRevolutions; + + //change if Clockwise + if (revolutionsClockwiseField != null ? Curve[currentSection].GetBool(revolutionsClockwiseField.FieldName) : revolutionsClockwise) targetAngle = -targetAngle; + + //calculate t ratio for lerping. 0- at start (from point), 1= at the end (to point) + int indexFrom, indexTo; + var t = GetT(out indexFrom, out indexTo, currentSection); + var angle = Mathf.Lerp(0, targetAngle, t); + + //sum up rotaitons + result = result*Quaternion.AngleAxis(angle, tangent); + } + } + } + } + } + + + // sum up rotations + result *= Quaternion.Euler(offsetAngle); + + // interpolation (rotation speed) + switch (rotationInterpolation) + { + case RotationInterpolationEnum.Lerp: + result = Quaternion.Lerp(ObjectToManipulate.rotation, rotation, lerpSpeed*Time.deltaTime); + break; + case RotationInterpolationEnum.Slerp: + result = Quaternion.Slerp(ObjectToManipulate.rotation, rotation, slerpSpeed*Time.deltaTime); + break; + } + + //success + return true; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectRotate.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectRotate.cs.meta new file mode 100644 index 0000000..8223ffa --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectRotate.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 23f6c63f13e40be449a87a9114fb11ff +timeCreated: 1471833132 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectScale.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectScale.cs new file mode 100644 index 0000000..6ab75a6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectScale.cs @@ -0,0 +1,74 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + /// Scale an object according to the cursor's position. Scale values are taken from a curve's Vector3 field + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcCursorObjectScale")] + [ + CcDescriptor( + Description = "Scale the object, according to cursor position. Scale values are taken from curve's field values.", + Name = "Scale Object By Cursor", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectScale123.png") + ] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcScaleObject")] + [ExecuteInEditMode] + public class BGCcCursorObjectScale : BGCcWithCursorObject + { + //=============================================================================================== + // Events + //=============================================================================================== + /// object was scaled + public event EventHandler ObjectScaled; + + //=============================================================================================== + // Fields(Persistent) + //=============================================================================================== + + [SerializeField] [Tooltip("Field to store the scale value at points. It should be a Vector3 field.")] private BGCurvePointField scaleField; + + public BGCurvePointField ScaleField + { + get { return scaleField; } + set { ParamChanged(ref scaleField, value); } + } + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + public override string Error + { + get { return ChoseMessage(base.Error, () => scaleField == null ? "Scale field is not defined." : null); } + } + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + + // Update is called once per frame + private void Update() + { + if (ObjectToManipulate == null || scaleField == null) return; + + var pointsCount = Curve.PointsCount; + + switch (pointsCount) + { + case 0: + return; + case 1: + ObjectToManipulate.localScale = Curve[0].GetVector3(scaleField.FieldName); + break; + default: + var result = LerpVector(scaleField.FieldName); + if (float.IsNaN(result.x) || float.IsNaN(result.y) || float.IsNaN(result.z)) return; + + ObjectToManipulate.localScale = result; + + if (ObjectScaled != null) ObjectScaled(this, null); + break; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectScale.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectScale.cs.meta new file mode 100644 index 0000000..458366f --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectScale.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f7dfbbb5e66f759498113fb337587365 +timeCreated: 1476113428 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectTranslate.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectTranslate.cs new file mode 100644 index 0000000..0398864 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectTranslate.cs @@ -0,0 +1,54 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Components +{ + /// Moves an object to cursor's position + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcCursorObjectTranslate")] + [ + CcDescriptor( + Description = "Translate an object to the position, the cursor provides.", + Name = "Translate Object By Cursor", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectTranslate123.png") + ] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcTranslateObject")] + [ExecuteInEditMode] + public class BGCcCursorObjectTranslate : BGCcWithCursorObject + { + //=============================================================================================== + // Events + //=============================================================================================== + /// object was moved + public event EventHandler ObjectTranslated; + + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + // Update is called once per frame + private void Update() + { + var transformToMove = ObjectToManipulate; + + if (transformToMove == null) return; + + var pointsCount = Curve.PointsCount; + + switch (pointsCount) + { + case 0: + return; + case 1: + transformToMove.position = Curve[0].PositionWorld; + break; + default: + + transformToMove.position = Cursor.CalculatePosition(); + + if (ObjectTranslated != null) ObjectTranslated(this, null); + + break; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectTranslate.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectTranslate.cs.meta new file mode 100644 index 0000000..b4e0a89 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursorObjectTranslate.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9d916ef28168e544d9dc5bb790f67ba0 +timeCreated: 1471733597 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs new file mode 100644 index 0000000..e4f71fd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs @@ -0,0 +1,696 @@ +using System; +using System.Collections; +using UnityEngine; +using UnityEngine.Events; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + /// Math solver for the curve. + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcMath")] + [DisallowMultipleComponent] + [ + CcDescriptor( + Description = "Math solver for the curve (position, tangent, total distance, position by closest point). With this component you can use math functions.", + Name = "Math", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcMath123.png") + ] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcMath")] + public class BGCcMath : BGCc, BGCurveMathI + { + //=============================================================================================== + // Static + //=============================================================================================== + // maximum parts for Base math sectionParts parameter + private const int PartsMax = 100; + //reusable empty vertices array + private static readonly Vector3[] EmptyVertices = new Vector3[0]; + + //=============================================================================================== + // Enums + //=============================================================================================== + /// Type of approximation + public enum MathTypeEnum + { + /// Every spline's section will be split to even parts + Base, + + /// Every spline's section will be split to uneven parts, based on the spline's curvature + Adaptive + } + + /// How math should be updated + public enum UpdateModeEnum + { + /// Always update math then spline is changed + Always = 0, + + /// Update math only if Axis Aligned Bounding Box for the spline is visible + AabbVisible = 1, + + /// Update math only if some renderer is visible + RendererVisible = 2, + } + + //=============================================================================================== + // Events (Not persistent) + //=============================================================================================== + + /// if underlying math is recalculated + public event EventHandler ChangedMath; + + + //=============================================================================================== + // Fields (Persistent) + //=============================================================================================== + + //=========================================================== Fields to calculate + [SerializeField] [Tooltip("Which fields you want to use.")] private BGCurveBaseMath.Fields fields = BGCurveBaseMath.Fields.Position; + + + //=========================================================== Math type + [SerializeField] [Tooltip("Math type to use.\r\n" + + "Base - uses uniformely split sections;\r\n " + + "Adaptive - uses non-uniformely split sections, based on the curvature. Expiremental.")] private MathTypeEnum mathType; + + + //=========================================================== Base + + [SerializeField] [Tooltip("The number of equal parts for each section, used by Base math.")] [Range(1, PartsMax)] private int sectionParts = 30; + + [SerializeField] [Tooltip("Use only 2 points for straight lines. Tangents may be calculated slightly different. Used by Base math.")] private bool optimizeStraightLines; + + //=========================================================== Adaptive + [SerializeField] [Tooltip("Tolerance, used by Adaptive Math. The bigger the tolerance- the lesser splits. " + + "Note: The final tolerance used by Math is based on this value but different.")] [Range(BGCurveAdaptiveMath.MinTolerance, BGCurveAdaptiveMath.MaxTolerance)] private + float tolerance = .2f; + + //=========================================================== Common + [SerializeField] [Tooltip("Points position will be used for tangent calculation. This can gain some performance")] private bool usePositionToCalculateTangents; + + + //=========================================================== Update modes + [SerializeField] [Tooltip("Updating math takes some resources. You can fine-tune in which cases math is updated." + + "\r\n1) Always- always update" + + "\r\n2) AabbVisible- update only if AABB (Axis Aligned Bounding Box) around points and controls is visible" + + "\r\n3) RendererVisible- update only if some renderer is visible" + )] private UpdateModeEnum updateMode; + + [SerializeField] [Tooltip("Renderer to check for updating math. Math will be updated only if renderer is visible")] private Renderer rendererForUpdateCheck; + + //=========================================================== Persistent Event + [SerializeField] [Tooltip("Event is fired, then math is recalculated")] private MathChangedEvent mathChangedEvent = new MathChangedEvent(); + + + //--------------------------------------------------------------------------------------------- + + + /// Underlying math type + public MathTypeEnum MathType + { + get { return mathType; } + set { ParamChanged(ref mathType, value); } + } + + //=========================================================== Base + /// How many parts to use for splitting every spline's section for Base Math + public int SectionParts + { + get { return Mathf.Clamp(sectionParts, 1, PartsMax); } + set { ParamChanged(ref sectionParts, Mathf.Clamp(value, 1, PartsMax)); } + } + + /// Should we use 2 points for straight lines or should we split it to sectionParts. Used by Base math. + public bool OptimizeStraightLines + { + get { return optimizeStraightLines; } + set { ParamChanged(ref optimizeStraightLines, value); } + } + + //=========================================================== Adaptive + /// Tolerance parameter for Adaptive math. Note, the final value math uses is based on it but differs + public float Tolerance + { + get { return tolerance; } + set { ParamChanged(ref tolerance, value); } + } + + + //=========================================================== Common + /// Which fields to calculate + public BGCurveBaseMath.Fields Fields + { + get { return fields; } + set { ParamChanged(ref fields, value); } + } + + + public bool UsePositionToCalculateTangents + { + get { return usePositionToCalculateTangents; } + set { ParamChanged(ref usePositionToCalculateTangents, value); } + } + + + public UpdateModeEnum UpdateMode + { + get { return updateMode; } + set { ParamChanged(ref updateMode, value); } + } + + public Renderer RendererForUpdateCheck + { + get { return rendererForUpdateCheck; } + set { ParamChanged(ref rendererForUpdateCheck, value); } + } + + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + public override string Error + { + get + { + return updateMode == UpdateModeEnum.RendererVisible && RendererForUpdateCheck == null + ? "Update mode is set to " + updateMode + ", however the RendererForUpdateCheck is null" + : null; + } + } + + public override string Warning + { + get + { + if (Curve.SnapType == BGCurve.SnapTypeEnum.Curve && Fields == BGCurveBaseMath.Fields.PositionAndTangent && !UsePositionToCalculateTangents) + return "Your curve's snap mode is Curve, and you are calculating tangents. However you use formula for tangents, instead of points positions." + + "This may result in wrong tangents. Set UsePositionToCalculateTangents to true."; + return null; + } + } + + public override string Info + { + get { return Math == null ? null : "Math uses " + Math.PointsCount + " points"; } + } + + public override bool SupportHandles + { + get { return true; } + } + + public override bool SupportHandlesSettings + { + get { return true; } + } + +#if UNITY_EDITOR + [Range(.5f, 1.5f)] [Tooltip("Spheres scale")] [SerializeField] private float spheresScale = 1; + [SerializeField] [Tooltip("Spheres color")] private Color spheresColor = Color.white; + [Range(2, 100)] [Tooltip("Maximum number of spheres. This parameter only affects how much points are shown in the Editor")] [SerializeField] private int spheresCount = 100; + + public float SpheresScale + { + get { return spheresScale; } + set { spheresScale = value; } + } + + public Color SpheresColor + { + get { return spheresColor; } + set { spheresColor = value; } + } + + public int SpheresCount + { + get { return spheresCount; } + set { spheresCount = value; } + } +#endif + + //=============================================================================================== + // Fields (Not persistent) + //=============================================================================================== + // underlying math solver. + private BGCurveBaseMath math; + + // visibility checking Component. It uses standard Unity callbacks method to trace attached renderer visibility (AabbVisible and RendererVisible modes) + private VisibilityCheck visibilityCheck; + + // Mesh filter for generated mesh with 2 points for visibility check (AabbVisible mode) + private MeshFilter meshFilter; + // Reusable array for 2 points for visibility check (AabbVisible mode) + private readonly Vector3[] vertices = new Vector3[2]; + + /// Underlying math solver. You should not cache it, unless you are sure, mathType can not be changed at runtime. + public BGCurveBaseMath Math + { + get + { + if (math == null) InitMath(null, null); + return math; + } + } + + //is new math object is required? + private bool NewMathRequired + { + get + { + return math == null + || (mathType == MathTypeEnum.Base && math.GetType() != typeof(BGCurveBaseMath)) + || (mathType == MathTypeEnum.Adaptive && math.GetType() != typeof(BGCurveAdaptiveMath)); + } + } + + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + public override void Start() + { + Curve.Changed += SendEventsIfMathIsNotCreated; + } + + public override void OnDestroy() + { + if (math != null) + { + math.Changed -= MathWasChanged; + math.ChangeRequested -= MathOnChangeRequested; + math.Dispose(); + } + ChangedParams -= InitMath; + } + + //=============================================================================================== + // Public Functions + //=============================================================================================== + + /// By default math is created only if it's required. Call this method to ensure math is created + public void EnsureMathIsCreated() + { +#pragma warning disable 0168 + //ensure math exists + var temp = Math; +#pragma warning restore 0168 + } + + /// Recalculate internal caches. this is a costly operation + /// Ignore all checks and force recalculation at any rate + public void Recalculate(bool force = false) + { + Math.Recalculate(force); + } + + + //================================ Misc + /// Is given field is calculated? + public bool IsCalculated(BGCurveBaseMath.Field field) + { + var math = Math; + return math != null && math.IsCalculated(field); + } + + /// Clamp distance to valid range + public float ClampDistance(float distance) + { + var math = Math; + return distance < 0 ? 0 : (distance > math.GetDistance() ? math.GetDistance() : distance); + } + + + //================================ Total Distance + //see interface for comments + public float GetDistance() + { + return Math.GetDistance(); + } + + + //================================ Calc by ratio + //see interface for comments + public Vector3 CalcByDistanceRatio(BGCurveBaseMath.Field field, float ratio, bool useLocal = false) + { + return Math.CalcByDistanceRatio(field, ratio, useLocal); + } + + //see interface for comments + public Vector3 CalcByDistanceRatio(float distanceRatio, out Vector3 tangent, bool useLocal = false) + { + return Math.CalcByDistanceRatio(distanceRatio, out tangent, useLocal); + } + + //see interface for comments + public Vector3 CalcPositionByDistanceRatio(float ratio, bool useLocal = false) + { + return Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, ratio, useLocal); + } + + //see interface for comments + public Vector3 CalcTangentByDistanceRatio(float ratio, bool useLocal = false) + { + return Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Tangent, ratio, useLocal); + } + + //see interface for comments + public Vector3 CalcPositionAndTangentByDistanceRatio(float distanceRatio, out Vector3 tangent, bool useLocal = false) + { + return Math.CalcPositionAndTangentByDistanceRatio(distanceRatio, out tangent, useLocal); + } + + //================================ Calc by distance + //see interface for comments + public Vector3 CalcByDistance(BGCurveBaseMath.Field field, float distance, bool useLocal = false) + { + return Math.CalcByDistance(field, distance, useLocal); + } + + //see interface for comments + public Vector3 CalcByDistance(float distance, out Vector3 tangent, bool useLocal = false) + { + return Math.CalcByDistance(distance, out tangent, useLocal); + } + + //see interface for comments + public Vector3 CalcPositionByDistance(float distance, bool useLocal = false) + { + return Math.CalcByDistance(BGCurveBaseMath.Field.Position, distance, useLocal); + } + + //see interface for comments + public Vector3 CalcTangentByDistance(float distance, bool useLocal = false) + { + return Math.CalcByDistance(BGCurveBaseMath.Field.Tangent, distance, useLocal); + } + + //see interface for comments + public Vector3 CalcPositionAndTangentByDistance(float distance, out Vector3 tangent, bool useLocal = false) + { + return Math.CalcPositionAndTangentByDistance(distance, out tangent, useLocal); + } + + /// Access calculated section's data by index + public BGCurveBaseMath.SectionInfo this[int i] + { + get { return Math[i]; } + } + + + //================================ Calc by closest point + //see interface for comments + public Vector3 CalcPositionByClosestPoint(Vector3 point, out float distance, out Vector3 tangent, bool skipSectionsOptimization = false, bool skipPointsOptimization = false) + { + return Math.CalcPositionByClosestPoint(point, out distance, out tangent, skipSectionsOptimization, skipPointsOptimization); + } + + //see interface for comments + public Vector3 CalcPositionByClosestPoint(Vector3 point, out float distance, bool skipSectionsOptimization = false, bool skipPointsOptimization = false) + { + return Math.CalcPositionByClosestPoint(point, out distance, skipSectionsOptimization, skipPointsOptimization); + } + + //see interface for comments + public Vector3 CalcPositionByClosestPoint(Vector3 point, bool skipSectionsOptimization = false, bool skipPointsOptimization = false) + { + return Math.CalcPositionByClosestPoint(point, skipSectionsOptimization, skipPointsOptimization); + } + + //================================ Calc section index + //see interface for comments + public int CalcSectionIndexByDistance(float distance) + { + return Math.CalcSectionIndexByDistance(distance); + } + + //see interface for comments + public int CalcSectionIndexByDistanceRatio(float distanceRatio) + { + return Math.CalcSectionIndexByDistanceRatio(distanceRatio); + } + + + //=============================================================================================== + // Private Functions + //=============================================================================================== + //we do not have to create a math implementation until it's needed, but we have to trace spline's changes and fire events + private void SendEventsIfMathIsNotCreated(object sender, BGCurveChangedArgs e) + { + //no more need to trace changes, since math is tracing it by itself + if (math != null) Curve.Changed -= SendEventsIfMathIsNotCreated; + //implementation is not created yet, but we need to fire events to indicate math 'would be' changed if it is created + else MathWasChanged(sender, e); + } + + //init math with current params + private void InitMath(object sender, EventArgs e) + { + //new config + var config = mathType == MathTypeEnum.Adaptive + ? new BGCurveAdaptiveMath.ConfigAdaptive(fields) {Tolerance = tolerance} + : new BGCurveBaseMath.Config(fields) {Parts = sectionParts}; + + config.UsePointPositionsToCalcTangents = usePositionToCalculateTangents; + config.OptimizeStraightLines = optimizeStraightLines; + config.Fields = fields; + + if (updateMode != UpdateModeEnum.Always && Application.isPlaying) + { + switch (updateMode) + { + case UpdateModeEnum.AabbVisible: + InitAabbVisibleBefore(config); + break; + case UpdateModeEnum.RendererVisible: + InitRendererVisible(config); + break; + } + } + + if (NewMathRequired) + { + //we need to create new math object + + var mathWasNull = math == null; + + if (mathWasNull) ChangedParams += InitMath; + else + { + math.ChangeRequested -= MathOnChangeRequested; + math.Changed -= MathWasChanged; + math.Dispose(); + } + + switch (MathType) + { + case MathTypeEnum.Base: + math = new BGCurveBaseMath(Curve, config); + break; + default: + // case MathTypeEnum.Adaptive: + math = new BGCurveAdaptiveMath(Curve, (BGCurveAdaptiveMath.ConfigAdaptive) config); + break; + } + + + math.Changed += MathWasChanged; + + if (!mathWasNull) MathWasChanged(this, null); + } + else + { + //we can reuse existing math object + + math.ChangeRequested -= MathOnChangeRequested; + //reinit math with new params (it will be recalculated as result) + math.Init(config); + } + + //init AABB + if (updateMode == UpdateModeEnum.AabbVisible) InitAabbVisibleAfter(); + } + + //before math was created (or inited) + private void InitAabbVisibleBefore(BGCurveBaseMath.Config config) + { + if (!Application.isPlaying) return; + + if (meshFilter != null) Destroy(meshFilter.gameObject); + + var aabbGameObject = new GameObject("AabbBox"); + aabbGameObject.transform.parent = transform; + var renderer = aabbGameObject.AddComponent(); + meshFilter = aabbGameObject.AddComponent(); + meshFilter.mesh = new Mesh(); + InitVisibilityCheck(config, renderer); + + MathOnChangeRequested(this, null); + } + + //after math was created (or inited) + private void InitAabbVisibleAfter() + { + if (!Application.isPlaying) return; + + math.ChangeRequested += MathOnChangeRequested; + } + + //math received change request (but not changed yet). This callback is called only if updateMode=UpdateModeEnum.AabbVisible + private void MathOnChangeRequested(object sender, EventArgs eventArgs) + { + if (!Application.isPlaying) return; + + // if visibilityCheck is not inited or the mesh is already visible, we dont need to recalculate the mesh + if (visibilityCheck == null || visibilityCheck.Visible) return; + + // here we should construct a mesh with 2 points (min to max), so Unity calls its OnBecameVisible OnBecameInvisible callbacks + // I'm not sure how fast it is, but it (probably) should be faster than calculating it manually without this mesh + var points = Curve.Points; + var mesh = meshFilter.sharedMesh; + + switch (points.Length) + { + case 0: + mesh.vertices = EmptyVertices; + break; + case 1: + vertices[0] = points[0].PositionWorld; + vertices[1] = vertices[0]; + mesh.vertices = vertices; + break; + default: + var matrix = transform.localToWorldMatrix; + var firstPoint = points[0].PositionWorld; + var pointsCount = points.Length; + var lastPointIndex = pointsCount - 1; + var closed = Curve.Closed; + + var min = firstPoint; + var max = firstPoint; + for (var i = 0; i < pointsCount; i++) + { + var point = points[i]; + var posLocal = point.PositionLocal; + var posWorld = matrix.MultiplyPoint(posLocal); + + //copy/pasted for the sake of performance + if (min.x > posWorld.x) min.x = posWorld.x; + if (min.y > posWorld.y) min.y = posWorld.y; + if (min.z > posWorld.z) min.z = posWorld.z; + + if (max.x < posWorld.x) max.x = posWorld.x; + if (max.y < posWorld.y) max.y = posWorld.y; + if (max.z < posWorld.z) max.z = posWorld.z; + + if (point.ControlType != BGCurvePoint.ControlTypeEnum.Absent) + { + if (closed || i != 0) + { + var controlWorld = matrix.MultiplyPoint(point.ControlFirstLocal + posLocal); + + //copy/pasted for the sake of performance + if (min.x > controlWorld.x) min.x = controlWorld.x; + if (min.y > controlWorld.y) min.y = controlWorld.y; + if (min.z > controlWorld.z) min.z = controlWorld.z; + + if (max.x < controlWorld.x) max.x = controlWorld.x; + if (max.y < controlWorld.y) max.y = controlWorld.y; + if (max.z < controlWorld.z) max.z = controlWorld.z; + } + if (closed || i != lastPointIndex) + { + var controlWorld = matrix.MultiplyPoint(point.ControlSecondLocal + posLocal); + + //copy/pasted for the sake of performance + if (min.x > controlWorld.x) min.x = controlWorld.x; + if (min.y > controlWorld.y) min.y = controlWorld.y; + if (min.z > controlWorld.z) min.z = controlWorld.z; + + if (max.x < controlWorld.x) max.x = controlWorld.x; + if (max.y < controlWorld.y) max.y = controlWorld.y; + if (max.z < controlWorld.z) max.z = controlWorld.z; + } + } + } + + vertices[0] = min; + vertices[1] = max; + + mesh.vertices = vertices; + break; + } + } + + + //setup renderer visible option for update mode + private void InitRendererVisible(BGCurveBaseMath.Config config) + { + InitVisibilityCheck(config, RendererForUpdateCheck); + } + + //attach visibility check component to target GameObject (the one, the renderer is attached to) + private void InitVisibilityCheck(BGCurveBaseMath.Config config, Renderer renderer) + { + if (visibilityCheck != null) + { + visibilityCheck.BecameVisible -= BecameVisible; + Destroy(visibilityCheck); + } + + if (renderer == null) return; + + visibilityCheck = renderer.gameObject.AddComponent(); + + visibilityCheck.BecameVisible += BecameVisible; + + config.ShouldUpdate = () => visibilityCheck.Visible; + } + + //became visible callback for use with VisibilityCheck Component + private void BecameVisible(object sender, EventArgs e) + { + math.Configuration.FireUpdate(); + } + + //math was changed callback + private void MathWasChanged(object sender, EventArgs e) + { + if (ChangedMath != null) ChangedMath(this, null); + + if (mathChangedEvent.GetPersistentEventCount() > 0) mathChangedEvent.Invoke(); + } + + //=============================================================================================== + // Private classes + //=============================================================================================== + //it's used for visibility checks + private sealed class VisibilityCheck : MonoBehaviour + { + //Fired when became visible + public event EventHandler BecameVisible; + + /// Is currently visible + public bool Visible { get; private set; } + + //================================== Unity Callbacks + private void OnBecameVisible() + { + Visible = true; + if (BecameVisible != null) BecameVisible(this, null); + } + + private void OnBecameInvisible() + { + Visible = false; + } + } + + //=============================================================================================== + // Unity Persistent Event + //=============================================================================================== + [Serializable] + public class MathChangedEvent : UnityEvent + { + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs.meta new file mode 100644 index 0000000..a94ab97 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcMath.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b6d20671ad38ded4fa2362df353b9a31 +timeCreated: 1471598370 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcSplitterPolyline.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcSplitterPolyline.cs new file mode 100644 index 0000000..afeb610 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcSplitterPolyline.cs @@ -0,0 +1,567 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + /// + /// Splits the curve to single line. This class does not change anything except providing point's positions. + /// Subclasses, like BGCcVisualizationLineRenderer or BGCcTriangulate2D uses this data for their own purposes. + /// + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcSplitterPolyline")] + [ + CcDescriptor( + Description = "Calculates points positions for polyline along the curve. It does not change or modify anything. Use Positions field to access points.", + Name = "Splitter Polyline", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcSplitterPolyline123.png") + ] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcSplitterPolyline")] + public class BGCcSplitterPolyline : BGCcWithMath + { + //=============================================================================================== + // Events + //=============================================================================================== + /// ui updated + public event EventHandler ChangedPositions; + + + //=============================================================================================== + // Enums + //=============================================================================================== + /// Split mode + public enum SplitModeEnum + { + /// Math precalculated data is reused + UseMathData = 0, + + /// Use specified number of parts for whole spline + PartsTotal = 1, + + /// Use specified number of parts for each spline's section + PartsPerSection = 2 + } + + //=============================================================================================== + // Fields (Persistent) + //=============================================================================================== + [SerializeField] [Tooltip("How to split the curve. " + + "TotalSections -total sections for whole curve;\r\n " + + "PartSections - each part (between 2 points) will use the same amount of splits;\r\n" + + "UseMathData -use data, precalculated by Math component. " + + "Note, you can tweak some params at Math as well.")] private SplitModeEnum splitMode = SplitModeEnum.UseMathData; + + [SerializeField] [Range(1, 1000)] [Tooltip("Total number of parts to split a curve to. " + + "The actual number of parts can be less than partsTotal due to optimization, but never more.")] private int partsTotal = 30; + + + [SerializeField] [Range(1, 150)] [Tooltip("Every section of the curve will be split on even parts. " + + "The actual number of parts can be less than partsPerSection due to optimization, but never more.")] private int partsPerSection = 30; + + [SerializeField] [Tooltip("Split straight lines. Straight lines are optimized by default and are not split.")] private bool doNotOptimizeStraightLines; + + [SerializeField] [Tooltip("By default positions in world coordinates. Set this parameter to true to use local coordinates. " + + "Local coordinates are calculated slower.")] protected bool useLocal; + + + /// Split mode + public SplitModeEnum SplitMode + { + get { return splitMode; } + set { ParamChanged(ref splitMode, value); } + } + + /// Number of parts for PartsTotal splitMode + public int PartsTotal + { + get { return Mathf.Clamp(partsTotal, 1, 1000); } + //idea.. we may skip updateui if splitmode is not PartsTotal + set { ParamChanged(ref partsTotal, Mathf.Clamp(value, 1, 1000)); } + } + + /// Number of parts for PartsPerSection splitMode + public int PartsPerSection + { + get { return Mathf.Clamp(partsPerSection, 1, 150); } + //idea.. we may skip updateui if splitmode is not PartsPerSection + set { ParamChanged(ref partsPerSection, Mathf.Clamp(value, 1, 150)); } + } + + + /// skip straight lines optimization. Used by Base Math + public bool DoNotOptimizeStraightLines + { + get { return doNotOptimizeStraightLines; } + set { ParamChanged(ref doNotOptimizeStraightLines, value); } + } + + /// Use local coordinates instead of world for positions + public virtual bool UseLocal + { + get { return useLocal; } + set { ParamChanged(ref useLocal, value); } + } + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + public override string Warning + { + get + { + var math = Math; + var warning = ""; + + if (math == null) return warning; + + //check math precision + switch (SplitMode) + { + case SplitModeEnum.PartsTotal: + + var curvedSectionsCount = math.Math.SectionsCount - (DoNotOptimizeStraightLines ? 0 : CountStraightLines(Math.Math, null)); + var partsForCurved = curvedSectionsCount == 0 ? 0 : PartsTotal/curvedSectionsCount; + + if (partsForCurved > math.SectionParts) + warning = "Math use less parts per section (" + math.SectionParts + "). You now use " + partsForCurved + + " parts for curved section. You need to increase Math's 'SectionParts' field accordingly to increase polyline precision."; + break; + case SplitModeEnum.PartsPerSection: + + if (PartsPerSection > math.SectionParts) + warning = "Math use less parts per section (" + math.SectionParts + "). You need to increase Math's 'SectionParts' field accordingly to increase polyline precision."; + + break; + } + return warning; + } + } + + public override string Info + { + get { return "Polyline has " + PointsCount + " points"; } + } + + + public override bool SupportHandles + { + get { return true; } + } + + public override bool SupportHandlesSettings + { + get { return true; } + } + +#if UNITY_EDITOR + [Range(.5f, 1.5f)] [Tooltip("Spheres scale")] [SerializeField] private float spheresScale = 1; + [SerializeField] [Tooltip("Spheres color")] private Color spheresColor = Color.white; + [Range(2, 100)] [Tooltip("Maximum number of spheres. This parameter only affects how much points are shown in the Editor")] [SerializeField] private int spheresCount = 100; + + public float SpheresScale + { + get { return spheresScale; } + set { spheresScale = value; } + } + + public Color SpheresColor + { + get { return spheresColor; } + set { spheresColor = value; } + } + + public int SpheresCount + { + get { return spheresCount; } + set { spheresCount = value; } + } +#endif + + //=============================================================================================== + // Fields (Not persistent) + //=============================================================================================== + + //do not remove readonly. Reusable positions list, storing last calculated positions + protected readonly List positions = new List(); + //if current data valid? + private bool dataValid; + //reusable array, storing if section is straight. + private bool[] straightBits; + + + //different providers for different modes + private PositionsProvider positionsProvider; + + + /// latest points count. It's not getting updated until it's queried + public int PointsCount + { + get + { + if (!dataValid) UpdateData(); + return positions == null ? 0 : positions.Count; + } + } + + /// latest points positions used. It's not getting updated until it's queried + public List Positions + { + get + { + if (!dataValid) UpdateData(); + return positions; + } + } + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + public override void Start() + { + AddListeners(); + } + + public override void OnDestroy() + { + RemoveListeners(); + } + + //=============================================================================================== + // Public methods + //=============================================================================================== + /// init all listeners for math and it's own params + public void AddListeners() + { + //monitor underlying math changes + Math.ChangedMath -= UpdateRequested; + Math.ChangedMath += UpdateRequested; + + //monitor own params + ChangedParams -= UpdateRequested; + ChangedParams += UpdateRequested; + } + + /// mark data as invalid + public void InvalidateData() + { + dataValid = false; + if (ChangedPositions != null) ChangedPositions(this, null); + } + + /// remove attached listeners + public void RemoveListeners() + { + try + { + Math.ChangedMath -= UpdateRequested; + ChangedParams -= UpdateRequested; + } + catch (MissingReferenceException) + { + } + } + + + //=============================================================================================== + // Private methods + //=============================================================================================== + //refresh data + private void UpdateData() + { + dataValid = true; + + + Transform myTransform; + try + { + myTransform = transform; + } + catch (MissingReferenceException) + { + RemoveListeners(); + return; + } + + + var noData = true; + + //have no idea how to cope with UndoRedo + try + { + noData = Math == null || Math.Math == null || Math.Math.SectionsCount == 0; + } + catch (MissingReferenceException) + { + } + + positions.Clear(); + if (noData) return; + + var baseMath = Math.Math; + var sectionsCount = baseMath.SectionsCount; + + //count number of straight lines + var straightLinesCount = 0; + if (!doNotOptimizeStraightLines) + { + //resize only if length < sectionsCount to reduce GC + if (straightBits == null || straightBits.Length < sectionsCount) Array.Resize(ref straightBits, sectionsCount); + straightLinesCount = CountStraightLines(baseMath, straightBits); + } + + //recalculate points + InitProvider(ref positionsProvider, this).Build(positions, straightLinesCount, straightBits); + + + if (!UseLocal) return; + + //slow convertion (world->local) + var matrix = myTransform.worldToLocalMatrix; + var count = positions.Count; + for (var i = 0; i < count; i++) positions[i] = matrix.MultiplyPoint(positions[i]); + } + + + //curve was updated + protected virtual void UpdateRequested(object sender, EventArgs e) + { + InvalidateData(); + } + + //init required provider. Each mode has it's own provider + private static PositionsProvider InitProvider(ref PositionsProvider positionsProvider, BGCcSplitterPolyline cc) + { + //assign positions provider if needed + var mode = cc.splitMode; + var providerObsolete = positionsProvider == null || !positionsProvider.Comply(mode); + switch (mode) + { + case SplitModeEnum.PartsTotal: + if (providerObsolete) positionsProvider = new PositionsProviderTotalParts(); + ((PositionsProviderTotalParts) positionsProvider).Init(cc.Math, cc.PartsTotal); + break; + case SplitModeEnum.PartsPerSection: + if (providerObsolete) positionsProvider = new PositionsProviderPartsPerSection(); + ((PositionsProviderPartsPerSection) positionsProvider).Init(cc.Math, cc.PartsPerSection); + break; + default: + // case SplitModeEnum.UseMathData: + if (providerObsolete) positionsProvider = new PositionsProviderMath(); + ((PositionsProviderMath) positionsProvider).Init(cc.Math); + break; + } + return positionsProvider; + } + + //count the number of straight lines + public static int CountStraightLines(BGCurveBaseMath math, bool[] straight) + { + var curve = math.Curve; + var points = curve.Points; + if (points.Length == 0) return 0; + + var sections = math.SectionInfos; + var sectionsCount = sections.Count; + var fillArray = straight != null; + + var straightLinesCount = 0; + var previousControlAbsent = points[0].ControlType == BGCurvePoint.ControlTypeEnum.Absent; + for (var i = 0; i < sectionsCount; i++) + { + var nextPoint = curve.Closed && i == sectionsCount - 1 ? points[0] : points[i + 1]; + var nextControlAbsent = nextPoint.ControlType == BGCurvePoint.ControlTypeEnum.Absent; + + if (previousControlAbsent && nextControlAbsent) + { + if (fillArray) straight[i] = true; + straightLinesCount++; + } + else if (fillArray) straight[i] = false; + + previousControlAbsent = nextControlAbsent; + } + return straightLinesCount; + } + + + //=============================================================================================== + // Helper classes + //=============================================================================================== + + //============================================= Abstract provider + /// Abstract provider + public abstract class PositionsProvider + { + //used math + protected BGCcMath Math; + + protected virtual void InitInner(BGCcMath math) + { + Math = math; + } + + /// if this provider can build points for the given mode + public abstract bool Comply(SplitModeEnum splitMode); + + /// calculate points fro polyline + public virtual void Build(List positions, int straightLinesCount, bool[] straightBits) + { + var math = Math.Math; + + var sections = math.SectionInfos; + var sectionsCount = sections.Count; + + + //first point always present + positions.Add(math[0][0].Position); + + //fill in points + if (straightLinesCount == 0) for (var i = 0; i < sectionsCount; i++) FillInSplitSection(sections[i], positions); + else + { + for (var i = 0; i < sectionsCount; i++) + { + var section = sections[i]; + + if (straightBits[i]) positions.Add(section[section.PointsCount - 1].Position); + else FillInSplitSection(section, positions); + } + } + } + + // add points for a section by a given number of points + protected static void FillIn(BGCurveBaseMath.SectionInfo section, List result, int parts) + { + var onePartDistance = section.Distance/parts; + for (var j = 1; j <= parts; j++) + { + Vector3 tangent; + Vector3 pos; + section.CalcByDistance(onePartDistance*j, out pos, out tangent, true, false); + result.Add(pos); + } + } + + // add points for a split section + protected abstract void FillInSplitSection(BGCurveBaseMath.SectionInfo section, List result); + } + + //============================================= Provider for total parts mode + /// Provider for total parts mode + public sealed class PositionsProviderTotalParts : PositionsProvider + { + private int parts; + private int reminderForCurved; + private int partsPerSectionFloor; + + + public void Init(BGCcMath math, int parts) + { + InitInner(math); + + this.parts = parts; + } + + public override bool Comply(SplitModeEnum splitMode) + { + return splitMode == SplitModeEnum.PartsTotal; + } + + public override void Build(List positions, int straightLinesCount, bool[] straightBits) + { + var curve = Math.Curve; + var sections = Math.Math.SectionInfos; + var sectionsCount = sections.Count; + + //at least one section is curved (maxParts>=sectionsCount, so floatParts >=1) + var floatParts = (parts - straightLinesCount)/(float) (sectionsCount - straightLinesCount); + + reminderForCurved = (int) ((parts - straightLinesCount)%(float) (sectionsCount - straightLinesCount)); + partsPerSectionFloor = Mathf.FloorToInt(floatParts); + + + if (parts < sectionsCount) + { + if (parts == 1) + { + //only one part per whole curve (one->last) + positions.Add(sections[0][0].Position); + positions.Add(curve.Closed ? Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, .5f) : sections[sectionsCount - 1][sections[sectionsCount - 1].PointsCount - 1].Position); + } + else if (parts == 2 && curve.Closed) + { + positions.Add(sections[0][0].Position); + positions.Add(Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, .3333f)); + positions.Add(Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, .6667f)); + } + else for (var i = 0; i <= parts; i++) positions.Add(Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, i/(float) parts)); + } + else base.Build(positions, straightLinesCount, straightBits); + } + + // add points for a split section + protected override void FillInSplitSection(BGCurveBaseMath.SectionInfo section, List result) + { + //curved + var partsForSection = partsPerSectionFloor; + if (reminderForCurved > 0) + { + partsForSection++; + reminderForCurved--; + } + + FillIn(section, result, partsForSection); + } + } + + //============================================= Provider for parts per section mode + + /// Provider for parts per section mode + public sealed class PositionsProviderPartsPerSection : PositionsProvider + { + private int parts; + + public void Init(BGCcMath math, int partsPerSection) + { + InitInner(math); + parts = partsPerSection; + } + + public override bool Comply(SplitModeEnum splitMode) + { + return splitMode == SplitModeEnum.PartsPerSection; + } + + // add points for a split section + protected override void FillInSplitSection(BGCurveBaseMath.SectionInfo section, List result) + { + FillIn(section, result, parts); + } + } + + //============================================= Provider for useMath mode + + /// Provider for useMath mode + public sealed class PositionsProviderMath : PositionsProvider + { + public void Init(BGCcMath ccMath) + { + InitInner(ccMath); + } + + public override bool Comply(SplitModeEnum splitMode) + { + return splitMode == SplitModeEnum.UseMathData; + } + + // add points for a split section + protected override void FillInSplitSection(BGCurveBaseMath.SectionInfo section, List result) + { + var sectionPoints = section.Points; + var count = sectionPoints.Count; + + for (var j = 1; j < count; j++) result.Add(sectionPoints[j].Position); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcSplitterPolyline.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcSplitterPolyline.cs.meta new file mode 100644 index 0000000..b8d137e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcSplitterPolyline.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 62cd433e62a5ee04c956c0f388f66df1 +timeCreated: 1474931604 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcTriangulate2D.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcTriangulate2D.cs new file mode 100644 index 0000000..cd7e82c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcTriangulate2D.cs @@ -0,0 +1,404 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + /// Triangulate 2D spline. Currently only simple polygons are supported + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcTriangulate2D")] + [DisallowMultipleComponent] + [ + CcDescriptor( + Description = "Triangulate 2D spline. Currently only simple polygons are supported.", + Name = "Triangulate 2D", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcTriangulate2D123.png") + ] + [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcTriangulate2D")] + [ExecuteInEditMode] + public class BGCcTriangulate2D : BGCcSplitterPolyline + { + //=============================================================================================== + // Static + //=============================================================================================== + //min scale for UV + private const float MinUvScale = 0.000001f; + //max scale for UV + private const float MaxUvScale = 1000000; + + //temp List to avoid GC (it's used by traingulation algorithm) + private static readonly List V = new List(); + + //=============================================================================================== + // Fields (Persistent) + //=============================================================================================== + + [SerializeField] [Tooltip("UV scale")] private Vector2 scaleUV = new Vector2(1, 1); + [SerializeField] [Tooltip("UV offset")] private Vector2 offsetUV = new Vector2(0, 0); + [SerializeField] [Tooltip("Flip triangles")] private bool flip; + [SerializeField] [Tooltip("Double sided")] private bool doubleSided; + [SerializeField] [Tooltip("UV scale for back side")] private Vector2 scaleBackUV = new Vector2(1, 1); + [SerializeField] [Tooltip("UV offset for back side")] private Vector2 offsetBackUV = new Vector2(0, 0); + [SerializeField] [Tooltip("Update mesh every frame, even if curve's not changed. This can be useful, if UVs are animated.")] private bool updateEveryFrame; + + + //the number of frame, last triangulation was build + private int updateAtFrame; + + //keeps track about running Coroutine for every frame update + private bool everyFrameUpdateIsRunning; + + /// Scale all UV values + public Vector2 ScaleUv + { + get { return scaleUV; } + set + { + if (Mathf.Abs(scaleUV.x - value.x) < BGCurve.Epsilon && Mathf.Abs(scaleUV.y - value.y) < BGCurve.Epsilon) return; + ParamChanged(ref scaleUV, value); + } + } + + /// Should faces be flipped + public bool Flip + { + get { return flip; } + set + { + if (flip == value) return; + ParamChanged(ref flip, value); + } + } + + /// Generate triangles for backside + public bool DoubleSided + { + get { return doubleSided; } + set { ParamChanged(ref doubleSided, value); } + } + + /// Should triangulation occur every frame even if curve is not changed + public bool UpdateEveryFrame + { + get { return updateEveryFrame; } + set + { + if (updateEveryFrame == value) return; + updateEveryFrame = value; + ParamChanged(ref updateEveryFrame, value); + + if (updateEveryFrame && !everyFrameUpdateIsRunning && gameObject.activeSelf && Application.isPlaying) StartCoroutine(UiUpdater()); + } + } + + // override parent UseLocal to be always true. I doubt, there is any way to use world's coordinates for meshes (like local for LineRenderer) + public override bool UseLocal + { + get { return true; } + set { } + } + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + + public override string Error + { + get { return !Curve.Mode2DOn ? "Curve should be in 2D mode" : null; } + } + + public override string Info + { + get { return "Mesh uses " + vertices.Count + " vertices and " + (triangles.Count / 3) + " triangles."; } + } + + //=============================================================================================== + // Fields (Not persistent) + //=============================================================================================== + + [NonSerialized] private MeshFilter meshFilter; + [NonSerialized] private readonly List vertices = new List(); + [NonSerialized] private readonly List points = new List(); + [NonSerialized] private readonly List uvs = new List(); + [NonSerialized] private readonly List triangles = new List(); + + + + public MeshFilter MeshFilter + { + get + { + //do not replace with ?? + if (meshFilter == null) meshFilter = GetComponent(); + return meshFilter; + } + } + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + + public override void Start() + { + base.Start(); + if (MeshFilter.sharedMesh == null) UpdateUI(); + + if (updateEveryFrame && gameObject.activeSelf && Application.isPlaying) StartCoroutine(UiUpdater()); + } + + void OnEnable() + { + if (updateEveryFrame && !everyFrameUpdateIsRunning && Application.isPlaying) StartCoroutine(UiUpdater()); + } + + void OnDisable() + { + if (updateEveryFrame && everyFrameUpdateIsRunning && Application.isPlaying) everyFrameUpdateIsRunning = false; + } + + //=============================================================================================== + // Public Functions + //=============================================================================================== + public void UpdateUI() + { + updateAtFrame = Time.frameCount; + + if (!Curve.Mode2DOn) return; + + var mode2D = Curve.Mode2D; + + var positions = Positions; + + var positionsCount = positions.Count; + //I dont know why, but triangulator works wrong in case first pos= last pos + if (Curve.Closed) positionsCount--; + + MeshFilter meshFilter; + try + { + meshFilter = MeshFilter; + } + catch (MissingReferenceException) + { + RemoveListeners(); + return; + } + var mesh = meshFilter.sharedMesh; + if (mesh == null) + { + mesh = new Mesh(); + meshFilter.mesh = mesh; + } + + vertices.Clear(); + triangles.Clear(); + uvs.Clear(); + if (positionsCount > 2) + { + //we need to triangulate + points.Clear(); + var minMax = new Vector4(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue); + for (var i = 0; i < positionsCount; i++) + { + var pos = positions[i]; + + Vector3 vert; + Vector2 point; + switch (mode2D) + { + case BGCurve.Mode2DEnum.XY: + vert = new Vector3(pos.x, pos.y); + point = new Vector2(pos.x, pos.y); + break; + case BGCurve.Mode2DEnum.XZ: + vert = new Vector3(pos.x, 0, pos.z); + point = new Vector2(pos.x, pos.z); + break; + default: + // case BGCurve.Mode2DEnum.YZ: + vert = new Vector3(0, pos.y, pos.z); + point = new Vector2(pos.y, pos.z); + break; + } + vertices.Add(vert); + points.Add(point); + + //min + if (point.x < minMax.x) minMax.x = point.x; + if (point.y < minMax.y) minMax.y = point.y; + //max + if (point.x > minMax.z) minMax.z = point.x; + if (point.y > minMax.w) minMax.w = point.y; + } + + //tris + Triangulate(points, triangles); + if (!flip) triangles.Reverse(); + + //uvs + var width = minMax.z - minMax.x; + var height = minMax.w - minMax.y; + var pointsCount = points.Count; + var scaleX = Mathf.Clamp(scaleUV.x, MinUvScale, MaxUvScale); + var scaleY = Mathf.Clamp(scaleUV.y, MinUvScale, MaxUvScale); + for (var i = 0; i < pointsCount; i++) + { + var point = points[i]; + uvs.Add(new Vector2(offsetUV.x + ((point.x - minMax.x) / width) * scaleX, offsetUV.y + ((point.y - minMax.y) / height) * scaleY)); + } + + // doubleSided + if (doubleSided) + { + //add points, we can not reuse the same points, cause we need unique UVs + var verticesCount = vertices.Count; + for (var i = 0; i < verticesCount; i++) vertices.Add(vertices[i]); + + //add triangles + var trianglesCount = triangles.Count; + for (var i = trianglesCount - 1; i >= 0; i--) triangles.Add(triangles[i] + verticesCount); + + //uvs + scaleX = Mathf.Clamp(scaleBackUV.x, MinUvScale, MaxUvScale); + scaleY = Mathf.Clamp(scaleBackUV.y, MinUvScale, MaxUvScale); + for (var i = 0; i < pointsCount; i++) + { + var point = points[i]; + uvs.Add(new Vector2(offsetBackUV.x + ((point.x - minMax.x) / width) * scaleX, offsetBackUV.y + ((point.y - minMax.y) / height) * scaleY)); + } + } + } + + mesh.Clear(); + mesh.SetVertices(vertices); + mesh.SetTriangles(triangles, 0); + mesh.SetUVs(0, uvs); + mesh.RecalculateNormals(); + } + + //=============================================================================================== + // Private Functions + //=============================================================================================== + // curve's changed + protected override void UpdateRequested(object sender, EventArgs e) + { + base.UpdateRequested(sender, e); + UpdateUI(); + } + + private IEnumerator UiUpdater() + { + everyFrameUpdateIsRunning = true; + while (updateEveryFrame) + { + if (updateAtFrame != Time.frameCount) UpdateUI(); + yield return null; + } + + everyFrameUpdateIsRunning = false; + } + + + //==================================== This code from http://wiki.unity3d.com/index.php?title=Triangulator + // Triangulate simple polygon. I have no idea how good this algorithm is and what it's actually doing + private static void Triangulate(List points, List tris) + { + tris.Clear(); + + int n = points.Count; + if (n < 3) return; + + V.Clear(); + + if (Area(points) > 0) for (int v = 0; v < n; v++) V.Add(v); + else for (int v = 0; v < n; v++) V.Add((n - 1) - v); + + int nv = n; + int count = 2*nv; + for (int m = 0, v = nv - 1; nv > 2;) + { + if ((count--) <= 0) return; + + int u = v; + if (nv <= u) u = 0; + + v = u + 1; + + if (nv <= v) v = 0; + int w = v + 1; + if (nv <= w) w = 0; + + if (Snip(points, u, v, w, nv, V)) + { + int a, b, c, s, t; + a = V[u]; + b = V[v]; + c = V[w]; + tris.Add(a); + tris.Add(b); + tris.Add(c); + m++; + for (s = v, t = v + 1; t < nv; s++, t++) V[s] = V[t]; + nv--; + count = 2*nv; + } + } + } + + private static float Area(List points) + { + int n = points.Count; + float A = 0.0f; + for (int p = n - 1, q = 0; q < n; p = q++) + { + Vector2 pval = points[p]; + Vector2 qval = points[q]; + A += pval.x*qval.y - qval.x*pval.y; + } + return (A*0.5f); + } + + private static bool Snip(List points, int u, int v, int w, int n, List V) + { + int p; + Vector2 A = points[V[u]]; + Vector2 B = points[V[v]]; + Vector2 C = points[V[w]]; + if (Mathf.Epsilon > (((B.x - A.x)*(C.y - A.y)) - ((B.y - A.y)*(C.x - A.x)))) return false; + for (p = 0; p < n; p++) + { + if ((p == u) || (p == v) || (p == w)) continue; + Vector2 P = points[V[p]]; + if (InsideTriangle(A, B, C, P)) return false; + } + return true; + } + + private static bool InsideTriangle(Vector2 A, Vector2 B, Vector2 C, Vector2 P) + { + float ax, ay, bx, by, cx, cy, apx, apy, bpx, bpy, cpx, cpy; + float cCROSSap, bCROSScp, aCROSSbp; + + ax = C.x - B.x; + ay = C.y - B.y; + bx = A.x - C.x; + by = A.y - C.y; + cx = B.x - A.x; + cy = B.y - A.y; + apx = P.x - A.x; + apy = P.y - A.y; + bpx = P.x - B.x; + bpy = P.y - B.y; + cpx = P.x - C.x; + cpy = P.y - C.y; + + aCROSSbp = ax*bpy - ay*bpx; + cCROSSap = cx*apy - cy*apx; + bCROSScp = bx*cpy - by*cpx; + + return ((aCROSSbp >= 0.0f) && (bCROSScp >= 0.0f) && (cCROSSap >= 0.0f)); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcTriangulate2D.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcTriangulate2D.cs.meta new file mode 100644 index 0000000..869f0cc --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcTriangulate2D.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 60c959525d457be479e941b787ed7a5d +timeCreated: 1476469986 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcVisualizationLineRenderer.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcVisualizationLineRenderer.cs new file mode 100644 index 0000000..b469c3f --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcVisualizationLineRenderer.cs @@ -0,0 +1,200 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Components +{ + /// + /// Visualize curve in Play mode with standard LineRenderer Component. + /// This component updates LineRenderer vertex count & positions only + /// + [HelpURL("http://www.bansheegz.com/BGCurve/Cc/BGCcVisualizationLineRenderer")] + [RequireComponent(typeof(LineRenderer))] + [DisallowMultipleComponent] + [ + CcDescriptor( + Description = "Visualize curve with standard LineRenderer Unity component.", + Name = "Cc Line Renderer", + Image = "Assets/BansheeGz/BGCurve/Icons/Components/BGCcVisualizationLineRenderer123.png") + ] + [AddComponentMenu("BansheeGz/BGCurve/Components/BGCcLineRenderer")] + public class BGCcVisualizationLineRenderer : BGCcSplitterPolyline + { + //=============================================================================================== + // Events + //=============================================================================================== + /// ui updated + public event EventHandler ChangedVisualization; + + //=============================================================================================== + // Fields (Persistent) + //=============================================================================================== + [SerializeField] [Tooltip("Update LineRenderer at Start method.")] private bool updateAtStart; + + /// If LineRenderer should be updated then Start is called + public bool UpdateAtStart + { + get { return updateAtStart; } + set { updateAtStart = value; } + } + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + public override string Error + { + get { return ChoseMessage(base.Error, () => (LineRenderer == null) ? "LineRenderer is null" : null); } + } + + public override string Warning + { + get + { + var warning = base.Warning; + + var lineRenderer = LineRenderer; + if (lineRenderer == null) return warning; + + if (!lineRenderer.useWorldSpace) + warning += "\r\nLineRenderer uses local space (LineRenderer.useWorldSpace=false)! " + + "This is not optimal, especially if you plan to update a curve at runtime. Try to set LineRenderer.useWorldSpace to true"; + + return warning.Length == 0 ? null : warning; + } + } + + public override string Info + { + get { return lineRenderer != null ? "LineRenderer uses " + PointsCount + " points" : "LineRenderer is null"; } + } + + public override bool SupportHandles + { + get { return false; } + } + + + //=============================================================================================== + // Fields (Not persistent) + //=============================================================================================== + //linerenderer cached + private LineRenderer lineRenderer; + + /// Get Unity's LineRenderer component + public LineRenderer LineRenderer + { + get + { + //do not replace with ?? + if (lineRenderer == null) lineRenderer = GetComponent(); + return lineRenderer; + } + } + + //=============================================================================================== + // Unity Callbacks + //=============================================================================================== + // Use this for initialization + public override void Start() + { + base.Start(); + + if (updateAtStart) UpdateUI(); + else Math.EnsureMathIsCreated(); + } + + //=============================================================================================== + // Public functions + //=============================================================================================== + //see parent for comments + public override void AddedInEditor() + { + UpdateUI(); + } + + /// Update underlying Unity's LineRenderer component + public void UpdateUI() + { + try + { + //have no idea how to cope with UndoRedo + if (Math == null) return; + } + catch (MissingReferenceException) + { + return; + } + var math = Math.Math; + + if (math == null) return; + + LineRenderer lineRenderer; + try + { + //have no idea how to cope with UndoRedo + lineRenderer = LineRenderer; + } + catch (MissingReferenceException) + { + return; + } + + if (lineRenderer == null) return; + + var curve = Curve; + + if (curve == null) return; + + + if (math.SectionsCount == 0) + { + //not enough points +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.numPositions = 0; +#else + lineRenderer.SetVertexCount(0); +#endif + + if (positions != null && positions.Count > 0 && ChangedVisualization != null) ChangedVisualization(this, null); + positions.Clear(); + } + else + { + //============== ok + useLocal = !lineRenderer.useWorldSpace; + var newPositions = Positions; + + //update LineRenderer + var count = newPositions.Count; + if (count > 0) + { +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.numPositions = count; +#else + lineRenderer.SetVertexCount(count); +#endif + //the only way to get rid of GC is to use slow one-by-one setter unfortunately + for (var i = 0; i < count; i++) lineRenderer.SetPosition(i, newPositions[i]); + } + else + { +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.numPositions = 0; +#else + lineRenderer.SetVertexCount(0); +#endif + } + if (ChangedVisualization != null) ChangedVisualization(this, null); + } + } + + //=============================================================================================== + // Private functions + //=============================================================================================== + //math/curve is changed + protected override void UpdateRequested(object sender, EventArgs e) + { + base.UpdateRequested(sender, e); + UpdateUI(); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcVisualizationLineRenderer.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcVisualizationLineRenderer.cs.meta new file mode 100644 index 0000000..32699a3 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcVisualizationLineRenderer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8a69af748a081a14dbc7aa333bece5af +timeCreated: 1471596363 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursor.cs new file mode 100644 index 0000000..da2d667 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursor.cs @@ -0,0 +1,97 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + /// CC + cursor + [RequireComponent(typeof (BGCcCursor))] + public abstract class BGCcWithCursor : BGCc + { + //=============================================================================================== + // Fields (Not persistent) + //=============================================================================================== + //cursor Cc component + private BGCcCursor cursor; + + public BGCcCursor Cursor + { + get + { + //do not replace with ?? + if (cursor == null) cursor = GetParent(); + return cursor; + } + } + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + + public override string Error + { + get { return Cursor == null ? "Cursor is null" : null; } + } + + + //=============================================================================================== + // Public methods + //=============================================================================================== + /// Lerp 2 Quaternion field values by current cursor position (optionally currentSection is provided to reduce required calculation) + public Quaternion LerpQuaternion(string fieldName, int currentSection = -1) + { + int indexFrom, indexTo; + var t = GetT(out indexFrom, out indexTo, currentSection); + + //get values + var from = Curve[indexFrom].GetQuaternion(fieldName); + var to = Curve[indexTo].GetQuaternion(fieldName); + + //not sure how to handle zero cases + if (from.x == 0 && from.y == 0 && from.z == 0 && from.w == 0) from = Quaternion.identity; + if (to.x == 0 && to.y == 0 && to.z == 0 && to.w == 0) to = Quaternion.identity; + + //lerp + var result = Quaternion.Lerp(@from, to, t); + return float.IsNaN(result.x) || float.IsNaN(result.y) || float.IsNaN(result.z) || float.IsNaN(result.w) ? Quaternion.identity : result; + } + + /// Lerp 2 Vector3 field values by current cursor position (optionally currentSection is provided to reduce required calculation) + public Vector3 LerpVector(string name, int currentSection = -1) + { + int indexFrom, indexTo; + var t = GetT(out indexFrom, out indexTo, currentSection); + + //get values + var from = Curve[indexFrom].GetVector3(name); + var to = Curve[indexTo].GetVector3(name); + + //lerp + return Vector3.Lerp(@from, to, t); + } + + /// get T value for interpolation (optionally currentSection is provided to reduce required calculation) + public float GetT(out int indexFrom, out int indexTo, int currentSection = -1) + { + var math = Cursor.Math.Math; + var distance = Cursor.Distance; + + GetFromToIndexes(out indexFrom, out indexTo, currentSection); + + //get t value + var section = math[indexFrom]; + var t = (distance - section.DistanceFromStartToOrigin)/section.Distance; + + return t; + } + + //=============================================================================================== + // Private methods + //=============================================================================================== + // get points indexes by cursor position (optionally currentSection is provided to reduce required calculation) + protected void GetFromToIndexes(out int indexFrom, out int indexTo, int currentSection = -1) + { + indexFrom = currentSection < 0 ? Cursor.CalculateSectionIndex() : currentSection; + indexTo = indexFrom == Curve.PointsCount - 1 ? 0 : indexFrom + 1; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursor.cs.meta new file mode 100644 index 0000000..e5a2a3d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b76de9a8934b6214a8672a403d2252ca +timeCreated: 1472620770 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursorObject.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursorObject.cs new file mode 100644 index 0000000..60ae08f --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursorObject.cs @@ -0,0 +1,33 @@ +using UnityEngine; + +namespace BansheeGz.BGSpline.Components +{ + /// CC + cursor + object to manipulate + public abstract class BGCcWithCursorObject : BGCcWithCursor + { + //=============================================================================================== + // Static + //=============================================================================================== + //error message to use (probably can be inlined without any effect) + private const string ErrorObjectNotSet = "Object To Manipulate is not set."; + + //=============================================================================================== + // Fields (Persistent) + //=============================================================================================== + [SerializeField] [Tooltip("Object to manipulate.\r\n")] private Transform objectToManipulate; + + public Transform ObjectToManipulate + { + get { return objectToManipulate; } + set { ParamChanged(ref objectToManipulate, value); } + } + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + public override string Error + { + get { return objectToManipulate == null ? ErrorObjectNotSet : null; } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursorObject.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursorObject.cs.meta new file mode 100644 index 0000000..d639fd8 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithCursorObject.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 12c8a5c3f07ca5c45b3361e5f8482f54 +timeCreated: 1471738385 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithMath.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithMath.cs new file mode 100644 index 0000000..147a7bc --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithMath.cs @@ -0,0 +1,33 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + /// Cc + math + [RequireComponent(typeof (BGCcMath))] + public abstract class BGCcWithMath : BGCc + { + //=============================================================================================== + // Fields (Not persistent) + //=============================================================================================== + private BGCcMath math; + + public BGCcMath Math + { + get + { + //do not replace with ?? + if (math == null) math = GetComponent(); + return math; + } + } + + //=============================================================================================== + // Editor stuff + //=============================================================================================== + public override string Error + { + get { return Math == null ? "Math is null" : null; } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithMath.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithMath.cs.meta new file mode 100644 index 0000000..2cf7a5b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcWithMath.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ea6e5d4a7e5fc4949b54bdf635d14073 +timeCreated: 1471733928 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve.meta new file mode 100644 index 0000000..479f49b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d243b7f5d60cbc64185d2dbbfaa3021b +folderAsset: yes +timeCreated: 1458400564 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCc.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCc.cs new file mode 100644 index 0000000..bdac355 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCc.cs @@ -0,0 +1,287 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// + /// Abstract superclass for components. + /// + /// Current Requirements: + /// 1) editor should be extended from BGCcEditor + /// 2) Should have a descriptor. + /// 3) Only one RequireComponent of type BGCc (parent). Parent is another Cc component, this component is totally depends on and can not operate without it. + /// + /// Cc stands for "Curve's component" + /// + [RequireComponent(typeof (BGCurve))] + public abstract class BGCc : MonoBehaviour + { + /// if component's parameters changed + public event EventHandler ChangedParams; + + /// Any information Cc wants to provide (for editor) + public virtual string Info + { + get { return null; } + } + + /// Warning (for editor) + public virtual string Warning + { + get { return null; } + } + + /// Error if something is wrong (for editor) + public virtual string Error + { + get { return null; } + } + + +#if UNITY_EDITOR + // ============================================== !!! This is editor only field +#pragma warning disable 0414 + //should CC's handles be shown in SceneView + [SerializeField] private bool showHandles = true; +#pragma warning restore 0414 +#endif + + /// Does this Cc supports handles in SceneView? + public virtual bool SupportHandles + { + get { return false; } + } + + /// Does this Cc supports some adjustable settings for handles in SceneView? + public virtual bool SupportHandlesSettings + { + get { return false; } + } + + //=============================================== Curve + private BGCurve curve; + + public BGCurve Curve + { + get + { + //do not replace with ?? + if (curve == null) curve = GetComponent(); + return curve; + } + } + + + //=============================================== Parent + //parent is another Cc component, this component is totally depends on and can not operate without it + [SerializeField] private BGCc parent; + + public void SetParent(BGCc parent) + { + this.parent = parent; + } + + public T GetParent() where T : BGCc + { + return (T) GetParent(typeof (T)); + } + + public BGCc GetParent(Type type) + { + if (parent != null) return parent; + parent = (BGCc) GetComponent(type); + return parent; + } + + + //=============================================== Name + //you can name your Cc + [SerializeField] private string ccName; + + public string CcName + { + get { return string.IsNullOrEmpty(ccName) ? "" + GetInstanceID() : ccName; } + set { ccName = value; } + } + + //=============================================== Transaction + //transaction is for events grouping only + private int transactionLevel; + + //=============================================== Descriptor + //descriptor is used to add icon, name and description to Cc + private CcDescriptor descriptor; + + + public CcDescriptor Descriptor + { + get + { + //do not replace with ?? + if (descriptor == null) descriptor = GetDescriptor(GetType()); + return descriptor; + } + } + + // www page, containing help info + public virtual string HelpURL + { + get + { + var helpUrl = GetHelpUrl(GetType()); + return helpUrl == null ? null : helpUrl.URL; + } + } + + //=================================================== Unity Methods + public virtual void Start() + { + } + + public virtual void OnDestroy() + { + } + + //=================================================== Methods + //in case any param changed + protected bool ParamChanged(ref T oldValue, T newValue) + { + var oldValueNull = oldValue == null; + var newValueNull = newValue == null; + if (oldValueNull && newValueNull) return false; + + if (oldValueNull == newValueNull && oldValue.Equals(newValue)) return false; + + oldValue = newValue; + FireChangedParams(); + return true; + } + + + /// if component has an error + public bool HasError() + { + return !string.IsNullOrEmpty(Error); + } + + /// if component has a warning + public bool HasWarning() + { + return !string.IsNullOrEmpty(Warning); + } + + //utility method for chosing error message + protected string ChoseMessage(string baseError, Func childError) + { + return !string.IsNullOrEmpty(baseError) ? baseError : childError(); + } + + /// if any parameter changed + public void FireChangedParams() + { + if (ChangedParams != null && transactionLevel == 0) ChangedParams(this, null); + } + + /// component was added via editor menu + public virtual void AddedInEditor() + { + } + + /// get parent Cc class + public Type GetParentClass() + { + return GetParentClass(GetType()); + } + + /// get parent Cc class + public static Type GetParentClass(Type ccType) + { + //gather required + var requiredList = BGReflectionAdapter.GetCustomAttributes(ccType, typeof (RequireComponent), true); + if (requiredList.Length == 0) return null; + + var result = new List(); + foreach (var item in requiredList) + { + var requiredComponent = (RequireComponent) item; + CheckRequired(requiredComponent.m_Type0, result); + CheckRequired(requiredComponent.m_Type1, result); + CheckRequired(requiredComponent.m_Type2, result); + } + + if (result.Count == 0) return null; + if (result.Count > 1) throw new CcException(ccType + " has more than one parent (extended from BGCc class), calculated by RequireComponent attribute"); + return result[0]; + } + + //add class if it's not abstract and a child of BGCc + private static void CheckRequired(Type type, List result) + { + if (type == null || BGReflectionAdapter.IsAbstract(type) || !BGReflectionAdapter.IsClass(type) || !BGReflectionAdapter.IsSubclassOf(type,typeof (BGCc)))return; + + result.Add(type); + } + + /// Check standard Unity's DisallowMultipleComponent attribute + public static bool IsSingle(Type ccType) + { + return BGReflectionAdapter.GetCustomAttributes(ccType, typeof(DisallowMultipleComponent), true).Length > 0; + } + + /// This is used to group events. Use it to change several params and fire one single event + public void Transaction(Action action) + { + transactionLevel++; + try + { + action(); + } + finally + { + transactionLevel--; + if (transactionLevel == 0) + { + if (ChangedParams != null) ChangedParams(this, null); + } + } + } + + //======================== descriptor for Editor + /// this descriptor is used by editor + [AttributeUsage(AttributeTargets.Class)] + public class CcDescriptor : Attribute + { + /// Component's name + public string Name { get; set; } + /// Component's desciption + public string Description { get; set; } + /// Component's icon + public string Image { get; set; } + } + /// Retrieves the descriptor from "type" + public static CcDescriptor GetDescriptor(Type type) + { + var propertyInfos = BGReflectionAdapter.GetCustomAttributes(type, typeof(CcDescriptor), false); + if (propertyInfos.Length > 0) return (CcDescriptor) propertyInfos[0]; + return null; + } + + // get Unity's HelpURLAttribute attrubute + private static HelpURLAttribute GetHelpUrl(Type type) + { + var propertyInfos = BGReflectionAdapter.GetCustomAttributes(type,typeof (HelpURLAttribute), false); + if (propertyInfos.Length > 0) return (HelpURLAttribute) propertyInfos[0]; + return null; + } + + //======================== Exception + /// Exception if something is wrong with Cc related stuff + public class CcException :Exception + { + public CcException(string message) : base(message) + { + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCc.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCc.cs.meta new file mode 100644 index 0000000..e2ff3d6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCc.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0ea9b7560ce13a143be3db48f8a69684 +timeCreated: 1471605336 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurve.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurve.cs new file mode 100644 index 0000000..5cf3bba --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurve.cs @@ -0,0 +1,2063 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace BansheeGz.BGSpline.Curve +{ + /// Basic class for spline's points data + [HelpURL("http://www.bansheegz.com/BGCurve/")] + [ExecuteInEditMode] + [DisallowMultipleComponent] + [Serializable] + [AddComponentMenu("BansheeGz/BGCurve/BGCurve")] + public class BGCurve : MonoBehaviour + { + #region static + + //=============================================================================================== + // Static + //=============================================================================================== + + //Package version + public const float Version = 1.22f; + //Epsilon value (very small value, that can be ignored). Assuming 1=1 meter (Unity's recommendation), it equals to (1*10^-5)=10 micrometers + public const float Epsilon = 0.00001f; + + //min snapping distance + public const float MinSnapDistance = 0.1f; + //max snapping distance + public const float MaxSnapDistance = 100; + + //Some private methods names (editor may invoke private methods and fields to properly handle Undo/Redo operations and points mode conversion) + public const string MethodAddPoint = "AddPoint"; + public const string MethodDeletePoint = "Delete"; + public const string MethodSetPointsNames = "SetPointsNames"; + public const string MethodAddField = "AddField"; + public const string MethodDeleteField = "DeleteField"; + public const string MethodConvertPoints = "ConvertPoints"; + + + //Event names (these events are fired at any rate) + public const string EventClosed = "closed is changed"; + public const string EventSnapType = "snapType is changed"; + public const string EventSnapAxis = "snapAxis is changed"; + public const string EventSnapDistance = "snapDistance is changed"; + public const string EventSnapTrigger = "snapTriggerInteraction is changed"; + public const string EventSnapBackfaces = "snapToBackFaces is changed"; + public const string EventSnapLayerMask = "snapLayerMask is changed"; + public const string EventAddField = "add a field"; + public const string EventDeleteField = "delete a field"; + public const string EventFieldName = "field name is changed"; + public const string Event2D = "2d mode is changed"; + public const string EventForceUpdate = "force update is changed"; + + public const string EventPointsMode = "points mode is changed"; + public const string EventClearAllPoints = "clear all points"; + public const string EventAddPoint = "add a point"; + public const string EventAddPoints = "add points"; + public const string EventDeletePoints = "delete points"; + public const string EventSwapPoints = "swap points"; + public const string EventReversePoints = "reverse points"; + + + //Event names (these events are fired only if events args are enabled). this is done for performance sake + public const string EventTransaction = "changes in transaction"; + public const string EventTransform = "transform is changed"; + public const string EventForcedUpdate = "forced update"; + public const string EventPointPosition = "point position is changed"; + public const string EventPointTransform = "point transform is changed"; + public const string EventPointControl = "point control is changed"; + public const string EventPointControlType = "point control type is changed"; + public const string EventPointField = "point field value is changed"; + + //static reusable array for snapping double sided + private static readonly RaycastHit[] raycastHitArray = new RaycastHit[50]; + //static reusable array for deleting points + private static readonly BGCurvePointI[] pointArray = new BGCurvePointI[1]; + //static reusable list for storing Unity objects + private static readonly List pointsList = new List(); + //static reusable list for storing points index + private static readonly List pointsIndexesList = new List(); + + #endregion + + #region enums + + //=============================================================================================== + // Enums + //=============================================================================================== + + /// 2D mode for a curve. If mode is on, only 2 points and controls coordinates matter, the third one is always 0 + public enum Mode2DEnum + { + Off, + XY, + XZ, + YZ + } + + /// + /// Snap mode for a curve. If mode is on, every curve's point (and every approximation point, if mode=Curve) will be snapped to the closest collider if any. + /// With 'Curve' mode, Base Math gives better result, than Adaptive Math, cause it splits the curve into equal parts. + /// Note, 'Curve' mode will add a huge overhead if you are changing the curve at runtime, cause for every approximation point 2 raycasts will be cast + /// + public enum SnapTypeEnum + { + /// No snapping + Off, + + /// Only curve's points are snapped + Points, + + /// Both curve's points and approximation points are snapped + Curve + } + + /// Snapping axis. For terrain use Y + public enum SnapAxisEnum + { + X, + Y, + Z + } + + /// Then events are fired + public enum EventModeEnum + { + /// events are fired once per frame in Update + Update, + + /// events are fired once per frame in LateUpdate. Use it if you are using animations + LateUpdate, + + /// events are suppressed + NoEvents + } + + /// Force Changed event firing + public enum ForceChangedEventModeEnum + { + /// Changed event is fired only if some change is detected + Off, + + /// Forced Changed event is fired only in Editor + EditorOnly, + + /// Forced Changed event is fired in Editor and every frame at Runtime + EditorAndRuntime + } + + /// How points are stored + public enum PointsModeEnum + { + /// Points are stored right inside curve's components. + Inlined, + + /// Points are stored as separate components(MonoBehaviours) attached to curve's GameObject. + Components, + + /// Points are stored as separate components(MonoBehaviours) attached to their own GameObjects. Unity's transform is not used. + GameObjectsNoTransform, + + /// + /// Points are stored as separate components(MonoBehaviours) attached to their own GameObjects. Unity's transform position is used as point position. + /// Rotation and Scale affects controls positions. + /// + GameObjectsTransform + } + + #endregion + + #region Fields & Events & Props & Delegates + + //=============================================================================================== + // Fields + //=============================================================================================== + + +#if UNITY_EDITOR + // ============================================== !!! This is editor ONLY field +#pragma warning disable 0414 + [SerializeField] private BGCurveSettings settings = new BGCurveSettings(); +#pragma warning restore 0414 +#endif + + // ======================================= Delegates + + /// Iteration method callback, used by ForEach method for iterating over each point + public delegate void IterationCallback(BGCurvePointI point, int index, int count); + + // ======================================= Events + + /// Any curve's change. By default events are fired once per frame in Update, set ImmediateChangeEvents to fire event as soon as any change + public event EventHandler Changed; + + /// Before any change. + public event EventHandler BeforeChange; + + // ======================================= Fields (persistent) + + // 2D mode + [Tooltip("2d Mode for a curve. In 2d mode, only 2 coordinates matter, the third will always be 0 (including controls). " + + "Handles in Editor will also be switched to 2d mode")] [SerializeField] private Mode2DEnum mode2D = Mode2DEnum.Off; + + //if curve is closed (e.g. if last and first point are connected) + [Tooltip("If curve is closed")] [SerializeField] private bool closed; + + + //points inlined + [SerializeField] private BGCurvePoint[] points = new BGCurvePoint[0]; + + //points components + [SerializeField] private BGCurvePointComponent[] pointsComponents = new BGCurvePointComponent[0]; + + //points as separate game objects + [SerializeField] private BGCurvePointGO[] pointsGameObjects = new BGCurvePointGO[0]; + + //custom fields + [SerializeField] private BGCurvePointField[] fields = new BGCurvePointField[0]; + + //snapping mode + [Tooltip("Snap type. A collider should exists for points to snap to." + + "\r\n 1) Off - snaping is off" + + "\r\n 2) Points - only curve's points will be snapped." + + "\r\n 3) Curve - both curve's points and split points will be snapped. " + + "With 'Curve' mode Base Math type gives better results, than Adaptive Math, cause snapping occurs after approximation." + + "Also, 'Curve' mode can add a huge overhead if you are changing curve's points at runtime.")] [SerializeField] private SnapTypeEnum snapType = SnapTypeEnum.Off; + + //snapping axis + [Tooltip("Axis for snapping points")] [SerializeField] private SnapAxisEnum snapAxis = SnapAxisEnum.Y; + + //snapping distance + [Tooltip("Snapping distance.")] [SerializeField] [Range(MinSnapDistance, MaxSnapDistance)] private float snapDistance = 10; + + //snapping layer mask + [Tooltip("Layer mask for snapping")] [SerializeField] private LayerMask snapLayerMask = -1; + + //should snapping take triggers into account + [Tooltip("Should snapping takes triggers into account")] [SerializeField] private QueryTriggerInteraction snapTriggerInteraction = QueryTriggerInteraction.UseGlobal; + + //should snapping take triggers into account + [Tooltip("Should snapping takes backfaces of colliders into account")] [SerializeField] private bool snapToBackFaces; + + //events mode + [Tooltip("Event mode for runtime")] [SerializeField] private EventModeEnum eventMode = EventModeEnum.Update; + + //points mode + [Tooltip("Points mode, how points are stored. " + + "\r\n 1) Inline - points stored inlined with the curve's component." + + "\r\n 2) Component - points are stored as MonoBehaviour scripts attached to the curve's GameObject." + + "\r\n 3) GameObject - points are stored as MonoBehaviour scripts attached to separate GameObject for each point.")] [SerializeField] private PointsModeEnum pointsMode = + PointsModeEnum.Inlined; + + //force firing Update event + [Tooltip("Force firing of Changed event. This can be useful if you use Unity's Animation. Do not use it unless you really need it.")] [SerializeField] private ForceChangedEventModeEnum + forceChangedEventMode; + + + // ======================================= Props + /// Curve's points + public BGCurvePointI[] Points + { + get + { + switch (pointsMode) + { + case PointsModeEnum.Inlined: + return points; + case PointsModeEnum.Components: + return pointsComponents; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + return pointsGameObjects; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + } + } + + /// Number of curve's points + public int PointsCount + { + get + { + switch (pointsMode) + { + case PointsModeEnum.Inlined: + return points.Length; + case PointsModeEnum.Components: + return pointsComponents.Length; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + return pointsGameObjects.Length; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + } + } + + /// Curve's custom fields + public BGCurvePointField[] Fields + { + get { return fields; } + } + + /// Number of curve's custom fields + public int FieldsCount + { + get { return fields.Length; } + } + + /// If curve is closed, e.g. last and first points are connected + public bool Closed + { + get { return closed; } + set + { + if (value == closed) return; + FireBeforeChange(EventClosed); + closed = value; + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Points, EventClosed)); + } + } + + /// How points are stored + public PointsModeEnum PointsMode + { + get { return pointsMode; } + set + { + if (pointsMode == value) return; + ConvertPoints(value); + } + } + + + /// In 2d mode only 2 coordinates matter, the 3rd one will always be 0 (including control) + public Mode2DEnum Mode2D + { + get { return mode2D; } + set + { + if (mode2D == value) return; + + Apply2D(value); + } + } + + /// Is 2D mode On? + public bool Mode2DOn + { + get { return mode2D != Mode2DEnum.Off; } + } + + /// Snapping mode + public SnapTypeEnum SnapType + { + get { return snapType; } + set + { + if (snapType == value) return; + FireBeforeChange(EventSnapType); + snapType = value; + if (snapType != SnapTypeEnum.Off) ApplySnapping(); + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Snap, EventSnapType)); + } + } + + /// Snapping axis. For terrain use Y + public SnapAxisEnum SnapAxis + { + get { return snapAxis; } + set + { + if (snapAxis == value) return; + FireBeforeChange(EventSnapAxis); + snapAxis = value; + if (snapType != SnapTypeEnum.Off) ApplySnapping(); + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Snap, EventSnapAxis)); + } + } + + /// Snapping distance + public float SnapDistance + { + get { return snapDistance; } + set + { + if (Math.Abs(snapDistance - value) < Epsilon) return; + + FireBeforeChange(EventSnapDistance); + snapDistance = Mathf.Clamp(value, MinSnapDistance, MaxSnapDistance); + if (snapType != SnapTypeEnum.Off) ApplySnapping(); + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Snap, EventSnapDistance)); + } + } + + /// Should snapping take triggers into account + public QueryTriggerInteraction SnapTriggerInteraction + { + get { return snapTriggerInteraction; } + set + { + if (snapTriggerInteraction == value) return; + + FireBeforeChange(EventSnapTrigger); + snapTriggerInteraction = value; + if (snapType != SnapTypeEnum.Off) ApplySnapping(); + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Snap, EventSnapTrigger)); + } + } + + /// Should snapping take colliders backfaces into account + public bool SnapToBackFaces + { + get { return snapToBackFaces; } + set + { + if (snapToBackFaces == value) return; + + FireBeforeChange(EventSnapBackfaces); + snapToBackFaces = value; + if (snapType != SnapTypeEnum.Off) ApplySnapping(); + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Snap, EventSnapBackfaces)); + } + } + + /// Snapping layer mask + public LayerMask SnapLayerMask + { + get { return snapLayerMask; } + set + { + if (snapLayerMask == value) return; + + FireBeforeChange(EventSnapLayerMask); + snapLayerMask = value; + if (snapType != SnapTypeEnum.Off) ApplySnapping(); + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Snap, EventSnapLayerMask)); + } + } + + /// Force firing of Changed event. This can be useful if you use Unity's Animation. Do not use it unless you really need it. + public ForceChangedEventModeEnum ForceChangedEventMode + { + get { return forceChangedEventMode; } + set + { + if (forceChangedEventMode == value) return; + + FireBeforeChange(EventForceUpdate); + forceChangedEventMode = value; + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Curve, EventForceUpdate)); + } + } + + //------------------------------ these fields are not persistent + //for batch operation (to avoid event firing for every operation) + private int transactionLevel; + + //list of events grouped by transaction (this is used only if UseEventsArgs is set to true) + private List changeList; + + //store custom fields structure for values. see FieldsTree comments for more info + private FieldsTree fieldsTree; + + //changed flag is reset every frame. + private bool changed; + + //fire Changed event as soon as change is made. By default they are grouped within a frame (for performance sake) + private bool immediateChangeEvents; + + //stores event mode for reset after SupressEvent is set to false. + private EventModeEnum eventModeOld = EventModeEnum.Update; + + //keeps last used eventType to use in FireFinalEvent. (if UseEventsArgs is false, we dont keep events list, fired during one single frame, and use only the last one) + private BGCurveChangedArgs.ChangeTypeEnum lastEventType; + + //keeps last event message to use in FireFinalEvent. (if UseEventsArgs is false, we dont keep events list, fired during one single frame, and use only the last one) + private string lastEventMessage; + + //list of points with Transforms attached () + private List pointsWithTransforms; + + + [Obsolete("It is not used anymore and should be removed")] + public bool TraceChanges + { + get { return Changed != null; } + set { } + } + + /// Disable events firing temporarily + public bool SupressEvents + { + get { return eventMode == EventModeEnum.NoEvents; } + set + { + if (value && eventMode != EventModeEnum.NoEvents) eventModeOld = eventMode; + eventMode = value ? EventModeEnum.NoEvents : eventModeOld; + } + } + + /// Use events args (no need for them if you do not use them). + public bool UseEventsArgs { get; set; } + + /// How events are fired + public EventModeEnum EventMode + { + get { return eventMode; } + set { eventMode = value; } + } + + /// Should events be fired immediately after the change. This mode is used by Editors and not recommended for runtime. + public bool ImmediateChangeEvents + { + get { return immediateChangeEvents; } + set { immediateChangeEvents = value; } + } + + //the list of events accumulated during transaction. (this is used only if UseEventsArgs is set to true) + private List ChangeList + { + get { return changeList ?? (changeList = new List()); } + } + + #endregion + + #region Public Functions + + //=============================================================================================== + // Public functions + //=============================================================================================== + // only required ones- no math. to use math use BGCurveBaseMath or BGCurveAdaptiveMath or your own class with provided classes as an example + + // ======================================= Points construction + /// Create a point, world coordinate are used + public BGCurvePoint CreatePointFromWorldPosition(Vector3 worldPos, BGCurvePoint.ControlTypeEnum controlType) + { + return new BGCurvePoint(this, worldPos, controlType, true); + } + + /// Create a point, world coordinate are used + public BGCurvePoint CreatePointFromWorldPosition(Vector3 worldPos, BGCurvePoint.ControlTypeEnum controlType, + Vector3 control1WorldPos, Vector3 control2WorldPos) + { + return new BGCurvePoint(this, worldPos, controlType, control1WorldPos, control2WorldPos, true); + } + + /// Create a point, local coordinate are used + public BGCurvePoint CreatePointFromLocalPosition(Vector3 localPos, BGCurvePoint.ControlTypeEnum controlType) + { + return new BGCurvePoint(this, localPos, controlType); + } + + /// Create a point, local coordinate are used + public BGCurvePoint CreatePointFromLocalPosition(Vector3 localPos, BGCurvePoint.ControlTypeEnum controlType, + Vector3 control1LocalPos, Vector3 control2LocalPos) + { + return new BGCurvePoint(this, localPos, controlType, control1LocalPos, control2LocalPos); + } + + + // ======================================= Points handling + /// Remove all points + public void Clear() + { + var pointsCount = PointsCount; + if (pointsCount == 0) return; + + FireBeforeChange(EventClearAllPoints); + + switch (pointsMode) + { + case PointsModeEnum.Inlined: + points = new BGCurvePoint[0]; + break; + case PointsModeEnum.Components: + if (pointsCount > 0) for (var i = pointsCount - 1; i >= 0; i--) DestroyIt(pointsComponents[i]); + pointsComponents = new BGCurvePointComponent[0]; + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + if (pointsCount > 0) for (var i = pointsCount - 1; i >= 0; i--) DestroyIt(pointsGameObjects[i].gameObject); + pointsGameObjects = new BGCurvePointGO[0]; + break; + } + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Points, EventClearAllPoints)); + } + + /// Returns a point's index + public int IndexOf(BGCurvePointI point) + { + return IndexOf(Points, point); + } + + + /// Add a point to the end + public BGCurvePointI AddPoint(BGCurvePoint point) + { + return AddPoint(point, PointsCount, null); + } + + /// Add a point at specified index + public BGCurvePointI AddPoint(BGCurvePoint point, int index) + { + return AddPoint(point, index, null); + } + + /// Add several points. + public void AddPoints(BGCurvePoint[] points) + { + AddPoints(points, PointsCount, false); + } + + /// Add several points at specified index. + public void AddPoints(BGCurvePoint[] points, int index) + { + AddPoints(points, index, false); + } + + /// Removes a point + public void Delete(BGCurvePointI point) + { + Delete(IndexOf(point), null); + } + + /// Removes a point at specified index + public void Delete(int index) + { + Delete(index, null); + } + + /// Removes several points + public void Delete(BGCurvePointI[] points) + { + Delete(points, null); + } + + /// Swaps 2 points + public void Swap(int index1, int index2) + { + if (index1 < 0 || index1 >= PointsCount || index2 < 0 || index2 >= PointsCount) throw new UnityException("Unable to remove a point. Invalid indexes: " + index1 + ", " + index2); + + FireBeforeChange(EventSwapPoints); + + var points = Points; + + var point1 = points[index1]; + var point2 = points[index2]; + + var hasTransform = point1.PointTransform != null || point2.PointTransform != null; + + points[index2] = point1; + points[index1] = point2; + + if (IsGoMode(pointsMode)) SetPointsNames(); + + if (hasTransform) CachePointsWithTransforms(); + + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Points, EventSwapPoints)); + } + + /// Reverse points order, keeping curve intact + public void Reverse() + { + var pointsCount = PointsCount; + + if (pointsCount < 2) return; + FireBeforeChange(EventReversePoints); + + var points = Points; + var hasFields = FieldsCount > 0; + var pointsMode = PointsMode; + + var mid = pointsCount >> 1; + var countMinusOne = pointsCount - 1; + for (var i = 0; i < mid; i++) + { + var point1 = points[i]; + var point2 = points[countMinusOne - i]; + + var position = point2.PositionLocal; + var controlType = point2.ControlType; + var control1 = point2.ControlFirstLocal; + var control2 = point2.ControlSecondLocal; + var fields2 = hasFields ? GetFieldsValues(point2, pointsMode) : null; + + point2.PositionLocal = point1.PositionLocal; + point2.ControlType = point1.ControlType; + point2.ControlFirstLocal = point1.ControlSecondLocal; + point2.ControlSecondLocal = point1.ControlFirstLocal; + if (hasFields) SetFieldsValues(point2, pointsMode, GetFieldsValues(point1, pointsMode)); + + point1.PositionLocal = position; + point1.ControlType = controlType; + point1.ControlFirstLocal = control2; + point1.ControlSecondLocal = control1; + if (hasFields) SetFieldsValues(point1, pointsMode, fields2); + } + + if (pointsCount%2 != 0) + { + //point at the center- we need to swap controls + var point = points[mid]; + var control = point.ControlFirstLocal; + point.ControlFirstLocal = point.ControlSecondLocal; + point.ControlSecondLocal = control; + } + + if (IsGoMode(pointsMode)) SetPointsNames(); + + CachePointsWithTransforms(); + + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Points, EventReversePoints)); + } + + /// Access a point by index + public BGCurvePointI this[int i] + { + get + { + switch (pointsMode) + { + case PointsModeEnum.Inlined: + return points[i]; + case PointsModeEnum.Components: + return pointsComponents[i]; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + return pointsGameObjects[i]; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + } + set + { + switch (pointsMode) + { + case PointsModeEnum.Inlined: + points[i] = (BGCurvePoint) value; + break; + case PointsModeEnum.Components: + pointsComponents[i] = (BGCurvePointComponent) value; + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + pointsGameObjects[i] = (BGCurvePointGO) value; + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + } + } + + // ============================================== Custom Fields + /// Add a custom field + public BGCurvePointField AddField(string name, BGCurvePointField.TypeEnum type) + { + return AddField(name, type, null); + } + + + /// Delete a custom field + public void DeleteField(BGCurvePointField field) + { + DeleteField(field, null); + } + + /// Get number of field + public int IndexOf(BGCurvePointField field) + { + return IndexOf(fields, field); + } + + /// is curve has a field with provided name + public bool HasField(string name) + { + if (FieldsCount == 0) return false; + foreach (var field in fields) if (String.Equals(name, field.FieldName)) return true; + return false; + } + + /// + /// get the index of field's value within array of values + /// this method is meant to be private, but we can not keep it private cause of performance + /// + public int IndexOfFieldValue(string name) + { + if (fieldsTree == null || !fieldsTree.Comply(fields)) PrivateUpdateFieldsValuesIndexes(); + return fieldsTree.GetIndex(name); + } + + /// all methods, prefixed with Private, are not meant to be called from outside of BGCurve package + // updates indexes for custom fields values. See FieldsTree for details. + public void PrivateUpdateFieldsValuesIndexes() + { + fieldsTree = fieldsTree ?? new FieldsTree(); + fieldsTree.Update(fields); + } + + // ============================================== 2D mode. + /// apply 2D mode to all points + public void Apply2D(Mode2DEnum value) + { + FireBeforeChange(Event2D); + mode2D = value; + + if (mode2D != Mode2DEnum.Off && PointsCount > 0) + { + Transaction(() => + { + var points = Points; + var count = points.Length; + for (var i = 0; i < count; i++) Apply2D(points[i]); + }); + } + else FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Points, Event2D)); + } + + /// change point's coordinate to comply to 2d mode + public virtual void Apply2D(BGCurvePointI point) + { + point.PositionLocal = point.PositionLocal; + point.ControlFirstLocal = point.ControlFirstLocal; + point.ControlSecondLocal = point.ControlSecondLocal; + } + + /// change vector coordinates to comply to 2d mode + public virtual Vector3 Apply2D(Vector3 point) + { + switch (mode2D) + { + case Mode2DEnum.XY: + return new Vector3(point.x, point.y, 0); + case Mode2DEnum.XZ: + return new Vector3(point.x, 0, point.z); + case Mode2DEnum.YZ: + return new Vector3(0, point.y, point.z); + } + return point; + } + + // ============================================== Snapping. + /// apply snapping to all points + public void ApplySnapping() + { + if (snapType == SnapTypeEnum.Off) return; + + var points = Points; + var length = points.Length; + for (var i = 0; i < length; i++) ApplySnapping(points[i]); + } + + /// apply snapping to one single point + public void ApplySnapping(BGCurvePointI point) + { + if (snapType == SnapTypeEnum.Off) return; + var pos = point.PositionWorld; + + if (ApplySnapping(ref pos)) point.PositionWorld = pos; + } + + /// apply snapping to one position and returns true if position was changed + public bool ApplySnapping(ref Vector3 pos) + { + if (snapType == SnapTypeEnum.Off) return false; + + //assign direction + Vector3 direction; + switch (snapAxis) + { + case SnapAxisEnum.Y: + direction = Vector3.up; + break; + case SnapAxisEnum.X: + direction = Vector3.right; + break; + default: + // case SnapAxisEnum.Z: + direction = Vector3.forward; + break; + } + + //cast front side + var resultPos = new Vector3(); + float minDistance = -1; + for (var k = 0; k < 2; k++) + { + var ray = new Ray(pos, k == 0 ? direction : -direction); + + RaycastHit hit; + if (!Physics.Raycast(ray, out hit, snapDistance, snapLayerMask, snapTriggerInteraction)) continue; + + if (!(minDistance < 0) && !(minDistance > hit.distance)) continue; + + minDistance = hit.distance; + resultPos = hit.point; + } + + //cast back side + if (snapToBackFaces) + { + for (var j = 0; j < 2; j++) + { + var count = Physics.RaycastNonAlloc(j == 0 + ? new Ray(new Vector3(pos.x + direction.x*snapDistance, pos.y + direction.y*snapDistance, pos.z + direction.z*snapDistance), -direction) + : new Ray(new Vector3(pos.x - direction.x*snapDistance, pos.y - direction.y*snapDistance, pos.z - direction.z*snapDistance), direction), + raycastHitArray, snapDistance, snapLayerMask, snapTriggerInteraction); + if (count == 0) continue; + + //iterate all unsorted results + for (var i = 0; i < count; i++) + { + var raycastHit = raycastHitArray[i]; + var distanceToCheck = snapDistance - raycastHit.distance; + if (!(minDistance < 0) && !(minDistance > distanceToCheck)) continue; + + minDistance = distanceToCheck; + resultPos = raycastHit.point; + } + } + } + + if (minDistance < 0) return false; + + //assign new pos + pos = resultPos; + + return true; + } + + + // ============================================== batch handling (to avoid event firing for every operation). + /// + /// Executes a batch operation. + /// During batch operation events firing will be suppressed, and event will be fired only after Transaction. + /// it is for event handling only . + /// + public void Transaction(Action action) + { + FireBeforeChange(EventTransaction); + transactionLevel++; + if (UseEventsArgs && transactionLevel == 1) ChangeList.Clear(); + try + { + action(); + } + finally + { + transactionLevel--; + if (transactionLevel == 0) + { + FireChange(UseEventsArgs + ? BGCurveChangedArgs.GetInstance(this, ChangeList.ToArray(), EventTransaction) + : null); + if (UseEventsArgs) ChangeList.Clear(); + } + } + } + + /// Current transaction level. + public int TransactionLevel + { + get { return transactionLevel; } + } + + // search for index within array + protected internal static int IndexOf(T[] array, T item) + { + return Array.IndexOf(array, item); + } + + + // ============================================== event handling + /// Fires BeforeChange event if not within transaction and events are not suppressed. + public void FireBeforeChange(string operation) + { + if (eventMode == EventModeEnum.NoEvents || transactionLevel > 0 || BeforeChange == null) return; + + BeforeChange(this, UseEventsArgs ? BGCurveChangedArgs.BeforeChange.GetInstance(operation) : null); + } + + /// Fires Changed event (if some conditions are met) + public void FireChange(BGCurveChangedArgs change, bool ignoreEventsGrouping = false, object sender = null) + { + if (eventMode == EventModeEnum.NoEvents || Changed == null) return; + + if (transactionLevel > 0 || (!immediateChangeEvents && !ignoreEventsGrouping)) + { + changed = true; + if (change != null) + { + lastEventType = change.ChangeType; + lastEventMessage = change.Message; + } + if (UseEventsArgs && !ChangeList.Contains(change)) ChangeList.Add((BGCurveChangedArgs) change.Clone()); + return; + } + + Changed(sender ?? this, change); + } + + // ============================================== Unity callbacks + public void Start() + { + CachePointsWithTransforms(); + } + + // Unity's Update callback + protected virtual void Update() + { + // is transform.hasChanged is true by default? + if (Time.frameCount == 1) transform.hasChanged = false; + if (eventMode != EventModeEnum.Update || Changed == null) return; + FireFinalEvent(); + } + + // Unity's LateUpdate callback + protected virtual void LateUpdate() + { + if (eventMode != EventModeEnum.LateUpdate || Changed == null) return; + FireFinalEvent(); + } + + // ============================================== Utility methods + /// world position to local position + public Vector3 ToLocal(Vector3 worldPoint) + { + return transform.InverseTransformPoint(worldPoint); + } + + /// local position to world position + public Vector3 ToWorld(Vector3 localPoint) + { + return transform.TransformPoint(localPoint); + } + + /// direction from world to local + public Vector3 ToLocalDirection(Vector3 direction) + { + return transform.InverseTransformDirection(direction); + } + + /// direction from local to world + public Vector3 ToWorldDirection(Vector3 direction) + { + return transform.TransformDirection(direction); + } + + /// execute Action for each point. Params are Point,index,length. + public void ForEach(IterationCallback iterationCallback) + { + //do not replace PointsCount with local var, cause it can be changed while iteration + for (var i = 0; i < PointsCount; i++) iterationCallback(Points[i], i, PointsCount); + } + + //update points GameObjects names and sort + private void SetPointsNames() + { + try + { + if (gameObject == null) return; + } + catch (MissingReferenceException) + { + return; + } + + var name = gameObject.name; + var length = pointsGameObjects.Length; + for (var i = 0; i < length; i++) + { + var go = pointsGameObjects[i].gameObject; + + //set name + go.name = name + "[" + i + "]"; + + //move to bottom + go.transform.SetSiblingIndex(go.transform.parent.childCount - 1); + } + } + + // copy arrays and add a new element + public static T[] Insert(T[] oldArray, int index, T[] newElements) + { + var newArray = new T[oldArray.Length + newElements.Length]; + + //copy before index + if (index > 0) Array.Copy(oldArray, newArray, index); + + //copy after index + if (index < oldArray.Length) Array.Copy(oldArray, index, newArray, index + newElements.Length, oldArray.Length - index); + + //copy new elements + Array.Copy(newElements, 0, newArray, index, newElements.Length); + + return newArray; + } + + // copy arrays and add a new element + public static T[] Insert(T[] oldArray, int index, T newElement) + { + var newArray = new T[oldArray.Length + 1]; + + //copy before index + if (index > 0) Array.Copy(oldArray, newArray, index); + + //copy after index + if (index < oldArray.Length) Array.Copy(oldArray, index, newArray, index + 1, oldArray.Length - index); + + newArray[index] = newElement; + + return newArray; + } + + // copy arrays and removes an element + public static T[] Remove(T[] oldArray, int index) + { + var newArray = new T[oldArray.Length - 1]; + if (index > 0) Array.Copy(oldArray, newArray, index); + + if (index < oldArray.Length - 1) Array.Copy(oldArray, index + 1, newArray, index, oldArray.Length - 1 - index); + + return newArray; + } + + /// standard c# toString override + public override string ToString() + { + return "BGCurve [id=" + GetInstanceID() + "], points=" + PointsCount; + } + + /// if this mode uses separate GameObjects for points + public static bool IsGoMode(PointsModeEnum pointsMode) + { + return pointsMode == PointsModeEnum.GameObjectsNoTransform || pointsMode == PointsModeEnum.GameObjectsTransform; + } + + // ============================================== Point's transforms + /// all methods, prefixed with Private, are not meant to be called from outside of BGCurve package + //if a transform was added to a point + public void PrivateTransformForPointAdded(int index) + { + if (index < 0 || PointsCount >= index) return; + if (pointsWithTransforms == null) pointsWithTransforms = new List(); + + if (pointsWithTransforms.IndexOf(index) == -1) pointsWithTransforms.Add(index); + } + + /// all methods, prefixed with Private, are not meant to be called from outside of BGCurve package + //if a transform was removed from a point + public void PrivateTransformForPointRemoved(int index) + { + if (pointsWithTransforms == null || pointsWithTransforms.IndexOf(index) == -1) return; + + pointsWithTransforms.Remove(index); + } + + #endregion + + #region Private Functions + + //=============================================================================================== + // Private functions + //=============================================================================================== + + // ============================================== Points + //add a point. this method is not meant to be public, Editor uses it via reflection + private BGCurvePointI AddPoint(BGCurvePoint point, int index, Func provider = null) + { + if (index < 0 || index > PointsCount) throw new UnityException("Unable to add a point. Invalid index: " + index); + + FireBeforeChange(EventAddPoint); + + BGCurvePointI result; + + //insert a point + switch (pointsMode) + { + case PointsModeEnum.Inlined: + points = Insert(points, index, point); + result = point; + break; + + case PointsModeEnum.Components: + var pointComponent = (BGCurvePointComponent) Convert(point, PointsModeEnum.Inlined, pointsMode, provider); + pointsComponents = Insert(pointsComponents, index, pointComponent); + result = pointComponent; + break; + + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + var pointGameObject = (BGCurvePointGO) Convert(point, PointsModeEnum.Inlined, pointsMode, provider); + pointsGameObjects = Insert(pointsGameObjects, index, pointGameObject); + + SetPointsNames(); + + result = pointGameObject; + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + + //fields + if (FieldsCount > 0) + { + var fieldValues = GetFieldsValues(result, pointsMode); + foreach (var field in fields) BGCurvePoint.PrivateFieldAdded(field, fieldValues); + } + + //point transforms + if ((point.PointTransform != null) || (pointsWithTransforms != null && pointsWithTransforms.Count > 0)) CachePointsWithTransforms(); + + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Point, EventAddPoint)); + + return result; + } + + //retrieve fields values from point + private BGCurvePoint.FieldsValues GetFieldsValues(BGCurvePointI point, PointsModeEnum pointsMode) + { + BGCurvePoint.FieldsValues fieldValues; + switch (pointsMode) + { + case PointsModeEnum.Inlined: + fieldValues = ((BGCurvePoint) point).PrivateValuesForFields; + break; + case PointsModeEnum.Components: + fieldValues = ((BGCurvePointComponent) point).Point.PrivateValuesForFields; + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + fieldValues = ((BGCurvePointGO) point).PrivateValuesForFields; + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + return fieldValues; + } + + //set fields values for point + private void SetFieldsValues(BGCurvePointI point, PointsModeEnum pointsMode, BGCurvePoint.FieldsValues fieldsValues) + { + switch (pointsMode) + { + case PointsModeEnum.Inlined: + ((BGCurvePoint) point).PrivateValuesForFields = fieldsValues; + break; + case PointsModeEnum.Components: + ((BGCurvePointComponent) point).Point.PrivateValuesForFields = fieldsValues; + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + ((BGCurvePointGO) point).PrivateValuesForFields = fieldsValues; + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + } + + // add several points. this method is not meant to be public, Editor uses it via reflection + private void AddPoints(BGCurvePoint[] points, int index, bool skipFieldsProcessing = false, Func provider = null) + { + if (points == null) return; + + var pointsLength = points.Length; + + if (pointsLength == 0) return; + + if (index < 0 || index > PointsCount) throw new UnityException("Unable to add points. Invalid index: " + index); + + + FireBeforeChange(EventAddPoints); + + BGCurvePointI[] addedPoints; + var hasPointTransform = pointsWithTransforms != null && pointsWithTransforms.Count > 0; + + //add points + switch (pointsMode) + { + case PointsModeEnum.Inlined: + + this.points = Insert(this.points, index, points); + if (!hasPointTransform) + { + for (var i = 0; i < pointsLength; i++) + { + if (points[i].PointTransform == null) continue; + hasPointTransform = true; + break; + } + } + addedPoints = points; + break; + case PointsModeEnum.Components: + + var toAdd = new BGCurvePointComponent[pointsLength]; + for (var i = 0; i < pointsLength; i++) + { + var point = points[i]; + hasPointTransform = hasPointTransform || point.PointTransform != null; + toAdd[i] = (BGCurvePointComponent) Convert(point, PointsModeEnum.Inlined, pointsMode, provider); + } + pointsComponents = Insert(pointsComponents, index, toAdd); + + addedPoints = points; + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + + var pointsToAdd = new BGCurvePointGO[pointsLength]; + for (var i = 0; i < pointsLength; i++) + { + var point = points[i]; + hasPointTransform = hasPointTransform || point.PointTransform != null; + pointsToAdd[i] = (BGCurvePointGO) Convert(point, PointsModeEnum.Inlined, pointsMode, provider); + } + pointsGameObjects = Insert(pointsGameObjects, index, pointsToAdd); + + SetPointsNames(); + + addedPoints = pointsToAdd; + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + + + //process fields + if (!skipFieldsProcessing && FieldsCount > 0) AddFields(pointsMode, addedPoints); + + //point transforms + if (hasPointTransform) CachePointsWithTransforms(); + + + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Points, EventAddPoints)); + } + + // removes a point. this method is not meant to be public, Editor uses it via reflection + private void Delete(int index, Action destroyer) + { + if (index < 0 || index >= PointsCount) throw new UnityException("Unable to remove a point. Invalid index: " + index); + + switch (pointsMode) + { + case PointsModeEnum.Inlined: + pointArray[0] = points[index]; + break; + case PointsModeEnum.Components: + pointArray[0] = pointsComponents[index]; + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + pointArray[0] = pointsGameObjects[index]; + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + Delete(pointArray, destroyer); + } + + // removes points. this method is not meant to be public, Editor uses it via reflection + private void Delete(BGCurvePointI[] pointsToDelete, Action destroyer) + { + if (pointsToDelete == null || pointsToDelete.Length == 0 || PointsCount == 0) return; + + pointsList.Clear(); + pointsIndexesList.Clear(); + + var oldPoints = Points; + + //find point indexes + var length = pointsToDelete.Length; + for (var i = 0; i < length; i++) + { + var index = Array.IndexOf(oldPoints, pointsToDelete[i]); + if (index >= 0) pointsIndexesList.Add(index); + } + + //no luck + if (pointsIndexesList.Count == 0) return; + + //at this point we know for sure we have to delete at least one point + FireBeforeChange(EventDeletePoints); + + //assign new array + var newLength = oldPoints.Length - pointsIndexesList.Count; + BGCurvePointI[] newPoints; + switch (pointsMode) + { + case PointsModeEnum.Inlined: + points = new BGCurvePoint[newLength]; + newPoints = points; + break; + case PointsModeEnum.Components: + pointsComponents = new BGCurvePointComponent[newLength]; + newPoints = pointsComponents; + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + pointsGameObjects = new BGCurvePointGO[newLength]; + newPoints = pointsGameObjects; + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + + //sort indexes to delete + pointsIndexesList.Sort(); + + //fill new array + var cursor = 0; + var count = pointsIndexesList.Count; + for (var i = 0; i < count; i++) + { + var indexToRemove = pointsIndexesList[i]; + + if (indexToRemove > cursor) Array.Copy(oldPoints, cursor, newPoints, cursor - i, indexToRemove - cursor); + + cursor = indexToRemove + 1; + + switch (pointsMode) + { + case PointsModeEnum.Components: + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + pointsList.Add(oldPoints[indexToRemove]); + break; + } + } + if (cursor < oldPoints.Length) Array.Copy(oldPoints, cursor, newPoints, cursor - count, oldPoints.Length - cursor); + + + //sort and set new names for GO points + switch (pointsMode) + { + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + SetPointsNames(); + break; + } + + //destroy + if (pointsList.Count > 0) + { + var pointsCount = pointsList.Count; + for (var i = 0; i < pointsCount; i++) + { + var toDelete = pointsList[i]; + + if (destroyer != null) destroyer(toDelete); + else + { + switch (pointsMode) + { + case PointsModeEnum.Components: + DestroyIt((Object) toDelete); + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + DestroyIt(((BGCurvePointGO) toDelete).gameObject); + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + } + } + } + + CachePointsWithTransforms(); + + pointsList.Clear(); + pointsIndexesList.Clear(); + + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Points, EventDeletePoints)); + } + + // ============================================== Point conversion + //convert between points store options, attached to GameObject. it's also accessed via reflection by Editor + // !! NOTE: do not change the order of different actions- it affects Undo/Redo operations + private void ConvertPoints(PointsModeEnum pointsMode, Func provider = null, Action destroyer = null) + { + var oldMode = PointsMode; + if (oldMode == pointsMode) return; + + FireBeforeChange(EventPointsMode); + + switch (oldMode) + { + case PointsModeEnum.Inlined: + + if (points.Length > 0) + { + //------------------------------------------------------- from inlined + + switch (pointsMode) + { + case PointsModeEnum.Components: + { + // to components + var toAdd = new BGCurvePointComponent[points.Length]; + for (var i = 0; i < points.Length; i++) toAdd[i] = (BGCurvePointComponent) Convert(points[i], oldMode, pointsMode, provider); + + this.pointsMode = pointsMode; + pointsComponents = Insert(pointsComponents, 0, toAdd); + + //no need to process fields, cause the same point is reused + } + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + { + // to gameobjects + var toAdd = new BGCurvePointGO[points.Length]; + + for (var i = 0; i < points.Length; i++) toAdd[i] = (BGCurvePointGO) Convert(points[i], oldMode, pointsMode, provider); + + this.pointsMode = pointsMode; + pointsGameObjects = Insert(pointsGameObjects, 0, toAdd); + + SetPointsNames(); + + //fields + if (FieldsCount > 0) AddFields(pointsMode, toAdd); + } + break; + } + points = new BGCurvePoint[0]; + } + break; + case PointsModeEnum.Components: + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + + var hasAnyPoint = oldMode == PointsModeEnum.Components && pointsComponents.Length > 0 || (IsGoMode(oldMode) && pointsGameObjects.Length > 0); + + if (hasAnyPoint) + { + //------------------------------------------------------- from components OR from GO + BGCurvePointI[] toRemove = null; + if (oldMode == PointsModeEnum.Components) + { + //------------------------------------------------------- from components + switch (pointsMode) + { + case PointsModeEnum.Inlined: + var pointsToAdd = new BGCurvePoint[pointsComponents.Length]; + + for (var i = 0; i < pointsComponents.Length; i++) pointsToAdd[i] = (BGCurvePoint) Convert(pointsComponents[i], oldMode, pointsMode, provider); + + points = Insert(points, 0, pointsToAdd); + + //no need to process fields, cause the same point is reused + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + var toAdd = new BGCurvePointGO[pointsComponents.Length]; + + for (var i = 0; i < pointsComponents.Length; i++) toAdd[i] = (BGCurvePointGO) Convert(pointsComponents[i], oldMode, pointsMode, provider); + + pointsGameObjects = Insert(pointsGameObjects, 0, toAdd); + + SetPointsNames(); + + //fields + if (FieldsCount > 0) AddFields(pointsMode, toAdd); + + break; + } + + toRemove = pointsComponents; + pointsComponents = new BGCurvePointComponent[0]; + } + else + { + //------------------------------------------------------- from GO + + switch (pointsMode) + { + case PointsModeEnum.Inlined: + + var pointsToAdd = new BGCurvePoint[pointsGameObjects.Length]; + + for (var i = 0; i < pointsGameObjects.Length; i++) pointsToAdd[i] = (BGCurvePoint) Convert(pointsGameObjects[i], oldMode, pointsMode, provider); + + points = Insert(points, 0, pointsToAdd); + + toRemove = pointsGameObjects; + break; + + case PointsModeEnum.Components: + + var toAdd = new BGCurvePointComponent[pointsGameObjects.Length]; + + for (var i = 0; i < pointsGameObjects.Length; i++) toAdd[i] = (BGCurvePointComponent) Convert(pointsGameObjects[i], oldMode, pointsMode, provider); + + pointsComponents = Insert(pointsComponents, 0, toAdd); + + toRemove = pointsGameObjects; + break; + + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + + for (var i = 0; i < pointsGameObjects.Length; i++) Convert(pointsGameObjects[i], oldMode, pointsMode, provider); + break; + } + + if (toRemove != null) pointsGameObjects = new BGCurvePointGO[0]; + } + + //------------------------------------------------------- from components OR from GO + //do not remove (it's here for undo/redo) + this.pointsMode = pointsMode; + if (toRemove != null) + { + //here we need to destroy Unity's persistent objects we dont use anymore (it should be the last action) + var useComponents = oldMode == PointsModeEnum.Components; + for (var i = 0; i < toRemove.Length; i++) + { + var pointComponent = toRemove[i]; + + if (destroyer != null) destroyer(pointComponent); + else DestroyIt(useComponents ? (Object) pointComponent : ((BGCurvePointGO) pointComponent).gameObject); + } + } + } + + break; + default: + throw new ArgumentOutOfRangeException("pointsMode"); + } + + this.pointsMode = pointsMode; + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Points, EventPointsMode)); + } + + //convert point's mode + private static BGCurvePointI Convert(BGCurvePointI point, PointsModeEnum from, PointsModeEnum to, Func provider) + { + BGCurvePointI result; + switch (from) + { + case PointsModeEnum.Inlined: + //------------------------------------------ From inline + switch (to) + { + case PointsModeEnum.Components: + + //---------- To components + + result = provider == null ? point.Curve.gameObject.AddComponent() : (BGCurvePointComponent) provider(); + ((BGCurvePointComponent) result).PrivateInit((BGCurvePoint) point); + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + + //---------- To GO + result = ConvertInlineToGo((BGCurvePoint) point, to, provider); + break; + default: + throw new ArgumentOutOfRangeException("to", to, null); + } + break; + case PointsModeEnum.Components: + //------------------------------------------ From Component + switch (to) + { + case PointsModeEnum.Inlined: + + //---------- To inline + + result = ((BGCurvePointComponent) point).Point; + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + + //---------- To GO + result = ConvertInlineToGo(((BGCurvePointComponent) point).Point, to, provider); + break; + default: + throw new ArgumentOutOfRangeException("to", to, null); + } + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + //------------------------------------------ From GO + + switch (to) + { + case PointsModeEnum.Inlined: + + //---------- To inline + + result = ConvertGoToInline((BGCurvePointGO) point, from); + break; + + case PointsModeEnum.Components: + + //---------- To Component + + result = provider != null ? (BGCurvePointComponent) provider() : point.Curve.gameObject.AddComponent(); + ((BGCurvePointComponent) result).PrivateInit(ConvertGoToInline((BGCurvePointGO) point, from)); + break; + case PointsModeEnum.GameObjectsNoTransform: + case PointsModeEnum.GameObjectsTransform: + ((BGCurvePointGO) point).PrivateInit(null, to); + result = point; + break; + default: + throw new ArgumentOutOfRangeException("to", to, null); + } + break; + default: + throw new ArgumentOutOfRangeException("from", @from, null); + } + + //point references + var pointTransform = point.PointTransform; + if (pointTransform != null) + { + BGCurveReferenceToPoint reference = null; + + if (from != PointsModeEnum.Inlined) reference = BGCurveReferenceToPoint.GetReferenceToPoint(point); + + if (to != PointsModeEnum.Inlined) + { + //not inlined + if (reference == null) reference = pointTransform.gameObject.AddComponent(); + reference.Point = result; + } + else + { + //inlined + if (reference != null) DestroyIt(reference); + } + } + + return result; + } + + //convert point from Inline to GameObject + private static BGCurvePointGO ConvertInlineToGo(BGCurvePoint point, PointsModeEnum to, Func provider) + { + BGCurvePointGO pointGO; + if (provider != null) pointGO = (BGCurvePointGO) provider(); + else + { + var gameObjectForPoint = new GameObject(); + var pointTransform = gameObjectForPoint.transform; + pointTransform.parent = point.Curve.transform; + pointTransform.localRotation = Quaternion.identity; + pointTransform.localPosition = Vector3.zero; + pointTransform.localScale = Vector3.one; + pointGO = gameObjectForPoint.AddComponent(); + } + + pointGO.PrivateInit(point, to); + + //transfer fields + pointGO.PrivateValuesForFields = point.PrivateValuesForFields; + + return pointGO; + } + + //convert point from GameObject to Inline + private static BGCurvePoint ConvertGoToInline(BGCurvePointGO pointGO, PointsModeEnum @from) + { + BGCurvePoint result; + switch (@from) + { + case PointsModeEnum.GameObjectsNoTransform: + result = new BGCurvePoint(pointGO.Curve, pointGO.PointTransform, pointGO.PositionLocal, pointGO.ControlType, pointGO.ControlFirstLocal, pointGO.ControlSecondLocal); + break; + case PointsModeEnum.GameObjectsTransform: + var transform = pointGO.PointTransform != null ? pointGO.PointTransform : pointGO.Curve.transform; + var control1 = transform.InverseTransformVector(pointGO.ControlFirstLocalTransformed); + var control2 = transform.InverseTransformVector(pointGO.ControlSecondLocalTransformed); + result = new BGCurvePoint(pointGO.Curve, pointGO.PointTransform, pointGO.PositionLocal, pointGO.ControlType, control1, control2); + break; + default: + throw new ArgumentOutOfRangeException("PointsModeEnum"); + } + + + //transfer fields + if (pointGO.Curve.FieldsCount > 0) result.PrivateValuesForFields = pointGO.PrivateValuesForFields; + + return result; + } + + + // ============================================== Events + //fires a "final" event. By default events are grouped within single frame and one single event is fired at Update or LateUpdate + private void FireFinalEvent() + { + var transformChanged = transform.hasChanged; + + var forceUpdateEveryFrame = forceChangedEventMode == ForceChangedEventModeEnum.EditorAndRuntime; + + if (!transformChanged && immediateChangeEvents && !forceUpdateEveryFrame) return; + + //check additionally for point's changes + if (pointsMode == PointsModeEnum.GameObjectsTransform) + { + var points = (BGCurvePointGO[]) Points; + var length = points.Length; + for (var i = 0; i < length; i++) + { + var point = points[i]; + var pointTransform = point.gameObject.transform; + if (!pointTransform.hasChanged) continue; + + pointTransform.hasChanged = false; + changed = true; + lastEventType = BGCurveChangedArgs.ChangeTypeEnum.Points; + lastEventMessage = EventPointPosition; + } + } + + //check points transforms + if (pointsWithTransforms != null) + { + var pointsWithTransformsCount = pointsWithTransforms.Count; + if (pointsWithTransformsCount > 0) + { + var points = Points; + var pointCount = points.Length; + for (var i = 0; i < pointsWithTransformsCount; i++) + { + var index = pointsWithTransforms[i]; + if (index >= pointCount) continue; + + var point = points[index]; + var pointTransform = point.PointTransform; + if (pointTransform == null || !pointTransform.hasChanged) continue; + + pointTransform.hasChanged = false; + changed = true; + lastEventType = BGCurveChangedArgs.ChangeTypeEnum.Points; + lastEventMessage = EventPointPosition; + } + } + } + + if (!transformChanged && !changed && !forceUpdateEveryFrame) return; + + if (changed) FireChange(UseEventsArgs ? BGCurveChangedArgs.GetInstance(this, lastEventType, lastEventMessage) : null, true); + else if (transformChanged) FireChange(UseEventsArgs ? BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.CurveTransform, EventTransform) : null, true); + else FireChange(UseEventsArgs ? BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Curve, EventForcedUpdate) : null, true); + + transform.hasChanged = changed = false; + } + + + // ============================================== Fields + + //add fields to provided points + private void AddFields(PointsModeEnum pointsMode, BGCurvePointI[] addedPoints) + { + foreach (var point in addedPoints) + { + var fieldsValues = GetFieldsValues(point, pointsMode); + foreach (var field in fields) BGCurvePoint.PrivateFieldAdded(field, fieldsValues); + } + } + + //add a custom field. this method is not meant to be public, Editor uses it via reflection + private BGCurvePointField AddField(string name, BGCurvePointField.TypeEnum type, Func provider = null) + { + //check if name is ok + BGCurvePointField.CheckName(this, name, true); + + FireBeforeChange(EventAddField); + + //at this point the change is certainly will occur + //add a field + var field = provider == null ? gameObject.AddComponent() : provider(); + field.hideFlags = HideFlags.HideInInspector; + field.Init(this, name, type); + + fields = Insert(fields, fields.Length, field); + + PrivateUpdateFieldsValuesIndexes(); + + if (PointsCount > 0) + { + //update all points + var points = Points; + foreach (var point in points) BGCurvePoint.PrivateFieldAdded(field, GetFieldsValues(point, pointsMode)); + } + + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Fields, EventAddField)); + + return field; + } + + // delete a custom field. this method is not meant to be public, Editor uses it via reflection + private void DeleteField(BGCurvePointField field, Action destroyer = null) + { + //find field index + var deletedIndex = IndexOf(fields, field); + if (deletedIndex < 0 || deletedIndex >= fields.Length) throw new UnityException("Unable to remove a fields. Invalid index: " + deletedIndex); + + //get the index for field's value + var indexOfField = IndexOfFieldValue(field.FieldName); + + FireBeforeChange(EventDeleteField); + + //at this point the change is certainly will occur + //remove field from list + fields = Remove(fields, deletedIndex); + + //update fields values indexes. See FieldsTree commments for more details + PrivateUpdateFieldsValuesIndexes(); + + if (PointsCount > 0) + { + //update all points + var points = Points; + foreach (var point in points) BGCurvePoint.PrivateFieldDeleted(field, indexOfField, GetFieldsValues(point, pointsMode)); + } + + //destroy field component + if (destroyer == null) DestroyIt(field); + else destroyer(field); + + + FireChange(BGCurveChangedArgs.GetInstance(this, BGCurveChangedArgs.ChangeTypeEnum.Fields, EventDeleteField)); + } + + // ============================================== Point's transforms + //find points with Transforms attached + private void CachePointsWithTransforms() + { + if (pointsWithTransforms != null) pointsWithTransforms.Clear(); + var points = Points; + var count = points.Length; + for (var i = 0; i < count; i++) + { + if (points[i].PointTransform != null) + { + if (pointsWithTransforms == null) pointsWithTransforms = new List(); + pointsWithTransforms.Add(i); + } + } + } + + // ============================================== Utils + //destroy Unity object + public static void DestroyIt(Object obj) + { + if (Application.isEditor) DestroyImmediate(obj); + else Destroy(obj); + } + + #endregion + + #region Private Classes + + //=============================================================================================== + // Private classes + //=============================================================================================== + + // stores info about how fields values should be stored. + // fields values are stored in arrays, so we need to keep track of index within this array for each field + private sealed class FieldsTree + { + private readonly Dictionary fieldName2Index = new Dictionary(); + + /// if current index is up-to-date? + public bool Comply(BGCurvePointField[] fields) + { + return fields == null ? fieldName2Index.Count == 0 : fieldName2Index.Count == fields.Length; + } + + /// get index by field's name + public int GetIndex(string name) + { + int index; + if (fieldName2Index.TryGetValue(name, out index)) return index; + throw new UnityException("Can not find a index of field " + name); + } + + /// update whole index + public void Update(BGCurvePointField[] fields) + { + fieldName2Index.Clear(); + int boolIndex = 0, + intIndex = 0, + floatIndex = 0, + vector3Index = 0, + boundsIndex = 0, + colorIndex = 0, + stringIndex = 0, + quaternionIndex = 0, + animationCurveIndex = 0, + gameObjectIndex = 0, + componentIndex = 0, + bgCurveIndex = 0, + bgCurvePointComponentIndex = 0, + bgCurvePointGOIndex = 0; + + foreach (var field in fields) + { + int index; + switch (field.Type) + { + case BGCurvePointField.TypeEnum.Bool: + index = boolIndex++; + break; + case BGCurvePointField.TypeEnum.Int: + index = intIndex++; + break; + case BGCurvePointField.TypeEnum.Float: + index = floatIndex++; + break; + case BGCurvePointField.TypeEnum.Vector3: + index = vector3Index++; + break; + case BGCurvePointField.TypeEnum.Bounds: + index = boundsIndex++; + break; + case BGCurvePointField.TypeEnum.Color: + index = colorIndex++; + break; + case BGCurvePointField.TypeEnum.String: + index = stringIndex++; + break; + case BGCurvePointField.TypeEnum.Quaternion: + index = quaternionIndex++; + break; + case BGCurvePointField.TypeEnum.AnimationCurve: + index = animationCurveIndex++; + break; + case BGCurvePointField.TypeEnum.GameObject: + index = gameObjectIndex++; + break; + case BGCurvePointField.TypeEnum.Component: + index = componentIndex++; + break; + case BGCurvePointField.TypeEnum.BGCurve: + index = bgCurveIndex++; + break; + case BGCurvePointField.TypeEnum.BGCurvePointComponent: + index = bgCurvePointComponentIndex++; + break; + case BGCurvePointField.TypeEnum.BGCurvePointGO: + index = bgCurvePointGOIndex++; + break; + default: + throw new UnityException("Unknown type " + field.Type); + } + + fieldName2Index[field.FieldName] = index; + } + } + } + + #endregion + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurve.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurve.cs.meta new file mode 100644 index 0000000..69f5610 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurve.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e70f079e2a6bf364e8185b765fbe61c0 +timeCreated: 1476942102 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveAdaptiveMath.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveAdaptiveMath.cs new file mode 100644 index 0000000..14352cf --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveAdaptiveMath.cs @@ -0,0 +1,421 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// + /// Adaptive curve subdivision math. It split the spline into uneven parts, based on the curvature. + /// Strictly speaking, it still uses uniform splitting, but it can omit and add points when needed, resulting in better approximation and less points. + /// + public class BGCurveAdaptiveMath : BGCurveBaseMath + { + //------------------------------------------------------------------------ + //min tolerance value + public const float MinTolerance = 0.1f; + //max tolerance value + public const float MaxTolerance = 0.9999750f; + //distance tolerance (to avoid spamming points at one single location) + public const float DistanceTolerance = 0.01f; + //max recursion level + private const int RecursionLimit = 24; + + //force section to recalculate + private bool ignoreSectionChangedCheckOverride; + + //normalized tolerance + private float toleranceRatio; + //normalized tolerance squared + private float toleranceRatioSquared; + + //tolerance + private float tolerance; + + /// Create new math with config options + public BGCurveAdaptiveMath(BGCurve curve, ConfigAdaptive config) + : base(curve, config) + { + } + + /// Init math with new config and recalculate data + public override void Init(Config config) + { + var configAdaptive = (ConfigAdaptive) config; + + tolerance = Mathf.Clamp(configAdaptive.Tolerance, MinTolerance, MaxTolerance); + + //pow 4 + tolerance *= tolerance; + tolerance *= tolerance; + + //normalized + toleranceRatio = 1/(1 - tolerance); + toleranceRatioSquared = toleranceRatio*toleranceRatio; + + //if old tolerance is different- we force section recalculation + ignoreSectionChangedCheckOverride = this.config == null || Math.Abs(((ConfigAdaptive) this.config).Tolerance - tolerance) > BGCurve.Epsilon; + + //recalculate + base.Init(config); + } + + //Reset pooled section with new data and recalculates if needed + protected override bool Reset(SectionInfo section, BGCurvePointI @from, BGCurvePointI to, int pointsCount) + { + return section.Reset(@from, to, section.PointsCount, ignoreSectionChangedCheck || ignoreSectionChangedCheckOverride); + } + + protected override bool IsUseDistanceToAdjustTangents(SectionInfo section, SectionInfo prevSection) + { + return true; + } + + //approximate split section + //this method contains some intentional copy/paste + protected override void CalculateSplitSection(SectionInfo section, BGCurvePointI @from, BGCurvePointI to) + { + //if set to true, tangent formula will be used to calc tangents + var calcTangents = cacheTangent && !config.UsePointPositionsToCalcTangents; + + + var points = section.points; + var count = points.Count; + //move all existing points to the pool (the number of points depends on the curvature) + for (var i = 0; i < count; i++) poolPointInfos.Add(points[i]); + points.Clear(); + + //original points and control types + var p0 = section.OriginalFrom; + var p1 = section.OriginalFromControl; + var p2 = section.OriginalToControl; + var p3 = section.OriginalTo; + + //type of the curve (0-absent,3-both Bezier, 1 or 2 - one of the points has Bezier controls) + var type = (section.OriginalFromControlType != BGCurvePoint.ControlTypeEnum.Absent ? 2 : 0) + (section.OriginalToControlType != BGCurvePoint.ControlTypeEnum.Absent ? 1 : 0); + + //===================================== first point + SectionPointInfo firstPoint; + var poolCursor = poolPointInfos.Count - 1; + if (poolCursor >= 0) + { + firstPoint = poolPointInfos[poolCursor]; + poolPointInfos.RemoveAt(poolCursor); + } + else firstPoint = new SectionPointInfo(); + firstPoint.Position = p0; + firstPoint.DistanceToSectionStart = 0; + points.Add(firstPoint); + + //==================================== split recursively + switch (type) + { + case 3: + RecursiveCubicSplit(section, p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, 0, calcTangents, 0, 1); + break; + case 2: + RecursiveQuadraticSplit(section, p0.x, p0.y, p0.z, p1.x, p1.y, p1.z, p3.x, p3.y, p3.z, 0, false, calcTangents, 0, 1); + break; + case 1: + RecursiveQuadraticSplit(section, p0.x, p0.y, p0.z, p2.x, p2.y, p2.z, p3.x, p3.y, p3.z, 0, true, calcTangents, 0, 1); + break; + } + + //===================================== last point + SectionPointInfo lastPoint; + poolCursor = poolPointInfos.Count - 1; + if (poolCursor >= 0) + { + lastPoint = poolPointInfos[poolCursor]; + poolPointInfos.RemoveAt(poolCursor); + } + else lastPoint = new SectionPointInfo(); + lastPoint.Position = p3; + points.Add(lastPoint); + + + //calculate distances (and optionally tangents) + //if set to true, points positions will be used to calculate tangents + calcTangents = cacheTangent && config.UsePointPositionsToCalcTangents; + var prevPoint = points[0]; + for (var i = 1; i < points.Count; i++) + { + var point = points[i]; + + var pos = point.Position; + var prevPos = prevPoint.Position; + + var dX = (double) pos.x - prevPos.x; + var dY = (double) pos.y - prevPos.y; + var dZ = (double) pos.z - prevPos.z; + + //distance + point.DistanceToSectionStart = prevPoint.DistanceToSectionStart + ((float) Math.Sqrt(dX*dX + dY*dY + dZ*dZ)); + + //tangents + if (calcTangents) point.Tangent = Vector3.Normalize(pos - prevPos); + + prevPoint = point; + } + + //set first and last points tangents (cause they was omitted during recursive split) + if (cacheTangent) + { + if (config.UsePointPositionsToCalcTangents) + { + firstPoint.Tangent = (points[1].Position - firstPoint.Position).normalized; + lastPoint.Tangent = points[points.Count - 2].Tangent; + } + else + { + switch (type) + { + case 0: + firstPoint.Tangent = lastPoint.Tangent = (lastPoint.Position - firstPoint.Position).normalized; + break; + case 1: + firstPoint.Tangent = Vector3.Normalize(section.OriginalToControl - section.OriginalFrom); + lastPoint.Tangent = Vector3.Normalize(section.OriginalTo - section.OriginalToControl); + break; + case 2: + firstPoint.Tangent = Vector3.Normalize(section.OriginalFromControl - section.OriginalFrom); + lastPoint.Tangent = Vector3.Normalize(section.OriginalTo - section.OriginalFromControl); + break; + case 3: + firstPoint.Tangent = Vector3.Normalize(section.OriginalFromControl - section.OriginalFrom); + lastPoint.Tangent = Vector3.Normalize(section.OriginalTo - section.OriginalToControl); + break; + } + } + } + } + + + //------------------------------------------------------------------------ Quadratic + //this method contains some intentional copy/paste + private void RecursiveQuadraticSplit(SectionInfo section, double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, int level, bool useSecond, + bool calcTangents, double fromT, double toT) + { + if (level > RecursionLimit) return; + + // is curve flat + // http://www.malinc.se/m/DeCasteljauAndBezier.php + // sqr(b) + sqr(c) < sqr(a) * tolerance + var dx01 = x0 - x1; + var dy01 = y0 - y1; + var dz01 = z0 - z1; + + var dx12 = x1 - x2; + var dy12 = y1 - y2; + var dz12 = z1 - z2; + + var dx02 = x0 - x2; + var dy02 = y0 - y2; + var dz02 = z0 - z2; + + var a = dx02*dx02 + dy02*dy02 + dz02*dz02; + var b = dx01*dx01 + dy01*dy01 + dz01*dz01; + var c = dx12*dx12 + dy12*dy12 + dz12*dz12; + + var temp = a*toleranceRatioSquared - b - c; + + if (4*b*c < temp*temp || a + b + c < DistanceTolerance) return; + + //at this point we know, the curve is not flat + // split (Casteljau algorithm) + var x01 = (x0 + x1)*.5; + var y01 = (y0 + y1)*.5; + var z01 = (z0 + z1)*.5; + + var x12 = (x1 + x2)*.5; + var y12 = (y1 + y2)*.5; + var z12 = (z1 + z2)*.5; + + var x012 = (x01 + x12)*.5; + var y012 = (y01 + y12)*.5; + var z012 = (z01 + z12)*.5; + + + var t = calcTangents ? (fromT + toT)*.5 : .0; + + var pos = new Vector3((float) x012, (float) y012, (float) z012); + + //apply snapping + if (curve.SnapType == BGCurve.SnapTypeEnum.Curve) curve.ApplySnapping(ref pos); + + //split first section + RecursiveQuadraticSplit(section, x0, y0, z0, x01, y01, z01, x012, y012, z012, level + 1, useSecond, calcTangents, fromT, t); + + //add point + SectionPointInfo pointInfo; + var poolCursor = poolPointInfos.Count - 1; + if (poolCursor >= 0) + { + pointInfo = poolPointInfos[poolCursor]; + poolPointInfos.RemoveAt(poolCursor); + } + else pointInfo = new SectionPointInfo(); + pointInfo.Position = pos; + section.points.Add(pointInfo); + + //tangents + if (calcTangents) + { + var control = useSecond ? section.OriginalToControl : section.OriginalFromControl; + //idea.. optimize it + pointInfo.Tangent = Vector3.Normalize(2*(1 - (float) t)*(control - section.OriginalFrom) + 2*(float) t*(section.OriginalTo - control)); + } + + //split second section + RecursiveQuadraticSplit(section, x012, y012, z012, x12, y12, z12, x2, y2, z2, level + 1, useSecond, calcTangents, t, toT); + } + + + //------------------------------------------------------------------------ Cubic + //this method contains some intentional copy/paste + private void RecursiveCubicSplit(SectionInfo section, double x0, double y0, double z0, double x1, double y1, double z1, double x2, double y2, double z2, double x3, double y3, double z3, + int level, bool calcTangents, double fromT, double toT) + { + if (level > RecursionLimit) return; + + // is curve flat + // http://www.malinc.se/m/DeCasteljauAndBezier.php + // sqr(b) + sqr(c) + sqr(d) < sqr(a) * tolerance + + var dx01 = x0 - x1; + var dy01 = y0 - y1; + var dz01 = z0 - z1; + + var dx12 = x1 - x2; + var dy12 = y1 - y2; + var dz12 = z1 - z2; + + var dx23 = x2 - x3; + var dy23 = y2 - y3; + var dz23 = z2 - z3; + + var dx03 = x0 - x3; + var dy03 = y0 - y3; + var dz03 = z0 - z3; + + var a = dx03*dx03 + dy03*dy03 + dz03*dz03; + var b = dx01*dx01 + dy01*dy01 + dz01*dz01; + var c = dx12*dx12 + dy12*dy12 + dz12*dz12; + var d = dx23*dx23 + dy23*dy23 + dz23*dz23; + + //idea.. optimize sqrt. Sqrt is expensive call, and 3 Sqrt calls is super expensive to say the least + if (Math.Sqrt(b*c) + Math.Sqrt(c*d) + Math.Sqrt(b*d) < (a*toleranceRatioSquared - b - c - d)*.5 || a + b + c + d < DistanceTolerance) return; + + //at this point we know, the curve is not flat + //split (Casteljau algorithm) + var x01 = (x0 + x1)*.5; + var y01 = (y0 + y1)*.5; + var z01 = (z0 + z1)*.5; + var x12 = (x1 + x2)*.5; + var y12 = (y1 + y2)*.5; + var z12 = (z1 + z2)*.5; + var x23 = (x2 + x3)*.5; + var y23 = (y2 + y3)*.5; + var z23 = (z2 + z3)*.5; + + var x012 = (x01 + x12)*.5; + var y012 = (y01 + y12)*.5; + var z012 = (z01 + z12)*.5; + var x123 = (x12 + x23)*.5; + var y123 = (y12 + y23)*.5; + var z123 = (z12 + z23)*.5; + + var x0123 = (x012 + x123)*.5; + var y0123 = (y012 + y123)*.5; + var z0123 = (z012 + z123)*.5; + + var t = calcTangents ? (fromT + toT)*.5 : .0; + + var pos = new Vector3((float) x0123, (float) y0123, (float) z0123); + + if (curve.SnapType == BGCurve.SnapTypeEnum.Curve) curve.ApplySnapping(ref pos); + + //split first section + RecursiveCubicSplit(section, x0, y0, z0, x01, y01, z01, x012, y012, z012, x0123, y0123, z0123, level + 1, calcTangents, fromT, t); + + //add point + SectionPointInfo pointInfo; + var poolCursor = poolPointInfos.Count - 1; + if (poolCursor >= 0) + { + pointInfo = poolPointInfos[poolCursor]; + poolPointInfos.RemoveAt(poolCursor); + } + else pointInfo = new SectionPointInfo(); + pointInfo.Position = pos; + section.points.Add(pointInfo); + + //tangent + if (calcTangents) + { + var tr = 1 - t; + //idea.. optimize it + pointInfo.Tangent = Vector3.Normalize(3*((float) (tr*tr))*(section.OriginalFromControl - section.OriginalFrom) + + 6*(float) (tr*t)*(section.OriginalToControl - section.OriginalFromControl) + + 3*(float) (t*t)*(section.OriginalTo - section.OriginalToControl)); + } + + + //split second section + RecursiveCubicSplit(section, x0123, y0123, z0123, x123, y123, z123, x23, y23, z23, x3, y3, z3, level + 1, calcTangents, t, toT); + } + + /// Configuration options for Adaptive Math + public class ConfigAdaptive : Config + { + /// + /// This parameter is used to calculate if curve's flat and no more splitting is required + /// Note: The final tolerance parameter, used by Math, is based on this value, but differs + /// + public float Tolerance = .2f; + + /// Construct new config + public ConfigAdaptive(Fields fields) : base(fields) + { + } + } + + public override string ToString() + { + return "Adaptive Math for curve (" + Curve + "), sections=" + SectionsCount; + } + } + + /* + Roger Willcocks flat criteria for quadratic (something wrong here) + var ax = 2*x1 - x2 - x0; + var ay = 2*y1 - y2 - y0; + var az = 2*z1 - z2 - z0; + ax *= ax; + ay *= ay; + az *= az; + + if (ax + ay + az < tolerance) return; +*/ + + /* + Roger Willcocks flat criteria for cubic (does not work well at all)- maybe a bbug or something- have no idea + var ax = 3*x1 - 2*x0 - x3; + var ay = 3*y1 - 2*y0 - y3; + var az = 3*z1 - 2*z0 - z3; + ax *= ax; + ay *= ay; + az *= az; + + var bx = 3*x2 - x0 - 2*x3; + var by = 3*y2 - y0 - 2*y3; + var bz = 3*z2 - z0 - 2*z3; + bx *= bx; + by *= by; + bz *= bz; + + if (Math.Max(ax, bx) + Math.Max(ay, by) + Math.Max(az, bz) < tolerance) return; +*/ +/* + // For Willckock's criteria: 16 and exponenta originate from the flatness calculation + tolerance *= tolerance*16; + */ +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveAdaptiveMath.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveAdaptiveMath.cs.meta new file mode 100644 index 0000000..88f470c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveAdaptiveMath.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a072c590a2e0f41498bf52d7125be6f5 +timeCreated: 1475717589 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveBaseMath.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveBaseMath.cs new file mode 100644 index 0000000..a4b273a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveBaseMath.cs @@ -0,0 +1,1587 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// + /// Basic math operations for curves (Distance, Position, Tangent, Closest point ). + /// It caches some data for quick access and recalculate it if curve changes. + /// It uses uniform split with forward differencing algorithm, which is the fastest available (for uniform split). + /// + public class BGCurveBaseMath : BGCurveMathI, IDisposable + { + #region events + + //=============================================================================================== + // Events + //=============================================================================================== + + /// Change was requested by changed curve's data + public event EventHandler ChangeRequested; + + /// Math was changed + public event EventHandler Changed; + + #endregion + + #region fields + + //=============================================================================================== + // Fields + //=============================================================================================== + + /// all possible attributes (fields) to calculate + public enum Field + { + Position = 1, + Tangent = 2, + } + + /// which fields to precalculate + public enum Fields + { + Position = 1, + PositionAndTangent = 3, + } + + //curve + protected readonly BGCurve curve; + //what and how to calc + protected Config config; + + //cached data for length calculations + protected readonly List cachedSectionInfos = new List(); + + // pools for sections + protected readonly List poolSectionInfos = new List(); + // pools for points + protected readonly List poolPointInfos = new List(); + + //curve's length + protected float cachedLength; + + //should we calculate position? (This is probably always true) + protected bool cachePosition; + //should we calculate tangent? + protected bool cacheTangent; + + //closest point calculator + protected BGCurveCalculatorClosestPoint closestPointCalculator; + + // frame when data was recalculated + private int recalculatedAtFrame = -1; + // frame when math was created + private int createdAtFrame; + + // force section recalculation, even if it's not changed + protected bool ignoreSectionChangedCheck; + + //some coefficients (these are used by approximation algorithm) + private double h; + private double h2; + private double h3; + + /// Suppress all warnings, printed to the log + public bool SuppressWarning { get; set; } + + /// get Curve + public BGCurve Curve + { + get { return curve; } + } + + /// Get calculated sections data + public List SectionInfos + { + get { return cachedSectionInfos; } + } + + /// Access calculated section's data by index + public SectionInfo this[int i] + { + get { return cachedSectionInfos[i]; } + } + + /// How much sections in total + public int SectionsCount + { + get { return cachedSectionInfos.Count; } + } + + /// Get last used config + public Config Configuration + { + get { return config; } + } + + // if tangent is calculated and formula is needed + protected bool NeedTangentFormula + { + get { return !config.UsePointPositionsToCalcTangents && cacheTangent; } + } + + /// How much approximation points are used in total + public int PointsCount + { + get + { + if (SectionsCount == 0) return 0; + var count = 0; + var length = cachedSectionInfos.Count; + for (var i = 0; i < length; i++) count += cachedSectionInfos[i].PointsCount; + return count; + } + } + + #endregion + + #region constructors + + //=============================================================================================== + // Constructors + //=============================================================================================== + + /// Math with default config settings + public BGCurveBaseMath(BGCurve curve) : this(curve, new Config(Fields.Position)) + { + } + + /// Math with config settings + public BGCurveBaseMath(BGCurve curve, Config config) + { + this.curve = curve; + curve.Changed += CurveChanged; + Init(config ?? new Config(Fields.Position)); + } + + /// This is an old constructor, left for compatibility. Only Fields.PositionWorld is calculated. + /// Use another constructor to specify which fields and how need to be calculated. + [Obsolete("Use another constructors")] + public BGCurveBaseMath(BGCurve curve, bool traceChanges, int parts = 30, bool usePointPositionsToCalcTangents = false) + : this(curve, new Config(Fields.Position) {Parts = parts, UsePointPositionsToCalcTangents = usePointPositionsToCalcTangents}) + { + } + + #endregion + + #region Init + + //=============================================================================================== + // Init + //=============================================================================================== + /// Init math with new config and recalculate it's data + public virtual void Init(Config config) + { + //if we calculated positions before (but not tangent) we should skip the check if section was changed or not and force recalculation (cause positions may not change) + if (this.config != null) + { + ignoreSectionChangedCheck = this.config.Fields == Fields.Position && config.Fields == Fields.PositionAndTangent; + this.config.Update -= ConfigOnUpdate; + } + else + { + ignoreSectionChangedCheck = false; + } + + //assign new config + this.config = config; + config.Parts = Mathf.Clamp(config.Parts, 1, 1000); + this.config.Update += ConfigOnUpdate; + + createdAtFrame = Time.frameCount; + cachePosition = Field.Position.In(config.Fields.Val()); + cacheTangent = Field.Tangent.In(config.Fields.Val()); + + //No fields- no need to calculate or trace anything. + if (!cachePosition && !cacheTangent) + throw new UnityException("No fields were chosen. Create math like this: new BGCurveBaseMath(curve, new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.Position))"); + + //some additional init steps for subclasses + AfterInit(config); + + //calculate data, based on new config + Recalculate(true); + } + + //some additional initialization for subclasses + protected virtual void AfterInit(Config config) + { + } + + #endregion + + #region Public methods + + //=============================================================================================== + // Public methods + //=============================================================================================== + + //=========================================== Calculate by formula + + /// Calculate point world position between 2 points by a formula. This is a slow method + /// Ratio between (0,1) + /// Use local coordinates instead of world + public virtual Vector3 CalcPositionByT(BGCurvePoint @from, BGCurvePoint to, float t, bool useLocal = false) + { + t = Mathf.Clamp01(t); + + var fromPos = useLocal ? from.PositionLocal : from.PositionWorld; + var toPos = useLocal ? to.PositionLocal : to.PositionWorld; + + Vector3 result; + if (from.ControlType == BGCurvePoint.ControlTypeEnum.Absent && to.ControlType == BGCurvePoint.ControlTypeEnum.Absent) + { + //lerp + result = fromPos + ((toPos - fromPos)*t); + } + else + { + var fromPosHandle = useLocal ? from.ControlSecondLocal + fromPos : from.ControlSecondWorld; + var toPosHandle = useLocal ? to.ControlFirstLocal + toPos : to.ControlFirstWorld; + + result = (from.ControlType != BGCurvePoint.ControlTypeEnum.Absent && to.ControlType != BGCurvePoint.ControlTypeEnum.Absent) + ? BGCurveFormulas.BezierCubic(t, fromPos, fromPosHandle, toPosHandle, toPos) + : BGCurveFormulas.BezierQuadratic(t, fromPos, (@from.ControlType == BGCurvePoint.ControlTypeEnum.Absent) ? toPosHandle : fromPosHandle, toPos); + } + return result; + } + + /// Calculate a tangent between 2 points by a formula. This is a slow method + /// Ratio between (0,1) + /// Use local coordinates instead of world + public virtual Vector3 CalcTangentByT(BGCurvePoint @from, BGCurvePoint to, float t, bool useLocal = false) + { + if (Curve.PointsCount < 2) return Vector3.zero; + + t = Mathf.Clamp01(t); + + var fromPos = useLocal ? from.PositionLocal : from.PositionWorld; + var toPos = useLocal ? to.PositionLocal : to.PositionWorld; + + Vector3 result; + if (from.ControlType == BGCurvePoint.ControlTypeEnum.Absent && to.ControlType == BGCurvePoint.ControlTypeEnum.Absent) + { + result = toPos - fromPos; + } + else + { + var fromPosHandle = useLocal ? from.ControlSecondLocal + fromPos : from.ControlSecondWorld; + var toPosHandle = useLocal ? to.ControlFirstLocal + toPos : to.ControlFirstWorld; + + result = (from.ControlType != BGCurvePoint.ControlTypeEnum.Absent && to.ControlType != BGCurvePoint.ControlTypeEnum.Absent) + ? BGCurveFormulas.BezierCubicDerivative(t, fromPos, fromPosHandle, toPosHandle, toPos) + : BGCurveFormulas.BezierQuadraticDerivative(t, fromPos, (@from.ControlType == BGCurvePoint.ControlTypeEnum.Absent) ? toPosHandle : fromPosHandle, toPos); + } + + return result.normalized; + } + + + //=========================================== Generic methods + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcByDistanceRatio(float distanceRatio, out Vector3 tangent, bool useLocal = false) + { + return CalcByDistance(cachedLength*distanceRatio, out tangent, useLocal); + } + + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcByDistance(float distance, out Vector3 tangent, bool useLocal = false) + { + if (distance < 0f) distance = 0f; + else if (distance > cachedLength) distance = cachedLength; + + Vector3 position; + BinarySearchByDistance(distance, out position, out tangent, true, true); + + if (useLocal) + { + position = curve.transform.InverseTransformPoint(position); + tangent = curve.transform.InverseTransformDirection(tangent); + } + + return position; + } + + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcByDistanceRatio(Field field, float distanceRatio, bool useLocal = false) + { + return CalcByDistance(field, cachedLength*distanceRatio, useLocal); + } + + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcByDistance(Field field, float distance, bool useLocal = false) + { + var pointsCount = curve.PointsCount; + switch (pointsCount) + { + case 0: + return Vector3.zero; + case 1: + return field == Field.Position ? curve[0].PositionWorld : Vector3.zero; + } + + if (distance < 0f) distance = 0f; + else if (distance > cachedLength) distance = cachedLength; + + var calcPosition = field == Field.Position; + Vector3 position, tangent; + BinarySearchByDistance(distance, out position, out tangent, calcPosition, !calcPosition); + + if (useLocal) + { + switch (field) + { + case Field.Position: + position = curve.transform.InverseTransformPoint(position); + break; + case Field.Tangent: + tangent = curve.transform.InverseTransformDirection(tangent); + break; + } + } + + return calcPosition ? position : tangent; + } + + //=========================================== Position and Tangent + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcPositionAndTangentByDistanceRatio(float distanceRatio, out Vector3 tangent, bool useLocal = false) + { + return CalcByDistanceRatio(distanceRatio, out tangent, useLocal); + } + + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcPositionAndTangentByDistance(float distance, out Vector3 tangent, bool useLocal = false) + { + return CalcByDistance(distance, out tangent, useLocal); + } + + //=========================================== Position + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcPositionByDistanceRatio(float distanceRatio, bool useLocal = false) + { + return CalcByDistanceRatio(Field.Position, distanceRatio, useLocal); + } + + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcPositionByDistance(float distance, bool useLocal = false) + { + return CalcByDistance(Field.Position, distance, useLocal); + } + + //=========================================== Tangent + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcTangentByDistanceRatio(float distanceRatio, bool useLocal = false) + { + return CalcByDistanceRatio(Field.Tangent, distanceRatio, useLocal); + } + + //using useLocal is significantly slower. See interface for more comments + public virtual Vector3 CalcTangentByDistance(float distance, bool useLocal = false) + { + return CalcByDistance(Field.Tangent, distance, useLocal); + } + + + //=========================================== Find Secton's index + + //see interface for comments + public int CalcSectionIndexByDistance(float distance) + { + return FindSectionIndexByDistance(ClampDistance(distance)); + } + + //see interface for comments + public int CalcSectionIndexByDistanceRatio(float ratio) + { + return FindSectionIndexByDistance(DistanceByRatio(ratio)); + } + + //=========================================== Closest Point + + //see interface for comments + public Vector3 CalcPositionByClosestPoint(Vector3 point, bool skipSectionsOptimization = false, bool skipPointsOptimization = false) + { + if (closestPointCalculator == null) closestPointCalculator = new BGCurveCalculatorClosestPoint(this); + float distance; + Vector3 tangent; + return closestPointCalculator.CalcPositionByClosestPoint(point, out distance, out tangent, skipSectionsOptimization, skipPointsOptimization); + } + + //see interface for comments + public Vector3 CalcPositionByClosestPoint(Vector3 point, out float distance, bool skipSectionsOptimization = false, bool skipPointsOptimization = false) + { + if (closestPointCalculator == null) closestPointCalculator = new BGCurveCalculatorClosestPoint(this); + Vector3 tangent; + return closestPointCalculator.CalcPositionByClosestPoint(point, out distance, out tangent, skipSectionsOptimization, skipPointsOptimization); + } + + //see interface for comments + public Vector3 CalcPositionByClosestPoint(Vector3 point, out float distance, out Vector3 tangent, bool skipSectionsOptimization = false, bool skipPointsOptimization = false) + { + if (closestPointCalculator == null) closestPointCalculator = new BGCurveCalculatorClosestPoint(this); + return closestPointCalculator.CalcPositionByClosestPoint(point, out distance, out tangent, skipSectionsOptimization, skipPointsOptimization); + } + + + //=========================================== Total Distance + //see interface for comments + public virtual float GetDistance() + { + return cachedLength; + } + + //=========================================== Curve's point world coordinates (faster then using point.positionWord etc.) + + /// Get point's world position + public Vector3 GetPosition(int pointIndex) + { + var count = cachedSectionInfos.Count; + + if (count == 0 || count <= pointIndex) return curve[pointIndex].PositionWorld; + + return pointIndex < count ? cachedSectionInfos[pointIndex].OriginalFrom : cachedSectionInfos[pointIndex - 1].OriginalTo; + } + + /// Get point's world first control position + public Vector3 GetControlFirst(int pointIndex) + { + var count = cachedSectionInfos.Count; + + if (count == 0) return curve[pointIndex].ControlFirstWorld; + + if (pointIndex == 0) return curve.Closed ? cachedSectionInfos[count - 1].OriginalToControl : curve[0].ControlFirstWorld; + + return cachedSectionInfos[pointIndex - 1].OriginalToControl; + } + + /// Get point's world second control position + public Vector3 GetControlSecond(int pointIndex) + { + var count = cachedSectionInfos.Count; + + if (count == 0) return curve[pointIndex].ControlSecondWorld; + + if (pointIndex == count) return curve.Closed ? cachedSectionInfos[count - 1].OriginalFromControl : curve[pointIndex].ControlSecondWorld; + + return cachedSectionInfos[pointIndex].OriginalFromControl; + } + + + //=========================================== Misc + /// Is given field is calculated? + /// true if field is calculated + public virtual bool IsCalculated(Field field) + { + return ((int) field & (int) config.Fields) != 0; + } + + // C# standard dispose + public virtual void Dispose() + { + curve.Changed -= CurveChanged; + config.Update -= ConfigOnUpdate; + cachedSectionInfos.Clear(); + poolSectionInfos.Clear(); + } + + + //=========================================== Calculate and cache required data + + /// Calculates and cache all required data for performance reason. It is an expensive operation. + public virtual void Recalculate(bool force = false) + { + if (ChangeRequested != null) ChangeRequested(this, null); + + if (!force && config.ShouldUpdate != null && !config.ShouldUpdate()) return; + + var currentSectionsCount = cachedSectionInfos.Count; + if (curve.PointsCount < 2) + { + cachedLength = 0; + if (currentSectionsCount > 0) cachedSectionInfos.Clear(); + if (Changed != null) Changed(this, null); + return; + } + + //we should at least warn about non-optimal usage of Recalculate (with more than 1 update per frame) + if (recalculatedAtFrame != Time.frameCount || Time.frameCount == createdAtFrame) recalculatedAtFrame = Time.frameCount; + else + Warning("We noticed you are updating math more than once per frame. This is not optimal. " + + "If you use curve.ImmediateChangeEvents by some reason, try to use curve.Transaction to wrap all the changes to one single event."); + + + var pointsCount = curve.PointsCount; + var sectionsCount = curve.Closed ? pointsCount : pointsCount - 1; + + //coefficients + h = 1.0/config.Parts; + h2 = h*h; + h3 = h2*h; + + //ensure all sections inited + if (currentSectionsCount != sectionsCount) + { + if (currentSectionsCount < sectionsCount) + { + //not enough sections + var toAddCount = sectionsCount - currentSectionsCount; + + //try to get from the pool + var poolCount = poolSectionInfos.Count; + var toAddBeforePoolCount = toAddCount; + for (var i = poolCount - 1; i >= 0 && toAddCount > 0; i--, toAddCount--) cachedSectionInfos.Add(poolSectionInfos[i]); + + //pool was used + var usedPoolCount = toAddBeforePoolCount - toAddCount; + if (usedPoolCount != 0) poolSectionInfos.RemoveRange(poolSectionInfos.Count - usedPoolCount, usedPoolCount); + + // we need to create new sections (pool is empty) + if (toAddCount > 0) for (var i = 0; i < toAddCount; i++) cachedSectionInfos.Add(new SectionInfo()); + } + else + { + //too many sections + var toRemoveCount = currentSectionsCount - sectionsCount; + for (var i = sectionsCount; i < currentSectionsCount; i++) poolSectionInfos.Add(cachedSectionInfos[i]); + cachedSectionInfos.RemoveRange(currentSectionsCount - toRemoveCount, toRemoveCount); + } + } + + //calculate fields for each section + for (var i = 0; i < pointsCount - 1; i++) CalculateSection(i, cachedSectionInfos[i], i == 0 ? null : cachedSectionInfos[i - 1], curve[i], curve[i + 1]); + + var lastSection = cachedSectionInfos[sectionsCount - 1]; + if (curve.Closed) + { + CalculateSection(sectionsCount - 1, lastSection, cachedSectionInfos[sectionsCount - 2], curve[pointsCount - 1], curve[0]); + if (cacheTangent) AdjustBoundaryPointsTangents(cachedSectionInfos[0], lastSection); + } + + cachedLength = lastSection.DistanceFromEndToOrigin; + + if (Changed != null) Changed(this, null); + } + + #endregion + + #region protected methods + + //print a message to console if condition is met and calls callback method + protected virtual void Warning(string message, bool condition = true, Action callback = null) + { + if (!condition || !Application.isPlaying) return; + + if (!SuppressWarning) Debug.Log("BGCurve[BGCurveBaseMath] Warning! " + message + ". You can suppress all warnings by using BGCurveBaseMath.SuppressWarning=true;"); + + if (callback != null) callback(); + } + + + //calculates one single section data + // Performance: + // * for example: ~100 000 section points (1000 curve's points with 100 parts each) with both controls + // ~7.8 ms for Position + // ~13.5 ms for PositionAndTangent + protected virtual void CalculateSection(int index, SectionInfo section, SectionInfo prevSection, BGCurvePointI @from, BGCurvePointI to) + { + if (section == null) section = new SectionInfo(); + + section.DistanceFromStartToOrigin = prevSection == null ? 0 : prevSection.DistanceFromEndToOrigin; + + var straightAndOptimized = config.OptimizeStraightLines && @from.ControlType == BGCurvePoint.ControlTypeEnum.Absent && to.ControlType == BGCurvePoint.ControlTypeEnum.Absent; + var pointsCount = straightAndOptimized ? 2 : config.Parts + 1; + + // do we need to recalc points? + if (Reset(section, @from, to, pointsCount)) + { + if (straightAndOptimized) + { + // ===================================================== Straight section with 2 points + Resize(section.points, 2); + + var startPoint = section.points[0]; + var endPoint = section.points[1]; + + startPoint.Position = section.OriginalFrom; + endPoint.Position = section.OriginalTo; + + //distance + endPoint.DistanceToSectionStart = Vector3.Distance(section.OriginalFrom, section.OriginalTo); + + //tangents + if (cacheTangent) startPoint.Tangent = endPoint.Tangent = (endPoint.Position - startPoint.Position).normalized; + } + else + { + // ===================================================== Section with {parts} smaller sections + CalculateSplitSection(section, @from, to); + } + if (cacheTangent) + { + section.OriginalFirstPointTangent = section[0].Tangent; + section.OriginalLastPointTangent = section[section.PointsCount - 1].Tangent; + } + } + + // we should adjust tangents for previous section's last point and first point of the current section + if (cacheTangent && prevSection != null) AdjustBoundaryPointsTangents(section, prevSection); + + section.DistanceFromEndToOrigin = section.DistanceFromStartToOrigin + section[section.PointsCount - 1].DistanceToSectionStart; + } + + //adjust neighbour adjacent points tangents + private void AdjustBoundaryPointsTangents(SectionInfo section, SectionInfo prevSection) + { + if (IsUseDistanceToAdjustTangents(section, prevSection)) + { + var distance1 = Vector3.SqrMagnitude(section[0].Position - section[1].Position); + var distance2 = Vector3.SqrMagnitude(prevSection[prevSection.PointsCount - 1].Position - prevSection[prevSection.PointsCount - 2].Position); + var overallDistance = distance1 + distance2; + + if (Math.Abs(overallDistance) < BGCurve.Epsilon) return; + + var ratio = distance1/overallDistance; + var reverseRatio = 1 - ratio; + + section[0].Tangent = prevSection[prevSection.PointsCount - 1].Tangent = Vector3.Normalize(new Vector3( + section.OriginalFirstPointTangent.x*ratio + prevSection.OriginalLastPointTangent.x*reverseRatio, + section.OriginalFirstPointTangent.y*ratio + prevSection.OriginalLastPointTangent.y*reverseRatio, + section.OriginalFirstPointTangent.z*ratio + prevSection.OriginalLastPointTangent.z*reverseRatio)); + } + else + { + //both tangents get adjusted + section[0].Tangent = prevSection[prevSection.PointsCount - 1].Tangent = Vector3.Normalize(new Vector3( + section.OriginalFirstPointTangent.x + prevSection.OriginalLastPointTangent.x, + section.OriginalFirstPointTangent.y + prevSection.OriginalLastPointTangent.y, + section.OriginalFirstPointTangent.z + prevSection.OriginalLastPointTangent.z)); + } + } + + //should we use distance between approximation points for adjusting boundary tangents + protected virtual bool IsUseDistanceToAdjustTangents(SectionInfo section, SectionInfo prevSection) + { + return config.OptimizeStraightLines && section.OriginalFromControlType == BGCurvePoint.ControlTypeEnum.Absent && + (section.OriginalToControlType == BGCurvePoint.ControlTypeEnum.Absent || prevSection.OriginalFromControlType == BGCurvePoint.ControlTypeEnum.Absent); + } + + //reset section's data and returns if recalculation is needed + protected virtual bool Reset(SectionInfo section, BGCurvePointI @from, BGCurvePointI to, int pointsCount) + { + return section.Reset(@from, to, pointsCount, ignoreSectionChangedCheck); + } + + + // this method contains some intentional 1) copy/paste 2) methods inlining 3) operators inlining- to increase performance + + /** + * Calculates one split section's data using forward differencing algorithm + * + * The technique of forward differencing allows us to compute the polynomial at t=0, + * and then incrementally calculate points by adding (and updating) the differences. + * + * Thanks to Russel Lindsay (https://gist.github.com/rlindsay/c55be560ec41144f521f) + * + * Formulas for difference between t and t+h for cubic, quadratic, and linear polynomials + * (notice that the difference between t and t+h for a cubic polynomial is quadratic ((3ak)t^2 + (3ak^2 + 2bk)t + ak^3 + bk^2 + ck), + * likewise the difference in the quadratic case is linear, and in the linear case is a constant) + * + * -------------------- + * Cubic polynomial (4 points, a, b, c, d) + * C(t) = a*t^3 + b*t^2 + c*t + d + * + * Cubic polynomial difference + * C(t + h) - C(t) http://www.wolframalpha.com/input/?i=%28a*%28t+%2B+h%29%5E3+%2B+b*%28t+%2B+h%29%5E2+%2B+c*%28t+%2B+h%29+%2B+d%29+-+%28a*t%5E3+%2B+b*t%5E2+%2B+c*t+%2B+d%29+ + * = ah^3 + 3ah^2 t + 3aht^2 + bh^2 + 2bht + ch + ---> i) = (3ah)t^2 + (3ah^2 + 2bh)t + ah^3 + bh^2 + ch + * + * -------------------- + * quadratic polynomial + * Q(t) = at^2 + bt + c + * + * quadratic polynomial difference + * Q(t + h) - Q(t) http://www.wolframalpha.com/input/?i=%28a%28t%2Bh%29%5E2+%2B+b%28t%2Bh%29+%2B+c%29+-+%28at%5E2+%2B+bt+%2B+c%29 + ---> ii) = (2ah)t + ah^2 + bh + * + * ------------------ + * linear polynomial + * L(t) = at + b + * + * linear polynomial difference + * L(t + h) - L(t) http://www.wolframalpha.com/input/?i=%28a%28t+%2B+h%29+%2B+b%29+-+%28at+%2B+b%29 + ---> iii) = ah + */ + + protected virtual void CalculateSplitSection(SectionInfo section, BGCurvePointI @from, BGCurvePointI to) + { + var parts = config.Parts; + Resize(section.points, parts + 1); + + var points = section.points; + + // all section's values + var fromPos = section.OriginalFrom; + var toPos = section.OriginalTo; + var control1 = section.OriginalFromControl; + var control2 = section.OriginalToControl; + + var controlFromAbsent = @from.ControlType == BGCurvePoint.ControlTypeEnum.Absent; + var controlToAbsent = to.ControlType == BGCurvePoint.ControlTypeEnum.Absent; + var noControls = controlFromAbsent && controlToAbsent; + var bothControls = !controlFromAbsent && !controlToAbsent; + if (!noControls && !bothControls && controlFromAbsent) control1 = control2; + + //snapping + var snapIsOn = curve.SnapType == BGCurve.SnapTypeEnum.Curve; + + //assign first last points directly to avoid accumulation errors + var firstPoint = points[0] ?? (section.points[0] = new SectionPointInfo()); + firstPoint.Position = fromPos; + var lastPoint = points[parts] ?? (section.points[parts] = new SectionPointInfo()); + lastPoint.Position = toPos; + + + if (noControls) + { + // ======================================================== NoControls + + var currentX = (double) fromPos.x; + var currentY = (double) fromPos.y; + var currentZ = (double) fromPos.z; + + var stepX = ((double) toPos.x - fromPos.x)/parts; + var stepY = ((double) toPos.y - fromPos.y)/parts; + var stepZ = ((double) toPos.z - fromPos.z)/parts; + + var fromToTangentWorld = Vector3.zero; + if (cacheTangent) fromToTangentWorld = (toPos - fromPos).normalized; + + lastPoint.DistanceToSectionStart = Vector3.Distance(toPos, fromPos); + var onePartDistance = lastPoint.DistanceToSectionStart/parts; + + //-------------------------------- Critical section + for (var i = 1; i < parts; i++) + { + var point = points[i]; + + currentX += stepX; + currentY += stepY; + currentZ += stepZ; + + var pos = new Vector3((float) currentX, (float) currentY, (float) currentZ); + + if (snapIsOn) curve.ApplySnapping(ref pos); + + point.Position = pos; + + //---------- tangents + if (cacheTangent) + { + if (config.UsePointPositionsToCalcTangents) + { + //-------- Calc by point's positions + var prevPoint = section[i - 1]; + var prevPosition = prevPoint.Position; + var tangent = new Vector3(pos.x - prevPosition.x, pos.y - prevPosition.y, pos.z - prevPosition.z); + //normalized inlined + var marnitude = (float) Math.Sqrt((double) tangent.x*(double) tangent.x + (double) tangent.y*(double) tangent.y + (double) tangent.z*(double) tangent.z); + tangent = ((double) marnitude > 9.99999974737875E-06) ? new Vector3(tangent.x/marnitude, tangent.y/marnitude, tangent.z/marnitude) : Vector3.zero; + + prevPoint.Tangent = point.Tangent = tangent; + } + else point.Tangent = fromToTangentWorld; + } + + point.DistanceToSectionStart = onePartDistance*i; + } + //-------------------------------- Critical section ends + + //assign last point separately to get rid of accumulation errors + if (cacheTangent) firstPoint.Tangent = lastPoint.Tangent = fromToTangentWorld; + } + else + { + //for tangents + double tX = 0, tY = 0, tZ = 0, firstTDx = 0, firstTDy = 0, firstTDz = 0; + + if (bothControls) + { + // ======================================================== Both Controls (Cubic Bezier) + + /* coefficients for control points (it's a standard Bezier matrix) + * you can get these numbers by converting parametric equation to standard polinomial form + * + * | 1 0 0 0| |A| | A | + * |-3 3 0 0| * |B| = | -3A + 3B | + * | 3 -6 3 0| |C| | 3A - 6B + 3C | + * |-1 3 -3 1| |D| |-A + 3B - 3C + D| + * + * http://www.wolframalpha.com/input/?i=%7B%7B1,+0,+0,+0%7D,%7B-3,+3,+0,+0%7D,+%7B3,+-6,+3,+0%7D,+%7B-1,+3,+-3,+1%7D%7D*%7B%7Bp_0%7D,+%7Bp_1%7D,+%7Bp_2%7D,+%7Bp_3%7D%7D + * + */ + // the same as in above matrix (top down) + var cx = 3*((double) control1.x - fromPos.x); + var cy = 3*((double) control1.y - fromPos.y); + var cz = 3*((double) control1.z - fromPos.z); + + var bx = 3*((double) control2.x - control1.x) - cx; + var by = 3*((double) control2.y - control1.y) - cy; + var bz = 3*((double) control2.z - control1.z) - cz; + + var ax = (double) toPos.x - fromPos.x - cx - bx; + var ay = (double) toPos.y - fromPos.y - cy - by; + var az = (double) toPos.z - fromPos.z - cz - bz; + + var pointX = (double) fromPos.x; + var pointY = (double) fromPos.y; + var pointZ = (double) fromPos.z; + + var axH3 = ax*h3; + var ax6H3 = 6*axH3; + var ayH3 = ay*h3; + var ay6H3 = 6*ayH3; + var azH3 = az*h3; + var az6H3 = 6*azH3; + + var bxH2 = bx*h2; + var byH2 = by*h2; + var bzH2 = bz*h2; + + /* First Difference + * the difference between t and t+h. Since the curve is cubic, difference is (from Formula i, see header) + * i) (3ah)t^2 + (3ah^2 + 2bh)t + ah^3 + bh^2 + ch + * + * Since we are calculating from the start of the curve, t = 0. + * + * http://www.wolframalpha.com/input/?i=(a*(0+%2B+h)%5E3+%2B+b*(0+%2B+h)%5E2+%2B+c*(0+%2B+h)+%2B+d)+-+(a*0%5E3+%2B+b*0%5E2+%2B+c*0+%2B+d) + * D1 = ah^3 + bh^2 + ch + */ + var firstDx = axH3 + bxH2 + cx*h; + var firstDy = ayH3 + byH2 + cy*h; + var firstDz = azH3 + bzH2 + cz*h; + + /* + * Second Difference: + * + * the difference between two successive first differences. Since the form of the first difference is quadratic, the difference + * between two of them is (from Formula ii, see header ) + * ii) (2ah)t + ah^2 + bh + * + * Substituting + * t = 0 to calculate the difference at the start of the curve, + * a = 3ah, + * b = 3ah^2 + 2bh (see D1 calculation, Formula i ) + * we get + * D2 = (6ah^2)t + 6ah^3 + 2bh^2 http://www.wolframalpha.com/input/?i=%282*3*a*h*h%29t+%2B+3*a*h*h%5E2+%2B+%283*a*h%5E2+%2B+2*b*h%29h + * = 6ah^3 + 2bh^2 + */ + var secondDx = ax6H3 + 2*bxH2; + var secondDy = ay6H3 + 2*byH2; + var secondDz = az6H3 + 2*bzH2; + + /* + * Third difference: + * + * the difference between two successive second differences. since the form is linear + * iii) ah + * substituting + * a = 6ah^2 (see D2 calculation) + * D3 = 6ah^3 http://www.wolframalpha.com/input/?i=6*a*h%5E2+*+h + * + */ + var thirdDx = ax6H3; + var thirdDy = ay6H3; + var thirdDz = az6H3; + + + double secondTDx = 0, secondTDy = 0, secondTDz = 0; + if (cacheTangent && !config.UsePointPositionsToCalcTangents) + { + //the same thing as with positions + //parametric to polinomial standard + //3*(1-t)^2*(p1-p0) + 6*(1-t)*t*(p2-p1) + 3*t^2*(p3-p2)=(-3*p0+9*p1-9*p2+3*p3)*t^2 + (6*p0-12*p1+6*p2)*t + (3*p1-3*p0) + var tbx = 6*((double) fromPos.x - 2*control1.x + control2.x); + var tby = 6*((double) fromPos.y - 2*control1.y + control2.y); + var tbz = 6*((double) fromPos.z - 2*control1.z + control2.z); + + var tax = 3*((double) -fromPos.x + 3*control1.x - 3*control2.x + toPos.x); + var tay = 3*((double) -fromPos.y + 3*control1.y - 3*control2.y + toPos.y); + var taz = 3*((double) -fromPos.z + 3*control1.z - 3*control2.z + toPos.z); + + //temp + var taxH2 = tax*h2; + var tayH2 = tay*h2; + var tazH2 = taz*h2; + + + // ii) (2ah)t + ah^2 + bh, t=0 + firstTDx = taxH2 + tbx*h; + firstTDy = tayH2 + tby*h; + firstTDz = tazH2 + tbz*h; + + // iii) = ah, a=2ah + secondTDx = 2*taxH2; + secondTDy = 2*tayH2; + secondTDz = 2*tazH2; + + tX = cx; + tY = cy; + tZ = cz; + + //normalized inlined + var magnitude = Math.Sqrt(tX*tX + tY*tY + tZ*tZ); + firstPoint.Tangent = magnitude > 9.99999974737875E-06 ? new Vector3((float) (tX/magnitude), (float) (tY/magnitude), (float) (tZ/magnitude)) : Vector3.zero; + } + + //-------------------------------- Critical section + for (var i = 1; i < parts; i++) + { + var point = points[i]; + + pointX += firstDx; + pointY += firstDy; + pointZ += firstDz; + + firstDx += secondDx; + firstDy += secondDy; + firstDz += secondDz; + + secondDx += thirdDx; + secondDy += thirdDy; + secondDz += thirdDz; + + var pos = new Vector3((float) pointX, (float) pointY, (float) pointZ); + + if (snapIsOn) curve.ApplySnapping(ref pos); + + point.Position = pos; + + if (cacheTangent) + { + if (config.UsePointPositionsToCalcTangents) + { + //-------- Calc by point's positions + var prevPoint = section[i - 1]; + var prevPosition = prevPoint.Position; + var tangent = new Vector3(pos.x - prevPosition.x, pos.y - prevPosition.y, pos.z - prevPosition.z); + //normalized inlined + var marnitude = (float) Math.Sqrt((double) tangent.x*(double) tangent.x + (double) tangent.y*(double) tangent.y + (double) tangent.z*(double) tangent.z); + tangent = ((double) marnitude > 9.99999974737875E-06) ? new Vector3(tangent.x/marnitude, tangent.y/marnitude, tangent.z/marnitude) : Vector3.zero; + + prevPoint.Tangent = point.Tangent = tangent; + } + else + { + tX += firstTDx; + tY += firstTDy; + tZ += firstTDz; + + firstTDx += secondTDx; + firstTDy += secondTDy; + firstTDz += secondTDz; + + //normalized inlined + var magnitude = Math.Sqrt(tX*tX + tY*tY + tZ*tZ); + point.Tangent = magnitude > 9.99999974737875E-06 ? new Vector3((float) (tX/magnitude), (float) (tY/magnitude), (float) (tZ/magnitude)) : Vector3.zero; + } + } + + // ---------- distance to section start (Vector3.Distance inlined) + var prevPos = section[i - 1].Position; + double deltaX = pos.x - prevPos.x; + double deltaY = pos.y - prevPos.y; + double deltaZ = pos.z - prevPos.z; + point.DistanceToSectionStart = section[i - 1].DistanceToSectionStart + ((float) Math.Sqrt(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ)); + } + //-------------------------------- Critical section ends + } + else + { + // ======================================================== One Control (Quadratic Bezier) + // see comments for cubic bezier for more details + // parametric to polinomial standard form + // (1-t)^2*p0 + 2(1-t)*t*p1+t^2*p2 = (p0-2p1+p2)*t^2 + (-2p0+2p1)*t + p0 + + var bx = 2*((double) control1.x - fromPos.x); + var by = 2*((double) control1.y - fromPos.y); + var bz = 2*((double) control1.z - fromPos.z); + + var ax = (double) fromPos.x - 2*control1.x + toPos.x; + var ay = (double) fromPos.y - 2*control1.y + toPos.y; + var az = (double) fromPos.z - 2*control1.z + toPos.z; + + // ii) = (2ah)t + ah^2 + bh, t=0 + var firstDx = ax*h2 + bx*h; + var firstDy = ay*h2 + by*h; + var firstDz = az*h2 + bz*h; + + // iii) ah, a=2ah + var secondDx = 2*ax*h2; + var secondDy = 2*ay*h2; + var secondDz = 2*az*h2; + + var pointX = (double) fromPos.x; + var pointY = (double) fromPos.y; + var pointZ = (double) fromPos.z; + + if (cacheTangent && !config.UsePointPositionsToCalcTangents) + { + //the same thing as with positions + //parametric to polinomial standard + // 2*(1-t)*(p1-p0) + 2t*(p2-p1) = (2*p0-4*p1+2*p2)*t + (2*p1-2*p0) + var tax = 2*((double) fromPos.x - 2*control1.x + toPos.x); + var tay = 2*((double) fromPos.y - 2*control1.y + toPos.y); + var taz = 2*((double) fromPos.z - 2*control1.z + toPos.z); + + // iii) = ah + firstTDx = tax*h; + firstTDy = tay*h; + firstTDz = taz*h; + + tX = 2*((double) control1.x - fromPos.x); + tY = 2*((double) control1.y - fromPos.y); + tZ = 2*((double) control1.z - fromPos.z); + + //normalized inlined + var magnitude = Math.Sqrt(tX*tX + tY*tY + tZ*tZ); + firstPoint.Tangent = magnitude > 9.99999974737875E-06 ? new Vector3((float) (tX/magnitude), (float) (tY/magnitude), (float) (tZ/magnitude)) : Vector3.zero; + } + //-------------------------------- Critical section + for (var i = 1; i < parts; i++) + { + var point = points[i]; + + pointX += firstDx; + pointY += firstDy; + pointZ += firstDz; + + firstDx += secondDx; + firstDy += secondDy; + firstDz += secondDz; + + var pos = new Vector3((float) pointX, (float) pointY, (float) pointZ); + + if (snapIsOn) curve.ApplySnapping(ref pos); + + point.Position = pos; + + if (cacheTangent) + { + if (config.UsePointPositionsToCalcTangents) + { + //-------- Calc by point's positions + var prevPoint = section[i - 1]; + var prevPosition = prevPoint.Position; + var tangent = new Vector3(pos.x - prevPosition.x, pos.y - prevPosition.y, pos.z - prevPosition.z); + //normalized inlined + var marnitude = (float) Math.Sqrt((double) tangent.x*(double) tangent.x + (double) tangent.y*(double) tangent.y + (double) tangent.z*(double) tangent.z); + tangent = ((double) marnitude > 9.99999974737875E-06) ? new Vector3(tangent.x/marnitude, tangent.y/marnitude, tangent.z/marnitude) : Vector3.zero; + + prevPoint.Tangent = point.Tangent = tangent; + } + else + { + tX += firstTDx; + tY += firstTDy; + tZ += firstTDz; + + //normalized inlined + var magnitude = Math.Sqrt(tX*tX + tY*tY + tZ*tZ); + point.Tangent = magnitude > 9.99999974737875E-06 ? new Vector3((float) (tX/magnitude), (float) (tY/magnitude), (float) (tZ/magnitude)) : Vector3.zero; + } + } + + // ---------- distance to section start (Vector3.Distance inlined) + var prevPos = section[i - 1].Position; + double deltaX = pos.x - prevPos.x; + double deltaY = pos.y - prevPos.y; + double deltaZ = pos.z - prevPos.z; + point.DistanceToSectionStart = section[i - 1].DistanceToSectionStart + ((float) Math.Sqrt(deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ)); + } + //-------------------------------- Critical section ends + } + + //last point's tangent + if (cacheTangent && !config.UsePointPositionsToCalcTangents) + { + tX += firstTDx; + tY += firstTDy; + tZ += firstTDz; + var magnitude = Math.Sqrt(tX*tX + tY*tY + tZ*tZ); + lastPoint.Tangent = magnitude > 9.99999974737875E-06 ? new Vector3((float) (tX/magnitude), (float) (tY/magnitude), (float) (tZ/magnitude)) : Vector3.zero; + } + } + + //last Point's distance + var beforeLastPoint = section[parts - 1]; + var beforeLastPos = beforeLastPoint.Position; + var lastPointPos = lastPoint.Position; + double dX = lastPointPos.x - beforeLastPos.x; + double dY = lastPointPos.y - beforeLastPos.y; + double dZ = lastPointPos.z - beforeLastPos.z; + lastPoint.DistanceToSectionStart = beforeLastPoint.DistanceToSectionStart + ((float) Math.Sqrt(dX*dX + dY*dY + dZ*dZ)); + + //last point's tangent + if (cacheTangent && config.UsePointPositionsToCalcTangents) + { + //-------- Calc by point's positions + + var tangent = new Vector3((float) dX, (float) dY, (float) dZ); + //normalized inlined + var marnitude = (float) Math.Sqrt((double) tangent.x*(double) tangent.x + (double) tangent.y*(double) tangent.y + (double) tangent.z*(double) tangent.z); + tangent = ((double) marnitude > 9.99999974737875E-06) ? new Vector3(tangent.x/marnitude, tangent.y/marnitude, tangent.z/marnitude) : Vector3.zero; + + lastPoint.Tangent = tangent; + } + } + + + //search cached data and returns point's position or tangent at given distance from curve's start + // * for example (1000 sections with 100 points each, so 100 000 points) with 10000 Random searches ~7ms + protected virtual void BinarySearchByDistance(float distance, out Vector3 position, out Vector3 tangent, bool calculatePosition, bool calculateTangent) + { + var pointsCount = Curve.PointsCount; + if (pointsCount < 2 || cachedSectionInfos.Count == 0) + { + position = Vector3.zero; + tangent = Vector3.zero; + if (pointsCount == 1 && calculatePosition) position = Curve[0].PositionWorld; + } + + // field was not set in the constructor, so it was not calculated and can not be accessed. + // Example, use new BGCurveBaseMath(new BGCurveBaseMath.Params(GetComponent(), BGCurveBaseMath.Fields.PositionAndTangent)) + // to calculate world's position and tangent + if (calculateTangent && ((int) Field.Tangent & (int) config.Fields) == 0) + throw new UnityException("Can not calculate tangent, cause it was not included in the 'fields' constructor parameter. " + + "For example, use new BGCurveBaseMath(curve, new BGCurveBaseMath.Config(" + + "BGCurveBaseMath.Fields.PositionAndTangent))" + + "to calculate world's position and tangent"); + + + var targetSection = cachedSectionInfos[FindSectionIndexByDistance(distance)]; + + //after we found a section, let's search within this section + targetSection.CalcByDistance(distance - targetSection.DistanceFromStartToOrigin, out position, out tangent, calculatePosition, calculateTangent); + } + + //find section by distance + protected int FindSectionIndexByDistance(float distance) + { + // ----- critical section start + int low = 0, mid = 0, high = cachedSectionInfos.Count, i = 0; + while (low < high) + { + mid = (low + high) >> 1; + var item = cachedSectionInfos[mid]; + + //success + if (distance >= item.DistanceFromStartToOrigin && distance <= item.DistanceFromEndToOrigin) break; + + if (distance < item.DistanceFromStartToOrigin) high = mid; + else low = mid + 1; + + //just in case + if (i++ > 100) throw new UnityException("Something wrong: more than 100 iterations inside BinarySearch"); + } + // ----- critical section end + + return mid; + } + + + //convert ratio to distance + protected float DistanceByRatio(float distanceRatio) + { + return GetDistance()*Mathf.Clamp01(distanceRatio); + } + + //ensure distance is within proper range + protected float ClampDistance(float distance) + { + return Mathf.Clamp(distance, 0, GetDistance()); + } + + public override string ToString() + { + return "Base Math for curve (" + Curve + "), sections=" + SectionsCount; + } + + #endregion + + #region private methods + + //=============================================================================================== + // Private functions + //=============================================================================================== + + protected void Resize(List points, int size) + { + var pointCount = points.Count; + if (pointCount == size) return; + + //size mismatch + if (pointCount < size) + { + //we need more points + var poolIndex = poolPointInfos.Count - 1; + for (var i = pointCount; i < size; i++) points.Add(poolIndex >= 0 ? poolPointInfos[poolIndex--] : new SectionPointInfo()); + + //pool was used + if (poolIndex != poolPointInfos.Count - 1) poolPointInfos.RemoveRange(poolIndex + 1, poolPointInfos.Count - 1 - poolIndex); + } + else + { + //we need less points + for (var i = size; i < pointCount; i++) poolPointInfos.Add(points[i]); + + points.RemoveRange(size, pointCount - size); + } + } + + + private void CurveChanged(object sender, BGCurveChangedArgs e) + { + ignoreSectionChangedCheck = e != null && e.ChangeType == BGCurveChangedArgs.ChangeTypeEnum.Snap; + Recalculate(); + ignoreSectionChangedCheck = false; + } + + private void ConfigOnUpdate(object sender, EventArgs eventArgs) + { + Recalculate(true); + } + + #endregion + + #region Helper model classes + + //=============================================================================================== + // Helper classes + //=============================================================================================== + + + /// params for calculations + public class Config + { + /// Which fields to calculate and cache. Do not use more fields then needed. + public Fields Fields = Fields.Position; + + /// number of parts each curve's section will be devided to. Range[1, 1000] + public int Parts = 30; + + /// Use points position instead of formula to calc tangents. This can increase performace. + public bool UsePointPositionsToCalcTangents; + + /// Do not split straight lines during precalculation (use only 2 points per section).Tangents may suffer + public bool OptimizeStraightLines; + + /// If not null it can control if math should update it's data. Updating cached data takes some resources, so this param can control updating strategy + public Func ShouldUpdate; + + /// If not null math will update on this event + public event EventHandler Update; + + + public Config() + { + } + + /// Fields (from BGCurveBaseMath.Field) you want to precalculate and cache. + /// 'None' means- no precalculation and caching will occur, but as a result you will be able to use CalcPositionByT and CalcTangentByT methods only. + /// See class documentation for more info. + public Config(Fields fields) + { + Fields = fields; + } + + protected bool Equals(Config other) + { + return Fields == other.Fields && Parts == other.Parts && UsePointPositionsToCalcTangents == other.UsePointPositionsToCalcTangents && + OptimizeStraightLines == other.OptimizeStraightLines; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((Config) obj); + } + + public override int GetHashCode() + { + var hashCode = (int) Fields; + hashCode = (hashCode*397) ^ Parts; + hashCode = (hashCode*397) ^ UsePointPositionsToCalcTangents.GetHashCode(); + hashCode = (hashCode*397) ^ OptimizeStraightLines.GetHashCode(); + return hashCode; + } + + /// Fire Updated event + public void FireUpdate() + { + if (Update != null) Update(this, null); + } + } + + /// information for one single section (between 2 points) of the curve + public class SectionInfo + { + /// distance from section start to curve start + public float DistanceFromStartToOrigin; + + /// distance from section end to curve start + public float DistanceFromEndToOrigin; + + //all the points in this section + protected internal readonly List points = new List(); + + + /// From location, used by calculation + public Vector3 OriginalFrom; + + /// To location, used by calculation + public Vector3 OriginalTo; + + /// From control type, used by calculation + public BGCurvePoint.ControlTypeEnum OriginalFromControlType; + + /// To control type, used by calculation + public BGCurvePoint.ControlTypeEnum OriginalToControlType; + + /// From control position, used by calculation + public Vector3 OriginalFromControl; + + /// To control position, used by calculation + public Vector3 OriginalToControl; + + // we need these 2 following fields, cause this section can get skipped while calculation, but adjacent sections may change, + // and this will affect adjacent points tangents + // so we need these "original tangents" to calculate final tangents in case this section will get skipped + /// First point tangent, calculated for the first time + public Vector3 OriginalFirstPointTangent; + + /// Last point tangent, calculated for the first time + public Vector3 OriginalLastPointTangent; + + /// Approximation points in the section + public List Points + { + get { return points; } + } + + /// Approximation points count + public int PointsCount + { + get { return points.Count; } + } + + /// Section's total distance + public float Distance + { + get { return DistanceFromEndToOrigin - DistanceFromStartToOrigin; } + } + + public override string ToString() + { + return "Section distance=(" + Distance + ")"; + } + + /// Get section's point by index + public SectionPointInfo this[int i] + { + get { return points[i]; } + set { points[i] = value; } + } + + /// Reset section's init data and returns true, if (re)calculation is needed + protected internal bool Reset(BGCurvePointI fromPoint, BGCurvePointI toPoint, int pointsCount, bool skipCheck) + { + var newFrom = fromPoint.PositionWorld; + var newTo = toPoint.PositionWorld; + var newFromControl = fromPoint.ControlSecondWorld; + var newToControl = toPoint.ControlFirstWorld; + + const float epsilon = 0.000001f; + if ( + !skipCheck + && points.Count == pointsCount + && OriginalFromControlType == fromPoint.ControlType + && OriginalToControlType == toPoint.ControlType + && Vector3.SqrMagnitude(new Vector3(OriginalFrom.x - newFrom.x, OriginalFrom.y - newFrom.y, OriginalFrom.z - newFrom.z)) < epsilon + && Vector3.SqrMagnitude(new Vector3(OriginalTo.x - newTo.x, OriginalTo.y - newTo.y, OriginalTo.z - newTo.z)) < epsilon + && Vector3.SqrMagnitude(new Vector3(OriginalFromControl.x - newFromControl.x, OriginalFromControl.y - newFromControl.y, OriginalFromControl.z - newFromControl.z)) < epsilon + && Vector3.SqrMagnitude(new Vector3(OriginalToControl.x - newToControl.x, OriginalToControl.y - newToControl.y, OriginalToControl.z - newToControl.z)) < epsilon + ) + return false; + + OriginalFrom = newFrom; + OriginalTo = newTo; + OriginalFromControlType = fromPoint.ControlType; + OriginalToControlType = toPoint.ControlType; + OriginalFromControl = newFromControl; + OriginalToControl = newToControl; + return true; + } + + //copy pasted binary search algorithm + public int FindPointIndexByDistance(float distanceWithinSection) + { + var pointsCountMinusOne = points.Count - 1; + + // ----- critical section start (copy paste) + int low = 0, mid = 0, high = points.Count, i = 0; + while (low < high) + { + mid = (low + high) >> 1; + var item = points[mid]; + + //success + if (!(distanceWithinSection < item.DistanceToSectionStart) && (mid == pointsCountMinusOne || points[mid + 1].DistanceToSectionStart >= distanceWithinSection)) break; + + if (distanceWithinSection < item.DistanceToSectionStart) high = mid; + else low = mid + 1; + + //just in case + if (i++ > 100) throw new UnityException("Something wrong: more than 100 iterations inside BinarySearch"); + } + // ----- critical section end + return mid; + } + + /// Calculates posiiton and distance by distance within this section. Note, it does not apply any checking for performance's sake + public void CalcByDistance(float distanceWithinSection, out Vector3 position, out Vector3 tangent, bool calculatePosition, bool calculateTangent) + { + position = Vector3.zero; + tangent = Vector3.zero; + + if (points.Count == 2) + { + //linear + var first = points[0]; + + if (Math.Abs(Distance) < BGCurve.Epsilon) + { + if (calculatePosition) position = first.Position; + if (calculateTangent) tangent = first.Tangent; + } + else + { + var ratio = distanceWithinSection/Distance; + var second = points[1]; + if (calculatePosition) position = Vector3.Lerp(first.Position, second.Position, ratio); + if (calculateTangent) tangent = Vector3.Lerp(first.Tangent, second.Tangent, ratio); + } + } + else + { + var pointIndex = FindPointIndexByDistance(distanceWithinSection); + var targetPoint = points[pointIndex]; + + //the very last point within section + if (pointIndex == points.Count - 1) + { + if (calculatePosition) position = targetPoint.Position; + if (calculateTangent) tangent = targetPoint.Tangent; + } + else + { + var nextPoint = points[pointIndex + 1]; + + //this is the distance between 2 points + var distanceBetweenTwoPoints = (nextPoint.DistanceToSectionStart - targetPoint.DistanceToSectionStart); + //this is smaller distance between 1st point and target distance. distanceWithinSection= the distance from section start to target distance + var distanceWithinTwoPoints = (distanceWithinSection - targetPoint.DistanceToSectionStart); + //zero division check + var ratio = Math.Abs(distanceBetweenTwoPoints) < BGCurve.Epsilon ? 0 : distanceWithinTwoPoints/distanceBetweenTwoPoints; + + //lerp target's field between 1st and 2nd points using a ratio, which is based on the distance between them + if (calculatePosition) position = Vector3.Lerp(targetPoint.Position, nextPoint.Position, ratio); + if (calculateTangent) tangent = Vector3.Lerp(targetPoint.Tangent, nextPoint.Tangent, ratio); + } + } + } + } + + /// information for one point within a section (BGCurveBaseMath.Section) + public class SectionPointInfo + { + /// point's world position + public Vector3 Position; + + + /// distance from the start of the section to this point + public float DistanceToSectionStart; + + /// point's world tangent + public Vector3 Tangent; + + //get field's value (position or tangent) + internal Vector3 GetField(Field field) + { + Vector3 result; + switch (field) + { + case Field.Position: + result = Position; + break; + case Field.Tangent: + result = Tangent; + break; + default: + throw new UnityException("Unknown field=" + field); + } + return result; + } + + //lerp field's value (position or tangent) between two points by ratio + internal Vector3 LerpTo(Field field, SectionPointInfo to, float ratio) + { + return Vector3.Lerp(GetField(field), to.GetField(field), ratio); + } + + + public override string ToString() + { + return "Point at (" + Position + ")"; + } + } + + #endregion + } + + #region Helper extensions for Field and Fields enums + + //=============================================================================================== + // Extensions + //=============================================================================================== + + //helper extension class for Field enum + public static class FieldExtensions + { + /// if given fieldEnum is contained in the mask + public static bool In(this BGCurveBaseMath.Field field, int mask) + { + return (field.Val() & mask) != 0; + } + + /// cast to int + public static int Val(this BGCurveBaseMath.Field field) + { + return (int) field; + } + } + + public static class FieldsExtensions + { + /// cast to int + public static int Val(this BGCurveBaseMath.Fields fields) + { + return (int) fields; + } + } + + #endregion +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveBaseMath.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveBaseMath.cs.meta new file mode 100644 index 0000000..e343af9 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveBaseMath.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2d95a3b4385ca2245a96749f7eab3753 +timeCreated: 1458540196 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveCalculatorClosestPoint.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveCalculatorClosestPoint.cs new file mode 100644 index 0000000..50b6e30 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveCalculatorClosestPoint.cs @@ -0,0 +1,656 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// + /// Closest point related calculations + /// + //this class contains some intentional copy/paste for the sake of performance + public class BGCurveCalculatorClosestPoint + { + // transitions ("safe" or not) + private static readonly int[] TransitionsForPartitions; + + // math to use for calculation + private readonly BGCurveBaseMath math; + + //reusable arrays to reduce GC + private bool[] excludedSections; + private float[] minSectionDistances; + + + static BGCurveCalculatorClosestPoint() + { + // Init transitions data + + //25=inside + const int nearPlane = (1 << 0) + (1 << 1) + (1 << 2) + (1 << 3) + (1 << 4) + (1 << 5) + (1 << 6) + (1 << 7) + (1 << 24); + const int farPlane = (1 << 16) + (1 << 17) + (1 << 18) + (1 << 19) + (1 << 20) + (1 << 21) + (1 << 22) + (1 << 23) + (1 << 26); + const int bottomPlane = (1 << 0) + (1 << 6) + (1 << 7) + (1 << 8) + (1 << 14) + (1 << 15) + (1 << 16) + (1 << 22) + (1 << 23); + const int topPlane = (1 << 2) + (1 << 3) + (1 << 4) + (1 << 10) + (1 << 11) + (1 << 12) + (1 << 18) + (1 << 19) + (1 << 20); + const int leftPlane = (1 << 0) + (1 << 1) + (1 << 2) + (1 << 8) + (1 << 9) + (1 << 10) + (1 << 16) + (1 << 17) + (1 << 18); + const int rightPlane = (1 << 4) + (1 << 5) + (1 << 6) + (1 << 12) + (1 << 13) + (1 << 14) + (1 << 20) + (1 << 21) + (1 << 22); + + //transition from->to which is considered safe in terms of mininum closest point search + //total 27 partitions + TransitionsForPartitions = new[] + { + //z==0 (near) + /*0*/ nearPlane | leftPlane | bottomPlane, + /*1*/ nearPlane | leftPlane, + /*2*/ nearPlane | leftPlane | topPlane, + /*3*/ nearPlane | topPlane, + /*4*/ nearPlane | rightPlane | topPlane, + /*5*/ nearPlane | rightPlane, + /*6*/ nearPlane | rightPlane | bottomPlane, + /*7*/ nearPlane | bottomPlane, + + //z==1 (middle) + /*8*/ leftPlane | bottomPlane, + /*9*/ leftPlane, + /*10*/ leftPlane | topPlane, + /*11*/ topPlane, + /*12*/ rightPlane | topPlane, + /*13*/ rightPlane, + /*14*/ rightPlane | bottomPlane, + /*15*/ bottomPlane, + + //z==2 (far) + /*16*/ farPlane | leftPlane | bottomPlane, + /*17*/ farPlane | leftPlane, + /*18*/ farPlane | leftPlane | topPlane, + /*19*/ farPlane | topPlane, + /*20*/ farPlane | rightPlane | topPlane, + /*21*/ farPlane | rightPlane, + /*22*/ farPlane | rightPlane | bottomPlane, + /*23*/ farPlane | bottomPlane, + + //3 left partitions in the middle + /*24*/ nearPlane, + /*25*/ 0, //inside + /*26*/ farPlane, + }; + } + + public BGCurveCalculatorClosestPoint(BGCurveBaseMath math) + { + this.math = math; + } + + //this method contains some intentional copy/paste for the sake of performance + public Vector3 CalcPositionByClosestPoint(Vector3 targetPoint, out float distance, out Vector3 tangent, bool skipSectionsOptimization = false, bool skipPointsOptimization = false) + { +/* + minimalistic thing to do- iterate all lines and use closest point to line formula. + + 2 ideas for optimization: + 1) Iterate all sections first, calculate min bounding box and cut off those sections far away from it + 2) Iterate points, and calculate min sphere radius to contain the result point. Then partition the space by the bounding box around this sphere, and cut off + all points, that can not be contained in the box or intersect this box with a line; +*/ + + var sections = math.SectionInfos; + var sectionsCount = sections.Count; + if (sectionsCount == 0) + { + distance = 0; + tangent = Vector3.zero; + return math.Curve.PointsCount == 1 ? math.Curve[0].PositionWorld : Vector3.zero; + } + + + //========================================================================================================================== + // Section Bbox partitioning (4 passes total) + //========================================================================================================================== + var sectionsOptimizationOn = !skipSectionsOptimization && math.Configuration.Parts > 8; + var minSectionIndex = 0; + var minSectionMaxDistance = float.MaxValue; + if (sectionsOptimizationOn) + { + //----------------------- Section Bbox Partitioning 1st pass (calculate min AABB (Axis Aligned Bounding Box) by square distance between point and section's AABB) + Array.Resize(ref excludedSections, sectionsCount); + Array.Resize(ref minSectionDistances, sectionsCount); + + var minBounds = new Bounds(); + var minAabbDistance = float.MaxValue; + for (var i = 0; i < sectionsCount; i++) + { + var section = sections[i]; + + + var fromAbsent = section.OriginalFromControlType == BGCurvePoint.ControlTypeEnum.Absent; + var toAbsent = section.OriginalToControlType == BGCurvePoint.ControlTypeEnum.Absent; + + var originalFrom = section.OriginalFrom; + var originalTo = section.OriginalTo; + var originalToControl = section.OriginalToControl; + + var fromToMinX = originalFrom.x > originalTo.x ? originalTo.x : originalFrom.x; + var fromToMinY = originalFrom.y > originalTo.y ? originalTo.y : originalFrom.y; + var fromToMinZ = originalFrom.z > originalTo.z ? originalTo.z : originalFrom.z; + + var fromToMaxX = originalFrom.x < originalTo.x ? originalTo.x : originalFrom.x; + var fromToMaxY = originalFrom.y < originalTo.y ? originalTo.y : originalFrom.y; + var fromToMaxZ = originalFrom.z < originalTo.z ? originalTo.z : originalFrom.z; + + float minX, minY, minZ, maxX, maxY, maxZ; + if (fromAbsent) + { + if (toAbsent) + { + //No controls + minX = fromToMinX; + minY = fromToMinY; + minZ = fromToMinZ; + maxX = fromToMaxX; + maxY = fromToMaxY; + maxZ = fromToMaxZ; + } + else + { + //To Control Present + minX = fromToMinX > originalToControl.x ? originalToControl.x : fromToMinX; + minY = fromToMinY > originalToControl.y ? originalToControl.y : fromToMinY; + minZ = fromToMinZ > originalToControl.z ? originalToControl.z : fromToMinZ; + + maxX = fromToMaxX < originalToControl.x ? originalToControl.x : fromToMaxX; + maxY = fromToMaxY < originalToControl.y ? originalToControl.y : fromToMaxY; + maxZ = fromToMaxZ < originalToControl.z ? originalToControl.z : fromToMaxZ; + } + } + else + { + var originalFromControl = section.OriginalFromControl; + if (toAbsent) + { + //From Control Present + minX = fromToMinX > originalFromControl.x ? originalFromControl.x : fromToMinX; + minY = fromToMinY > originalFromControl.y ? originalFromControl.y : fromToMinY; + minZ = fromToMinZ > originalFromControl.z ? originalFromControl.z : fromToMinZ; + + maxX = fromToMaxX < originalFromControl.x ? originalFromControl.x : fromToMaxX; + maxY = fromToMaxY < originalFromControl.y ? originalFromControl.y : fromToMaxY; + maxZ = fromToMaxZ < originalFromControl.z ? originalFromControl.z : fromToMaxZ; + } + else + { + //Both Controls + var fromToControlToMinX = fromToMinX > originalToControl.x ? originalToControl.x : fromToMinX; + var fromToControlToMinY = fromToMinY > originalToControl.y ? originalToControl.y : fromToMinY; + var fromToControlToMinZ = fromToMinZ > originalToControl.z ? originalToControl.z : fromToMinZ; + + var fromToControlToMaxX = fromToMaxX < originalToControl.x ? originalToControl.x : fromToMaxX; + var fromToControlToMaxY = fromToMaxY < originalToControl.y ? originalToControl.y : fromToMaxY; + var fromToControlToMaxZ = fromToMaxZ < originalToControl.z ? originalToControl.z : fromToMaxZ; + + minX = fromToControlToMinX > originalFromControl.x ? originalFromControl.x : fromToControlToMinX; + minY = fromToControlToMinY > originalFromControl.y ? originalFromControl.y : fromToControlToMinY; + minZ = fromToControlToMinZ > originalFromControl.z ? originalFromControl.z : fromToControlToMinZ; + + maxX = fromToControlToMaxX < originalFromControl.x ? originalFromControl.x : fromToControlToMaxX; + maxY = fromToControlToMaxY < originalFromControl.y ? originalFromControl.y : fromToControlToMaxY; + maxZ = fromToControlToMaxZ < originalFromControl.z ? originalFromControl.z : fromToControlToMaxZ; + } + } + + var deltaX = maxX - minX; + var deltaY = maxY - minY; + var deltaZ = maxZ - minZ; + var extents = new Vector3(deltaX*.5f, deltaY*.5f, deltaZ*.5f); + minBounds.extents = extents; + minBounds.center = new Vector3(minX + extents.x, minY + extents.y, minZ + extents.z); + + + var sqrDistance = minBounds.SqrDistance(targetPoint); + excludedSections[i] = false; + minSectionDistances[i] = sqrDistance; + + if (!(minAabbDistance > sqrDistance)) continue; + + minAabbDistance = sqrDistance; + minSectionIndex = i; + } + + //calc max (between points and their related controls) + var minSection = sections[minSectionIndex]; + minSectionMaxDistance = MaxDistance(minSection, targetPoint) - BGCurve.Epsilon; + + //----------------------- Section Bbox Partitioning 2nd pass (1) cut off sections, which min distance to point more than max distance to min sections AABB and 2) adjusting min section ) + var sectionsLeft = 0; + var maxDistanceChanged = false; + var start = minSectionIndex; + var end = Mathf.Max(start + 1, sectionsCount - start); + for (var i = 1; i < end; i++) + { + //the reason why we iterate simulteneously- to decrease chances of MaxDistance expensive calls + //to end + var j = start + i; + if (j < sectionsCount) + { + var section = sections[j]; + + if (minSectionDistances[j] > minSectionMaxDistance) excludedSections[j] = true; + else + { + var sectionDistance = MaxDistance(section, targetPoint); + if (minSectionMaxDistance > sectionDistance) + { + minSectionMaxDistance = sectionDistance; + maxDistanceChanged = true; + } + sectionsLeft++; + } + } + + //to zero (copy/pasted) + j = start - i; + if (j >= 0) + { + var section = sections[j]; + + if (minSectionDistances[j] > minSectionMaxDistance) excludedSections[j] = true; + else + { + var sectionDistance = MaxDistance(section, targetPoint); + if (minSectionMaxDistance > sectionDistance) + { + minSectionMaxDistance = sectionDistance; + maxDistanceChanged = true; + } + sectionsLeft++; + } + } + } + + + //----------------------- Section Bbox Partitioning 3rd pass (since minSectionMaxDistance may be changed in 2nd pass, we need to iterate sections and filter them again) + if (maxDistanceChanged && sectionsLeft > 1) + for (var i = 0; i < sectionsCount; i++) if (!excludedSections[i] && minSectionDistances[i] > minSectionMaxDistance) excludedSections[i] = true; + } + + //========================================================================================================================== + // Lines AABB partitioning + //========================================================================================================================== + var pointsOptimizationOn = !skipPointsOptimization; + var closestLineMaxDistance = float.MaxValue; + var fromDistance = float.MaxValue; + var fromLess = true; + var resetFrom = true; + if (pointsOptimizationOn) + { + for (var i = 0; i < sectionsCount; i++) + { + if (sectionsOptimizationOn && excludedSections[i]) + { + resetFrom = true; + continue; + } + + var section = sections[i]; + var points = section.Points; + var pointsCount = points.Count; + + if (resetFrom) + { + resetFrom = false; + fromDistance = Vector3.SqrMagnitude(section[0].Position - targetPoint); + fromLess = fromDistance <= closestLineMaxDistance; + } + + for (var j = 1; j < pointsCount; j++) + { + var to = points[j]; + + var toPos = to.Position; + + //sqr magnitude inlined + var deltaX = toPos.x - targetPoint.x; + var deltaY = toPos.y - targetPoint.y; + var deltaZ = toPos.z - targetPoint.z; + var toDistance = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; + + var toLess = toDistance <= closestLineMaxDistance; + + if (fromLess && toLess) closestLineMaxDistance = fromDistance > toDistance ? fromDistance : toDistance; + + fromLess = toLess; + fromDistance = toDistance; + } + } + + //====================================================================== Section Bbox partitioning (again) + //----------------------- Section Bbox Partitioning 4th pass (cause closestLineMaxDistance may be smaller than minSectionMaxDistance we used before) + if (sectionsOptimizationOn && closestLineMaxDistance < minSectionMaxDistance) + for (var i = 0; i < sectionsCount; i++) if (!excludedSections[i] && minSectionDistances[i] > closestLineMaxDistance) excludedSections[i] = true; + } + + + //================================================================================================ + // Final Pass + //================================================================================================ + var firstPoint = sections[0][0]; + var fromPoint = firstPoint; + var result = fromPoint.Position; + var minDistance = Vector3.SqrMagnitude(targetPoint - fromPoint.Position); + var sectionIndex = 0; + var pointIndex = 0; + var resultLerp = 0f; + + var fromPartition = -1; + var resetFromPoint = true; + + + Vector3 min = Vector3.zero, max = Vector3.zero; + if (pointsOptimizationOn) + { + //bounding Box over sphere (for points optimization) + var radius = (float) Math.Sqrt(closestLineMaxDistance); + min = new Vector3(targetPoint.x - radius, targetPoint.y - radius, targetPoint.z - radius); + max = new Vector3(targetPoint.x + radius, targetPoint.y + radius, targetPoint.z + radius); + } + + for (var i = 0; i < sectionsCount; i++) + { + if (sectionsOptimizationOn && excludedSections[i]) + { + resetFromPoint = true; + continue; + } + + + var section = sections[i]; + var points = section.Points; + + if (resetFromPoint) + { + resetFromPoint = false; + fromPoint = section[0]; + + if (pointsOptimizationOn) + { + //------------------------------------------ points optimization + //xy quadrant clockwise (0-7) + var fromPos = fromPoint.Position; + var zSet = false; + if (fromPos.x < min.x) + { + if (fromPos.y < min.y) fromPartition = 0; + else if (fromPos.y > max.y) fromPartition = 2; + else fromPartition = 1; + } + else if (fromPos.x > max.x) + { + if (fromPos.y < min.y) fromPartition = 6; + else if (fromPos.y > max.y) fromPartition = 4; + else fromPartition = 5; + } + else + { + if (fromPos.y < min.y) fromPartition = 7; + else if (fromPos.y > max.y) fromPartition = 3; + else + { + if (fromPos.z > max.z) fromPartition = 26; + else if (fromPos.z < min.z) fromPartition = 24; + else fromPartition = 25; + zSet = true; + } + } + //z shift + if (!zSet) + { + if (fromPos.z > max.z) fromPartition = fromPartition | 16; + else if (fromPos.z > min.z) fromPartition = fromPartition | 8; + } + } + } + + var pointsCount = points.Count; + for (var j = 1; j < pointsCount; j++) + { + var toPoint = points[j]; + var toPointPos = toPoint.Position; + + var excludedByOptimization = false; + var toPartition = -1; + if (pointsOptimizationOn) + { + //------------------------------------------ points optimization + // copy/pasted + var zSet = false; + if (toPointPos.x < min.x) + { + if (toPointPos.y < min.y) toPartition = 0; + else if (toPointPos.y > max.y) toPartition = 2; + else toPartition = 1; + } + else if (toPointPos.x > max.x) + { + if (toPointPos.y < min.y) toPartition = 6; + else if (toPointPos.y > max.y) toPartition = 4; + else toPartition = 5; + } + else + { + if (toPointPos.y < min.y) toPartition = 7; + else if (toPointPos.y > max.y) toPartition = 3; + else + { + //center + if (toPointPos.z > max.z) toPartition = 26; + else if (toPointPos.z < min.z) toPartition = 24; + else toPartition = 25; //inside + zSet = true; + } + } + //z shift + if (!zSet) + { + if (toPointPos.z > max.z) toPartition = toPartition | 16; + else if (toPointPos.z > min.z) toPartition = toPartition | 8; + } + + excludedByOptimization = (TransitionsForPartitions[fromPartition] & (1 << toPartition)) != 0; + } + + + if (!excludedByOptimization) + { + float ratio; + var gettingCloser = false; + //============================================================================= Get closest point on line formula: Line(from->to), Point(targetPoint) + // closest on line + double pointX; + double pointY; + double pointZ; + + var fromPos = fromPoint.Position; + var toPos = toPoint.Position; + + var fromTargetX = (double) targetPoint.x - (double) fromPos.x; + var fromTargetY = (double) targetPoint.y - (double) fromPos.y; + var fromTargetZ = (double) targetPoint.z - (double) fromPos.z; + + var fromToX = (double) toPos.x - (double) fromPos.x; + var fromToY = (double) toPos.y - (double) fromPos.y; + var fromToZ = (double) toPos.z - (double) fromPos.z; + + //sqr magnitude inlined + var fromToSquaredDistance = (float) (fromToX*fromToX + fromToY*fromToY + fromToZ*fromToZ); + + + if (Math.Abs(fromToSquaredDistance) < BGCurve.Epsilon) + { + gettingCloser = true; + ratio = 1; + pointX = toPos.x; + pointY = toPos.y; + pointZ = toPos.z; + } + else + { + // dot inlined + var dot = (float) (fromTargetX*fromToX + fromTargetY*fromToY + fromTargetZ*fromToZ); + + if (dot < 0) + { + ratio = 0; + pointX = fromPos.x; + pointY = fromPos.y; + pointZ = fromPos.z; + } + else if (dot > fromToSquaredDistance) + { + gettingCloser = true; + ratio = 1; + pointX = toPos.x; + pointY = toPos.y; + pointZ = toPos.z; + } + else + { + var dotRatio = dot / fromToSquaredDistance; + ratio = dotRatio; + pointX = fromPos.x + fromToX*dotRatio; + pointY = fromPos.y + fromToY*dotRatio; + pointZ = fromPos.z + fromToZ*dotRatio; + } + } + + //------------------------------------------------------ Compare with min distance + //sqr magnitude inlined + var deltaX = (double) targetPoint.x - (double) pointX; + var deltaY = (double) targetPoint.y - (double) pointY; + var deltaZ = (double) targetPoint.z - (double) pointZ; + var sqrMagnitude = (float) (deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ); + if (sqrMagnitude < minDistance) + { + minDistance = sqrMagnitude; + result.x = (float) pointX; + result.y = (float) pointY; + result.z = (float) pointZ; + sectionIndex = i; + + if (gettingCloser) + { + //if we are getting closer-> simply move the pointer to current point + if (j == pointsCount - 1 && i < sectionsCount - 1) + { + //if it's the last point in the current section-> move pointer to 1st point of the next section (to calc distances correctly) + sectionIndex = i + 1; + pointIndex = 0; + } + else + { + pointIndex = j; + } + + resultLerp = 0; + } + else + { + //current closest point somewhere on this line (resultLerp show how far from [j - 1] to [j]) + pointIndex = j - 1; + resultLerp = ratio; + } + } + } + + fromPoint = toPoint; + fromPartition = toPartition; + } + } + + //================================================================================================ + // Final result + //================================================================================================ + var resultSection = sections[sectionIndex]; + if (resultLerp > 0 && resultLerp < 1 && pointIndex < resultSection.PointsCount - 1) + { + var lerpFrom = resultSection[pointIndex]; + var lerpTo = resultSection[pointIndex + 1]; + + tangent = Vector3.Lerp(lerpFrom.Tangent, lerpTo.Tangent, resultLerp); + distance = sections[sectionIndex].DistanceFromStartToOrigin + Mathf.Lerp(lerpFrom.DistanceToSectionStart, lerpTo.DistanceToSectionStart, resultLerp); + } + else + { + var resultPoint = sections[sectionIndex][pointIndex]; + + tangent = resultPoint.Tangent; + distance = sections[sectionIndex].DistanceFromStartToOrigin + resultPoint.DistanceToSectionStart; + } + + return result; + } + + //max distance between a point and a section + private static float MaxDistance(BGCurveBaseMath.SectionInfo section, Vector3 position) + { +// var fromDistance = Vector3.SqrMagnitude(section.OriginalFrom - position); + var deltaX = section.OriginalFrom.x - position.x; + var deltaY = section.OriginalFrom.y - position.y; + var deltaZ = section.OriginalFrom.z - position.z; + var fromDistance = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; + + +// var toDistance = Vector3.SqrMagnitude(section.OriginalTo - position); + deltaX = section.OriginalTo.x - position.x; + deltaY = section.OriginalTo.y - position.y; + deltaZ = section.OriginalTo.z - position.z; + var toDistance = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; + + + var fromControlAbsent = section.OriginalFromControlType == BGCurvePoint.ControlTypeEnum.Absent; + var toControlAbsent = section.OriginalToControlType == BGCurvePoint.ControlTypeEnum.Absent; + float maxDistance; + if (fromControlAbsent && toControlAbsent) + { + maxDistance = Mathf.Max(fromDistance, toDistance); + } + else + { + if (fromControlAbsent) + { + // var toControlDistance = Vector3.SqrMagnitude(section.OriginalToControl - position); + deltaX = section.OriginalToControl.x - position.x; + deltaY = section.OriginalToControl.y - position.y; + deltaZ = section.OriginalToControl.z - position.z; + var toControlDistance = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; + + + maxDistance = Mathf.Max(Mathf.Max(fromDistance, toDistance), toControlDistance); + } + else if (toControlAbsent) + { + // var fromControlDistance = Vector3.SqrMagnitude(section.OriginalFromControl - position); + deltaX = section.OriginalFromControl.x - position.x; + deltaY = section.OriginalFromControl.y - position.y; + deltaZ = section.OriginalFromControl.z - position.z; + var fromControlDistance = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; + + + maxDistance = Mathf.Max(Mathf.Max(fromDistance, toDistance), fromControlDistance); + } + else + { + // var fromControlDistance = Vector3.SqrMagnitude(section.OriginalFromControl - position); + deltaX = section.OriginalFromControl.x - position.x; + deltaY = section.OriginalFromControl.y - position.y; + deltaZ = section.OriginalFromControl.z - position.z; + var fromControlDistance = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; + + // var toControlDistance = Vector3.SqrMagnitude(section.OriginalToControl - position); + deltaX = section.OriginalToControl.x - position.x; + deltaY = section.OriginalToControl.y - position.y; + deltaZ = section.OriginalToControl.z - position.z; + var toControlDistance = deltaX*deltaX + deltaY*deltaY + deltaZ*deltaZ; + + maxDistance = Mathf.Max(Mathf.Max(Mathf.Max(fromDistance, toDistance), fromControlDistance), toControlDistance); + } + } + return maxDistance; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveCalculatorClosestPoint.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveCalculatorClosestPoint.cs.meta new file mode 100644 index 0000000..83a8d0d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveCalculatorClosestPoint.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 40763d37e0dc903468aa5813eb0d99d0 +timeCreated: 1474035777 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveChangedArgs.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveChangedArgs.cs new file mode 100644 index 0000000..d268b7b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveChangedArgs.cs @@ -0,0 +1,179 @@ +using System; + +namespace BansheeGz.BGSpline.Curve +{ + /// + /// THIS NEED TO BE REWORKED. + /// + /// Curve's change information. It's used only if Use curve.UseEventsArgs=true + /// + /// Multiple- muliple changes + /// CurveTransform- curve transform changed + /// Points- point(s) was added or removed or swapped, or 'closed' attribute changed + /// Point - point position changed + /// PointControl - point's controls changed + /// PointControlType -point's control type changed + /// Fields -point's fields changed + /// + public class BGCurveChangedArgs : EventArgs, ICloneable + { + //reusable event instance + private static readonly BGCurveChangedArgs Instance = new BGCurveChangedArgs(); + + + //all possible types of changes + public enum ChangeTypeEnum + { + Multiple, + CurveTransform, + Points, + Point, + Fields, + Snap, + Curve + } + + //type of the change + private ChangeTypeEnum changeType; + + //changed curve + private BGCurve curve; + //changed point + private BGCurvePointI point; + //event message + private string message; + //multiple changes + private BGCurveChangedArgs[] multipleChanges; + + /// Type of the change + public ChangeTypeEnum ChangeType + { + get { return changeType; } + } + + /// Changed curve + public BGCurve Curve + { + get { return curve; } + } + + /// Change message + public string Message + { + get { return message; } + } + + /// Multiple changes + public BGCurveChangedArgs[] MultipleChanges + { + get { return multipleChanges; } + } + + /* + public BGCurveChangedArgs(BGCurve curve, ChangeTypeEnum changeType) + { + this.curve = curve; + this.changeType = changeType; + } + + public BGCurveChangedArgs(BGCurve curve, BGCurvePoint point, ChangeTypeEnum changeType) : this(curve, changeType) + { + this.point = point; + } + + public BGCurveChangedArgs(BGCurve curve, BGCurveChangedArgs[] multipleChanges) + { + this.curve = curve; + changeType = ChangeTypeEnum.Multiple; + this.multipleChanges = multipleChanges; + } + */ + + private BGCurveChangedArgs() + { + } + + /// Init and get event instance + public static BGCurveChangedArgs GetInstance(BGCurve curve, ChangeTypeEnum type, string message) + { + Instance.curve = curve; + Instance.changeType = type; + Instance.message = message; + Instance.multipleChanges = null; + Instance.point = null; + return Instance; + } + + /// Init and get event instance + public static BGCurveChangedArgs GetInstance(BGCurve curve, BGCurveChangedArgs[] changes, string changesInTransaction) + { + Instance.curve = curve; + Instance.changeType = ChangeTypeEnum.Multiple; + Instance.message = BGCurve.EventTransaction; + Instance.multipleChanges = changes; + Instance.point = null; + return Instance; + } + + /// Init and get event instance + public static BGCurveChangedArgs GetInstance(BGCurve curve, BGCurvePointI point, string changesInTransaction) + { + Instance.curve = curve; + Instance.changeType = ChangeTypeEnum.Point; + Instance.message = BGCurve.EventTransaction; + Instance.point = point; + return Instance; + } + + /// Clone event + public object Clone() + { + return new BGCurveChangedArgs + { + changeType = changeType, + curve = curve, + multipleChanges = multipleChanges, + message = message, + point = point + }; + } + + protected bool Equals(BGCurveChangedArgs other) + { + return changeType == other.changeType && Equals(curve, other.curve) ; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((BGCurveChangedArgs) obj); + } + + public override int GetHashCode() + { + var hashCode = (int) changeType; + hashCode = (hashCode*397) ^ (curve != null ? curve.GetHashCode() : 0); + return hashCode; + } + + /// Before change event + public class BeforeChange : EventArgs + { + public static readonly BeforeChange BeforeChangeInstance = new BeforeChange(); + + public string Operation; + + private BeforeChange() + { + } + + public static BeforeChange GetInstance(string operation) + { + BeforeChangeInstance.Operation = operation; + return BeforeChangeInstance; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveChangedArgs.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveChangedArgs.cs.meta new file mode 100644 index 0000000..192bddf --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveChangedArgs.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 42a0fb8b80d3c5747ad89e7288172f3a +timeCreated: 1459523844 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulaMath.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulaMath.cs new file mode 100644 index 0000000..274d721 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulaMath.cs @@ -0,0 +1,290 @@ +using System; +using UnityEngine; + + +namespace BansheeGz.BGSpline.Curve +{ + /// + /// Do not use it. This is an old deprecated math, using parametric formulas to get position and tangent. + /// It does not have any advantage over BGCurveBaseMath, which is slightly faster and have a little lesser memory footprint. + /// We leave this class for testing and reference purposes only. + /// + [Obsolete("Use BGCurveBaseMath. This class is for testing purpose only")] + public class BGCurveFormulaMath : BGCurveBaseMath + { + // cached data (t=some ratio [0,1], tr=1-t, t2=t*t, etc.). + //position + private float[] bakedT; + private float[] bakedT2; + private float[] bakedTr2; + private float[] bakedT3; + private float[] bakedTr3; + private float[] bakedTr2xTx3; + private float[] bakedT2xTrx3; + private float[] bakedTxTrx2; + + //tangent related + private float[] bakedTr2x3; + private float[] bakedTxTrx6; + private float[] bakedT2x3; + private float[] bakedTx2; + private float[] bakedTrx2; + + public BGCurveFormulaMath(BGCurve curve, Config config) + : base(curve, config) + { + } + + //some additional init + protected override void AfterInit(Config config) + { + //let's bake some data + var parts = config.Parts; + var sectionPointsCount = parts + 1; + + Array.Resize(ref bakedT, sectionPointsCount); + + Array.Resize(ref bakedT2, sectionPointsCount); + Array.Resize(ref bakedTr2, sectionPointsCount); + Array.Resize(ref bakedT3, sectionPointsCount); + Array.Resize(ref bakedTr3, sectionPointsCount); + + Array.Resize(ref bakedTr2xTx3, sectionPointsCount); + Array.Resize(ref bakedT2xTrx3, sectionPointsCount); + Array.Resize(ref bakedTxTrx2, sectionPointsCount); + + if (NeedTangentFormula) + { + Array.Resize(ref bakedTr2x3, sectionPointsCount); + Array.Resize(ref bakedTxTrx6, sectionPointsCount); + Array.Resize(ref bakedT2x3, sectionPointsCount); + Array.Resize(ref bakedTx2, sectionPointsCount); + Array.Resize(ref bakedTrx2, sectionPointsCount); + } + + for (var i = 0; i <= parts; i++) + { + var t = i/(float) parts; + var tr = 1 - t; + var t2 = t*t; + var tr2 = tr*tr; + + bakedT[i] = t; + + bakedT2[i] = t2; + bakedTr2[i] = tr2; + bakedT3[i] = t2*t; + bakedTr3[i] = tr2*tr; + + bakedTr2xTx3[i] = 3*tr2*t; + bakedT2xTrx3[i] = 3*tr*t2; + bakedTxTrx2[i] = 2*tr*t; + + if (!NeedTangentFormula) continue; + + + bakedTr2x3[i] = 3*tr2; + bakedTxTrx6[i] = 6*tr*t; + bakedT2x3[i] = 3*t2; + bakedTx2[i] = 2*t; + bakedTrx2[i] = 2*tr; + } + } + + //standard c# dispose + public override void Dispose() + { + base.Dispose(); + + var emptyArray = new float[0]; + bakedT = emptyArray; + bakedT2 = emptyArray; + bakedTr2 = emptyArray; + bakedT3 = emptyArray; + bakedTr3 = emptyArray; + bakedTr2xTx3 = emptyArray; + bakedT2xTrx3 = emptyArray; + bakedTxTrx2 = emptyArray; + + bakedTr2x3 = emptyArray; + bakedTxTrx6 = emptyArray; + bakedT2x3 = emptyArray; + bakedTx2 = emptyArray; + bakedTrx2 = emptyArray; + } + + //calculate one split section data + protected override void CalculateSplitSection(SectionInfo section, BGCurvePointI @from, BGCurvePointI to) + { + Resize(section.points, config.Parts + 1); + + //======================================== + // Calculate points + //======================================== + //-----------section data + var fromPos = section.OriginalFrom; + var toPos = section.OriginalTo; + var control1 = section.OriginalFromControl; + var control2 = section.OriginalToControl; + + var controlFromAbsent = @from.ControlType == BGCurvePoint.ControlTypeEnum.Absent; + var controlToAbsent = to.ControlType == BGCurvePoint.ControlTypeEnum.Absent; + var noControls = controlFromAbsent && controlToAbsent; + var bothControls = !controlFromAbsent && !controlToAbsent; + if (!noControls && !bothControls && controlFromAbsent) control1 = control2; + + //snapping + var snapIsOn = curve.SnapType == BGCurve.SnapTypeEnum.Curve; + + + //-----------calc some data + + // no controls + Vector3 fromTo = Vector3.zero, fromToTangentWorld = Vector3.zero; + if (noControls) + { + fromTo = toPos - fromPos; + if (cacheTangent) fromToTangentWorld = (to.PositionWorld - @from.PositionWorld).normalized; + } + + // tangent related + Vector3 control1MinusFrom = Vector3.zero, control2MinusControl1 = Vector3.zero, toMinusControl2 = Vector3.zero, toMinusControl1 = Vector3.zero; + if (!config.UsePointPositionsToCalcTangents && cacheTangent) + { + control1MinusFrom = control1 - fromPos; + if (bothControls) + { + control2MinusControl1 = control2 - control1; + toMinusControl2 = toPos - control2; + } + else + { + toMinusControl1 = toPos - control1; + } + } + + + //----------- Critical block starts + var length = bakedT.Length; + for (var i = 0; i < length; i++) + { + var point = section.points[i] ?? (section.points[i] = new SectionPointInfo()); + + Vector3 pos; + + if (noControls) + { + // ================= NoControls + // ---------- position + var t = bakedT[i]; + pos = new Vector3(fromPos.x + fromTo.x * t, fromPos.y + fromTo.y * t, fromPos.z + fromTo.z * t); + + if (snapIsOn) curve.ApplySnapping(ref pos); + + point.Position = pos; + + //---------- tangents + if (cacheTangent) point.Tangent = fromToTangentWorld; + } + else + { + // ================= At least One control + //---------- position + + if (bothControls) + { + var tr3 = bakedTr3[i]; + var tr2xTx3 = bakedTr2xTx3[i]; + var t2xTrx3 = bakedT2xTrx3[i]; + var t3 = bakedT3[i]; + + pos = new Vector3(tr3 * fromPos.x + tr2xTx3 * control1.x + t2xTrx3 * control2.x + t3 * toPos.x, + tr3 * fromPos.y + tr2xTx3 * control1.y + t2xTrx3 * control2.y + t3 * toPos.y, + tr3 * fromPos.z + tr2xTx3 * control1.z + t2xTrx3 * control2.z + t3 * toPos.z); + } + else + { + var tr2 = bakedTr2[i]; + var txTrx2 = bakedTxTrx2[i]; + var t2 = bakedT2[i]; + + pos = new Vector3(tr2 * fromPos.x + txTrx2 * control1.x + t2 * toPos.x, + tr2 * fromPos.y + txTrx2 * control1.y + t2 * toPos.y, + tr2 * fromPos.z + txTrx2 * control1.z + t2 * toPos.z); + } + + if (snapIsOn) curve.ApplySnapping(ref pos); + + point.Position = pos; + + + //---------- tangents + if (cacheTangent) + { + if (config.UsePointPositionsToCalcTangents) + { + //-------- Calc by point's positions + //we skip 1st point, cause we do not have enough info for it. we'll set it at the next step + if (i != 0) + { + var prevPoint = section[i - 1]; + + var prevPosition = prevPoint.Position; + + var tangent = new Vector3(pos.x - prevPosition.x, pos.y - prevPosition.y, pos.z - prevPosition.z); + //Vector3.normalized inlined (tangent=tangent.normalized) + var marnitude = (float)Math.Sqrt((double)tangent.x * (double)tangent.x + (double)tangent.y * (double)tangent.y + (double)tangent.z * (double)tangent.z); + tangent = ((double)marnitude > 9.99999974737875E-06) ? new Vector3(tangent.x / marnitude, tangent.y / marnitude, tangent.z / marnitude) : Vector3.zero; + + prevPoint.Tangent = tangent; + + //we will adjust it later (if there is another section after this one , otherwise- no more data for more precise calculation) + if (i == config.Parts) point.Tangent = prevPoint.Tangent; + } + } + else + { + //-------- Calc by a formula + Vector3 tangent; + if (bothControls) + { + var tr2x3 = bakedTr2x3[i]; + var txTrx6 = bakedTxTrx6[i]; + var t2x3 = bakedT2x3[i]; + tangent = new Vector3(tr2x3 * control1MinusFrom.x + txTrx6 * control2MinusControl1.x + t2x3 * toMinusControl2.x, + tr2x3 * control1MinusFrom.y + txTrx6 * control2MinusControl1.y + t2x3 * toMinusControl2.y, + tr2x3 * control1MinusFrom.z + txTrx6 * control2MinusControl1.z + t2x3 * toMinusControl2.z); + } + else + { + var trx2 = bakedTrx2[i]; + var tx2 = bakedTx2[i]; + tangent = new Vector3(trx2 * control1MinusFrom.x + tx2 * toMinusControl1.x, + trx2 * control1MinusFrom.y + tx2 * toMinusControl1.y, + trx2 * control1MinusFrom.z + tx2 * toMinusControl1.z); + } + + //Vector3.normalized inlined (tangent=tangent.normalized) + var marnitude = (float)Math.Sqrt((double)tangent.x * (double)tangent.x + (double)tangent.y * (double)tangent.y + (double)tangent.z * (double)tangent.z); + tangent = ((double)marnitude > 9.99999974737875E-06) ? new Vector3(tangent.x / marnitude, tangent.y / marnitude, tangent.z / marnitude) : Vector3.zero; + + // set tangent + point.Tangent = tangent; + } + } + } + + + if (i == 0) continue; + + // ---------- distance to section start (Vector3.Distance inlined) + var prevPos = section[i - 1].Position; + double x = pos.x - prevPos.x; + double y = pos.y - prevPos.y; + double z = pos.z - prevPos.z; + point.DistanceToSectionStart = section[i - 1].DistanceToSectionStart + ((float)Math.Sqrt(x * x + y * y + z * z)); + } + //----------- Critical block ends + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulaMath.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulaMath.cs.meta new file mode 100644 index 0000000..b35740a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulaMath.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 53f2137c1b19f4641861ad8607f250af +timeCreated: 1475717228 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulas.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulas.cs new file mode 100644 index 0000000..7ce3b14 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulas.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// Spline related formulas. + public static class BGCurveFormulas + { + /// Cubic Bezier curve interpolation. More info + // P0=from, P1=fromControl, P2=toControl, P3=to + public static Vector3 BezierCubic(float t, Vector3 from, Vector3 fromControl, Vector3 toControl, Vector3 to) + { + // tr= t reverse + var tr = 1 - t; + var tr2 = tr*tr; + var t2 = t*t; + + return tr*tr2*from + 3*tr2*t*fromControl + 3*tr*t2*toControl + t*t2*to; + } + + /// Quadratic Bezier curve interpolation. More info + // P0=from, P1=control, P2 = to + public static Vector3 BezierQuadratic(float t, Vector3 from, Vector3 control, Vector3 to) + { + // tr= t reverse + var tr = 1 - t; + var tr2 = tr*tr; + var t2 = t*t; + + return tr2*from + 2*tr*t*control + t2*to; + } + + /// Cubic Bezier curve derivative. More info + // P0=from, P1=fromControl, P2=toControl, P3=to + public static Vector3 BezierCubicDerivative(float t, Vector3 from, Vector3 fromControl, Vector3 toControl, Vector3 to) + { + // tr= t reverse + var tr = 1 - t; + + return 3*(tr*tr)*(fromControl - from) + 6*tr*t*(toControl - fromControl) + 3*(t*t)*(to - toControl); + } + + /// Quadratic Bezier curve derivative. More info + // P0=from, P1=control, P2 = to + public static Vector3 BezierQuadraticDerivative(float t, Vector3 from, Vector3 control, Vector3 to) + { + // tr= t reverse + var tr = 1 - t; + + return 2*tr*(control - from) + 2*t*(to - control); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulas.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulas.cs.meta new file mode 100644 index 0000000..a250dc4 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveFormulas.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 076c586f3afa833488d8fc4e60e81684 +timeCreated: 1472028225 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveMathI.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveMathI.cs new file mode 100644 index 0000000..29977c1 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveMathI.cs @@ -0,0 +1,129 @@ +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// This is an interface for curve's Math solver + public interface BGCurveMathI + { + + //=============================================================================================== + // Generic (position or tangent) + //=============================================================================================== + + /// Calculate spline's field value by distance ratio. + /// field to retrieve (like position or tangent etc.) + /// Ratio between (0,1) + /// Use local coordinates instead of world + /// result field's value + Vector3 CalcByDistanceRatio(BGCurveBaseMath.Field field, float distanceRatio, bool useLocal = false); + + /// Calculate spline's field value by distance. + /// field to retrieve + /// distance from the curve's start between (0, GetDistance()) + /// Use local coordinates instead of world + /// result field's value + Vector3 CalcByDistance(BGCurveBaseMath.Field field, float distance, bool useLocal = false); + + //=============================================================================================== + // Position and tangent + //=============================================================================================== + /// Calculate both spline's fields (position and tangent) by distance ratio. + /// Ratio between (0,1) + /// result tangent + /// Use local coordinates instead of world + /// result position + Vector3 CalcByDistanceRatio(float distanceRatio, out Vector3 tangent, bool useLocal = false); + + /// Calculate both curve's fields (position and tangent) by distance. + /// distance from the curve's start between (0, GetDistance()) + /// result tangent + /// Use local coordinates instead of world + /// result position + Vector3 CalcByDistance(float distance, out Vector3 tangent, bool useLocal = false); + + /// Calculate approximate spline's point position using distance ratio. + /// Ratio between (0,1) + /// result tangent + /// Use local coordinates instead of world + /// result position + Vector3 CalcPositionAndTangentByDistanceRatio(float distanceRatio, out Vector3 tangent, bool useLocal = false); + + /// Calculate approximate spline's point position using distance. + /// distance from curve's start between (0, GetDistance()) + /// result tangent + /// Use local coordinates instead of world + /// result position + Vector3 CalcPositionAndTangentByDistance(float distance, out Vector3 tangent, bool useLocal = false); + + //=============================================================================================== + // Position + //=============================================================================================== + /// Calculate approximate spline's point position using distance ratio. + /// Ratio between (0,1) + /// Use local coordinates instead of world + Vector3 CalcPositionByDistanceRatio(float distanceRatio, bool useLocal = false); + + /// Calculate approximate spline's point position using distance. + /// distance from curve's start between (0, GetDistance()) + /// Use local coordinates instead of world + Vector3 CalcPositionByDistance(float distance, bool useLocal = false); + + //=============================================================================================== + // Tangent + //=============================================================================================== + /// Calculate approximate spline's tangent using distance ratio. + /// Ratio between (0,1) + /// Use local coordinates instead of world + Vector3 CalcTangentByDistanceRatio(float distanceRatio, bool useLocal = false); + + /// Calculate approximate spline's tangent using distance. + /// distance from curve's start between (0, GetDistance()) + /// Use local coordinates instead of world + Vector3 CalcTangentByDistance(float distance, bool useLocal = false); + + //=============================================================================================== + // Section index + //=============================================================================================== + /// Calculate spline's section using distance. + /// distance from curve's start between (0, GetDistance()) + int CalcSectionIndexByDistance(float distance); + + /// Calculate spline's section using distance ratio. + /// Ratio between (0,1) + int CalcSectionIndexByDistanceRatio(float ratio); + + //=============================================================================================== + // By closest point + //=============================================================================================== + /// Calculate spline's world point position by a point, which is closest to a given point. + /// Point's position + /// Skip any optimization at section level, if any + /// Skip any optimization at approximation points level, if any + /// Position on the spline, which is closest to a given point + Vector3 CalcPositionByClosestPoint(Vector3 point, bool skipSectionsOptimization = false, bool skipPointsOptimization = false); + + /// Calculate spline's world point position and distance by a point, which is closest to a given point. + /// Point's position + /// Result distance from the start of the spline + /// Skip any optimization at section level, if any + /// Skip any optimization at approximation points level, if any + /// Position on the spline, which is closest to a given point + Vector3 CalcPositionByClosestPoint(Vector3 point, out float distance, bool skipSectionsOptimization = false, bool skipPointsOptimization = false); + + /// Calculate spline's world point position, distance and tangent by a point, which is closest to a given point. + /// Point's position + /// Result distance from the start of the spline + /// Result tangent + /// Skip any optimization at section level, if any + /// Skip any optimization at approximation points level, if any + /// Position on the spline, which is closest to a given point + Vector3 CalcPositionByClosestPoint(Vector3 point, out float distance, out Vector3 tangent, bool skipSectionsOptimization = false, bool skipPointsOptimization = false); + + //=============================================================================================== + // Total spline's length + //=============================================================================================== + /// Get spline's approximate total distance + /// Spline's total distance + float GetDistance(); + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveMathI.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveMathI.cs.meta new file mode 100644 index 0000000..d58dd1d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveMathI.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: dbf2e4dc3f6bfad45936d71c418d16e3 +timeCreated: 1477133076 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePoint.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePoint.cs new file mode 100644 index 0000000..fe2a4c6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePoint.cs @@ -0,0 +1,817 @@ +using System; +using System.Collections.Generic; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// One inlined point data + // !!! Note, there is a BGCurvePointGO class, partially copied from this class + [Serializable] + public class BGCurvePoint : BGCurvePointI + { + + #region enums + + /// possible point's control types + public enum ControlTypeEnum + { + /// no control point + Absent, + + /// 2 points, symmetrical to each other + BezierSymmetrical, + + /// 2 points, independant + BezierIndependant + } + + /// helper enum for system fields + public enum FieldEnum + { + PositionWorld, + PositionLocal, + ControlFirstWorld, + ControlFirstLocal, + ControlSecondWorld, + ControlSecondLocal + } + + #endregion + + #region constructors + + /// All coordinates are Local by default. positionLocal relative to curve's transform, controls are relative to positionLocal. Set useWorldCoordinates to true to use world coordinates + public BGCurvePoint(BGCurve curve, Vector3 position, bool useWorldCoordinates = false) : this(curve, position, ControlTypeEnum.Absent, useWorldCoordinates) + { + } + + /// All coordinates are Local by default. positionLocal relative to curve's transform, controls are relative to positionLocal. Set useWorldCoordinates to true to use world coordinates + public BGCurvePoint(BGCurve curve, Vector3 position, ControlTypeEnum controlType, bool useWorldCoordinates = false) + : this(curve, position, controlType, Vector3.zero, Vector3.zero, useWorldCoordinates) + { + } + + /// All coordinates are Local by default. positionLocal relative to curve's transform, controls are relative to positionLocal. Set useWorldCoordinates to true to use world coordinates + public BGCurvePoint(BGCurve curve, Vector3 position, ControlTypeEnum controlType, Vector3 controlFirst, Vector3 controlSecond, bool useWorldCoordinates = false) + : this(curve, null , position, controlType, controlFirst, controlSecond, useWorldCoordinates) + { + } + + /// All coordinates are Local by default. positionLocal relative to curve's transform, controls are relative to positionLocal. Set useWorldCoordinates to true to use world coordinates + public BGCurvePoint(BGCurve curve, Transform pointTransform, Vector3 position, ControlTypeEnum controlType, Vector3 controlFirst, Vector3 controlSecond, bool useWorldCoordinates = false ) + { + this.curve = curve; + this.controlType = controlType; + this.pointTransform = pointTransform; + + if (useWorldCoordinates) + { + positionLocal = curve.transform.InverseTransformPoint(position); + controlFirstLocal = curve.transform.InverseTransformDirection(controlFirst - position); + controlSecondLocal = curve.transform.InverseTransformDirection(controlSecond - position); + } + else + { + positionLocal = position; + controlFirstLocal = controlFirst; + controlSecondLocal = controlSecond; + } + } + + #endregion + + #region fields + + //control type + [SerializeField] private ControlTypeEnum controlType; + + //relative to curve position + [SerializeField] private Vector3 positionLocal; + + //relative to point position + [SerializeField] private Vector3 controlFirstLocal; + [SerializeField] private Vector3 controlSecondLocal; + + [SerializeField] private Transform pointTransform; + + + //point's curve + [SerializeField] private BGCurve curve; + + //custom fields values for all points. it's an array with only one element. the reason why we store it like this- is to reduce storage and serialization costs. + [SerializeField] private FieldsValues[] fieldsValues; + + /// The curve, point's belong to + public BGCurve Curve + { + get { return curve; } + } + + /// This field is not meant for use outside of BGCurve package + //all fields values + public FieldsValues PrivateValuesForFields + { + get + { + if (fieldsValues == null || fieldsValues.Length < 1 || fieldsValues[0] == null) fieldsValues = new[] {new FieldsValues()}; + return fieldsValues[0]; + } + set + { + if (fieldsValues == null || fieldsValues.Length < 1 || fieldsValues[0] == null) fieldsValues = new[] {new FieldsValues()}; + fieldsValues[0] = value; + } + } + + // =============================================== Position + //see interface for comments + public Vector3 PositionLocal + { + get { return pointTransform == null ? positionLocal : curve.transform.InverseTransformPoint(pointTransform.position); } + set { SetPosition(value); } + } + + //see interface for comments + public Vector3 PositionLocalTransformed + { + get + { + return pointTransform == null + ? curve.transform.TransformPoint(positionLocal) - curve.transform.position + : pointTransform.position - curve.transform.position; + } + set { SetPosition(value + curve.transform.position, true); } + } + + //see interface for comments + public Vector3 PositionWorld + { + get { return pointTransform == null ? curve.transform.TransformPoint(positionLocal) : pointTransform.position; } + set { SetPosition(value, true); } + } + + + // =============================================== First Handle + //see interface for comments + public Vector3 ControlFirstLocal + { + get { return controlFirstLocal; } + set { SetControlFirstLocal(value); } + } + + //see interface for comments + public Vector3 ControlFirstLocalTransformed + { + get { return (pointTransform == null ? curve.transform : pointTransform).TransformVector(controlFirstLocal); } + set + { + var transform = pointTransform == null ? curve.transform : pointTransform; + SetControlFirstLocal(transform.InverseTransformVector(value)); + } + } + + //see interface for comments + public Vector3 ControlFirstWorld + { + get + { + if (pointTransform == null) + return curve.transform.TransformPoint(new Vector3(positionLocal.x + controlFirstLocal.x, positionLocal.y + controlFirstLocal.y, positionLocal.z + controlFirstLocal.z)); + + return pointTransform.position + pointTransform.TransformVector(controlFirstLocal); + } + set + { + var pos = pointTransform == null ? curve.transform.InverseTransformPoint(value) - positionLocal : pointTransform.InverseTransformVector(value - pointTransform.position); + SetControlFirstLocal(pos); + } + } + + + // =============================================== Second Handle + //see interface for comments + public Vector3 ControlSecondLocal + { + get { return controlSecondLocal; } + set { SetControlSecondLocal(value); } + } + + //see interface for comments + public Vector3 ControlSecondLocalTransformed + { + get { return (pointTransform == null ? curve.transform : pointTransform).TransformVector(controlSecondLocal); } + set + { + var transform = pointTransform == null ? curve.transform : pointTransform; + SetControlSecondLocal(transform.InverseTransformVector(value)); + } + } + + + //see interface for comments + public Vector3 ControlSecondWorld + { + get + { + if (pointTransform == null) + return curve.transform.TransformPoint(new Vector3(positionLocal.x + controlSecondLocal.x, positionLocal.y + controlSecondLocal.y, positionLocal.z + controlSecondLocal.z)); + + return pointTransform.position + pointTransform.TransformVector(controlSecondLocal); + } + set + { + var pos = pointTransform == null ? curve.transform.InverseTransformPoint(value) - positionLocal : pointTransform.InverseTransformVector(value - pointTransform.position); + SetControlSecondLocal(pos); + } + } + + + // =============================================== Control type + //see interface for comments + public ControlTypeEnum ControlType + { + get { return controlType; } + set + { + if (controlType == value) return; + + curve.FireBeforeChange(BGCurve.EventPointControlType); + + controlType = value; + + if (controlType == ControlTypeEnum.BezierSymmetrical) controlSecondLocal = -controlFirstLocal; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointControlType) : null, sender: this); + } + } + + + // =============================================== Transform + public Transform PointTransform + { + get { return pointTransform; } + set + { + if (pointTransform == value) return; + + curve.FireBeforeChange(BGCurve.EventPointTransform); + + var oldTransformNull = pointTransform == null && value != null; + var newTransformNull = value == null && pointTransform != null; + + //we need to transfer system fields + var control1 = ControlFirstLocalTransformed; + var control2 = ControlSecondLocalTransformed; + var positionWorld = PositionWorld; + + pointTransform = value; + + // transfer system fields + if (pointTransform != null) + { + pointTransform.position = positionWorld; + controlFirstLocal = pointTransform.InverseTransformVector(control1); + controlSecondLocal = pointTransform.InverseTransformVector(control2); + } + else + { + positionLocal = curve.transform.InverseTransformPoint(positionWorld); + controlFirstLocal = curve.transform.InverseTransformVector(control1); + controlSecondLocal = curve.transform.InverseTransformVector(control2); + } + + + // inform curve + if (oldTransformNull) curve.PrivateTransformForPointAdded(curve.IndexOf(this)); + else if (newTransformNull) curve.PrivateTransformForPointRemoved(curve.IndexOf(this)); + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointTransform) : null, sender: this); + } + } + + #endregion + + #region custom fields + + //=============================================================================================== + // Custom Fields (see interface for comments) + //=============================================================================================== + //----------------------------------- Getters + public T GetField(string name) + { + var type = typeof(T); + var value = GetField(name, type); + var field = (T) value; + return field; + } + + public float GetFloat(string name) + { + return PrivateValuesForFields.floatValues[curve.IndexOfFieldValue(name)]; + } + + public bool GetBool(string name) + { + return PrivateValuesForFields.boolValues[curve.IndexOfFieldValue(name)]; + } + + public int GetInt(string name) + { + return PrivateValuesForFields.intValues[curve.IndexOfFieldValue(name)]; + } + + public Vector3 GetVector3(string name) + { + return PrivateValuesForFields.vector3Values[curve.IndexOfFieldValue(name)]; + } + + public Quaternion GetQuaternion(string name) + { + return PrivateValuesForFields.quaternionValues[curve.IndexOfFieldValue(name)]; + } + + public Bounds GetBounds(string name) + { + return PrivateValuesForFields.boundsValues[curve.IndexOfFieldValue(name)]; + } + + public Color GetColor(string name) + { + return PrivateValuesForFields.colorValues[curve.IndexOfFieldValue(name)]; + } + + public object GetField(string name, Type type) + { + return FieldTypes.GetField(curve, type, name, PrivateValuesForFields); + } + + //----------------------------------- Setters + public void SetField(string name, T value) + { + SetField(name, value, typeof(T)); + } + + public void SetField(string name, object value, Type type) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + FieldTypes.SetField(curve, type, name, value, PrivateValuesForFields); + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetFloat(string name, float value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.floatValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetBool(string name, bool value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.boolValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetInt(string name, int value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.intValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetVector3(string name, Vector3 value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.vector3Values[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetQuaternion(string name, Quaternion value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.quaternionValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetBounds(string name, Bounds value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.boundsValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetColor(string name, Color value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.colorValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + #endregion + + #region Misc public methods + + //================================================================================ + // Misc public functions + //================================================================================ + /// return system Vector 3 field + public Vector3 Get(FieldEnum field) + { + Vector3 result; + switch (field) + { + //position + case FieldEnum.PositionWorld: + result = PositionWorld; + break; + case FieldEnum.PositionLocal: + result = positionLocal; + break; + + //first control + case FieldEnum.ControlFirstWorld: + result = ControlFirstWorld; + break; + case FieldEnum.ControlFirstLocal: + result = controlFirstLocal; + break; + + //second control + case FieldEnum.ControlSecondWorld: + result = ControlSecondWorld; + break; + default: + result = controlSecondLocal; + break; + } + return result; + } + + //see interface for comments + + public override string ToString() + { + return "Point [localPosition=" + positionLocal + "]"; + } + + #endregion + + #region private methods + + //set local position + private void SetPosition(Vector3 value, bool worldSpaceIsUsed = false) + { + curve.FireBeforeChange(BGCurve.EventPointPosition); + + //snapping + if (curve.SnapType != BGCurve.SnapTypeEnum.Off) + { + if (worldSpaceIsUsed) curve.ApplySnapping(ref value); + else + { + //we need to transfer space before applying snapping + var pos = curve.transform.TransformPoint(value); + if (curve.ApplySnapping(ref pos)) value = curve.transform.InverseTransformPoint(pos); + } + } + + + //assign position + if (pointTransform == null) + { + if (worldSpaceIsUsed) + { + var localPos = curve.transform.InverseTransformPoint(value); + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) localPos = curve.Apply2D(localPos); + positionLocal = localPos; + } + else + { + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + positionLocal = value; + } + } + else + { + //2d mode with curve's transform changed is not working correctly + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + pointTransform.position = worldSpaceIsUsed ? value : curve.transform.TransformPoint(value); + } + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointPosition) : null, sender: this); + } + + //set local control 1 + private void SetControlFirstLocal(Vector3 value) + { + curve.FireBeforeChange(BGCurve.EventPointControl); + + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + + if (controlType == ControlTypeEnum.BezierSymmetrical) controlSecondLocal = -value; + + controlFirstLocal = value; + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointControl) : null, sender: this); + } + + //set local control 2 (it's basically copy/paste from SetControlFirstLocal, but we can not use delegates here because of performance) + private void SetControlSecondLocal(Vector3 value) + { + curve.FireBeforeChange(BGCurve.EventPointControl); + + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + + if (controlType == ControlTypeEnum.BezierSymmetrical) controlFirstLocal = -value; + + controlSecondLocal = value; + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointControl) : null, sender: this); + } + + /// all methods, prefixed with Private, are not meant to be called from outside of BGCurve package + // field deleted callback + public static void PrivateFieldDeleted(BGCurvePointField field, int indexOfField, FieldsValues fieldsValues) + { + switch (field.Type) + { + case BGCurvePointField.TypeEnum.Bool: + Ensure(ref fieldsValues.boolValues); + fieldsValues.boolValues = BGCurve.Remove(fieldsValues.boolValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.Int: + Ensure(ref fieldsValues.intValues); + fieldsValues.intValues = BGCurve.Remove(fieldsValues.intValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.Float: + Ensure(ref fieldsValues.floatValues); + fieldsValues.floatValues = BGCurve.Remove(fieldsValues.floatValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.Vector3: + Ensure(ref fieldsValues.vector3Values); + fieldsValues.vector3Values = BGCurve.Remove(fieldsValues.vector3Values, indexOfField); + break; + case BGCurvePointField.TypeEnum.Bounds: + Ensure(ref fieldsValues.boundsValues); + fieldsValues.boundsValues = BGCurve.Remove(fieldsValues.boundsValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.Color: + Ensure(ref fieldsValues.colorValues); + fieldsValues.colorValues = BGCurve.Remove(fieldsValues.colorValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.String: + Ensure(ref fieldsValues.stringValues); + fieldsValues.stringValues = BGCurve.Remove(fieldsValues.stringValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.Quaternion: + Ensure(ref fieldsValues.quaternionValues); + fieldsValues.quaternionValues = BGCurve.Remove(fieldsValues.quaternionValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.AnimationCurve: + Ensure(ref fieldsValues.animationCurveValues); + fieldsValues.animationCurveValues = BGCurve.Remove(fieldsValues.animationCurveValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.GameObject: + Ensure(ref fieldsValues.gameObjectValues); + fieldsValues.gameObjectValues = BGCurve.Remove(fieldsValues.gameObjectValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.Component: + Ensure(ref fieldsValues.componentValues); + fieldsValues.componentValues = BGCurve.Remove(fieldsValues.componentValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.BGCurve: + Ensure(ref fieldsValues.bgCurveValues); + fieldsValues.bgCurveValues = BGCurve.Remove(fieldsValues.bgCurveValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.BGCurvePointComponent: + Ensure(ref fieldsValues.bgCurvePointComponentValues); + fieldsValues.bgCurvePointComponentValues = BGCurve.Remove(fieldsValues.bgCurvePointComponentValues, indexOfField); + break; + case BGCurvePointField.TypeEnum.BGCurvePointGO: + Ensure(ref fieldsValues.bgCurvePointGOValues); + fieldsValues.bgCurvePointGOValues = BGCurve.Remove(fieldsValues.bgCurvePointGOValues, indexOfField); + break; + default: + throw new ArgumentOutOfRangeException("field.Type", field.Type, "Unsupported type " + field.Type); + } + } + + /// all methods, prefixed with Private, are not meant to be called from outside of BGCurve package + // field added callback + public static void PrivateFieldAdded(BGCurvePointField field, FieldsValues fieldsValues) + { + var type = FieldTypes.GetType(field.Type); + var item = BGReflectionAdapter.IsValueType(type) ? Activator.CreateInstance(type) : null; + + switch (field.Type) + { + case BGCurvePointField.TypeEnum.Bool: + Ensure(ref fieldsValues.boolValues); + fieldsValues.boolValues = BGCurve.Insert(fieldsValues.boolValues, fieldsValues.boolValues.Length, (bool) item); + break; + case BGCurvePointField.TypeEnum.Int: + Ensure(ref fieldsValues.intValues); + fieldsValues.intValues = BGCurve.Insert(fieldsValues.intValues, fieldsValues.intValues.Length, (int) item); + break; + case BGCurvePointField.TypeEnum.Float: + Ensure(ref fieldsValues.floatValues); + fieldsValues.floatValues = BGCurve.Insert(fieldsValues.floatValues, fieldsValues.floatValues.Length, (float) item); + break; + case BGCurvePointField.TypeEnum.Vector3: + Ensure(ref fieldsValues.vector3Values); + fieldsValues.vector3Values = BGCurve.Insert(fieldsValues.vector3Values, fieldsValues.vector3Values.Length, (Vector3) item); + break; + case BGCurvePointField.TypeEnum.Bounds: + Ensure(ref fieldsValues.boundsValues); + fieldsValues.boundsValues = BGCurve.Insert(fieldsValues.boundsValues, fieldsValues.boundsValues.Length, (Bounds) item); + break; + case BGCurvePointField.TypeEnum.Color: + Ensure(ref fieldsValues.colorValues); + fieldsValues.colorValues = BGCurve.Insert(fieldsValues.colorValues, fieldsValues.colorValues.Length, (Color) item); + break; + case BGCurvePointField.TypeEnum.String: + Ensure(ref fieldsValues.stringValues); + fieldsValues.stringValues = BGCurve.Insert(fieldsValues.stringValues, fieldsValues.stringValues.Length, (string) item); + break; + case BGCurvePointField.TypeEnum.Quaternion: + Ensure(ref fieldsValues.quaternionValues); + fieldsValues.quaternionValues = BGCurve.Insert(fieldsValues.quaternionValues, fieldsValues.quaternionValues.Length, (Quaternion) item); + break; + case BGCurvePointField.TypeEnum.AnimationCurve: + Ensure(ref fieldsValues.animationCurveValues); + fieldsValues.animationCurveValues = BGCurve.Insert(fieldsValues.animationCurveValues, fieldsValues.animationCurveValues.Length, (AnimationCurve) item); + break; + case BGCurvePointField.TypeEnum.GameObject: + Ensure(ref fieldsValues.gameObjectValues); + fieldsValues.gameObjectValues = BGCurve.Insert(fieldsValues.gameObjectValues, fieldsValues.gameObjectValues.Length, (GameObject) item); + break; + case BGCurvePointField.TypeEnum.Component: + Ensure(ref fieldsValues.componentValues); + fieldsValues.componentValues = BGCurve.Insert(fieldsValues.componentValues, fieldsValues.componentValues.Length, (Component) item); + break; + case BGCurvePointField.TypeEnum.BGCurve: + Ensure(ref fieldsValues.bgCurveValues); + fieldsValues.bgCurveValues = BGCurve.Insert(fieldsValues.bgCurveValues, fieldsValues.bgCurveValues.Length, (BGCurve) item); + break; + case BGCurvePointField.TypeEnum.BGCurvePointComponent: + Ensure(ref fieldsValues.bgCurvePointComponentValues); + fieldsValues.bgCurvePointComponentValues = BGCurve.Insert(fieldsValues.bgCurvePointComponentValues, fieldsValues.bgCurvePointComponentValues.Length, (BGCurvePointComponent) item); + break; + case BGCurvePointField.TypeEnum.BGCurvePointGO: + Ensure(ref fieldsValues.bgCurvePointGOValues); + fieldsValues.bgCurvePointGOValues = BGCurve.Insert(fieldsValues.bgCurvePointGOValues, fieldsValues.bgCurvePointGOValues.Length, (BGCurvePointGO) item); + break; + default: + throw new ArgumentOutOfRangeException("field.Type", field.Type, "Unsupported type " + field.Type); + } + } + + //ensure list is not null + private static void Ensure(ref T[] array) + { + if (array == null) array = new T[0]; + } + + #endregion + + #region helper classes + + //================================================================================ + // Values for the fields + //================================================================================ + /// All values for custom fields + //the reason we store it like this- is to reduce memory and serialization cost + [Serializable] + public sealed class FieldsValues + { + // c# + [SerializeField] public bool[] boolValues; + [SerializeField] public int[] intValues; + [SerializeField] public float[] floatValues; + [SerializeField] public string[] stringValues; + + // Unity structs + [SerializeField] public Vector3[] vector3Values; + [SerializeField] public Bounds[] boundsValues; + [SerializeField] public Color[] colorValues; + [SerializeField] public Quaternion[] quaternionValues; + + // Unity objects + [SerializeField] public AnimationCurve[] animationCurveValues; + [SerializeField] public GameObject[] gameObjectValues; + [SerializeField] public Component[] componentValues; + + // BGCurve + [SerializeField] public BGCurve[] bgCurveValues; + [SerializeField] public BGCurvePointComponent[] bgCurvePointComponentValues; + [SerializeField] public BGCurvePointGO[] bgCurvePointGOValues; + } + + //================================================================================ + // Types for the fields + //================================================================================ + /// Types for custom fields + public static class FieldTypes + { + private static readonly Dictionary> type2fieldGetter = new Dictionary>(); + private static readonly Dictionary> type2fieldSetter = new Dictionary>(); + private static readonly Dictionary type2Type = new Dictionary(); + + static FieldTypes() + { + // All these getters/setters are used only for classes now. For structs and primitives there is overriden getXXX setXXX methods (to get rid of boxing/unboxing). + //primitives + Register(BGCurvePointField.TypeEnum.Bool, typeof(bool), (value, index) => value.boolValues[index], (value, index, o) => value.boolValues[index] = Convert.ToBoolean((object) o)); + Register(BGCurvePointField.TypeEnum.Int, typeof(int), (value, index) => value.intValues[index], (value, index, o) => value.intValues[index] = Convert.ToInt32((object) o)); + Register(BGCurvePointField.TypeEnum.Float, typeof(float), (value, index) => value.floatValues[index], (value, index, o) => value.floatValues[index] = Convert.ToSingle((object) o)); + + //string + Register(BGCurvePointField.TypeEnum.String, typeof(string), (value, index) => value.stringValues[index], (value, index, o) => value.stringValues[index] = (string) o); + + //unity structs and classes + Register(BGCurvePointField.TypeEnum.Vector3, typeof(Vector3), (value, index) => value.vector3Values[index], (value, index, o) => value.vector3Values[index] = (Vector3) o); + Register(BGCurvePointField.TypeEnum.Bounds, typeof(Bounds), (value, index) => + { + var r = value.boundsValues[index]; + return r; + }, (value, index, o) => value.boundsValues[index] = (Bounds) o); + Register(BGCurvePointField.TypeEnum.Quaternion, typeof(Quaternion), (value, index) => value.quaternionValues[index], + (value, index, o) => value.quaternionValues[index] = (Quaternion) o); + Register(BGCurvePointField.TypeEnum.Color, typeof(Color), (value, index) => value.colorValues[index], (value, index, o) => value.colorValues[index] = (Color) o); + Register(BGCurvePointField.TypeEnum.AnimationCurve, typeof(AnimationCurve), (value, index) => value.animationCurveValues[index], + (value, index, o) => value.animationCurveValues[index] = (AnimationCurve) o); + + //unity GO and components + Register(BGCurvePointField.TypeEnum.GameObject, typeof(GameObject), (value, index) => value.gameObjectValues[index], + (value, index, o) => value.gameObjectValues[index] = (GameObject) o); + Register(BGCurvePointField.TypeEnum.Component, typeof(Component), (value, index) => value.componentValues[index], + (value, index, o) => value.componentValues[index] = (Component) o); + + //bg curve related + Register(BGCurvePointField.TypeEnum.BGCurve, typeof(BGCurve), (value, index) => value.bgCurveValues[index], (value, index, o) => value.bgCurveValues[index] = (BGCurve) o); + Register(BGCurvePointField.TypeEnum.BGCurvePointComponent, typeof(BGCurvePointComponent), (value, index) => value.bgCurvePointComponentValues[index], + (value, index, o) => value.bgCurvePointComponentValues[index] = (BGCurvePointComponent) o); + Register(BGCurvePointField.TypeEnum.BGCurvePointGO, typeof(BGCurvePointGO), (value, index) => value.bgCurvePointGOValues[index], + (value, index, o) => value.bgCurvePointGOValues[index] = (BGCurvePointGO) o); + } + + // register data about one type + private static void Register(BGCurvePointField.TypeEnum typeEnum, Type type, Func getter, Action setter) + { + type2Type[typeEnum] = type; + type2fieldGetter[type] = getter; + type2fieldSetter[type] = setter; + } + + /// Get c# type(class), used for value of custom field with type "type" + public static Type GetType(BGCurvePointField.TypeEnum type) + { + return type2Type[type]; + } + + /// retrieve value for particular field with name "name" and type "type" + public static object GetField(BGCurve curve, Type type, string name, FieldsValues values) + { + Func getter; + if (!type2fieldGetter.TryGetValue(type, out getter)) throw new UnityException("Unsupported type for a field, type= " + type); + + return getter(values, IndexOfFieldRelative(curve, name)); + } + + /// set value for particular field with name "name" and type "type" + public static void SetField(BGCurve curve, Type type, string name, object value, FieldsValues values) + { + Action setter; + if (!type2fieldSetter.TryGetValue(type, out setter)) throw new UnityException("Unsupported type for a field, type= " + type); + + setter(values, IndexOfFieldRelative(curve, name), value); + } + + //get the index of field's value within array of values + private static int IndexOfFieldRelative(BGCurve curve, string name) + { + var result = curve.IndexOfFieldValue(name); + + if (result < 0) throw new UnityException("Can not find a field with name " + name); + + return result; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePoint.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePoint.cs.meta new file mode 100644 index 0000000..3df06c5 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePoint.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 21ab56f25c33efa44a87617a91ebd7eb +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointComponent.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointComponent.cs new file mode 100644 index 0000000..f9b0031 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointComponent.cs @@ -0,0 +1,191 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// Point, attached to a separate Component (MonoBehaviour) + // this class uses composition pattern + public class BGCurvePointComponent : MonoBehaviour, BGCurvePointI + { + [SerializeField] private BGCurvePoint point; + + public BGCurve Curve + { + get { return point.Curve; } + } + + public Vector3 PositionLocal + { + get { return point.PositionLocal; } + set { point.PositionLocal = value; } + } + + public Vector3 PositionLocalTransformed + { + get { return point.PositionLocalTransformed; } + set { point.PositionLocalTransformed = value; } + } + + public Vector3 PositionWorld + { + get { return point.PositionWorld; } + set { point.PositionWorld = value; } + } + + public Vector3 ControlFirstLocal + { + get { return point.ControlFirstLocal; } + set { point.ControlFirstLocal = value; } + } + + public Vector3 ControlFirstLocalTransformed + { + get { return point.ControlFirstLocalTransformed; } + set { point.ControlFirstLocalTransformed = value; } + } + + public Vector3 ControlFirstWorld + { + get { return point.ControlFirstWorld; } + set { point.ControlFirstWorld = value; } + } + + public Vector3 ControlSecondLocal + { + get { return point.ControlSecondLocal; } + set { point.ControlSecondLocal = value; } + } + + public Vector3 ControlSecondLocalTransformed + { + get { return point.ControlSecondLocalTransformed; } + set { point.ControlSecondLocalTransformed = value; } + } + + public Vector3 ControlSecondWorld + { + get { return point.ControlSecondWorld; } + set { point.ControlSecondWorld = value; } + } + + public BGCurvePoint.ControlTypeEnum ControlType + { + get { return point.ControlType; } + set { point.ControlType = value; } + } + + public Transform PointTransform + { + get { return point.PointTransform; } + set { point.PointTransform = value; } + } + + public float GetFloat(string name) + { + return point.GetFloat(name); + } + + public bool GetBool(string name) + { + return point.GetBool(name); + } + + public int GetInt(string name) + { + return point.GetInt(name); + } + + public Vector3 GetVector3(string name) + { + return point.GetVector3(name); + } + + public Quaternion GetQuaternion(string name) + { + return point.GetQuaternion(name); + } + + public Bounds GetBounds(string name) + { + return point.GetBounds(name); + } + + public Color GetColor(string name) + { + return point.GetColor(name); + } + + public T GetField(string name) + { + return point.GetField(name); + } + + public object GetField(string name, Type type) + { + return point.GetField(name, type); + } + + public void SetField(string name, object value, Type type) + { + point.SetField(name, value, type); + } + + public void SetField(string name, T value) + { + point.SetField(name, value); + } + + public void SetFloat(string name, float value) + { + point.SetFloat(name, value); + } + + public void SetBool(string name, bool value) + { + point.SetBool(name, value); + } + + public void SetInt(string name, int value) + { + point.SetInt(name, value); + } + + public void SetVector3(string name, Vector3 value) + { + point.SetVector3(name, value); + } + + public void SetQuaternion(string name, Quaternion value) + { + point.SetQuaternion(name, value); + } + + public void SetBounds(string name, Bounds value) + { + point.SetBounds(name, value); + } + + public void SetColor(string name, Color value) + { + point.SetColor(name, value); + } + + public BGCurvePoint Point + { + get { return point; } + } + + /// all methods, prefixed with Private, are not meant to be called from outside of BGCurve package + // this should be called once at creating time + public void PrivateInit(BGCurvePoint point) + { + this.point = point; + hideFlags = HideFlags.HideInInspector; + } + + public override string ToString() + { + return point == null ? "no data" : (point +" as Component"); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointComponent.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointComponent.cs.meta new file mode 100644 index 0000000..c8664ec --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointComponent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8cdc035869a65674f92b3b83794effb9 +timeCreated: 1475051178 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointField.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointField.cs new file mode 100644 index 0000000..1ae12b6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointField.cs @@ -0,0 +1,152 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// Meta data (name, type and settings) for custom point's field + [Serializable] + public class BGCurvePointField : MonoBehaviour + { + // all possible types for the field's value. + // Note, even if your desired type is not supported, + // you still can use it via Unity's standard Component type (assign any MonoBehaviour derived script to it) or via GameObject + public enum TypeEnum + { + //C# + Bool = 0, + Int = 1, + Float = 2, + String = 3, + + //Unity structs + Vector3 = 100, + Bounds = 101, + Color = 102, + Quaternion = 103, + + //Unity classes + AnimationCurve = 200, + GameObject = 201, + Component = 202, + + //BG related + BGCurve = 300, + BGCurvePointComponent = 301, + BGCurvePointGO= 302 + } + + //BGCurve + [SerializeField] private BGCurve curve; + //field's name. It should be unique, not null, English chars only, 16 chars max + [SerializeField] private string fieldName; + //field's type + [SerializeField] private TypeEnum type; + +#if UNITY_EDITOR + // ============================================== !!! This is editor ONLY fields +#pragma warning disable 0414 + + [SerializeField] private bool showHandles = true; + [SerializeField] private int handlesType; + [SerializeField] private Color handlesColor = Color.white; + [SerializeField] private bool showInPointsMenu = true; +#pragma warning restore 0414 +#endif + /// Field's name. It should be unique, not null, English chars only, 16 chars max + public string FieldName + { + get { return fieldName; } + set + { + if (string.Equals(FieldName, value)) return; + CheckName(curve, value, true); + + curve.FireBeforeChange(BGCurve.EventFieldName); + + fieldName = value; + curve.PrivateUpdateFieldsValuesIndexes(); + + curve.FireChange(BGCurveChangedArgs.GetInstance(curve, BGCurveChangedArgs.ChangeTypeEnum.Fields, BGCurve.EventFieldName), sender: this); + } + } + + /// Field's type + public TypeEnum Type + { + //type can not be changed + get { return type; } + } + + /// Owning curve + public BGCurve Curve + { + get { return curve; } + } + + + /// Init the field. It should be called once at creation + public void Init(BGCurve curve, string fieldName, TypeEnum type) + { + if (!string.IsNullOrEmpty(this.fieldName)) throw new UnityException("You can not init twice."); + + CheckName(curve, fieldName, true); + this.curve = curve; + this.fieldName = fieldName; + this.type = type; + } + + /// Check if name is ok. It should be unique, not null, English chars only, 16 chars max + public static string CheckName(BGCurve curve, string name, bool throwException = false) + { + string error = null; + if (string.IsNullOrEmpty(name)) error = "Field's name can not be null"; + else if (name.Length > 16) error = "Name should be 16 chars max. Current name has " + name.Length + " chars."; + else + { + var firstChar = name[0]; + if (!((firstChar >= 'A' && firstChar <= 'Z') || (firstChar >= 'a' && firstChar <= 'z'))) error = "Name should start with a English letter."; + else + { + for (var i = 1; i < name.Length; i++) + { + var @char = name[i]; + if ((@char >= 'A' && @char <= 'Z') || (@char >= 'a' && @char <= 'z') || (@char >= '0' && @char <= '9')) continue; + + error = "Name should contain English letters or numbers only."; + break; + } + if (error==null && curve.HasField(name)) error = "Field with name '" + name + "' already exists."; + } + } + + if (throwException && error != null) throw new UnityException(error); + + return error; + } + + //---------------------------------- Object overrides + + protected bool Equals(BGCurvePointField other) + { + return Equals(curve, other.curve) && string.Equals(fieldName, other.fieldName); + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != this.GetType()) return false; + return Equals((BGCurvePointField) obj); + } + + public override int GetHashCode() + { + return (curve != null ? curve.GetHashCode() : 0) ^ (fieldName != null ? fieldName.GetHashCode() : 0); + } + + public override string ToString() + { + return fieldName; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointField.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointField.cs.meta new file mode 100644 index 0000000..e147864 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointField.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 06627f7d7396a40418f87b2a58e6ddbe +timeCreated: 1474917757 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointGO.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointGO.cs new file mode 100644 index 0000000..a4c399a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointGO.cs @@ -0,0 +1,649 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// Point, attached to separate GameObject + [DisallowMultipleComponent] + // Note, some code was copy pasted from BGCurvePoint class + public class BGCurvePointGO : MonoBehaviour, BGCurvePointI + { + #region fields + + //control type + [SerializeField] private BGCurvePoint.ControlTypeEnum controlType; + + //relative to curve position + [SerializeField] private Vector3 positionLocal; + + //relative to point position + [SerializeField] private Vector3 controlFirstLocal; + [SerializeField] private Vector3 controlSecondLocal; + + //transform for using as point position + [SerializeField] private Transform pointTransform; + + + //point's curve + [SerializeField] private BGCurve curve; + + //custom fields values for all points. it's an array with only one element. the reason why we store it like this- is to reduce storage and serialization costs. + [SerializeField] private BGCurvePoint.FieldsValues[] fieldsValues; + + /// The curve, point's belong to + public BGCurve Curve + { + get { return curve; } + } + + /// This field is not meant for use outside of BGCurve package + //all fields values + public BGCurvePoint.FieldsValues PrivateValuesForFields + { + get + { + if (fieldsValues == null || fieldsValues.Length < 1 || fieldsValues[0] == null) fieldsValues = new[] {new BGCurvePoint.FieldsValues()}; + return fieldsValues[0]; + } + set + { + if (fieldsValues == null || fieldsValues.Length < 1 || fieldsValues[0] == null) fieldsValues = new[] {new BGCurvePoint.FieldsValues()}; + fieldsValues[0] = value; + } + } + + + // =============================================== Position + + //see interface for comments + public Vector3 PositionLocal + { + get + { + if (pointTransform != null) return curve.transform.InverseTransformPoint(pointTransform.position); + + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + return positionLocal; + case BGCurve.PointsModeEnum.GameObjectsTransform: + return curve.transform.InverseTransformPoint(transform.position); + default: + throw WrongMode(); + } + } + set { SetPosition(value); } + } + + //see interface for comments + public Vector3 PositionLocalTransformed + { + get + { + if(pointTransform != null) return pointTransform.position - curve.transform.position; + + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + return curve.transform.TransformPoint(positionLocal) - curve.transform.position; + case BGCurve.PointsModeEnum.GameObjectsTransform: + return transform.position - curve.transform.position; + default: + throw WrongMode(); + } + } + set { SetPosition(value + curve.transform.position, true); } + } + + //see interface for comments + public Vector3 PositionWorld + { + get + { + if (pointTransform != null) return pointTransform.position; + + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + return curve.transform.TransformPoint(positionLocal); + case BGCurve.PointsModeEnum.GameObjectsTransform: + return transform.position; + default: + throw WrongMode(); + } + } + set { SetPosition(value, true); } + } + + + // =============================================== First Handle + //see interface for comments + public Vector3 ControlFirstLocal + { + get { return controlFirstLocal; } + set { SetControlFirstLocal(value); } + } + + //see interface for comments + public Vector3 ControlFirstLocalTransformed + { + get { return TargetTransform.TransformVector(controlFirstLocal); } + set { SetControlFirstLocal(TargetTransform.InverseTransformVector(value)); } + } + + + //see interface for comments + public Vector3 ControlFirstWorld + { + get + { + if (pointTransform != null) return pointTransform.position + pointTransform.TransformVector(controlFirstLocal); + + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + return curve.transform.TransformPoint(new Vector3(positionLocal.x + controlFirstLocal.x, positionLocal.y + controlFirstLocal.y, positionLocal.z + controlFirstLocal.z)); + case BGCurve.PointsModeEnum.GameObjectsTransform: + return transform.position + transform.TransformVector(controlFirstLocal); + default: + throw WrongMode(); + } + } + set + { + Vector3 localPos; + if (pointTransform != null) localPos = pointTransform.InverseTransformVector(value - pointTransform.position); + else + { + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + localPos = curve.transform.InverseTransformPoint(value) - PositionLocal; + break; + case BGCurve.PointsModeEnum.GameObjectsTransform: + localPos = transform.InverseTransformVector(value - transform.position); + break; + default: + throw WrongMode(); + } + } + SetControlFirstLocal(localPos); + } + } + + + // =============================================== Second Handle + //see interface for comments + public Vector3 ControlSecondLocal + { + get { return controlSecondLocal; } + set { SetControlSecondLocal(value); } + } + + //see interface for comments + public Vector3 ControlSecondLocalTransformed + { + get { return TargetTransform.TransformVector(controlSecondLocal); } + set { SetControlSecondLocal(TargetTransform.InverseTransformVector(value)); } + } + + + //see interface for comments + public Vector3 ControlSecondWorld + { + get + { + if (pointTransform != null) return pointTransform.position + pointTransform.TransformVector(controlSecondLocal); + + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + return curve.transform.TransformPoint(new Vector3(positionLocal.x + controlSecondLocal.x, positionLocal.y + controlSecondLocal.y, positionLocal.z + controlSecondLocal.z)); + case BGCurve.PointsModeEnum.GameObjectsTransform: + return transform.position + transform.TransformVector(controlSecondLocal); + default: + throw WrongMode(); + } + } + set + { + Vector3 localPos; + if (pointTransform != null) localPos = pointTransform.InverseTransformVector(value - pointTransform.position); + else + { + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + localPos = curve.transform.InverseTransformPoint(value) - PositionLocal; + break; + case BGCurve.PointsModeEnum.GameObjectsTransform: + localPos = transform.InverseTransformVector(value - transform.position); + break; + default: + throw WrongMode(); + } + } + SetControlSecondLocal(localPos); + } + } + + // =============================================== Control type + //see interface for comments + public BGCurvePoint.ControlTypeEnum ControlType + { + get { return controlType; } + set + { + if (controlType == value) return; + + curve.FireBeforeChange(BGCurve.EventPointControlType); + + controlType = value; + + if (controlType == BGCurvePoint.ControlTypeEnum.BezierSymmetrical) controlSecondLocal = -controlFirstLocal; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointControlType) : null, sender: this); + } + } + + // =============================================== Transform + public Transform PointTransform + { + get { return pointTransform; } + set + { + if (pointTransform == value) return; + + curve.FireBeforeChange(BGCurve.EventPointTransform); + + var oldTransformNull = pointTransform == null && value != null; + var newTransformNull = value == null && pointTransform != null; + + //we need to transfer system fields + var control1 = ControlFirstLocalTransformed; + var control2 = ControlSecondLocalTransformed; + var positionWorld = PositionWorld; + + pointTransform = value; + + // transfer system fields + if (pointTransform != null) + { + pointTransform.position = positionWorld; + controlFirstLocal = pointTransform.InverseTransformVector(control1); + controlSecondLocal = pointTransform.InverseTransformVector(control2); + } + else + { + switch (curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + positionLocal = curve.transform.InverseTransformPoint(positionWorld); + controlFirstLocal = curve.transform.InverseTransformVector(control1); + controlSecondLocal = curve.transform.InverseTransformVector(control2); + break; + case BGCurve.PointsModeEnum.GameObjectsTransform: + transform.position = positionWorld; + controlFirstLocal = transform.InverseTransformVector(control1); + controlSecondLocal = transform.InverseTransformVector(control2); + break; + default: + throw new ArgumentOutOfRangeException("curve.PointsMode"); + } + } + + + // inform curve + if (oldTransformNull) curve.PrivateTransformForPointAdded(curve.IndexOf(this)); + else if (newTransformNull) curve.PrivateTransformForPointRemoved(curve.IndexOf(this)); + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointTransform) : null, sender: this); + } + } + + + //target transform (used to calculate control positions) + private Transform TargetTransform + { + get + { + if (pointTransform != null) return pointTransform; + + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + return curve.transform; + case BGCurve.PointsModeEnum.GameObjectsTransform: + return transform; + default: + throw WrongMode(); + } + } + } + + #endregion + + #region custom fields + + //=============================================================================================== + // Custom Fields (see interface for comments) + //=============================================================================================== + //----------------------------------- Getters + public T GetField(string name) + { + var type = typeof(T); + var value = GetField(name, type); + var field = (T) value; + return field; + } + + public float GetFloat(string name) + { + return PrivateValuesForFields.floatValues[curve.IndexOfFieldValue(name)]; + } + + public bool GetBool(string name) + { + return PrivateValuesForFields.boolValues[curve.IndexOfFieldValue(name)]; + } + + public int GetInt(string name) + { + return PrivateValuesForFields.intValues[curve.IndexOfFieldValue(name)]; + } + + public Vector3 GetVector3(string name) + { + return PrivateValuesForFields.vector3Values[curve.IndexOfFieldValue(name)]; + } + + public Quaternion GetQuaternion(string name) + { + return PrivateValuesForFields.quaternionValues[curve.IndexOfFieldValue(name)]; + } + + public Bounds GetBounds(string name) + { + return PrivateValuesForFields.boundsValues[curve.IndexOfFieldValue(name)]; + } + + public Color GetColor(string name) + { + return PrivateValuesForFields.colorValues[curve.IndexOfFieldValue(name)]; + } + + public object GetField(string name, Type type) + { + return BGCurvePoint.FieldTypes.GetField(curve, type, name, PrivateValuesForFields); + } + + //----------------------------------- Setters + public void SetField(string name, T value) + { + SetField(name, value, typeof(T)); + } + + public void SetField(string name, object value, Type type) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + BGCurvePoint.FieldTypes.SetField(curve, type, name, value, PrivateValuesForFields); + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetFloat(string name, float value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.floatValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetBool(string name, bool value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.boolValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetInt(string name, int value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.intValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetVector3(string name, Vector3 value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.vector3Values[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetQuaternion(string name, Quaternion value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.quaternionValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetBounds(string name, Bounds value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.boundsValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + public void SetColor(string name, Color value) + { + curve.FireBeforeChange(BGCurve.EventPointField); + + PrivateValuesForFields.colorValues[curve.IndexOfFieldValue(name)] = value; + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointField) : null, sender: this); + } + + #endregion + + #region Misc public methods + + //================================================================================ + // Misc public functions + //================================================================================ + + public override string ToString() + { + return "Point [localPosition=" + positionLocal + "]"; + } + + #endregion + + #region private methods + + //set position + private void SetPosition(Vector3 value, bool worldSpaceIsUsed = false) + { + curve.FireBeforeChange(BGCurve.EventPointPosition); + + //snapping + if (curve.SnapType != BGCurve.SnapTypeEnum.Off) + { + if (worldSpaceIsUsed) curve.ApplySnapping(ref value); + else + { + //we need to transfer space before applying snapping + var pos = curve.transform.TransformPoint(value); + if (curve.ApplySnapping(ref pos)) value = curve.transform.InverseTransformPoint(pos); + } + } + + + //assign position + if (pointTransform != null) + { + //2d mode with curve's transform changed is not working correctly + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + pointTransform.position = worldSpaceIsUsed ? value : curve.transform.TransformPoint(value); + } + else + { + switch (Curve.PointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + if (worldSpaceIsUsed) + { + var localPos = curve.transform.InverseTransformPoint(value); + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) localPos = curve.Apply2D(localPos); + positionLocal = localPos; + } + else + { + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + positionLocal = value; + } + break; + case BGCurve.PointsModeEnum.GameObjectsTransform: + if (worldSpaceIsUsed) + { + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.transform.TransformPoint(curve.Apply2D(curve.transform.InverseTransformPoint(value))); + transform.position = value; + } + else + { + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + transform.position = curve.transform.TransformPoint(value); + } + break; + default: + throw WrongMode(); + } + } + + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointPosition) : null, sender: this); + } + + + //set local control 1 + private void SetControlFirstLocal(Vector3 value) + { + curve.FireBeforeChange(BGCurve.EventPointControl); + + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + + if (controlType == BGCurvePoint.ControlTypeEnum.BezierSymmetrical) controlSecondLocal = -value; + + controlFirstLocal = value; + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointControl) : null, sender: this); + } + + //set local control 2 (it's basically copy/paste from SetControlFirstLocal, but we can not use delegates here because of performance) + private void SetControlSecondLocal(Vector3 value) + { + curve.FireBeforeChange(BGCurve.EventPointControl); + + if (curve.Mode2D != BGCurve.Mode2DEnum.Off) value = curve.Apply2D(value); + + if (controlType == BGCurvePoint.ControlTypeEnum.BezierSymmetrical) controlFirstLocal = -value; + + controlSecondLocal = value; + curve.FireChange(curve.UseEventsArgs ? BGCurveChangedArgs.GetInstance(Curve, this, BGCurve.EventPointControl) : null, sender: this); + } + + #endregion + + #region Not copy pasted + + //================================================================================= + // This is not copy/pasted part + //================================================================================= + + /// all methods, prefixed with Private, are not meant to be called from outside of BGCurve package + //Init with data. No events are fired. point==null for pointsMode switching. + public void PrivateInit(BGCurvePoint point, BGCurve.PointsModeEnum pointsMode) + { + if (point != null) + { + // init from new point + curve = point.Curve; + controlType = point.ControlType; + pointTransform = point.PointTransform; + + switch (pointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + positionLocal = point.PositionLocal; + controlFirstLocal = point.ControlFirstLocal; + controlSecondLocal = point.ControlSecondLocal; + break; + case BGCurve.PointsModeEnum.GameObjectsTransform: + transform.localPosition = point.PositionLocal; + + //transformed locals are always the same + var targetTransform = pointTransform != null ? pointTransform : transform; + controlFirstLocal = targetTransform.InverseTransformVector(point.ControlFirstLocalTransformed); + controlSecondLocal = targetTransform.InverseTransformVector(point.ControlSecondLocalTransformed); + break; + default: + throw new ArgumentOutOfRangeException("pointsMode", pointsMode, null); + } + } + else + { + // change pointsMode + Transform targetTransform; + switch (pointsMode) + { + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + { + if (Curve.PointsMode != BGCurve.PointsModeEnum.GameObjectsTransform) + throw new ArgumentOutOfRangeException("Curve.PointsMode", "Curve points mode should be equal to GameObjectsTransform"); + + positionLocal = transform.localPosition; + + //transformed locals are always the same + targetTransform = pointTransform != null ? pointTransform : curve.transform; + break; + } + case BGCurve.PointsModeEnum.GameObjectsTransform: + { + if (Curve.PointsMode != BGCurve.PointsModeEnum.GameObjectsNoTransform) + throw new ArgumentOutOfRangeException("Curve.PointsMode", "Curve points mode should be equal to GameObjectsNoTransform"); + + transform.position = PositionWorld; + + //transformed locals are always the same + targetTransform = pointTransform != null ? pointTransform : transform; + break; + } + default: + throw new ArgumentOutOfRangeException("pointsMode", pointsMode, null); + } + + controlFirstLocal = targetTransform.InverseTransformVector(ControlFirstLocalTransformed); + controlSecondLocal = targetTransform.InverseTransformVector(ControlSecondLocalTransformed); + + } + } + + + //creates wrong pointMode exception + private static ArgumentOutOfRangeException WrongMode() + { + return new ArgumentOutOfRangeException("Curve.PointsMode"); + } + + #endregion + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointGO.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointGO.cs.meta new file mode 100644 index 0000000..453bdf1 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointGO.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 225ae2218b76c4f4980b49b463e9ab12 +timeCreated: 1476535139 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointI.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointI.cs new file mode 100644 index 0000000..98c4db0 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointI.cs @@ -0,0 +1,103 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// This is interface for one single curve's point + public interface BGCurvePointI + { + /// The Curve, this point is attached to + BGCurve Curve { get; } + + //==================================================================== + // system fields + //==================================================================== + /// Local position. It's relative to curve's origin. All transformations are ignored + Vector3 PositionLocal { get; set; } + /// Local position. It's relative to curve's origin. All transformations are applied + Vector3 PositionLocalTransformed { get; set; } + /// World position. + Vector3 PositionWorld { get; set; } + + /// Local position for first control (inbound). It's relative to point's position, all transformations are ignored + Vector3 ControlFirstLocal { get; set; } + /// Local position for first control (inbound). It's relative to point's position with all transformations applied + Vector3 ControlFirstLocalTransformed { get; set; } + /// World position for first control (inbound) + Vector3 ControlFirstWorld { get; set; } + + /// Local position for second control (outbound). It's relative to point's position, all transformations are ignored + Vector3 ControlSecondLocal { get; set; } + /// Local position for second control (outbound). It's relative to point's position with all transformations applied + Vector3 ControlSecondLocalTransformed { get; set; } + /// World position for second control (outbound) + Vector3 ControlSecondWorld { get; set; } + + /// Point's controls type. + BGCurvePoint.ControlTypeEnum ControlType { get; set; } + + /// Use this transform as point's position. + Transform PointTransform { get; set; } + + //==================================================================== + // custom fields + //==================================================================== + + // we need overriden getters/setters for structs/primitives to avoid boxing/unboxing + + //------------------------------- Getters + /// Get custom field value. + T GetField(string name); + /// Get custom field value. + object GetField(string name, Type type); + + /// Get float custom field value. + float GetFloat(string name); + + /// Get bool custom field value. + bool GetBool(string name); + + /// Get int custom field value. + int GetInt(string name); + + /// Get Vector3 custom field value. + Vector3 GetVector3(string name); + + /// Get Quaternion custom field value. + Quaternion GetQuaternion(string name); + + /// Get Bounds custom field value. + Bounds GetBounds(string name); + + /// Get Color custom field value. + Color GetColor(string name); + + + //------------------------------- Setters + /// Set custom field value. + void SetField(string name, T value); + /// Set custom field value. + void SetField(string name, object value, Type type); + + /// Set float custom field value. + void SetFloat(string name, float value); + + /// Set bool custom field value. + void SetBool(string name, bool value); + + /// Set int custom field value. + void SetInt(string name, int value); + + /// Set Vector3 custom field value. + void SetVector3(string name, Vector3 value); + + /// Set Quaternion custom field value. + void SetQuaternion(string name, Quaternion value); + + /// Set Bounds custom field value. + void SetBounds(string name, Bounds value); + + /// Set Color custom field value. + void SetColor(string name, Color value); + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointI.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointI.cs.meta new file mode 100644 index 0000000..1facdb0 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurvePointI.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 38ff6611c69f3da4d8e7aa49ed3bbe53 +timeCreated: 1475050532 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveReferenceToPoint.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveReferenceToPoint.cs new file mode 100644 index 0000000..8ff3e0d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveReferenceToPoint.cs @@ -0,0 +1,60 @@ +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ + /// This is an indicator class, showing that GameObject is used as transform for Curve's point. It is used by Editor only + public class BGCurveReferenceToPoint : MonoBehaviour + { + [SerializeField] private BGCurvePointComponent pointComponent; + [SerializeField] private BGCurvePointGO pointGo; + + /// referenced point + public BGCurvePointI Point + { + get { return pointGo != null ? (BGCurvePointI) pointGo : pointComponent; } + set + { + if (value == null) + { + pointGo = null; + pointComponent = null; + } + else + { + if (value is BGCurvePointGO) + { + pointGo = (BGCurvePointGO) value; + pointComponent = null; + } + else if (value is BGCurvePointComponent) + { + pointComponent = (BGCurvePointComponent) value; + pointGo = null; + } + else + { + pointGo = null; + pointComponent = null; + } + } + } + } + + /// find referenced point, attached to target gameobject + public static BGCurveReferenceToPoint GetReferenceToPoint(BGCurvePointI point) + { + if (point.PointTransform == null) return null; + var referencesToPoints = point.PointTransform.GetComponents(); + if (referencesToPoints.Length == 0) return null; + + + var length = referencesToPoints.Length; + for (var i = 0; i < length; i++) + { + var referencesToPoint = referencesToPoints[i]; + if (referencesToPoint.Point == point) return referencesToPoint; + } + return null; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveReferenceToPoint.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveReferenceToPoint.cs.meta new file mode 100644 index 0000000..eeef629 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveReferenceToPoint.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7c9402229daf9f443a9b18c328178235 +timeCreated: 1477988451 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveSettings.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveSettings.cs new file mode 100644 index 0000000..f8a7a13 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveSettings.cs @@ -0,0 +1,366 @@ +using System; +using UnityEngine; + +namespace BansheeGz.BGSpline.Curve +{ +#if UNITY_EDITOR + // ========================== This class is supposed to work in Editor ONLY + + /// Warning!! This class is for Editor ONLY. It contains curve settings + // many tooltips and range attributes are currently not used + [Serializable] + public class BGCurveSettings + { + #region Fields & enums + + public enum HandlesTypeEnum + { + Configurable, + Standard, + FreeMove + } + + public enum ShowCurveModeEnum + { + CurveSelected, + CurveOrParentSelected, + Always + } + + + //=============================================================== Curve itself + [SerializeField] [Tooltip("Hide Game Object's handles")] private bool hideHandles; + + [SerializeField] [Tooltip("Distance from the camera, at which new points are created")] private float newPointDistance = 2; + + [SerializeField] [Tooltip("Show curve in the scene or not. If not, all handles are disabled as well")] private bool showCurve = true; + + [SerializeField] [Tooltip("Show curve mode")] private ShowCurveModeEnum showCurveMode = ShowCurveModeEnum.CurveOrParentSelected; + + [SerializeField] [Range(1, 50)] [Tooltip("Number of sections between two curves points.\r\n It's used for displaying in editor only")] private int sections = 20; + + + [SerializeField] [Tooltip("Show Points Menu buttons in the editor (for Points tab)")] private bool showPointMenu = true; + + //tangents + [SerializeField] [Tooltip("Show points tangents in the scene")] private bool showTangents; + [SerializeField] [Tooltip("Point tangent arrow size in the scene")] [Range(.3f, 2)] private float tangentsSize = .7f; + [SerializeField] [Tooltip("Point tangent color in the scene")] private Color tangentsColor = Color.white; + [SerializeField] [Range(1, 3)] [Tooltip("Number of tangents for every section")] private int tangentsPerSection = 1; + + // control type for new points + [SerializeField] [Tooltip("Control type for new points")] private BGCurvePoint.ControlTypeEnum controlType; + + [SerializeField] [Tooltip("Curve is drawn on top of objects")] private bool vRay; + + [SerializeField] [Tooltip("Curve's color in the scene")] private Color lineColor = Color.red; + + + //=============================================================== Control Type field + + [SerializeField] [Tooltip("Show points control types in the editor (for Points tab)")] private bool showPointControlType = true; + + //=============================================================== Position field + + [SerializeField] [Tooltip("Show points positions in the editor (for Points tab)")] private bool showPointPosition = true; + + [SerializeField] [Tooltip("Show points handles in the scene")] private bool showHandles = true; + + + [SerializeField] [Tooltip("Points handles type" + + "\r\n 1)FreeMove- standard Unity freemove handles" + + "\r\n 2)Standard-standard handles" + + "\r\n 3)Configurable- configurable handles")] private HandlesTypeEnum handlesType = HandlesTypeEnum.Configurable; + + + [SerializeField] private SettingsForHandles handlesSettings = new SettingsForHandles(); + + [SerializeField] [Tooltip("Show points positions labels in the scene ")] private bool showLabels = true; + + [SerializeField] [Tooltip("Point's labels color in the scene")] private Color labelColor = Color.white; + + + [SerializeField] [Tooltip("Show points positions in the scene")] private bool showPositions; + + [SerializeField] [Tooltip("Point's labels color when selected in the scene")] private Color labelColorSelected = Color.green; + + [SerializeField] [Tooltip("Show spheres at points locations in the scene")] private bool showSpheres = true; + + [SerializeField] [Range(.01f, 1)] [Tooltip("Point's sphere radius in the scene")] private float sphereRadius = .1f; + + [SerializeField] [Tooltip("Point's sphere color in the scene")] private Color sphereColor = Color.red; + + + //=============================================================== Controls fields + + [SerializeField] [Tooltip("Show points controls positions in the editor (for Points tab)")] private bool showPointControlPositions = true; + + [SerializeField] [Tooltip("Show points control handles in the scene")] private bool showControlHandles = true; + + [SerializeField] [Tooltip("Points control handles type\r\n 1)FreeMove- standard Unity freemove handles\r\n " + + "2)Standard-standard handles\r\n 3)Configurable- configurable handles")] private HandlesTypeEnum controlHandlesType = HandlesTypeEnum.Configurable; + + [SerializeField] private SettingsForHandles controlHandlesSettings = new SettingsForHandles {AxisScale = .7f, PlanesScale = .7f, Alpha = .7f}; + + [SerializeField] [Tooltip("Points control handles color")] private Color controlHandlesColor = Color.cyan; + + [SerializeField] [Tooltip("Show points control labels in the scene ")] private bool showControlLabels = true; + + [SerializeField] [Tooltip("Show points control positions in the scene")] private bool showControlPositions; + + [SerializeField] [Tooltip("Control point's labels color in the scene")] private Color labelControlColor = Color.yellow; + + //=============================================================== Transform field + + [SerializeField] [Tooltip("Show points transform field in the editor (for Points tab)")] private bool showTransformField; + + //=============================================================== Misc + + [SerializeField] private bool existing; + + #endregion + + #region Props + + public bool HideHandles + { + get { return hideHandles; } + set { hideHandles = value; } + } + + public float NewPointDistance + { + get { return newPointDistance; } + set { newPointDistance = value; } + } + + public bool ShowPointControlType + { + get { return showPointControlType; } + set { showPointControlType = value; } + } + + public bool ShowPointPosition + { + get { return showPointPosition; } + set { showPointPosition = value; } + } + + public bool ShowPointControlPositions + { + get { return showPointControlPositions; } + set { showPointControlPositions = value; } + } + + public bool ShowPointMenu + { + get { return showPointMenu; } + set { showPointMenu = value; } + } + + public bool ShowCurve + { + get { return showCurve; } + set { showCurve = value; } + } + + public ShowCurveModeEnum ShowCurveMode + { + get { return showCurveMode; } + set { showCurveMode = value; } + } + + public bool ShowHandles + { + get { return showHandles; } + set { showHandles = value; } + } + + public bool ShowTangents + { + get { return showTangents; } + set { showTangents = value; } + } + + public float TangentsSize + { + get { return tangentsSize; } + set { tangentsSize = value; } + } + + public Color TangentsColor + { + get { return tangentsColor; } + set { tangentsColor = value; } + } + + public int TangentsPerSection + { + get { return Mathf.Clamp(tangentsPerSection, 1, 3); } + set { tangentsPerSection = Mathf.Clamp(value, 1, 3); } + } + + public HandlesTypeEnum HandlesType + { + get { return handlesType; } + set { handlesType = value; } + } + + public SettingsForHandles HandlesSettings + { + get { return handlesSettings; } + set { handlesSettings = value; } + } + + public int Sections + { + get { return Mathf.Clamp(sections, 1, 50); } + set { sections = Mathf.Clamp(value, 1, 50); } + } + + public bool VRay + { + get { return vRay; } + set { vRay = value; } + } + + public Color LineColor + { + get { return lineColor; } + set { lineColor = value; } + } + + public bool ShowControlHandles + { + get { return showControlHandles; } + set { showControlHandles = value; } + } + + public HandlesTypeEnum ControlHandlesType + { + get { return controlHandlesType; } + set { controlHandlesType = value; } + } + + public SettingsForHandles ControlHandlesSettings + { + get { return controlHandlesSettings; } + set { controlHandlesSettings = value; } + } + + public Color ControlHandlesColor + { + get { return controlHandlesColor; } + set { controlHandlesColor = value; } + } + + public bool ShowLabels + { + get { return showLabels; } + set { showLabels = value; } + } + + public bool ShowPositions + { + get { return showPositions; } + set { showPositions = value; } + } + + public bool ShowControlPositions + { + get { return showControlPositions; } + set { showControlPositions = value; } + } + + public Color LabelColor + { + get { return labelColor; } + set { labelColor = value; } + } + + public Color LabelColorSelected + { + get { return labelColorSelected; } + set { labelColorSelected = value; } + } + + public bool ShowSpheres + { + get { return showSpheres; } + set { showSpheres = value; } + } + + public float SphereRadius + { + get { return sphereRadius; } + set { sphereRadius = value; } + } + + public Color SphereColor + { + get { return sphereColor; } + set { sphereColor = value; } + } + + public BGCurvePoint.ControlTypeEnum ControlType + { + get { return controlType; } + set { controlType = value; } + } + + public bool Existing + { + get { return existing; } + set { existing = value; } + } + + public bool ShowControlLabels + { + get { return showControlLabels; } + set { showControlLabels = value; } + } + + public Color LabelControlColor + { + get { return labelControlColor; } + set { labelControlColor = value; } + } + + public bool ShowTransformField + { + get { return showTransformField; } + set { showTransformField = value; } + } + + #endregion + + #region classes + + [Serializable] + public class SettingsForHandles + { + public bool RemoveX; + public bool RemoveY; + public bool RemoveZ; + + public bool RemoveXZ; + public bool RemoveXY; + public bool RemoveYZ; + + [Range(.5f, 1.5f)] public float AxisScale = 1; + + [Range(.5f, 1.5f)] public float PlanesScale = 1; + + [Range(.5f, 1f)] public float Alpha = 1; + + + public bool Disabled + { + get { return RemoveX && RemoveY && RemoveZ && RemoveXY && RemoveXZ && RemoveYZ; } + } + } + + #endregion + } +#endif +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveSettings.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveSettings.cs.meta new file mode 100644 index 0000000..8652f11 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGCurveSettings.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5330eda6cdebde54585ac3d72c6979d4 +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGReflectionAdapter.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGReflectionAdapter.cs new file mode 100644 index 0000000..03a6157 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGReflectionAdapter.cs @@ -0,0 +1,71 @@ +using System; + +#if NETFX_CORE +using System.Reflection; +using System.Collections.Generic; +#endif + +namespace BansheeGz.BGSpline.Curve +{ + /// Reflection related stuff + //thanks to qwerty + public static class BGReflectionAdapter + { +#if NETFX_CORE + public static object[] GetCustomAttributes(Type type, Type attributeType, bool inherit) + { + var enumerator = type.GetTypeInfo().GetCustomAttributes(attributeType, inherit); + var result = new List(); + foreach(var item in enumerator) result.Add(item); + return result.ToArray(); + } + + public static bool IsAbstract(Type type) + { + return type.GetTypeInfo().IsAbstract; + } + + public static bool IsClass(Type type) + { + return type.GetTypeInfo().IsClass; + } + + public static bool IsSubclassOf(Type type, Type typeToCheck) + { + return type.GetTypeInfo().IsSubclassOf(typeToCheck); + } + + public static bool IsValueType(Type type) + { + return type.GetTypeInfo().IsValueType; + } +#else + + public static object[] GetCustomAttributes(Type type, Type attributeType, bool inherit) + { + return type.GetCustomAttributes(attributeType, inherit); + } + + public static bool IsAbstract(Type type) + { + return type.IsAbstract; + } + + public static bool IsClass(Type type) + { + return type.IsClass; + } + + public static bool IsSubclassOf(Type type, Type typeToCheck) + { + return type.IsSubclassOf(typeToCheck); + } + + public static bool IsValueType(Type type) + { + return type.IsValueType; + } + +#endif + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGReflectionAdapter.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGReflectionAdapter.cs.meta new file mode 100644 index 0000000..5559ad1 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Curve/BGReflectionAdapter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f27a57cfa8411464a9eeaf545adb9782 +timeCreated: 1481951176 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor.meta new file mode 100644 index 0000000..a9eebb8 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c14afad4dd4b6ca45bb6d96cdc5a10ba +folderAsset: yes +timeCreated: 1458400581 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc.meta new file mode 100644 index 0000000..3e3aa6c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5e85ccb67b51ad4419baa0304f8171c0 +folderAsset: yes +timeCreated: 1472482935 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorChangeLinearEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorChangeLinearEditor.cs new file mode 100644 index 0000000..97870a1 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorChangeLinearEditor.cs @@ -0,0 +1,55 @@ +using System; +using BansheeGz.BGSpline.Components; +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof (BGCcCursorChangeLinear))] + public class BGCcCursorChangeLinearEditor : BGCcEditor + { + private GUIContent speedFieldContent; + private GUIContent delayFieldContent; + + private BGCcCursorChangeLinear ChangeLinear + { + get { return (BGCcCursorChangeLinear) cc; } + } + + protected override void InternalOnInspectorGUI() + { + BGEditorUtility.Assign(ref speedFieldContent, () => new GUIContent("Speed Field", "Speed field to take a speed from. Each point will have it's own speed. Should be a float field.")); + BGEditorUtility.Assign(ref delayFieldContent, () => new GUIContent("Delay Field", "Delay field to take a delay from. Each point will have it's own delay. Should be a float field.")); + + //speed + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.CustomField(speedFieldContent, cc.Curve, ChangeLinear.SpeedField, BGCurvePointField.TypeEnum.Float, field => ChangeLinear.SpeedField = field); + + if (ChangeLinear.SpeedField == null) EditorGUILayout.PropertyField(serializedObject.FindProperty("speed")); + }); + + //delay + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.CustomField(delayFieldContent, cc.Curve, ChangeLinear.DelayField, BGCurvePointField.TypeEnum.Float, field => ChangeLinear.DelayField = field); + + if (ChangeLinear.DelayField == null) EditorGUILayout.PropertyField(serializedObject.FindProperty("delay")); + }); + + + EditorGUILayout.PropertyField(serializedObject.FindProperty("overflowControl")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("adjustByTotalLength")); + + try + { + //by some reason NullReferenceException exceptions are fired at certain GUI passes + EditorGUILayout.PropertyField(serializedObject.FindProperty("pointReachedEvent")); + } + catch (NullReferenceException) + { + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorChangeLinearEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorChangeLinearEditor.cs.meta new file mode 100644 index 0000000..045e573 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorChangeLinearEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4692c2e962ea94945bf21a4a27e5cb01 +timeCreated: 1472632339 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorDrawer.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorDrawer.cs new file mode 100644 index 0000000..dbb0cc0 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorDrawer.cs @@ -0,0 +1,11 @@ +using BansheeGz.BGSpline.Components; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + //we need it cause a curve can have multiple cursors and we have to be able to chose between them + [CustomPropertyDrawer(typeof (BGCcCursor), true)] + public class BGCcCursorDrawer : BGCcChoseDrawer + { + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorDrawer.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorDrawer.cs.meta new file mode 100644 index 0000000..6651100 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 833c28bf8ee4eef4a86a4a1923b07370 +timeCreated: 1473056718 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorEditor.cs new file mode 100644 index 0000000..fe64e9e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorEditor.cs @@ -0,0 +1,48 @@ +using UnityEngine; +using BansheeGz.BGSpline.Components; +using UnityEditor; + +//add points filter + pager for Editor + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof (BGCcCursor))] + public class BGCcCursorEditor : BGCcEditor + { + private BGCcCursor Cursor + { + get { return (BGCcCursor) cc; } + } + + protected override void ShowHandlesSettings() + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("handlesScale")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("handlesColor")); + } + + protected override void InternalOnInspectorGUI() + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("distance")); + + var distanceRatio = Cursor.DistanceRatio; + var newValue = EditorGUILayout.Slider("Distance Ratio", distanceRatio, 0, 1); + if (BGEditorUtility.AnyChange(distanceRatio, newValue)) Cursor.DistanceRatio = newValue; + } + + protected override void InternalOnSceneGUI() + { + var cursor = Cursor; + + if (cursor == null) return; + + var position = cursor.CalculatePosition(); + + var handleSize = BGEditorUtility.GetHandleSize(position, BGPrivateField.Get(cursor, "handlesScale")); + BGEditorUtility.SwapHandlesColor(BGPrivateField.Get(cursor, "handlesColor"), () => + { + Handles.ArrowCap(0, position + Vector3.up*handleSize*1.2f, Quaternion.LookRotation(Vector3.down), handleSize); + Handles.SphereCap(0, position, Quaternion.LookRotation(Vector3.down), handleSize*.15f); + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorEditor.cs.meta new file mode 100644 index 0000000..bd278ce --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 956394c991ece5441b4221426379b206 +timeCreated: 1472497101 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectEditor.cs new file mode 100644 index 0000000..8e35a8d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectEditor.cs @@ -0,0 +1,13 @@ +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + + public class BGCcCursorObjectEditor : BGCcEditor + { + protected override void InternalOnInspectorGUI() + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("objectToManipulate")); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectEditor.cs.meta new file mode 100644 index 0000000..bb0b5a8 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: adad197ec8512394b850b4507ad76e42 +timeCreated: 1472771193 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectRotateEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectRotateEditor.cs new file mode 100644 index 0000000..92c344f --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectRotateEditor.cs @@ -0,0 +1,133 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Components; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof(BGCcCursorObjectRotate))] + public class BGCcCursorObjectRotateEditor : BGCcCursorObjectEditor + { + private GUIContent rotationFieldContent; + private GUIContent revolutionsFieldContent; + private GUIContent clockwiseFieldContent; + + private BGCcCursorObjectRotate ObjectRotate + { + get { return (BGCcCursorObjectRotate) cc; } + } + + protected override void ShowHandlesSettings() + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("handlesScale")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("handlesColor")); + } + + protected override void InternalOnInspectorGUI() + { + base.InternalOnInspectorGUI(); + + // reusable labels + BGEditorUtility.Assign(ref rotationFieldContent, + () => new GUIContent("Rotation Field", "Rotation field to take a rotation from. Each point will have it's own rotation. Should be a Quaternion field.")); + BGEditorUtility.Assign(ref revolutionsFieldContent, + () => new GUIContent("Revolutions Field", "Field to store additional revolutions around tangent. It should be an int field.")); + BGEditorUtility.Assign(ref clockwiseFieldContent, + () => new GUIContent("Revolutions Clockwise Field", "Field to store if the rotation around tangent should be clockwise. It should be a bool field.")); + + + //type of the rotation 1) tangent (without field) 2) by field's values + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.CustomField(rotationFieldContent, cc.Curve, ObjectRotate.RotationField, BGCurvePointField.TypeEnum.Quaternion, field => ObjectRotate.RotationField = field); + + if (ObjectRotate.RotationField != null) + { + //============================== field is used + + BGEditorUtility.VerticalBox(() => + { + // additional revolutions + BGEditorUtility.CustomField(revolutionsFieldContent, cc.Curve, ObjectRotate.RevolutionsAroundTangentField, BGCurvePointField.TypeEnum.Int, + field => ObjectRotate.RevolutionsAroundTangentField = field); + if (ObjectRotate.RevolutionsAroundTangentField == null) EditorGUILayout.PropertyField(serializedObject.FindProperty("revolutionsAroundTangent")); + + // clockwise? + BGEditorUtility.CustomField(clockwiseFieldContent, cc.Curve, ObjectRotate.RevolutionsClockwiseField, + BGCurvePointField.TypeEnum.Bool, field => ObjectRotate.RevolutionsClockwiseField = field); + + if (ObjectRotate.RevolutionsClockwiseField == null) EditorGUILayout.PropertyField(serializedObject.FindProperty("revolutionsClockwise")); + }); + } + else + { + //============================== no field- tangent is used + BGEditorUtility.VerticalBox(() => + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("upMode")); + switch (ObjectRotate.UpMode) + { + case BGCcCursorObjectRotate.RotationUpEnum.WorldCustom: + case BGCcCursorObjectRotate.RotationUpEnum.LocalCustom: + case BGCcCursorObjectRotate.RotationUpEnum.TargetParentUpCustom: + EditorGUILayout.PropertyField(serializedObject.FindProperty("upCustom")); + break; + } + }); + } + }); + + + //interpolation + BGEditorUtility.VerticalBox(() => + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("rotationInterpolation")); + + switch (ObjectRotate.RotationInterpolation) + { + case BGCcCursorObjectRotate.RotationInterpolationEnum.Lerp: + EditorGUILayout.PropertyField(serializedObject.FindProperty("lerpSpeed")); + break; + case BGCcCursorObjectRotate.RotationInterpolationEnum.Slerp: + EditorGUILayout.PropertyField(serializedObject.FindProperty("slerpSpeed")); + break; + } + }); + + EditorGUILayout.PropertyField(serializedObject.FindProperty("offsetAngle")); + } + + protected override void InternalOnSceneGUI() + { + var curve = ObjectRotate.Curve; + + if (curve == null || curve.PointsCount == 0) return; + + BGCcCursor cursor; + try + { + cursor = ObjectRotate.Cursor; + } + catch (MissingReferenceException) + { + return; + } + + if (cursor == null) return; + + var math = cursor.Math; + + if (math == null || !math.IsCalculated(BGCurveBaseMath.Field.Tangent)) return; + + var position = cursor.CalculatePosition(); + + //by field + var result = Quaternion.identity; + if (!ObjectRotate.TryToCalculateRotation(ref result)) return; + + var handleSize = BGEditorUtility.GetHandleSize(position, BGPrivateField.Get(ObjectRotate, "handlesScale")); + BGEditorUtility.SwapHandlesColor(BGPrivateField.Get(ObjectRotate, "handlesColor"), () => { Handles.ArrowCap(0, position, result, handleSize); }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectRotateEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectRotateEditor.cs.meta new file mode 100644 index 0000000..59e046b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectRotateEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 266bbca06f7204b49acadb4414d50a4e +timeCreated: 1472502623 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectScaleEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectScaleEditor.cs new file mode 100644 index 0000000..8cfe006 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectScaleEditor.cs @@ -0,0 +1,31 @@ +using UnityEngine; +using BansheeGz.BGSpline.Components; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof(BGCcCursorObjectScale))] + public class BGCcCursorObjectScaleEditor : BGCcCursorObjectEditor + { + private GUIContent scaleFieldContent; + + private BGCcCursorObjectScale ObjectScale + { + get { return (BGCcCursorObjectScale)cc; } + } + + protected override void InternalOnInspectorGUI() + { + base.InternalOnInspectorGUI(); + + BGEditorUtility.Assign(ref scaleFieldContent, () => new GUIContent("Scale Field", "Scale field to take a scale from. Each point will have it's own scale. Should be Vector3 field.")); + + BGEditorUtility.CustomField(scaleFieldContent, cc.Curve, ObjectScale.ScaleField, BGCurvePointField.TypeEnum.Vector3, field => + { + ObjectScale.ScaleField = field; + }); + } + + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectScaleEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectScaleEditor.cs.meta new file mode 100644 index 0000000..efe1d42 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectScaleEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5f25eaece0b3d1a4f8bfc3205c5201b8 +timeCreated: 1476115388 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectTranslateEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectTranslateEditor.cs new file mode 100644 index 0000000..1a586ff --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectTranslateEditor.cs @@ -0,0 +1,10 @@ +using BansheeGz.BGSpline.Components; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof (BGCcCursorObjectTranslate))] + public class BGCcCursorObjectTranslateEditor : BGCcCursorObjectEditor + { + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectTranslateEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectTranslateEditor.cs.meta new file mode 100644 index 0000000..28c2457 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcCursorObjectTranslateEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2e7270fc1194afd4f9ba2d7e8ea9c78c +timeCreated: 1472495980 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcMathEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcMathEditor.cs new file mode 100644 index 0000000..728c70c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcMathEditor.cs @@ -0,0 +1,117 @@ +using System; +using BansheeGz.BGSpline.Components; +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof(BGCcMath))] + public class BGCcMathEditor : BGCcEditor + { + private BGCcMath Math + { + get { return ((BGCcMath) cc); } + } + + + protected override void InternalOnEnable() + { + //ensure math is created and listeners attached + var math = Math.Math; + math.SuppressWarning = math.SuppressWarning; + } + + protected override void InternalOnInspectorGUI() + { + BGEditorUtility.Horizontal(() => + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("fields")); +// if (GUILayout.Button("Update")) Math.Recalculate(); + }); + + + BGEditorUtility.VerticalBox(() => + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("mathType")); + + switch (Math.MathType) + { + case BGCcMath.MathTypeEnum.Base: + EditorGUILayout.PropertyField(serializedObject.FindProperty("sectionParts")); + break; + case BGCcMath.MathTypeEnum.Adaptive: + EditorGUILayout.PropertyField(serializedObject.FindProperty("tolerance")); + break; + } + }); + + EditorGUILayout.PropertyField(serializedObject.FindProperty("optimizeStraightLines")); + + if (Math.Fields == BGCurveBaseMath.Fields.PositionAndTangent) + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("usePositionToCalculateTangents")); + } + BGEditorUtility.VerticalBox(() => + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("updateMode")); + if (Math.UpdateMode == BGCcMath.UpdateModeEnum.RendererVisible) + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("rendererForUpdateCheck")); + } + }); + + try + { + //by some reason NullReferenceException exceptions are fired at certain GUI passes + EditorGUILayout.PropertyField(serializedObject.FindProperty("mathChangedEvent")); + } + catch (NullReferenceException) + { + } + } + + protected override void ShowHandlesSettings() + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("spheresScale")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("spheresColor")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("spheresCount")); + } + + protected override void InternalOnUndoRedo() + { + if (Math != null) Math.Recalculate(); + } + + + protected override void InternalOnSceneGUI() + { + var mathCc = Math; + + if (mathCc == null || mathCc.Math == null || mathCc.Math.SectionsCount == 0) return; + + if (mathCc.Curve.ForceChangedEventMode != BGCurve.ForceChangedEventModeEnum.Off) mathCc.Recalculate(); + + var math = mathCc.Math; + + var sphereScale = BGPrivateField.Get(mathCc, "spheresScale"); + + BGEditorUtility.SwapHandlesColor(BGPrivateField.Get(mathCc, "spheresColor"), () => + { + var count = BGPrivateField.Get(mathCc, "spheresCount"); + + for (var i = 0; i < math.SectionsCount; i++) + { + var section = math[i]; + var points = section.Points; + for (var j = 0; j < points.Count; j++) + { + var pos = points[j].Position; + Handles.SphereCap(0, pos, Quaternion.identity, sphereScale*BGEditorUtility.GetHandleSize(pos, .07f)); + if (count-- <= 0) return; + } + } + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcMathEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcMathEditor.cs.meta new file mode 100644 index 0000000..e15b928 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcMathEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a541fa5a221b56f44b68ed52c066a05b +timeCreated: 1472499639 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcSplitterPolylineEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcSplitterPolylineEditor.cs new file mode 100644 index 0000000..bc2c981 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcSplitterPolylineEditor.cs @@ -0,0 +1,101 @@ +using BansheeGz.BGSpline.Components; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof(BGCcSplitterPolyline))] + public class BGCcSplitterPolylineEditor : BGCcEditor + { + protected bool paramsChanged; + private bool listenersAdded; + + private BGCcSplitterPolyline Splitter + { + get { return (BGCcSplitterPolyline) cc; } + } + + protected override void InternalOnEnable() + { + if (!Splitter.enabled) return; + + if (Application.isPlaying) return; + Splitter.AddListeners(); + listenersAdded = true; + Splitter.InvalidateData(); + } + + protected override void InternalOnDestroy() + { + if (Application.isPlaying) return; + + if (Splitter != null) Splitter.RemoveListeners(); + } + + protected override void InternalOnInspectorGUI() + { + if (!listenersAdded) InternalOnEnable(); + + paramsChanged = false; + BGEditorUtility.ChangeCheck(() => + { + BGEditorUtility.VerticalBox(() => + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("splitMode")); + + switch (Splitter.SplitMode) + { + case BGCcSplitterPolyline.SplitModeEnum.PartsTotal: + EditorGUILayout.PropertyField(serializedObject.FindProperty("partsTotal")); + break; + case BGCcSplitterPolyline.SplitModeEnum.PartsPerSection: + EditorGUILayout.PropertyField(serializedObject.FindProperty("partsPerSection")); + break; + } + }); + + EditorGUILayout.PropertyField(serializedObject.FindProperty("doNotOptimizeStraightLines")); + + AdditionalParams(); + }, () => paramsChanged = true); + } + + protected virtual void AdditionalParams() + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("useLocal")); + } + + protected override void ShowHandlesSettings() + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("spheresScale")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("spheresColor")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("spheresCount")); + } + + protected override void InternalOnSceneGUI() + { + var splitter = Splitter; + if (splitter == null) return; + + var positions = splitter.Positions; + + if (positions == null || positions.Count == 0) return; + + var sphereScale = BGPrivateField.Get(splitter, "spheresScale"); + + BGEditorUtility.SwapHandlesColor(BGPrivateField.Get(splitter, "spheresColor"), () => + { + var count = Mathf.Min(positions.Count, BGPrivateField.Get(splitter, "spheresCount")); + + var localToWorldMatrix = splitter.transform.localToWorldMatrix; + for (var i = 0; i < count; i++) + { + var position = positions[i]; + if (splitter.UseLocal) position = localToWorldMatrix.MultiplyPoint(position); + + Handles.SphereCap(0, position, Quaternion.identity, sphereScale*BGEditorUtility.GetHandleSize(position, .07f)); + } + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcSplitterPolylineEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcSplitterPolylineEditor.cs.meta new file mode 100644 index 0000000..2015976 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcSplitterPolylineEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 43309ae1504d40645bdf732681273088 +timeCreated: 1474944881 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcTriangulate2DEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcTriangulate2DEditor.cs new file mode 100644 index 0000000..f06003d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcTriangulate2DEditor.cs @@ -0,0 +1,46 @@ +using UnityEngine; +using BansheeGz.BGSpline.Components; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + + [CustomEditor(typeof(BGCcTriangulate2D))] + public class BGCcTriangulate2DEditor : BGCcSplitterPolylineEditor + { + + private BGCcTriangulate2D Triangulate2D + { + get { return (BGCcTriangulate2D)cc; } + } + + protected override void AdditionalParams() + { + var updateEveryFrameProperty = serializedObject.FindProperty("updateEveryFrame"); + + EditorGUILayout.PropertyField(updateEveryFrameProperty); + EditorGUILayout.PropertyField(serializedObject.FindProperty("flip")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("scaleUV")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("offsetUV")); + BGEditorUtility.VerticalBox(() => + { + var doubleSidedProperty = serializedObject.FindProperty("doubleSided"); + EditorGUILayout.PropertyField(doubleSidedProperty); + if (doubleSidedProperty.boolValue) + { + EditorGUILayout.PropertyField(serializedObject.FindProperty("scaleBackUV")); + EditorGUILayout.PropertyField(serializedObject.FindProperty("offsetBackUV")); + } + }); + + //launch coroutine + if (updateEveryFrameProperty.boolValue != Triangulate2D.UpdateEveryFrame && Application.isPlaying && updateEveryFrameProperty.boolValue) Triangulate2D.UpdateEveryFrame = true; + } + + protected override void InternalOnInspectorGUIPost() + { + if (paramsChanged) Triangulate2D.UpdateUI(); + } + + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcTriangulate2DEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcTriangulate2DEditor.cs.meta new file mode 100644 index 0000000..4ea1ae1 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcTriangulate2DEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5883d53d633a9954482d82352bb39465 +timeCreated: 1476470318 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcVisualizationLineRendererEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcVisualizationLineRendererEditor.cs new file mode 100644 index 0000000..7a89aff --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcVisualizationLineRendererEditor.cs @@ -0,0 +1,33 @@ +using BansheeGz.BGSpline.Components; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof (BGCcVisualizationLineRenderer))] + public class BGCcVisualizationLineRendererEditor : BGCcSplitterPolylineEditor + { + + private BGCcVisualizationLineRenderer LineRenderer + { + get { return (BGCcVisualizationLineRenderer) cc; } + } + + protected override void InternalOnInspectorGUI() + { + base.InternalOnInspectorGUI(); + + EditorGUILayout.PropertyField(serializedObject.FindProperty("updateAtStart")); + + } + + protected override void AdditionalParams() + { + //we no need useLocal param, cause it depends on LineRenderer itself + } + + protected override void InternalOnInspectorGUIPost() + { + if (paramsChanged) LineRenderer.UpdateUI(); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcVisualizationLineRendererEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcVisualizationLineRendererEditor.cs.meta new file mode 100644 index 0000000..307263e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Cc/BGCcVisualizationLineRendererEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: fc136e2fcbf2c97468e0b45cf219d5e6 +timeCreated: 1472500588 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve.meta new file mode 100644 index 0000000..3dfc6b2 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6817f9bdaece0b449a012e1592389b6f +folderAsset: yes +timeCreated: 1472482776 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCcEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCcEditor.cs new file mode 100644 index 0000000..e778871 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCcEditor.cs @@ -0,0 +1,173 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; +namespace BansheeGz.BGSpline.Editor +{ + public class BGCcEditor : UnityEditor.Editor + { + public event EventHandler ChangedParent; + + + protected BGCc cc; + private Type parentClass; + + //================================================================= Unity callbacks + protected virtual void OnEnable() + { + cc = (BGCc) target; + + if (cc == null) return; + + //get all required components + parentClass = cc.GetParentClass(); + + + InternalOnEnable(); + + cc.ChangedParams -= ChangedParams; + cc.ChangedParams += ChangedParams; + + Undo.undoRedoPerformed -= InternalOnUndoRedo; + Undo.undoRedoPerformed += InternalOnUndoRedo; + } + + + protected virtual void OnDestroy() + { + Undo.undoRedoPerformed -= InternalOnUndoRedo; + cc.ChangedParams -= ChangedParams; + InternalOnDestroy(); + } + + public override void OnInspectorGUI() + { + serializedObject.Update(); + + + var componentChanged = BGEditorUtility.ChangeCheck(() => + { + //custom fields + InternalOnInspectorGUI(); + + // ------------- parents + if (parentClass != null) + { + var possibleParents = cc.GetComponents(parentClass); + if (possibleParents.Length > 1) + { + BGEditorUtility.Horizontal(() => + { + GUILayout.Space(10); + BGEditorUtility.VerticalBox(() => + { + var myParent = cc.GetParent(parentClass); + var options = new string[possibleParents.Length]; + var index = 0; + for (var i = 0; i < possibleParents.Length; i++) + { + var possibleParent = possibleParents[i]; + if (possibleParent == myParent) index = i; + options[i] = ((BGCc)possibleParent).CcName; + } + + //show popup + var label = BGCc.GetDescriptor(parentClass).Name ?? parentClass.Name; + var newIndex = EditorGUILayout.Popup(label, index, options); + if (newIndex != index) + { + Undo.RecordObject(cc, "parent change"); + cc.SetParent((BGCc) possibleParents[newIndex]); + if (ChangedParent != null) ChangedParent(this, null); + } + }); + }); + } + } + }); + + + //-------------- handles + if (cc.SupportHandles && !BGCurveSettingsForEditor.CcInspectorHandlesOff) + { + BGEditorUtility.Horizontal(() => + { + GUILayout.Space(10); + BGEditorUtility.VerticalBox(() => + { + var showHandlesProperty = serializedObject.FindProperty("showHandles"); + EditorGUILayout.PropertyField(showHandlesProperty); + if (cc.SupportHandlesSettings && showHandlesProperty.boolValue) BGEditorUtility.Indent(1, ShowHandlesSettings); + }); + }); + } + + //-------------- status + var info = cc.Info; + BGEditorUtility.HelpBox(info, MessageType.Info, !string.IsNullOrEmpty(info)); + + //-------------- warning + var warning = cc.Warning; + BGEditorUtility.HelpBox(warning, MessageType.Warning, !string.IsNullOrEmpty(warning)); + + //-------------- error + var error = cc.Error; + BGEditorUtility.HelpBox(error, MessageType.Error, !string.IsNullOrEmpty(error)); + + if (!GUI.changed) return; + + Undo.RecordObject(cc, "fields change"); + + serializedObject.ApplyModifiedProperties(); + EditorUtility.SetDirty(cc); + + if (componentChanged) cc.FireChangedParams(); + + InternalOnInspectorGUIPost(); + } + + protected virtual void ShowHandlesSettings() + { + } + + + private void ChangedParams(object sender, EventArgs e) + { + Repaint(); + } + + + public virtual void OnSceneGUI() + { + if (!cc.SupportHandles || !BGPrivateField.GetShowHandles(cc)) return; + InternalOnSceneGUI(); + } + + + //================================================================= Internal to override + + protected virtual void InternalOnEnable() + { + } + + protected virtual void InternalOnDestroy() + { + } + + protected virtual void InternalOnInspectorGUI() + { + } + + protected virtual void InternalOnSceneGUI() + { + } + + protected virtual void InternalOnInspectorGUIPost() + { + } + + protected virtual void InternalOnUndoRedo() + { + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCcEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCcEditor.cs.meta new file mode 100644 index 0000000..2ad57bf --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCcEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 60c2111cab2041a4890fd960ef4748ae +timeCreated: 1472495704 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditor.cs new file mode 100644 index 0000000..e581b55 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditor.cs @@ -0,0 +1,520 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using System.Linq; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + //idea.. do points paging + [CustomEditor(typeof(BGCurve))] + public class BGCurveEditor : UnityEditor.Editor + { + private const int ToolBarHeight = 20; + + //static + private static readonly Color32 LockViewActiveColor = new Color32(255, 252, 58, 255); + internal static BGOverlayMessage OverlayMessage; + //for curves, which are not selected in hierarchy + private static readonly Dictionary curve2Painter = new Dictionary(); + private static BGCurvePainterGizmo CurrentGizmoPainter; + private static BGCurve CurrentCurve; + private static Texture2D headerTexture; + + // non-static + private BGCurveEditorTab[] editors; + + private Texture2D[] headers; + + private Rect toolBarRect; + private Texture2D stickerTextureOk; + private Texture2D stickerTextureActive; + private Texture2D stickerTextureWarning; + private Texture2D stickerTextureError; + private Texture2D settingsTexture; + + private GUIStyle stickerStyle; + + public BGCurve Curve { get; private set; } + public BGCurveBaseMath Math { get; private set; } + + public static bool lastPlayMode; + + private BGTransformMonitor transformMonitor; + + //selected points + private BGCurveEditorPointsSelection editorSelection; + private int undoGroup = -1; + + protected void OnEnable() + { + Curve = (BGCurve) target; + + //wth + if (Curve == null) return; + + CurrentCurve = Curve; + transformMonitor = BGTransformMonitor.GetMonitor(Curve); + + + var settings = BGPrivateField.GetSettings(Curve); + + + //painter and math + if (curve2Painter.ContainsKey(Curve)) + { + curve2Painter[Curve].Dispose(); + curve2Painter.Remove(Curve); + } + + Math = NewMath(Curve, settings); + CurrentGizmoPainter = new BGCurvePainterGizmo(Math); + + + //overlay + BGEditorUtility.Assign(ref OverlayMessage, () => new BGOverlayMessage()); + + //probably we do not need it for play mode.. probably + if (!Application.isPlaying) + { + //they are not persistent + Curve.ImmediateChangeEvents = true; + Curve.BeforeChange += BeforeCurveChange; + Curve.Changed += CurveChanged; + } + + + if (!settings.Existing) + { + //newly created + settings.Existing = true; + + var defaultSettings = BGCurveSettingsOperations.LoadDefault(); + if (defaultSettings != null) BGPrivateField.SetSettings(Curve, defaultSettings); + } + + //load textures + BGEditorUtility.Assign(ref headerTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGCurveLogo123)); + stickerTextureOk = BGEditorUtility.Texture1X1(new Color32(46, 143, 168, 255)); + stickerTextureError = BGEditorUtility.Texture1X1(new Color32(255, 0, 0, 255)); + stickerTextureWarning = BGEditorUtility.Texture1X1(new Color32(255, 206, 92, 255)); + stickerTextureActive = BGEditorUtility.Texture1X1(new Color32(44, 160, 90, 255)); + + //selection + editorSelection = new BGCurveEditorPointsSelection(Curve, this); + + // editors + editors = new BGCurveEditorTab[] + { + new BGCurveEditorPoints(this, serializedObject, editorSelection), new BGCurveEditorComponents(this, serializedObject), + new BGCurveEditorFields(this, serializedObject, editorSelection), new BGCurveEditorSettings(this, serializedObject) + }; + + headers = editors.Select(editor => editor.Header2D).ToArray(); + foreach (var editor in editors) editor.OnEnable(); + + //do it every frame + EditorApplication.update -= OverlayMessage.Check; + EditorApplication.update += OverlayMessage.Check; + + Undo.undoRedoPerformed -= InternalOnUndoRedo; + Undo.undoRedoPerformed += InternalOnUndoRedo; + } + + private static BGCurveBaseMath NewMath(BGCurve curve, BGCurveSettings settings) + { + return new BGCurveBaseMath(curve, NewConfig(settings)); + } + + private static BGCurveBaseMath.Config NewConfig(BGCurveSettings settings) + { + return new BGCurveBaseMath.Config(settings.ShowTangents ? BGCurveBaseMath.Fields.PositionAndTangent : BGCurveBaseMath.Fields.Position) {Parts = settings.Sections}; + } + + private static void AdjustMath(BGCurveSettings settings, BGCurveBaseMath math) + { + if (settings.Sections != math.Configuration.Parts + || (settings.ShowTangents && !math.IsCalculated(BGCurveBaseMath.Field.Tangent)) + || (!settings.ShowTangents && math.IsCalculated(BGCurveBaseMath.Field.Tangent))) + { + math.Init(NewConfig(settings)); + } + } + + private void CurveChanged(object sender, BGCurveChangedArgs e) + { + if (Curve == null) return; + + if (undoGroup > 0) Undo.CollapseUndoOperations(undoGroup); + undoGroup = -1; + EditorUtility.SetDirty(Curve); + + if (Curve.FieldsCount > 0) foreach (var field in Curve.Fields) EditorUtility.SetDirty(field); + + var pointsMode = Curve.PointsMode; + if (Curve.PointsCount > 0 && pointsMode != BGCurve.PointsModeEnum.Inlined) + { + switch (pointsMode) + { + case BGCurve.PointsModeEnum.Components: + foreach (var point in Curve.Points) EditorUtility.SetDirty((BGCurvePointComponent) point); + break; + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + case BGCurve.PointsModeEnum.GameObjectsTransform: + foreach (var point in Curve.Points) + { + var curvePointGo = (BGCurvePointGO) point; + EditorUtility.SetDirty(curvePointGo); + EditorUtility.SetDirty(curvePointGo.gameObject); + } + break; + } + } + + foreach (var editor in editors) editor.OnCurveChanged(e); + + transformMonitor.CheckForChange(); + } + + private void BeforeCurveChange(object sender, BGCurveChangedArgs.BeforeChange e) + { +// Undo.IncrementCurrentGroup(); + undoGroup = Undo.GetCurrentGroup(); + + var operation = e != null && e.Operation != null ? e.Operation : "Curve change"; + + Undo.RecordObject(Curve, operation); + + + if (Curve.FieldsCount > 0) foreach (var field in Curve.Fields) Undo.RecordObject(field, operation); + + var pointsMode = Curve.PointsMode; + if (Curve.PointsCount > 0) + { + var points = Curve.Points; + foreach (var point in points) if (point.PointTransform != null) Undo.RecordObject(point.PointTransform, operation); + + if (pointsMode != BGCurve.PointsModeEnum.Inlined) + { + switch (pointsMode) + { + case BGCurve.PointsModeEnum.Components: + foreach (var point in points) Undo.RecordObject((BGCurvePointComponent) point, operation); + break; + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + case BGCurve.PointsModeEnum.GameObjectsTransform: + foreach (var point in points) + { + var pointGo = (BGCurvePointGO) point; + Undo.RecordObject(pointGo, operation); + if (pointsMode == BGCurve.PointsModeEnum.GameObjectsTransform) Undo.RecordObject(pointGo.transform, operation); + } + break; + } + } + } + } + + public void OnDisable() + { + try + { + EditorApplication.update -= OverlayMessage.Check; + } + catch (ArgumentException) + { + return; + } + + if (editors != null) foreach (var editor in editors) if (editor != null) editor.OnDisable(); + + if (transformMonitor != null) transformMonitor.Release(); + + Dispose(); + } + + + private void Dispose() + { + CurrentCurve = null; + CurrentGizmoPainter = null; + Undo.undoRedoPerformed -= InternalOnUndoRedo; + + if (Math != null) Math.Dispose(); + Math = null; + } + + private void InternalOnUndoRedo() + { + transformMonitor.CheckForChange(); + + Curve.PrivateUpdateFieldsValuesIndexes(); + + if (BGCurve.IsGoMode(Curve.PointsMode)) BGPrivateField.Invoke(Curve, BGCurve.MethodSetPointsNames); + + foreach (var editor in editors) editor.OnUndoRedo(); + + if (Math != null) Math.Recalculate(); + + Repaint(); + SceneView.RepaintAll(); + } + + public void OnDestroy() + { + if (editors != null) foreach (var editor in editors) if (editor != null) editor.OnDestroy(); + + Curve.BeforeChange -= BeforeCurveChange; + Curve.Changed -= CurveChanged; + + Dispose(); + + Tools.hidden = false; + } + + public override void OnInspectorGUI() + { + //adjust math if needed + AdjustMath(BGPrivateField.GetSettings(Curve), Math); + + //styles + BGEditorUtility.Assign(ref stickerStyle, () => new GUIStyle("Label") {fontSize = 18, alignment = TextAnchor.MiddleCenter, normal = new GUIStyleState {textColor = Color.white}}); + BGEditorUtility.Assign(ref settingsTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGSettingsIcon123)); + + serializedObject.Update(); + + // =========== Header + DrawLogo(); + + // =========== lock view + BGEditorUtility.Horizontal(() => + { + var temp = BGCurveSettingsForEditor.LockView; + BGCurveSettingsForEditor.LockView = BGEditorUtility.ButtonOnOff(ref temp, "Lock view", "Disable selection of any object in the scene, except points", LockViewActiveColor, + new GUIContent("Turn Off", "Click to turn this mode off"), + new GUIContent("Turn On", "Click to turn this mode on")); + + if (GUILayout.Button(settingsTexture, GUILayout.MaxWidth(24), GUILayout.MaxHeight(24))) BGCurveSettingsForEditorWindow.Open(); + }); + + //warning + BGEditorUtility.HelpBox("You can not chose another objects in the scene, except points.", MessageType.Warning, + BGCurveSettingsForEditor.LockView, () => GUILayout.Space(8)); + + // =========== Tabs + if (BGCurveSettingsForEditor.CurrentTab < 0 || BGCurveSettingsForEditor.CurrentTab > headers.Length - 1) BGCurveSettingsForEditor.CurrentTab = 0; + var newTab = GUILayout.Toolbar(BGCurveSettingsForEditor.CurrentTab, headers, GUILayout.Height(ToolBarHeight)); + //do not move this method(GUILayoutUtility.GetLastRect() is used) + ShowStickers(); + if (BGCurveSettingsForEditor.CurrentTab != newTab) GUI.FocusControl(""); + BGCurveSettingsForEditor.CurrentTab = newTab; + editors[BGCurveSettingsForEditor.CurrentTab].OnInspectorGui(); + + if (!GUI.changed) return; // if no change- return + + foreach (var editor in editors) editor.OnApply(); + + transformMonitor.CheckForChange(); + } + + //shows error sticker if any component has error + private void ShowStickers() + { + if (Event.current.type == EventType.Repaint) toolBarRect = GUILayoutUtility.GetLastRect(); + + const int height = 18; + var oneTabWidth = toolBarRect.width/editors.Length; + + for (var i = 0; i < editors.Length; i++) + { + var editor = editors[i]; + var error = MessageType.None; + var message = editor.GetStickerMessage(ref error); + if (message == null) continue; + + //show sticker + var width = stickerStyle.CalcSize(new GUIContent(message)).x; + + var rect = new Rect(toolBarRect.x + oneTabWidth*(i + 1) - width, toolBarRect.y + 1, width, height); + + GUI.DrawTexture(rect, GetStickerTexture(error, i)); + GUI.Label(rect, message, stickerStyle); + } + } + + private Texture2D GetStickerTexture(MessageType error, int index) + { + return error == MessageType.Error + ? stickerTextureError + : error == MessageType.Warning + ? stickerTextureWarning + : BGCurveSettingsForEditor.CurrentTab == index + ? stickerTextureActive + : stickerTextureOk; + } + + protected virtual void DrawLogo() + { + DrawLogo(headerTexture); + } + + + protected static void DrawLogo(Texture2D logo) + { + var rect = GUILayoutUtility.GetRect(0, 0); + rect.width = logo.width*.5f; + rect.height = logo.height*.5f; + rect.y += 1; + GUILayout.Space(rect.height + 1); + GUI.DrawTexture(rect, logo); + } + + public void OnSceneGUI() + { + var settings = BGPrivateField.GetSettings(Curve); + + AdjustMath(settings, Math); + + if (Curve.ForceChangedEventMode != BGCurve.ForceChangedEventModeEnum.Off) Math.Recalculate(true); + + + if (settings.HandlesSettings != null && settings.HandlesType == BGCurveSettings.HandlesTypeEnum.Configurable + || settings.ControlHandlesSettings != null && settings.ControlHandlesType == BGCurveSettings.HandlesTypeEnum.Configurable) BGEditorUtility.ReloadSnapSettings(); + + + OverlayMessage.OnSceneGui(); + + var frustum = GeometryUtility.CalculateFrustumPlanes(SceneView.currentDrawingSceneView.camera); + + // process all editors + foreach (var editor in editors) editor.OnSceneGui(frustum); + + editorSelection.Process(Event.current); + + + transformMonitor.CheckForChange(); + } + + public static void AddPoint(BGCurve curve, BGCurvePoint point, int index) + { + BGPrivateField.Invoke(curve, BGCurve.MethodAddPoint, point, index, GetPointProvider(curve.PointsMode, curve)); + } + + public static void DeletePoint(BGCurve curve, int index) + { + BGPrivateField.Invoke(curve, BGCurve.MethodDeletePoint, new[] {typeof(int), typeof(Action)}, index, GetPointDestroyer(curve.PointsMode, curve)); + } + + public static void DeletePoints(BGCurve curve, BGCurvePointI[] points) + { + BGPrivateField.Invoke(curve, BGCurve.MethodDeletePoint, new[] {typeof(BGCurvePointI[]), typeof(Action)}, points, GetPointDestroyer(curve.PointsMode, curve)); + } + + + public static Func GetPointProvider(BGCurve.PointsModeEnum pointsMode, BGCurve curve) + { + //init provider + Func provider = null; + switch (pointsMode) + { + case BGCurve.PointsModeEnum.Components: + provider = () => Undo.AddComponent(curve.gameObject); + break; + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + case BGCurve.PointsModeEnum.GameObjectsTransform: + provider = () => + { + var pointGO = new GameObject(); + var transform = pointGO.transform; + transform.parent = curve.transform; + transform.localRotation = Quaternion.identity; + transform.localPosition = Vector3.zero; + transform.localScale = Vector3.one; + + Undo.RegisterCreatedObjectUndo(pointGO, "Create point"); + var point = Undo.AddComponent(pointGO); + return point; + }; + break; + } + return provider; + } + + public static Action GetPointDestroyer(BGCurve.PointsModeEnum pointsMode, BGCurve curve) + { + //init destroyer + Action destroyer = null; + switch (pointsMode) + { + case BGCurve.PointsModeEnum.Components: + destroyer = point => Undo.DestroyObjectImmediate((UnityEngine.Object) point); + break; + case BGCurve.PointsModeEnum.GameObjectsNoTransform: + case BGCurve.PointsModeEnum.GameObjectsTransform: + destroyer = point => Undo.DestroyObjectImmediate(((MonoBehaviour) point).gameObject); + break; + } + return destroyer; + } + + + [MenuItem("GameObject/Create Other/BansheeGz/BG Curve")] + public static void CreateCurve(MenuCommand command) + { + var curveObject = new GameObject("BGCurve"); + Undo.RegisterCreatedObjectUndo(curveObject, "Undo Create BGCurve"); + curveObject.AddComponent(); + Selection.activeGameObject = curveObject; + } + + [DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.Selected | GizmoType.InSelectionHierarchy)] + public static void DrawGizmos(BGCurve curve, GizmoType gizmoType) + { + var playMode = EditorApplication.isPlaying; + + if (lastPlayMode != playMode) + { + lastPlayMode = playMode; + + foreach (var painterGizmo in curve2Painter) painterGizmo.Value.Dispose(); + curve2Painter.Clear(); + } + + var settings = BGPrivateField.GetSettings(curve); + if (!ComplyForDrawGizmos(curve, gizmoType, settings)) return; + + if (CurrentCurve != null && curve.GetInstanceID() == CurrentCurve.GetInstanceID()) + { + if (CurrentGizmoPainter != null) CurrentGizmoPainter.DrawCurve(); + } + else + { + //curve is not selected in hierarchy + var painter = BGEditorUtility.Ensure(curve2Painter, curve, () => new BGCurvePainterGizmo(NewMath(curve, settings), true)); + AdjustMath(settings, painter.Math); + if (curve.ForceChangedEventMode != BGCurve.ForceChangedEventModeEnum.Off && !Application.isPlaying) painter.Math.Recalculate(); + painter.DrawCurve(); + } + } + + public static bool ComplyForDrawGizmos(BGCurve curve, GizmoType gizmoType, BGCurveSettings settings) + { + if (curve.PointsCount == 0) return false; + + if (!settings.ShowCurve) return false; + if (Selection.Contains(curve.gameObject) && settings.VRay) return false; + if (settings.ShowCurveMode == BGCurveSettings.ShowCurveModeEnum.CurveSelected && !Comply(gizmoType, GizmoType.Selected)) return false; + + if (BGCurvePointGOEditor.PointSelected) return true; + + if (settings.ShowCurveMode == BGCurveSettings.ShowCurveModeEnum.CurveOrParentSelected && !Comply(gizmoType, GizmoType.InSelectionHierarchy)) return false; + return true; + } + + public static bool Comply(GizmoType gizmoType, GizmoType toCompare) + { + return (gizmoType & toCompare) != 0; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditor.cs.meta new file mode 100644 index 0000000..80ff9aa --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 93887c59e11763c4791cc3f6063e3ff0 +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorComponents.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorComponents.cs new file mode 100644 index 0000000..b66491c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorComponents.cs @@ -0,0 +1,661 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using Object = UnityEngine.Object; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGCurveEditorComponents : BGCurveEditorTab + { + private const int ConnectorLineAlpha = 100; + private const int HeaderAlpha = 25; + private const int HeaderFoldedAlpha = 75; + + private static bool customEditorsOn = true; + + + private Texture2D collapseTexture; + private Texture2D expandTexture; + private Texture2D addTexture; + private Texture2D deleteTexture; + private Texture2D whiteTexture; + private Texture2D onTexture; + private Texture2D offTexture; + private Texture2D handlesOnTexture; + private Texture2D handlesOffTexture; + + private readonly Tree tree; + private BGCc[] components; + + public BGCurveEditorComponents(BGCurveEditor editor, SerializedObject curveObject) + : base(editor, curveObject, BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGComponents123)) + { + tree = new Tree(Curve); + } + + + private bool HasError + { + get { return AnyComponentHasError(Curve); } + } + + private bool HasWarning + { + get { return AnyComponentHasWarning(Curve); } + } + + // ================================================================================ Inspector + public override void OnInspectorGui() + { + BGEditorUtility.Assign(ref whiteTexture, () => BGEditorUtility.Texture1X1(Color.white)); + BGEditorUtility.Assign(ref collapseTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGCollapseAll123)); + BGEditorUtility.Assign(ref expandTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGExpandAll123)); + BGEditorUtility.Assign(ref addTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGAdd123)); + BGEditorUtility.Assign(ref deleteTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGDelete123)); + BGEditorUtility.Assign(ref onTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGOn123)); + BGEditorUtility.Assign(ref offTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGOff123)); + BGEditorUtility.Assign(ref handlesOnTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHandlesOn123)); + BGEditorUtility.Assign(ref handlesOffTexture, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHandlesOff123)); + + + components = Curve.GetComponents(); + var length = components.Length; + + tree.Refresh(components); + + if (tree.InitException != null) + { + EditorGUILayout.HelpBox("There was an error initializing editors for component's Tree View: " + tree.InitException.Message + + "\r\n\r\nYou still can use default Unity's editors for components below.", MessageType.Error); + return; + } + + + var hasError = HasError; + var hasWarning = HasWarning; + + BGEditorUtility.HorizontalBox(() => + { + EditorGUILayout.LabelField("Components: " + length + " (" + (hasError ? "Error" : "Ok") + ")"); + + GUILayout.FlexibleSpace(); + + // turn on/off handles + if (BGEditorUtility.ButtonWithIcon(BGCurveSettingsForEditor.CcInspectorHandlesOff ? handlesOffTexture : handlesOnTexture, "Turn on/off handles settings in Inspector")) + { + BGCurveSettingsForEditor.CcInspectorHandlesOff = !BGCurveSettingsForEditor.CcInspectorHandlesOff; + } + EditorGUILayout.Separator(); + + // turn on/off colored tree + if (BGEditorUtility.ButtonWithIcon(customEditorsOn ? onTexture : offTexture, "Use custom UI for components (colored tree) and hide standard unity editors for components")) + { + customEditorsOn = !customEditorsOn; + tree.Refresh(null, true); + } + EditorGUILayout.Separator(); + + if (length > 0) + { + // collapse/expand + if (BGEditorUtility.ButtonWithIcon(collapseTexture, "Collapse all components")) tree.ExpandCollapseAll(true); + EditorGUILayout.Separator(); + if (BGEditorUtility.ButtonWithIcon(expandTexture, "Expand all components")) tree.ExpandCollapseAll(false); + EditorGUILayout.Separator(); + + + // delete all Ccs + if (BGEditorUtility.ButtonWithIcon(deleteTexture, "Delete all components") + && BGEditorUtility.Confirm("Delete", "Are you sure you want to delete " + length + " component(s)?", "Delete")) tree.Delete(); + EditorGUILayout.Separator(); + } + + //add new Cc + if (BGEditorUtility.ButtonWithIcon(addTexture, "Add new component")) BGCcAddWindow.Open(Curve, type => AddComponent(Curve, type)); + }); + + + if (length > 0) + { + // warnings/errors + if (hasWarning || hasError) + { + for (var i = 0; i < components.Length; i++) + { + var component = components[i]; + + var name = (component.Descriptor != null ? component.Descriptor.Name + " " : "") + component.CcName; + + var error = component.Error; + if (!string.IsNullOrEmpty(error)) BGEditorUtility.HelpBox("Component error [" + name + "]: " + error, MessageType.Error); + + var warning = component.Warning; + if (!string.IsNullOrEmpty(warning)) BGEditorUtility.HelpBox("Component warning [" + name + "]: " + warning, MessageType.Warning); + } + } + else BGEditorUtility.HelpBox("No warnings or errors", MessageType.Info); + + // tree GUI + tree.OnInspectorGui(); + } + else + EditorGUILayout.HelpBox( + "Hit the Plus icon to add a component" + + "\r\n" + + "\r\n" + + "Components allows to add functionality without any scripting." + , MessageType.Info); + + + if (hasError ^ HasError || hasWarning ^ HasWarning) EditorApplication.RepaintHierarchyWindow(); + } + + private static BGCc AddComponent(BGCurve curve, Type type) + { + var newCc = Undo.AddComponent(curve.gameObject, type); + if (newCc == null) return null; + + var bgCc = ((BGCc) newCc); + UnityEditorInternal.InternalEditorUtility.SetIsInspectorExpanded(bgCc, true); + bgCc.AddedInEditor(); + EditorUtility.SetDirty(curve.gameObject); + return bgCc; + } + + public override void OnEnable() + { + tree.Refresh(); + } + + public override void OnDisable() + { + tree.OnDestroy(); + } + + public override void OnSceneGui(Plane[] frustum) + { + if (!customEditorsOn) return; + + tree.OnSceneGui(); + } + + public override string GetStickerMessage(ref MessageType type) + { + var length = Curve.GetComponents().Length; + if (length != 0) + { + bool hasError = false, hasWarning = false; + ComponentsStatus(Curve, ref hasError, ref hasWarning); + type = hasError ? MessageType.Error : hasWarning ? MessageType.Warning : MessageType.None; + } + + return type != MessageType.None ? "!!" : "" + length; + } + + + public static bool AnyComponentHasError(BGCurve curve) + { + var components = curve.GetComponents(); + if (components == null || components.Length == 0) return false; + return components.Any(t => t.HasError()); + } + + public static bool AnyComponentHasWarning(BGCurve curve) + { + var components = curve.GetComponents(); + if (components == null || components.Length == 0) return false; + return components.Any(t => t.HasWarning()); + } + + public static void ComponentsStatus(BGCurve curve, ref bool hasError, ref bool hasWarning) + { + var components = curve.GetComponents(); + if (components == null || components.Length == 0) return; + + foreach (var component in components) + { + if (component.HasError()) hasError = true; + if (component.HasWarning()) hasWarning = true; + } + } + + + // ================================================================================ Tree + //tree structure of Cc's + internal sealed class Tree : BGTreeView + { + private Dictionary level2LinkTexture = GetLevel2LinkTexture(); + + private static Dictionary GetLevel2LinkTexture() + { + return new Dictionary + { + {0, BGEditorUtility.Texture1X1(new Color32(255, 0, 0, ConnectorLineAlpha))}, + {1, BGEditorUtility.Texture1X1(new Color32(0, 255, 0, ConnectorLineAlpha))}, + {2, BGEditorUtility.Texture1X1(new Color32(0, 0, 255, ConnectorLineAlpha))}, + {3, BGEditorUtility.Texture1X1(new Color32(255, 255, 0, ConnectorLineAlpha))}, + }; + } + + private readonly Dictionary level2Color = new Dictionary + { + {0, new Color32(255, 0, 0, HeaderAlpha)}, + {1, new Color32(0, 255, 0, HeaderAlpha)}, + {2, new Color32(0, 0, 255, HeaderAlpha)}, + {3, new Color32(255, 255, 0, HeaderAlpha)}, + }; + + private readonly Dictionary level2FoldedColor = new Dictionary + { + {0, new Color32(255, 0, 0, HeaderFoldedAlpha)}, + {1, new Color32(0, 255, 0, HeaderFoldedAlpha)}, + {2, new Color32(0, 0, 255, HeaderFoldedAlpha)}, + {3, new Color32(255, 255, 0, HeaderFoldedAlpha)}, + }; + + private readonly Texture2D whiteTexture; + + + private readonly Dictionary> type2NodeList = new Dictionary>(); + + public BGCurve Curve; + public BGCc.CcException InitException; + + private int count; + + public Tree(BGCurve curve) : base(new Config(2, 8, 0, 2, 0)) + { + Curve = curve; + + whiteTexture = BGEditorUtility.Texture1X1(Color.white); + } + + public void Refresh(BGCc[] components = null, bool force = false) + { + if (components == null) components = Curve.GetComponents(); + + //it should be enough + if (count == components.Length && !force) return; + + SetHideFlag(components, customEditorsOn ? HideFlags.HideInInspector : HideFlags.None); + + //Recalc + var instanceId2Collapsed = new Dictionary(); + //try to preserve expanded/collapsed state + if (Roots.Count > 0) foreach (var root in Roots) root.FillState(instanceId2Collapsed); + + OnDestroy(); + Roots.Clear(); + type2NodeList.Clear(); + + + if (!customEditorsOn) return; + + + try + { + InitException = null; + + //try to init custom tree view for components + count = components.Length; + foreach (var cc in components) + { + var node = new CcNode(this, cc); + + if (instanceId2Collapsed.ContainsKey(cc.GetInstanceID())) node.Collapsed = true; + + var type = cc.GetType(); + + if (!type2NodeList.ContainsKey(type)) type2NodeList[type] = new List(); + + type2NodeList[type].Add(node); + } + + foreach (var list in type2NodeList.Values) foreach (var node in list) if (!node.Processed) node.ProcessStructure(); + } + catch (BGCc.CcException e) + { + InitException = e; + //fallback (show default stuff) + SetHideFlag(components, HideFlags.None); + } + } + + private static void SetHideFlag(BGCc[] components, HideFlags hideFlags) + { + foreach (var component in components) component.hideFlags = hideFlags; + } + + + public CcNode Get(BGCc cc) + { + var nodes = type2NodeList[cc.GetType()]; + + return nodes.FirstOrDefault(node => node.Cc == cc); + } + + public void Delete() + { + foreach (var root in Roots) root.Delete(); + + GUIUtility.ExitGUI(); + } + + public void OnDestroy() + { + foreach (var root in Roots) root.OnDestroy(); + } + + public override Texture2D GetLinkTexture(int level) + { + if (level2LinkTexture[0] == null) level2LinkTexture = GetLevel2LinkTexture(); + return level2LinkTexture.Count > level ? level2LinkTexture[level] : whiteTexture; + } + + private Color GetColor(int level, bool collapsed, Func defaultColor) + { + return level2Color.Count > level ? (collapsed ? level2FoldedColor[level] : level2Color[level]) : defaultColor(); + } + + public void OnSceneGui() + { + foreach (var root in Roots) root.OnSceneGui(); + } + + public override void OnInspectorGui() + { + if (!customEditorsOn) + { + EditorGUILayout.HelpBox("You disabled tree view. Use standard Unity editors below to change parameters.", MessageType.Warning); + return; + } + + + try + { + for (var i = 0; i < Roots.Count; i++) + { + var root = Roots[i]; + if (i != 0) EditorGUILayout.Separator(); + root.OnInspectorGui(); + } + } + catch (BGEditorUtility.ExitException) + { + Refresh(); + GUIUtility.ExitGUI(); + } + } + + // ================================================================================ Tree Node + // one cc + internal sealed class CcNode : BGTreeNode + { + public bool Processed; + //Cc= Curve's component + public readonly BGCc Cc; + private readonly BGCc.CcDescriptor descriptor; + + private readonly Texture2D enabledTexture; + private readonly Texture2D disabledTexture; + private readonly Texture2D helpTexture; + private readonly Texture2D deleteTexture; + private readonly Texture2D addTexture; + private readonly Texture2D changeNameTexture; + + private GUIStyle headerFoldoutStyle; + private GUIStyle headerFoldoutStyleDisabled; + private GUIStyle okStyle; + private GUIStyle errorStyle; + private GUIStyle coloredBoxStyle; + + + private readonly BGCcEditor ccEditor; + private readonly MethodInfo onSceneGuiMethod; + private readonly Type parentType; + private GUIStyle headerBoxStyle; + + + public override bool Collapsed + { + get { return !UnityEditorInternal.InternalEditorUtility.GetIsInspectorExpanded(Cc); } + set { UnityEditorInternal.InternalEditorUtility.SetIsInspectorExpanded(Cc, !value); } + } + + internal CcNode(Tree tree, BGCc cc) : base(tree) + { + Cc = cc; + descriptor = cc.Descriptor; + + var editor = UnityEditor.Editor.CreateEditor(cc); + + if (!(editor is BGCcEditor)) throw new BGCc.CcException("Unable to init an Editor for " + cc.GetType() + ": editor does not extend from BGCcEditor."); + + ccEditor = (BGCcEditor) editor; + ccEditor.ChangedParent += ChangedParent; +// UnityEditor.Editor.CreateCachedEditor(cc, null, ref ccEditor); + + onSceneGuiMethod = ccEditor.GetType().GetMethod("OnSceneGUI", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); + + enabledTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGTickYes123); + disabledTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGTickNo123); + helpTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHelp123); + deleteTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGDelete123); + addTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGAdd123); + changeNameTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGCcEditName123); + + parentType = cc.GetParentClass(); + } + + private Tree MyTree + { + get { return (Tree) Tree; } + } + + private void ChangedParent(object sender, EventArgs e) + { + MyTree.Refresh(null, true); + } + + public override void ProcessStructure() + { + if (parentType == null) + { + MyTree.Roots.Add(this); + } + else + { + Parent = MyTree.Get(Cc.GetParent(parentType)); + } + Processed = true; + } + + //true if exit gui pass + public override void OnInspectorGuiInternal(int level) + { + BGEditorUtility.Assign(ref okStyle, () => new GUIStyle("Label") {normal = {textColor = new Color32(66, 166, 33, 255)}, fontStyle = FontStyle.Bold}); + BGEditorUtility.Assign(ref errorStyle, () => new GUIStyle("Label") {normal = {textColor = new Color32(166, 66, 33, 255)}, fontStyle = FontStyle.Bold}); + BGEditorUtility.Assign(ref headerBoxStyle, () => new GUIStyle {padding = new RectOffset(4, 4, 4, 4)}); + BGEditorUtility.Assign(ref headerFoldoutStyle, () => new GUIStyle(EditorStyles.foldout) {fontStyle = FontStyle.Bold, clipping = TextClipping.Clip}); + BGEditorUtility.Assign(ref headerFoldoutStyleDisabled, () => new GUIStyle(headerFoldoutStyle) {normal = {textColor = Color.gray}}); + + var color = MyTree.GetColor(level, Collapsed, () => Color.white); + color.a = ConnectorLineAlpha; + + //colored box + BGEditorUtility.SwapGuiColor(color, () => EditorGUILayout.BeginVertical(BGEditorUtility.Assign(ref coloredBoxStyle, () => new GUIStyle("Box") + { + padding = new RectOffset(), + margin = new RectOffset(), + border = new RectOffset(4, 4, 4, 4), + normal = {background = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGBoxWhite123)} + }))); + + //header + HeaderUi(level, !String.IsNullOrEmpty(Cc.Error)); + + + if (!Collapsed) + { + BGEditorUtility.VerticalBox(() => + { + //show inspector + ccEditor.OnInspectorGUI(); + }); + } + + //do not remove it (EditorGUILayout.BeginVertical is a little higher- colored box) + EditorGUILayout.EndVertical(); + } + + private void HeaderUi(int level, bool hasError) + { + var color = MyTree.GetColor(level, Collapsed, () => new Color(0, 0, 0, 0)); + BGEditorUtility.SwapGuiBackgroundColor(color, () => + { + BGEditorUtility.Horizontal(headerBoxStyle, () => + { + BGEditorUtility.Indent(1, () => + { + var content = new GUIContent(descriptor == null ? Cc.GetType().Name : descriptor.Name + " (" + BGEditorUtility.Trim(Cc.CcName, 10) + ")", + descriptor == null ? null : descriptor.Description); + var width = headerFoldoutStyle.CalcSize(content).x + 16; + + BGEditorUtility.SwapLabelWidth((int) width, () => + { + //foldout (we dont use layout version cause it does not support clickin on labels) + Collapsed = EditorGUI.Foldout( + GUILayoutUtility.GetRect(width, 16f), + Collapsed, + content, + true, + Cc.enabled ? headerFoldoutStyle : headerFoldoutStyleDisabled); + }); + }); + + GUILayout.FlexibleSpace(); + + // status(error or Ok) + EditorGUI.LabelField(GUILayoutUtility.GetRect(70, 16, EditorStyles.label), hasError ? "Error" : "Ok.", hasError ? errorStyle : okStyle); + + + //help url + if (!String.IsNullOrEmpty(Cc.HelpURL)) + { + if (BGEditorUtility.ButtonWithIcon(helpTexture, "Open help in the browser")) Application.OpenURL(Cc.HelpURL); + EditorGUILayout.Separator(); + } + + //change name + if (BGEditorUtility.ButtonWithIcon(changeNameTexture, "Change the name")) BGCcChangeNameWindow.Open(Cc); + EditorGUILayout.Separator(); + + //add a child + if (BGEditorUtility.ButtonWithIcon(addTexture, "Add a component, which is dependant on this component")) + BGCcAddWindow.Open(MyTree.Curve, type => + { + //cache some data + var gameObject = Cc.Curve.gameObject; + var oldComponents = gameObject.GetComponents(); + var currentCcType = Cc.GetType(); + + //add + var addedCc = AddComponent(MyTree.Curve, type); + if (addedCc == null) return; + + //we need to process all the way up to the Cc and link Ccs to right (newly created) parents + var parentClass = addedCc.GetParentClass(); + var recursionLimit = 16; + var cc = addedCc; + while (parentClass!=null && recursionLimit-- > 0) + { + if (currentCcType == parentClass) + { + //we reached the current Cc + cc.SetParent(Cc); + break; + } + + //going up + var possibleParents = gameObject.GetComponents(parentClass); + var parent = possibleParents.Where(possibleParent => !oldComponents.Contains(possibleParent)).Cast().FirstOrDefault(); + + if (parent == null) break; + + cc.SetParent(parent); + cc = parent; + parentClass = cc.GetParentClass(); + } + }, Cc.GetType()); + EditorGUILayout.Separator(); + + + //enable/disable + if (BGEditorUtility.ButtonWithIcon(Cc.enabled ? enabledTexture : disabledTexture, "Enable/disable a component")) Enable(!Cc.enabled); + EditorGUILayout.Separator(); + + //delete + if (!BGEditorUtility.ButtonWithIcon(deleteTexture, "Remove this component")) return; + + + //remove + Delete(); + + EditorUtility.SetDirty(MyTree.Curve.gameObject); + + //not sure how to make proper exit + throw new BGEditorUtility.ExitException(); + }); + }); + } + + private void Enable(bool enabled) + { + Cc.enabled = enabled; + IterateChildren(node => node.Enable(enabled)); + } + + public void Delete() + { + IterateChildren(node => node.Delete()); + + if (ccEditor != null) + { + ccEditor.ChangedParent -= ChangedParent; + Object.DestroyImmediate(ccEditor); + } + + Undo.DestroyObjectImmediate(Cc); + } + + public void OnDestroy() + { + IterateChildren(node => node.OnDestroy()); + + if (ccEditor == null) return; + + ccEditor.ChangedParent -= ChangedParent; + Object.DestroyImmediate(ccEditor); + } + + public void OnSceneGui() + { + IterateChildren(node => node.OnSceneGui()); + + if (onSceneGuiMethod != null) onSceneGuiMethod.Invoke(ccEditor, null); + } + + public void FillState(Dictionary instanceId2Collapsed) + { + if (Collapsed) instanceId2Collapsed[Cc.GetInstanceID()] = true; + + IterateChildren(node => node.FillState(instanceId2Collapsed)); + } + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorComponents.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorComponents.cs.meta new file mode 100644 index 0000000..4708210 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorComponents.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0e8f1f93e9ec8ac46a3c01f3077087df +timeCreated: 1471761097 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorFields.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorFields.cs new file mode 100644 index 0000000..18d9b6f --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorFields.cs @@ -0,0 +1,982 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGCurveEditorFields : BGCurveEditorTab + { + //label width in percents + private const int LabelWidth = 30; + + // ====================================== Fields + private readonly Texture2D deleteIcon; + private readonly Texture2D addIcon; + + + private TableUi systemUi; + private TableUi customUi; + + private SystemField[] systemFields; + private PointField[] customFields; + private string newFieldName; + private BGCurvePointField.TypeEnum newFieldType; + private readonly BGCurveEditorPointsSelection editorSelection; + + public BGCurveEditorFields(BGCurveEditor editor, SerializedObject curveObject, BGCurveEditorPointsSelection editorSelection) + : base(editor, curveObject, BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGFields123)) + { + this.editorSelection = editorSelection; + + addIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGAdd123); + deleteIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGDelete123); + } + + + // ================================================================================ Inspector + public override void OnInspectorGui() + { + var settings = BGPrivateField.GetSettings(Curve); + + BGEditorUtility.HelpBox("Curve UI is disabled in settings. All handles are disabled too.", MessageType.Warning, !settings.ShowCurve); + + BGEditorUtility.Assign(ref customUi, () => new TableUi("Custom fields", new[] {"#", "Name", "Type", "?", "Delete"}, new[] {5, 40, 40, 5, 10})); + BGEditorUtility.Assign(ref systemUi, () => new TableUi("System fields", new[] {"Name", "Value"}, new[] {LabelWidth, 100 - LabelWidth})); + + BGEditorUtility.Assign(ref systemFields, () => new[] + { + (SystemField) new SystemFieldPosition(settings), + new SystemFieldControls(settings), + new SystemFieldControlsType(settings), + new SystemFieldTransform(settings), + }); + + var fields = Curve.Fields; + var hasFields = fields != null && fields.Length > 0; + + if (hasFields && (customFields == null || customFields.Length != fields.Length) || !hasFields && customFields != null && customFields.Length != fields.Length) + { + customFields = new PointField[fields.Length]; + + for (var i = 0; i < fields.Length; i++) customFields[i] = new PointField(fields[i], i, deleteIcon); + } + + + //warnings + BGEditorUtility.HelpBox("All handles for positions are disabled.", MessageType.Warning, settings.HandlesSettings.Disabled); + BGEditorUtility.HelpBox("All handles for controls are disabled.", MessageType.Warning, settings.ControlHandlesSettings.Disabled); + + //====================== Custom fields + customUi.Init(); + //add row + customUi.NextColumn(rect => EditorGUI.LabelField(rect, "Name"), 12); + customUi.NextColumn(rect => newFieldName = EditorGUI.TextField(rect, newFieldName), 28); + customUi.NextColumn(rect => BGEditorUtility.PopupField(rect, newFieldType, @enum => newFieldType = (BGCurvePointField.TypeEnum) @enum), 50); + customUi.NextColumn(rect => + { + if (!GUI.Button(rect, addIcon)) return; + + if (NameHasError(Curve, newFieldName)) return; + + BGPrivateField.Invoke(Curve, BGCurve.MethodAddField, newFieldName, newFieldType, (Func) (() => Undo.AddComponent(Curve.gameObject))); + GUIUtility.hotControl = 0; + GUIUtility.ExitGUI(); + }, 10); + + customUi.NextRow(); + var warning = ""; + + if (customFields == null || customFields.Length == 0) customUi.NextRow("Name should be 16 chars max, starts with a letter and contain English chars and numbers only."); + else + { + //header + customUi.DrawHeaders(); + + //fields + var quaternionWithHandlesCount = 0; + + BGEditorUtility.ChangeCheck(() => + { + foreach (var customField in customFields) + { + if (customField.Field.Type == BGCurvePointField.TypeEnum.Quaternion && BGPrivateField.GetHandlesType(customField.Field) != 0) quaternionWithHandlesCount++; + customField.Ui(customUi); + } + }, SceneView.RepaintAll); + + if (quaternionWithHandlesCount > 1) warning = "You have more than one Quaternion field with Handles enabled. Only first field will be shown in Scene View"; + //footer + customUi.NextRow("?- Show in Points Menu/Scene View"); + } + //inform layout manager + GUILayoutUtility.GetRect(customUi.Width, customUi.Height); + + BGEditorUtility.HelpBox(warning, MessageType.Warning, warning.Length > 0); + + //====================== System fields + systemUi.Init(); + + BGEditorUtility.ChangeCheck(() => + { + foreach (var field in systemFields) field.Ui(systemUi); + }, SceneView.RepaintAll); + + //inform layout manager + GUILayoutUtility.GetRect(systemUi.Width, systemUi.Height); + GUILayout.Space(4); + } + + private static bool NameHasError(BGCurve curve, string name) + { + var error = BGCurvePointField.CheckName(curve, name); + if (error == null) return false; + + BGEditorUtility.Inform("Error", error); + return true; + } + + + public override string GetStickerMessage(ref MessageType type) + { + return "" + Curve.FieldsCount; + } + + + public override void OnSceneGui(Plane[] frustum) + { + if (Curve.PointsCount == 0) return; + + //show handles (including labels) if any + PointField.OnSceneGui(frustum, Curve, Settings, editorSelection); + } + + //=================================================== UI Builder (idea.. refactor it later) + private sealed class TableUi + { + private const float Offset = 10; + private const int TitleOffset = 10; + + private readonly string[] headers; //headers + private readonly int[] sizes; //column sizes percentages + private readonly float height; //line height + + private readonly GUIStyle headerStyle; + private readonly GUIStyle cellStyle; + private readonly GUIStyle titleStyle; + private readonly GUIStyle centeredLabelStyle; + + private readonly string title; + + public GUIStyle CenteredLabelStyle + { + get { return centeredLabelStyle; } + } + + + private Rect lastRect; //last rect from Layout manager + + public float Width { get; private set; } + + public float Height + { + get { return rows*height + Offset; } + } + + public int[] Sizes + { + get { return sizes; } + } + + private float rows; //not data, but ui lines + private Vector2 cursor; + private int currentColumn; + + public TableUi(string title, string[] headers, int[] sizes) + { + this.headers = headers; + this.sizes = sizes; + this.title = title; + + headerStyle = new GUIStyle(GetStyle(BGEditorUtility.Image.BGBoxWithBorder123)); + centeredLabelStyle = new GUIStyle("Label") {alignment = TextAnchor.MiddleCenter}; + + cellStyle = GetStyle(BGEditorUtility.Image.BGTableCell123); + titleStyle = GetStyle(BGEditorUtility.Image.BGTableTitle123); + titleStyle.border = titleStyle.padding = new RectOffset(TitleOffset, TitleOffset, 2, 2); + + height = cellStyle.CalcSize(new GUIContent("Test")).y; + + Init(); + } + + public void Init() + { + //---------------------------------- init sizes + lastRect = GUILayoutUtility.GetLastRect(); + Width = lastRect.width; + cursor = new Vector2(lastRect.xMin, lastRect.yMax + Offset); + rows = 0; + currentColumn = 0; + + //---------------------------------- title + EditorGUI.LabelField(new Rect(cursor.x, cursor.y, titleStyle.CalcSize(new GUIContent(title)).x + TitleOffset*2, height), title, titleStyle); + NextRow(); + } + + //---------------------------------- headers + public void DrawHeaders() + { + for (var i = 0; i < headers.Length; i++) NextColumn(rect => EditorGUI.LabelField(rect, headers[i]), sizes[i], true); + NextRow(); + } + + private static GUIStyle GetStyle(BGEditorUtility.Image background) + { + return new GUIStyle("Label") + { + padding = new RectOffset(2, 2, 2, 2), + border = new RectOffset(2, 2, 2, 2), + normal = new GUIStyleState + { + background = BGEditorUtility.LoadTexture2D(background) + } + }; + } + + public void NextColumn(string label, Action action, int widthInPercent = 0, GUIStyle labelStyle = null, bool header = false) + { + var columnWidth = Width*(widthInPercent > 0 ? widthInPercent : sizes[currentColumn])/100f; + + var rect = new Rect(cursor.x, cursor.y, columnWidth, height); + EditorGUI.LabelField(rect, "", header ? headerStyle : cellStyle); + + if (label != null) + { + rect.width /= 2; + EditorGUI.LabelField(rect, label, labelStyle ?? GUI.skin.label); + rect.x += rect.width; + } + + if (action != null) action(rect); + + cursor.x += columnWidth; + currentColumn++; + } + + public void NextColumn(Action action, int widthInPercent = 0, bool header = false) + { + NextColumn(null, action, widthInPercent, header: header); + } + + public void NextColumn(string label, string description, int widthInPercent = 0, bool header = false) + { + NextColumn(rect => EditorGUI.LabelField(rect, new GUIContent(label, description)), widthInPercent, header); + } + + public void NextRow() + { + cursor.x = lastRect.xMin; + cursor.y += height; + currentColumn = 0; + rows++; + } + + public void NextRow(string message) + { + EditorGUI.LabelField(new Rect(cursor.x, cursor.y, Width, height), message, cellStyle); + NextRow(); + } + } + + //=========================================================================================== Custom fields + private sealed class PointField + { + private enum HandlesType + { + None, + Label, + Direction, + DistanceFromPoint, + Bounds, + BoundsAroundPoint, + Link, + Rotation + } + + private readonly BGCurvePointField field; + private readonly int index; + private readonly Texture2D deleteIcon; + + private static readonly Dictionary Type2SupportHandles = new Dictionary(); + private static readonly Dictionary Type2Handles = new Dictionary(); + + private static readonly Func FieldWithHandlesPredicate = + field => BGPrivateField.GetShowHandles(field) && SupportHandles(field.Type) && BGPrivateField.GetHandlesType(field) != 0; + + private static readonly Func FieldWithLabelPredicate = field => BGPrivateField.GetHandlesType(field) == (int) HandlesType.Label; + + private static Color[] handlesColor; + private static GUIStyle labelStyle; + private static GUIStyle selectedlabelStyle; + + private static bool[] visiblePoints; + private static Color32 latestLabelBackColor; + + public BGCurvePointField Field + { + get { return field; } + } + + static PointField() + { + Register(BGCurvePointField.TypeEnum.Bool, new Enum[] {HandlesType.None, HandlesType.Label}); + Register(BGCurvePointField.TypeEnum.Int, new Enum[] {HandlesType.None, HandlesType.Label}); + Register(BGCurvePointField.TypeEnum.Float, new Enum[] {HandlesType.None, HandlesType.Label, HandlesType.DistanceFromPoint}); + Register(BGCurvePointField.TypeEnum.String, new Enum[] {HandlesType.None, HandlesType.Label}); + + Register(BGCurvePointField.TypeEnum.Vector3, new Enum[] {HandlesType.None, HandlesType.Label, HandlesType.Direction, HandlesType.BoundsAroundPoint}); + Register(BGCurvePointField.TypeEnum.Bounds, new Enum[] {HandlesType.None, HandlesType.Bounds}); + Register(BGCurvePointField.TypeEnum.Quaternion, new Enum[] {HandlesType.None, HandlesType.Rotation}); + Register(BGCurvePointField.TypeEnum.Color, new Enum[] {HandlesType.None, HandlesType.Label}); + + Register(BGCurvePointField.TypeEnum.GameObject, new Enum[] {HandlesType.None, HandlesType.Label, HandlesType.Link}); + Register(BGCurvePointField.TypeEnum.Component, new Enum[] {HandlesType.None, HandlesType.Label}); + + Register(BGCurvePointField.TypeEnum.BGCurve, new Enum[] {HandlesType.None, HandlesType.Link}); + Register(BGCurvePointField.TypeEnum.BGCurvePointComponent, new Enum[] {HandlesType.None, HandlesType.Label, HandlesType.Link}); + Register(BGCurvePointField.TypeEnum.BGCurvePointGO, new Enum[] {HandlesType.None, HandlesType.Label, HandlesType.Link}); + } + + private static void Register(BGCurvePointField.TypeEnum typeEnum, Enum[] handlesTypes) + { + Type2SupportHandles[typeEnum] = true; + Type2Handles[typeEnum] = handlesTypes; + } + + public PointField(BGCurvePointField field, int index, Texture2D deleteIcon) + { + this.field = field; + this.index = index; + this.deleteIcon = deleteIcon; + } + + public void Ui(TableUi ui) + { + var cursor = 0; + + // ========================== First row + //number + ui.NextColumn("" + index, "Field's index", GetWidth(ui, ref cursor)); + + //name + ui.NextColumn(rect => + { + BGEditorUtility.TextField(rect, field.FieldName, s => + { + if (NameHasError(field.Curve, s)) return; + Change(() => field.FieldName = s); + }, true); + }, GetWidth(ui, ref cursor)); + + //type + ui.NextColumn(field.Type.ToString(), "Field's Type", GetWidth(ui, ref cursor)); + + //show in Points menu + ui.NextColumn(rect => BGEditorUtility.BoolField(rect, BGPrivateField.GetShowInPointsMenu(field), b => Change(() => BGPrivateField.SetShowInPointsMenu(field, b))), + GetWidth(ui, ref cursor)); + + //delete icon + ui.NextColumn(rect => + { + if (!GUI.Button(rect, deleteIcon) || !BGEditorUtility.Confirm("Delete", "Are you sure you want to delete '" + field.FieldName + "' field?", "Delete")) return; + + BGPrivateField.Invoke(field.Curve, BGCurve.MethodDeleteField, field, (Action) Undo.DestroyObjectImmediate); + + GUIUtility.ExitGUI(); + }, GetWidth(ui, ref cursor)); + + //\r\n + ui.NextRow(); + + // ========================== Second row + //does not support + if (!SupportHandles(field.Type)) return; + + ui.NextColumn(" Handles", "Field's index", 25); + + //handles type + ui.NextColumn( + rect => BGEditorUtility.PopupField(rect, (HandlesType) BGPrivateField.GetHandlesType(field), Type2Handles[field.Type], + b => Change(() => BGPrivateField.SetHandlesType(field, (int) ((HandlesType) b)))), 30); + + //Handles color + ui.NextColumn(rect => BGEditorUtility.ColorField(rect, BGPrivateField.GetHandlesColor(field), b => Change(() => BGPrivateField.SetHandlesColor(field, b))), 30); + + //show handles in Scene View + ui.NextColumn(rect => BGEditorUtility.BoolField(rect, BGPrivateField.GetShowHandles(field), b => Change(() => BGPrivateField.SetShowHandles(field, b))), 5); + + //empty column under delete button + ui.NextColumn(rect => EditorGUI.LabelField(rect, ""), 10); + + //\r\n + ui.NextRow(); + } + + private void Change(Action action) + { + Undo.RecordObject(field, "Field change"); + action(); + EditorUtility.SetDirty(field); + } + + private static bool SupportHandles(BGCurvePointField.TypeEnum typeEnum) + { + return Type2SupportHandles.ContainsKey(typeEnum); + } + + private static int GetWidth(TableUi ui, ref int cursor) + { + var widthInPercent = ui.Sizes[cursor]; + cursor++; + return widthInPercent; + } + + public static void OnSceneGui(Plane[] frustum, BGCurve curve, BGCurveSettings settings, BGCurveEditorPointsSelection editorSelection) + { + Array.Resize(ref visiblePoints, curve.PointsCount); + curve.ForEach((point, i, count) => visiblePoints[i] = GeometryUtility.TestPlanesAABB(frustum, new Bounds(point.PositionWorld, Vector3.one))); + + + var fieldsCount = curve.FieldsCount; + var fields = curve.Fields; + var showPointsNumbers = settings.ShowLabels; + + var fieldsWithHandlesCount = 0; + var fieldsWithLabelCount = 0; + if (fieldsCount > 0) + { + fieldsWithHandlesCount = fields.Count(FieldWithHandlesPredicate); + if (fieldsWithHandlesCount > 0) + { + Array.Resize(ref handlesColor, fieldsWithHandlesCount); + var cursor = 0; + for (var i = 0; i < fieldsCount; i++) + { + var f = fields[i]; + if (!FieldWithHandlesPredicate(f)) continue; + + if (FieldWithLabelPredicate(f)) fieldsWithLabelCount++; + handlesColor[cursor++] = BGPrivateField.GetHandlesColor(f); + } + } + } + + // nothing to show + if (!showPointsNumbers && fieldsWithHandlesCount == 0) return; + + + if (fieldsWithHandlesCount > 0) + { + //not a label + curve.ForEach((point, i, length) => + { + if (!visiblePoints[i]) return; + + var pos = point.PositionWorld; + + var quanterionShown = false; + var fieldCursor = 0; + for (var j = 0; j < fields.Length; j++) + { + var field = fields[j]; + var handlesType = (HandlesType) BGPrivateField.GetHandlesType(field); + + if (handlesType == 0) continue; + + if (handlesType == HandlesType.Label) + { + fieldCursor++; + continue; + } + + var color = handlesColor[fieldCursor++]; + switch (handlesType) + { + case HandlesType.DistanceFromPoint: + BGEditorUtility.SwapHandlesColor(color, () => + Handles.CircleCap(0, pos, Quaternion.LookRotation(SceneView.currentDrawingSceneView.camera.transform.position - pos), point.GetField(field.FieldName))); + break; + case HandlesType.BoundsAroundPoint: + Bounds bounds; + switch (field.Type) + { + case BGCurvePointField.TypeEnum.Bounds: + bounds = point.GetField(field.FieldName); + bounds.center = pos; + break; + default: + //vector3 + var vector3 = point.GetField(field.FieldName); + bounds = new Bounds(pos, vector3); + break; + } + BGEditorUtility.DrawBound(bounds, new Color(color.r, color.g, color.b, 0.05f), color); + break; + case HandlesType.Bounds: + var boundsValue = point.GetField(field.FieldName); + if (boundsValue.extents != Vector3.zero) + { + BGEditorUtility.DrawBound(boundsValue, new Color(color.r, color.g, color.b, 0.05f), color); + BGEditorUtility.SwapHandlesColor(color, () => Handles.DrawDottedLine(boundsValue.center, pos, 4)); + } + break; + case HandlesType.Direction: + var vector3Value = point.GetField(field.FieldName); + if (vector3Value != Vector3.zero) + BGEditorUtility.SwapHandlesColor(color, () => Handles.ArrowCap(0, pos, Quaternion.LookRotation(vector3Value), vector3Value.magnitude)); + break; + case HandlesType.Rotation: + if (quanterionShown) break; + + quanterionShown = true; + + var quaternionValue = point.GetField(field.FieldName); + if (quaternionValue.x < BGCurve.Epsilon && quaternionValue.y < BGCurve.Epsilon && quaternionValue.z < BGCurve.Epsilon && quaternionValue.w < BGCurve.Epsilon) + quaternionValue = Quaternion.identity; + + var newValue = Handles.RotationHandle(quaternionValue, pos); + point.SetField(field.FieldName, newValue); + + + BGEditorUtility.SwapHandlesColor(color, () => + { + var rotated = newValue*Vector3.forward*BGEditorUtility.GetHandleSize(pos, 2); + var toPos = pos + rotated; + Handles.ArrowCap(0, toPos, newValue, 1); + Handles.DrawDottedLine(pos, toPos, 10); + }); + break; + case HandlesType.Link: + switch (field.Type) + { + case BGCurvePointField.TypeEnum.GameObject: + var go = point.GetField(field.FieldName); + if (go != null) BGEditorUtility.SwapHandlesColor(color, () => Handles.DrawDottedLine(go.transform.position, pos, 4)); + break; + case BGCurvePointField.TypeEnum.BGCurve: + var bgCurve = point.GetField(field.FieldName); + if (bgCurve != null) BGEditorUtility.SwapHandlesColor(color, () => Handles.DrawDottedLine(bgCurve.transform.position, pos, 4)); + break; + case BGCurvePointField.TypeEnum.BGCurvePointComponent: + var pointComponent = point.GetField(field.FieldName); + if (pointComponent != null) BGEditorUtility.SwapHandlesColor(color, () => Handles.DrawDottedLine(pointComponent.PositionWorld, pos, 4)); + break; + case BGCurvePointField.TypeEnum.BGCurvePointGO: + var pointGO = point.GetField(field.FieldName); + if (pointGO != null) BGEditorUtility.SwapHandlesColor(color, () => Handles.DrawDottedLine(pointGO.PositionWorld, pos, 4)); + break; + } + break; + } + } + }); + } + + // nothing more to show + if (!showPointsNumbers && fieldsWithLabelCount == 0) return; + + //=============================== Labels + + //styles + var labelColor = settings.LabelColor; + var selectedColor = settings.LabelColorSelected; + var backColor = BGCurveSettingsForEditor.ColorForLabelBackground; + + if (labelStyle == null || labelStyle.normal.textColor != labelColor || labelStyle.normal.background == null + || latestLabelBackColor.r != backColor.r || latestLabelBackColor.g != backColor.g || latestLabelBackColor.b != backColor.b || latestLabelBackColor.a != backColor.a) + { + latestLabelBackColor = backColor; + labelStyle = new GUIStyle("Label") + { + richText = true, + border = new RectOffset(2, 2, 2, 2), + clipping = TextClipping.Overflow, + wordWrap = false, + normal = + { + background = BGEditorUtility.TextureWithBorder(8, 1, backColor, new Color32(backColor.r, backColor.g, backColor.b, 255)), + textColor = labelColor + } + }; + + selectedlabelStyle = new GUIStyle(labelStyle) + { + normal = + { + background = BGEditorUtility.TextureWithBorder(8, 1, new Color(selectedColor.r, selectedColor.g, selectedColor.b, .1f), selectedColor), + textColor = selectedColor + } + }; + } + + + curve.ForEach((point, i, length) => + { + if (!visiblePoints[i]) return; + + var pos = point.PositionWorld; + + var style = !editorSelection.Contains(point) ? labelStyle : selectedlabelStyle; + var text = ""; + + //point numbers and pos + if (showPointsNumbers) + { + text += "# : " + i + "\r\n"; + if (settings.ShowPositions) text += "P : " + pos + "\r\n"; + } + + //fields + if (fieldsWithLabelCount > 0) + { + for (var j = 0; j < fieldsCount; j++) + { + var field = fields[j]; + if (!FieldWithHandlesPredicate(field) || !FieldWithLabelPredicate(field)) continue; + + text += BGEditorUtility.ColorIt(curve.IndexOf(field) + " : " + point.GetField(field.FieldName, BGCurvePoint.FieldTypes.GetType(field.Type)), + BGEditorUtility.ToHex(BGPrivateField.GetHandlesColor(field))) + "\r\n"; + } + } + + var normalized = (SceneView.currentDrawingSceneView.camera.transform.position - pos).normalized; + var handleSize = BGEditorUtility.GetHandleSize(pos, .25f); + var shiftLeft = -Vector3.Cross(normalized, Vector3.up); + var shiftBottom = Vector3.Cross(normalized, Vector3.right)*.3f; + Handles.Label(pos + handleSize*shiftLeft + handleSize*shiftBottom, text.Substring(0, text.Length - 2), style); + }); + } + } + + //=========================================================================================== Abstract system field + private abstract class SystemField + { + protected readonly BGCurveSettings Settings; + + public virtual bool ShowInPointsMenu { get; set; } + + private readonly GUIContent title; + + protected SystemField(BGCurveSettings settings, GUIContent title) + { + this.title = title; + Settings = settings; + } + + public virtual void Ui(TableUi ui) + { + ui.NextColumn(rect => EditorGUI.LabelField(rect, title), 100, true); + ui.NextRow(); + + // show in point menu + NextBoolRow(ui, "Show in Points Menu", "Show in Points Menu (Points Tab)", ShowInPointsMenu, newValue => ShowInPointsMenu = newValue); + } + + protected void NextBoolRow(TableUi ui, string label, string tooltip, bool value, Action valueSetter) + { + ui.NextColumn(label, tooltip); + ui.NextColumn(rect => BGEditorUtility.ToggleField(rect, value, valueSetter)); + ui.NextRow(); + } + + protected void NextEnumRow(TableUi ui, string label, string tooltip, Enum value, Action valueSetter) + { + ui.NextColumn(label, tooltip); + ui.NextColumn(rect => BGEditorUtility.PopupField(rect, value, valueSetter)); + ui.NextRow(); + } + + protected void NextSliderRow(TableUi ui, string label, string tooltip, float value, float from, float to, Action valueSetter) + { + ui.NextColumn(label, tooltip); + ui.NextColumn(rect => BGEditorUtility.SliderField(rect, value, @from, to, valueSetter)); + ui.NextRow(); + } + + protected void NextColorRow(TableUi ui, string label, string tooltip, Color color, Action func) + { + ui.NextColumn(label, tooltip); + ui.NextColumn(rect => BGEditorUtility.ColorField(rect, color, func)); + ui.NextRow(); + } + } + + //=========================================================================================== Abstract Vector(s) Based Field + private abstract class SystemVectorField : SystemField + { + public virtual bool ShowHandles { get; set; } + + public virtual BGCurveSettings.HandlesTypeEnum HandlesType { get; set; } + + public virtual BGCurveSettings.SettingsForHandles HandlesSettings + { + get { return null; } + } + + public virtual bool ShowLabels { get; set; } + public virtual bool ShowPositions { get; set; } + public virtual Color LabelColor { get; set; } + + protected SystemVectorField(BGCurveSettings settings, GUIContent title) + : base(settings, title) + { + } + + private void Next3BoolRow(TableUi ui, string label, string tooltip, + string xLabel, string yLabel, string zLabel, + bool xValue, bool yValue, bool zValue, + Action xSetter, Action ySetter, Action zSetter) + { + ui.NextColumn(label, tooltip); + const int widthInPercent = (100 - LabelWidth)/3; + ui.NextColumn(xLabel, rect => BGEditorUtility.ToggleField(rect, xValue, xSetter), widthInPercent, ui.CenteredLabelStyle); + ui.NextColumn(yLabel, rect => BGEditorUtility.ToggleField(rect, yValue, ySetter), widthInPercent, ui.CenteredLabelStyle); + ui.NextColumn(zLabel, rect => BGEditorUtility.ToggleField(rect, zValue, zSetter), widthInPercent, ui.CenteredLabelStyle); + ui.NextRow(); + } + + public override void Ui(TableUi ui) + { + base.Ui(ui); + + NextBoolRow(ui, "Show Handles", "Show handles in Scene View", ShowHandles, newValue => ShowHandles = newValue); + if (ShowHandles) + { + NextEnumRow(ui, " Handles Types", "Type for the handle", HandlesType, newValue => HandlesType = (BGCurveSettings.HandlesTypeEnum) newValue); + + if (HandlesType == BGCurveSettings.HandlesTypeEnum.Configurable) + { + NextSliderRow(ui, " Handles Axis Size", "Size of the Axis handles in Scene View", HandlesSettings.AxisScale, .5f, 1.5f, newValue => HandlesSettings.AxisScale = newValue); + NextSliderRow(ui, " Handles Plane Size", "Size of the Plane handles in Scene View", HandlesSettings.PlanesScale, .5f, 1.5f, + newValue => HandlesSettings.PlanesScale = newValue); + NextSliderRow(ui, " Handles Alpha", "Alpha color of handles in Scene View", HandlesSettings.Alpha, .5f, 1f, newValue => HandlesSettings.Alpha = newValue); + + Next3BoolRow(ui, " Remove Axis", "Remove Axis handles", + "X", "Y", "Z", + HandlesSettings.RemoveX, HandlesSettings.RemoveY, HandlesSettings.RemoveZ, + newValue => HandlesSettings.RemoveX = newValue, newValue => HandlesSettings.RemoveY = newValue, newValue => HandlesSettings.RemoveZ = newValue + ); + + Next3BoolRow(ui, " Remove Planes", "Remove Planes handles", + "XZ", "XY", "YZ", + HandlesSettings.RemoveXZ, HandlesSettings.RemoveXY, HandlesSettings.RemoveYZ, + newValue => HandlesSettings.RemoveXZ = newValue, newValue => HandlesSettings.RemoveXY = newValue, newValue => HandlesSettings.RemoveYZ = newValue + ); + } + } + + NextBoolRow(ui, "Show Labels", "Show labels in Scene View", ShowLabels, newValue => ShowLabels = newValue); + if (ShowLabels) + { + NextBoolRow(ui, " Show Positions", "Show vector positions in Scene View", ShowPositions, newValue => ShowPositions = newValue); + NextColorRow(ui, " Labels color", "Color for labels in Scene View", LabelColor, newValue => LabelColor = newValue); + AdditionalLabelFields(ui); + } + } + + protected virtual void AdditionalLabelFields(TableUi ui) + { + } + } + + //=========================================================================================== Position + private sealed class SystemFieldPosition : SystemVectorField + { + public override bool ShowHandles + { + get { return Settings.ShowHandles; } + set { Settings.ShowHandles = value; } + } + + public override BGCurveSettings.SettingsForHandles HandlesSettings + { + get { return Settings.HandlesSettings; } + } + + public override BGCurveSettings.HandlesTypeEnum HandlesType + { + get { return Settings.HandlesType; } + set { Settings.HandlesType = value; } + } + + public override bool ShowInPointsMenu + { + get { return Settings.ShowPointPosition; } + set { Settings.ShowPointPosition = value; } + } + + public override bool ShowLabels + { + get { return Settings.ShowLabels; } + set { Settings.ShowLabels = value; } + } + + public override bool ShowPositions + { + get { return Settings.ShowPositions; } + set { Settings.ShowPositions = value; } + } + + public override Color LabelColor + { + get { return Settings.LabelColor; } + set { Settings.LabelColor = value; } + } + + private Color LabelColorSelected + { + get { return Settings.LabelColorSelected; } + set { Settings.LabelColorSelected = value; } + } + + private bool ShowSpheres + { + get { return Settings.ShowSpheres; } + set { Settings.ShowSpheres = value; } + } + + private float SpheresRadius + { + get { return Settings.SphereRadius; } + set { Settings.SphereRadius = value; } + } + + private Color SpheresColor + { + get { return Settings.SphereColor; } + set { Settings.SphereColor = value; } + } + + public SystemFieldPosition(BGCurveSettings settings) + : base(settings, new GUIContent("Positions", "Point's positions")) + { + } + + protected override void AdditionalLabelFields(TableUi ui) + { + NextColorRow(ui, "Labels color for selected", "Color for labels in Scene View, when they are selected", LabelColorSelected, newValue => LabelColorSelected = newValue); + } + + public override void Ui(TableUi ui) + { + base.Ui(ui); + + NextBoolRow(ui, "Show spheres", "Show spheres at points positions in Scene View", ShowSpheres, b => ShowSpheres = b); + if (ShowSpheres) + { + NextSliderRow(ui, " Sphere radius", "Sphere radius in Scene View", SpheresRadius, .01f, 1, f => SpheresRadius = f); + NextColorRow(ui, " Sphere color", "Sphere color in Scene View", SpheresColor, f => SpheresColor = f); + } + } + } + + //=========================================================================================== Controls + private sealed class SystemFieldControls : SystemVectorField + { + public override bool ShowHandles + { + get { return Settings.ShowControlHandles; } + set { Settings.ShowControlHandles = value; } + } + + public override BGCurveSettings.HandlesTypeEnum HandlesType + { + get { return Settings.ControlHandlesType; } + set { Settings.ControlHandlesType = value; } + } + + + public override BGCurveSettings.SettingsForHandles HandlesSettings + { + get { return Settings.ControlHandlesSettings; } + } + + public override bool ShowInPointsMenu + { + get { return Settings.ShowPointControlPositions; } + set { Settings.ShowPointControlPositions = value; } + } + + public override bool ShowLabels + { + get { return Settings.ShowControlLabels; } + set { Settings.ShowControlLabels = value; } + } + + public override bool ShowPositions + { + get { return Settings.ShowControlPositions; } + set { Settings.ShowControlPositions = value; } + } + + private Color HandlesColor + { + get { return Settings.ControlHandlesColor; } + set { Settings.ControlHandlesColor = value; } + } + + public override Color LabelColor + { + get { return Settings.LabelControlColor; } + set { Settings.LabelControlColor = value; } + } + + + public SystemFieldControls(BGCurveSettings settings) + : base(settings, new GUIContent("Controls", "Point's Bezier control positions")) + { + } + + public override void Ui(TableUi ui) + { + base.Ui(ui); + + NextColorRow(ui, "Handles Color", "Color of handles in Scene View", HandlesColor, newValue => HandlesColor = newValue); + } + } + + + //=========================================================================================== Control Type + private sealed class SystemFieldControlsType : SystemField + { + public override bool ShowInPointsMenu + { + get { return Settings.ShowPointControlType; } + set { Settings.ShowPointControlType = value; } + } + + public SystemFieldControlsType(BGCurveSettings settings) + : base(settings, new GUIContent("Control Type", "Point's control type (Absent, Bezier)")) + { + } + } + + //=========================================================================================== Transform Field + private sealed class SystemFieldTransform : SystemField + { + public override bool ShowInPointsMenu + { + get { return Settings.ShowTransformField; } + set { Settings.ShowTransformField = value; } + } + + public SystemFieldTransform(BGCurveSettings settings) + : base(settings, new GUIContent("Transform", "Transform to use as point's position")) + { + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorFields.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorFields.cs.meta new file mode 100644 index 0000000..6b40990 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorFields.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7939caedfb503f9489e4f0524336a58b +timeCreated: 1471761766 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoint.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoint.cs new file mode 100644 index 0000000..a5c7938 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoint.cs @@ -0,0 +1,526 @@ +using System; +using System.Linq; +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + //one single point's GUI + public class BGCurveEditorPoint + { + private readonly Texture2D deleteTexture; + private readonly Texture2D addBeforeTexture; + private readonly Texture2D moveUpTexture; + private readonly Texture2D moveDownTexture; + private readonly Texture2D copyTexture; + private readonly Texture2D pasteTexture; + + private readonly BGCurveEditorPointsSelection editorSelection; + private readonly Func mathProvider; + + private GUIStyle controlLabelStyle; + + public BGCurveEditorPoint(Func mathProvider, BGCurveEditorPointsSelection editorSelection) + { + this.mathProvider = mathProvider; + this.editorSelection = editorSelection; + + //textures + deleteTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGDelete123); + addBeforeTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGAdd123); + moveUpTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGMoveUp123); + moveDownTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGMoveDown123); + copyTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGCopy123); + pasteTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGPaste123); + } + + internal void OnInspectorGui(BGCurvePointI point, int index, BGCurveSettings settings) + { + var mode2D = point.Curve.Mode2D; + + + //point transform + if (point.Curve.PointsMode != BGCurve.PointsModeEnum.Inlined && point.PointTransform != null) + { + var referenceToPoint = BGCurveReferenceToPoint.GetReferenceToPoint(point); + if (referenceToPoint == null) point.PointTransform.gameObject.AddComponent().Point = point; + } + + BGEditorUtility.HorizontalBox(() => + { + if (editorSelection != null) editorSelection.InspectorSelectionRect(point); + + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.SwapLabelWidth(60, () => + { + if (!settings.ShowPointPosition && !settings.ShowPointControlType) + { + BGEditorUtility.Horizontal(() => + { + //nothing to show- only label + EditorGUILayout.LabelField("Point " + index); + PointButtons(point, index, settings); + }); + BGEditorUtility.StartIndent(1); + } + else + { + //control type + if (settings.ShowPointControlType) + { + BGEditorUtility.Horizontal(() => + { + point.ControlType = (BGCurvePoint.ControlTypeEnum) EditorGUILayout.EnumPopup("Point " + index, point.ControlType); + PointButtons(point, index, settings); + }); + BGEditorUtility.StartIndent(1); + } + + //position + if (settings.ShowPointPosition) + { + if (!settings.ShowPointControlType) + { + BGEditorUtility.Horizontal(() => + { + PositionField("Point " + index, point, mode2D, index); + PointButtons(point, index, settings); + }); + BGEditorUtility.StartIndent(1); + } + else PositionField("Pos", point, mode2D, index); + } + } + }); + + // control positions + if (point.ControlType != BGCurvePoint.ControlTypeEnum.Absent && settings.ShowPointControlPositions) + { + // 1st + ControlField(point, mode2D, 1); + + // 2nd + ControlField(point, mode2D, 2); + } + + //transform + if (settings.ShowTransformField) + BGEditorUtility.ComponentField("Transform", point.PointTransform, transform => + { + if (transform != null) + { + Undo.RecordObject(transform, "Object moved"); + + if (point.Curve.PointsMode != BGCurve.PointsModeEnum.Inlined) Undo.AddComponent(transform.gameObject).Point = point; + } + + if (point.PointTransform != null) + { + var referenceToPoint = BGCurveReferenceToPoint.GetReferenceToPoint(point); + if (referenceToPoint != null) Undo.DestroyObjectImmediate(referenceToPoint); + } + + point.PointTransform = transform; + }); + + + //fields + if (point.Curve.FieldsCount > 0) ShowFields(point); + + BGEditorUtility.EndIndent(1); + }); + }); + } + + private void ControlField(BGCurvePointI point, BGCurve.Mode2DEnum mode2D, int index) + { + Vector3 pos; + string tooltipDetails, details; + Action newValueAction; + switch (BGCurveSettingsForEditor.InspectorControlCoordinateSpace) + { + case BGCurveSettingsForEditor.CoordinateSpaceEnum.Local: + tooltipDetails = "local"; + details = "L"; + if (index == 1) + { + pos = point.ControlFirstLocal; + newValueAction = vector3 => point.ControlFirstLocal = vector3; + } + else + { + pos = point.ControlSecondLocal; + newValueAction = vector3 => point.ControlSecondLocal = vector3; + } + break; + case BGCurveSettingsForEditor.CoordinateSpaceEnum.LocalTransformed: + tooltipDetails = "local transformed"; + details = "LT"; + + if (index == 1) + { + pos = point.ControlFirstLocalTransformed; + newValueAction = vector3 => point.ControlFirstLocalTransformed = vector3; + } + else + { + pos = point.ControlSecondLocalTransformed; + newValueAction = vector3 => point.ControlSecondLocalTransformed = vector3; + } + break; + case BGCurveSettingsForEditor.CoordinateSpaceEnum.World: + tooltipDetails = "world"; + details = "W"; + + if (index == 1) + { + pos = point.ControlFirstWorld; + newValueAction = vector3 => point.ControlFirstWorld = vector3; + } + else + { + pos = point.ControlSecondWorld; + newValueAction = vector3 => point.ControlSecondWorld = vector3; + } + break; + default: + throw new ArgumentOutOfRangeException("BGCurveSettingsForEditor.InspectorPointControlsCoordinates"); + } + + var label = "Control " + index + " (" + details + ")"; + var tooltip = "Point " + (index == 0 ? "1st" : "2nd") + " control position in " + tooltipDetails + " space. You can change points space in BGCurve Editor settings (gear icon)"; + + + + if (mode2D == BGCurve.Mode2DEnum.Off) BGEditorUtility.Vector3Field(label, tooltip, pos, newValueAction); + else Vector2Field(label, tooltip, pos, mode2D, newValueAction); + + } + + private void PositionField(string name, BGCurvePointI point, BGCurve.Mode2DEnum mode2D, int index) + { + var math = mathProvider(); + + Vector3 pos; + Action newValueAction; + string tooltipDetails; + string details; + switch (BGCurveSettingsForEditor.InspectorPointCoordinateSpace) + { + case BGCurveSettingsForEditor.CoordinateSpaceEnum.World: + pos = math == null ? point.PositionWorld : math.GetPosition(index); + newValueAction = vector3 => point.PositionWorld = vector3; + tooltipDetails = "world"; + details = "W"; + break; + case BGCurveSettingsForEditor.CoordinateSpaceEnum.LocalTransformed: + pos = point.PositionLocalTransformed; + newValueAction = vector3 => point.PositionLocalTransformed = vector3; + tooltipDetails = "local transformed"; + details = "LT"; + break; + case BGCurveSettingsForEditor.CoordinateSpaceEnum.Local: + pos = point.PositionLocal; + newValueAction = vector3 => point.PositionLocal = vector3; + tooltipDetails = "local"; + details = "L"; + break; + default: + throw new ArgumentOutOfRangeException("BGCurveSettingsForEditor.InspectorPointCoordinates"); + } + + BGEditorUtility.SwapLabelWidth(80, () => + { + var label = name + "(" + details + ")"; + var tooltip = "Point's position in " + tooltipDetails + " space. You can change points space in BGCurve Editor settings (gear icon)"; + + if (mode2D == BGCurve.Mode2DEnum.Off) BGEditorUtility.Vector3Field(label, tooltip, pos, newValueAction); + else Vector2Field(label, tooltip, pos, mode2D, newValueAction); + }); + } + + private void Vector2Field(string label, string tooltip, Vector3 value, BGCurve.Mode2DEnum mode2D, Action newValueAction) + { + Vector2 val; + switch (mode2D) + { + case BGCurve.Mode2DEnum.XY: + val = value; + break; + case BGCurve.Mode2DEnum.XZ: + val = new Vector2(value.x, value.z); + break; + case BGCurve.Mode2DEnum.YZ: + val = new Vector2(value.y, value.z); + break; + default: + throw new ArgumentOutOfRangeException("mode2D", mode2D, null); + } + + BGEditorUtility.Vector2Field(label, tooltip, val, vector2 => + { + Vector3 newValue; + switch (mode2D) + { + case BGCurve.Mode2DEnum.XY: + newValue = vector2; + break; + case BGCurve.Mode2DEnum.XZ: + newValue = new Vector3(vector2.x, 0, vector2.y); + break; + case BGCurve.Mode2DEnum.YZ: + newValue = new Vector3(0, vector2.x, vector2.y); + break; + default: + throw new ArgumentOutOfRangeException("mode2D", mode2D, null); + } + newValueAction(newValue); + }); + } + + + private static void ShowFields(BGCurvePointI point) + { + foreach (var field in point.Curve.Fields.Where(BGPrivateField.GetShowInPointsMenu)) ShowField(point, field); + } + + public static void ShowField(BGCurvePointI point, BGCurvePointField field, Action animationCurveCallback = null) + { + var name = point.Curve.IndexOf(field) + ") " + field.FieldName; + switch (field.Type) + { + case BGCurvePointField.TypeEnum.Bool: + BGEditorUtility.BoolField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.Int: + BGEditorUtility.IntField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.Float: + BGEditorUtility.FloatField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.Vector3: + BGEditorUtility.Vector3Field(name, null, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.Bounds: + BGEditorUtility.BoundsField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.Color: + BGEditorUtility.ColorField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.String: + BGEditorUtility.TextField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v), false); + break; + case BGCurvePointField.TypeEnum.AnimationCurve: + BGEditorUtility.Horizontal(() => + { + BGEditorUtility.AnimationCurveField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + + if (animationCurveCallback != null && GUILayout.Button("Set", GUILayout.Width(40))) animationCurveCallback(field.FieldName, point.GetField(field.FieldName)); + }); + + break; + case BGCurvePointField.TypeEnum.Quaternion: + BGEditorUtility.QuaternionField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.GameObject: + BGEditorUtility.GameObjectField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.Component: + BGEditorUtility.ComponentChoosableField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.BGCurve: + BGEditorUtility.BGCurveField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + case BGCurvePointField.TypeEnum.BGCurvePointComponent: + BGEditorUtility.Horizontal(() => + { + BGEditorUtility.BGCurvePointComponentField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + var currentPoint = point.GetField(field.FieldName); + + if (currentPoint == null || currentPoint.Curve.PointsCount < 2) return; + + var indexOfField = currentPoint.Curve.IndexOf(currentPoint); + + if (GUILayout.Button("" + indexOfField, GUILayout.Width(40))) BGCurveChosePointWindow.Open(indexOfField, currentPoint.Curve, c => point.SetField(field.FieldName, c)); + }); + break; + case BGCurvePointField.TypeEnum.BGCurvePointGO: + BGEditorUtility.BGCurvePointGOField(name, point.GetField(field.FieldName), v => point.SetField(field.FieldName, v)); + break; + } + } + + + private void PointButtons(BGCurvePointI point, int index, BGCurveSettings settings) + { + if (!settings.ShowPointMenu) return; + + var curve = point.Curve; + + //================== Copy + if (BGEditorUtility.ButtonWithIcon(copyTexture, PointCopyPaste.Instance.CopyTooltip)) PointCopyPaste.Instance.Copy(point); + GUILayout.Space(2); + + //================== Paste + if (BGEditorUtility.ButtonWithIcon(pasteTexture, PointCopyPaste.Instance.PasteTooltip)) PointCopyPaste.Instance.Paste(point); + GUILayout.Space(2); + + //================== Add before + if (BGEditorUtility.ButtonWithIcon(addBeforeTexture, "Insert a point before this point")) + BGCurveEditor.AddPoint(curve, BGNewPointPositionManager.InsertBefore(curve, index, settings.ControlType, settings.Sections), index); + GUILayout.Space(2); + + + //=========================== Move Up + if (index > 0 && BGEditorUtility.ButtonWithIcon(moveUpTexture, "Move the point up")) curve.Swap(index - 1, index); + GUILayout.Space(2); + + //=========================== Move Down + if (index < curve.PointsCount - 1 && BGEditorUtility.ButtonWithIcon(moveDownTexture, "Move the point down")) curve.Swap(index, index + 1); + GUILayout.Space(2); + + + //=========================== Delete + if (BGEditorUtility.ButtonWithIcon(deleteTexture, "Delete the point")) + { + BGCurveEditor.DeletePoint(curve, index); + if (editorSelection != null) editorSelection.Remove(point); + GUIUtility.ExitGUI(); + } + } + + + public void OnSceneGUI(BGCurvePointI point, int index, BGCurveSettings settings, Quaternion rotation, Plane[] frustum) + { + var math = mathProvider(); + var positionWorld = math == null ? point.Curve[index].PositionWorld : math.GetPosition(index); + + //adjust rotation + if (point.PointTransform != null) rotation = BGCurveEditorPoints.GetRotation(point.PointTransform); + else if (point.Curve.PointsMode == BGCurve.PointsModeEnum.GameObjectsTransform) rotation = BGCurveEditorPoints.GetRotation(((BGCurvePointGO) point).transform); + + if (settings.ShowControlHandles && settings.ShowCurve && (editorSelection == null || !editorSelection.HasSelected() || editorSelection.SingleSelected(point))) + { + // ============================================== Controls Handles + if (point.ControlType != BGCurvePoint.ControlTypeEnum.Absent) + { + var controlFirstWorld = math == null ? point.Curve[index].ControlFirstWorld : math.GetControlFirst(index); + var controlSecondWorld = math == null ? point.Curve[index].ControlSecondWorld : math.GetControlSecond(index); + + BGEditorUtility.SwapHandlesColor(settings.ControlHandlesColor, () => + { + Handles.DrawLine(positionWorld, controlFirstWorld); + Handles.DrawLine(positionWorld, controlSecondWorld); + + if (ShowingHandles) + { + // control handles different types + var newPositionFirst = BGEditorUtility.Handle(GetUniqueNumber(index) - 1, settings.ControlHandlesType, controlFirstWorld, rotation, settings.ControlHandlesSettings); + var newPositionSecond = BGEditorUtility.Handle(GetUniqueNumber(index) - 2, settings.ControlHandlesType, controlSecondWorld, rotation, settings.ControlHandlesSettings); + + if (BGEditorUtility.AnyChange(controlFirstWorld, newPositionFirst)) point.ControlFirstWorld = newPositionFirst; + if (BGEditorUtility.AnyChange(controlSecondWorld, newPositionSecond)) point.ControlSecondWorld = newPositionSecond; + } + }); + + if (settings.ShowControlLabels) + { + ShowControlLabel(settings, frustum, controlFirstWorld, point.ControlFirstLocal, "1"); + ShowControlLabel(settings, frustum, controlSecondWorld, point.ControlSecondLocal, "2"); + } + } + } + + //if only one point is selected and this is the selected point- do not print anything further + if (editorSelection != null && editorSelection.HasSelected() && editorSelection.SingleSelected(point)) return; + + // ============================================== Move Handles + if ((editorSelection == null || !editorSelection.HasSelected()) && settings.ShowCurve && settings.ShowHandles && ShowingHandles) + { + var newPos = BGEditorUtility.Handle(GetUniqueNumber(index), settings.HandlesType, positionWorld, rotation, settings.HandlesSettings); + + if (BGEditorUtility.AnyChange(positionWorld, newPos)) point.PositionWorld = newPos; + } + } + + private static bool ShowingHandles + { + get { return Tools.current != Tool.View; } + } + + private void ShowControlLabel(BGCurveSettings settings, Plane[] frustum, Vector3 positionWorld, Vector3 positionLocal, string label) + { + BGEditorUtility.Assign(ref controlLabelStyle, () => new GUIStyle("Label") {normal = new GUIStyleState {textColor = settings.LabelControlColor}}); + + if (GeometryUtility.TestPlanesAABB(frustum, new Bounds(positionWorld, Vector3.one))) + Handles.Label(positionWorld, label + (settings.ShowControlPositions ? " " + positionLocal : ""), controlLabelStyle); + } + + + //this is to generate Unity UGUI ids (for handles). + private static int GetUniqueNumber(int index) + { + return (-index - 1)*3; + } + + private sealed class PointCopyPaste + { + public static readonly PointCopyPaste Instance = new PointCopyPaste(); + + public readonly string CopyTooltip = "Copy " + + "\r\n1) ControlType, " + + "\r\n2) Position (Local), " + + "\r\n3) Control1 (LocalTransformed), " + + "\r\n4) Control2 (LocalTransformed), " + + "\r\n5) PointTransform"; + + public string PasteTooltip; + + private BGCurvePoint.ControlTypeEnum controlType; + private Vector3 positionLocal; + private Vector3 control1LocalTransformed; + private Vector3 control2LocalTransformed; + private Transform pointTransform; + + private PointCopyPaste() + { + InitPasteTooltip(); + } + + public void Copy(BGCurvePointI point) + { + controlType = point.ControlType; + positionLocal = point.PositionLocal; + control1LocalTransformed = point.ControlFirstLocalTransformed; + control2LocalTransformed = point.ControlSecondLocalTransformed; + pointTransform = point.PointTransform; + + InitPasteTooltip(); + } + + private void InitPasteTooltip() + { + PasteTooltip = "Paste " + + "\r\n1) ControlType=" + controlType + + "\r\n2) Position (Local)=" + positionLocal + + "\r\n3) Control1 (LocalTransformed)=" + control1LocalTransformed + + "\r\n4) Control2 (LocalTransformed)=" + control2LocalTransformed + + "\r\n5) PointTransform=" + pointTransform; + } + + public void Paste(BGCurvePointI point) + { + point.Curve.Transaction(() => + { + point.ControlType = controlType; + point.PositionLocal = positionLocal; + point.ControlFirstLocalTransformed = control1LocalTransformed; + point.ControlSecondLocalTransformed = control2LocalTransformed; + point.PointTransform = pointTransform; + }); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoint.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoint.cs.meta new file mode 100644 index 0000000..780b617 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoint.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b3d23774d53900447be90cd0a79f7bed +timeCreated: 1458524671 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoints.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoints.cs new file mode 100644 index 0000000..2c37ccd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoints.cs @@ -0,0 +1,538 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + //GUI for all points + public class BGCurveEditorPoints : BGCurveEditorTab + { + // ====================================== Static const + private static readonly Color32 HiddenPointMenuColor = new Color32(144, 195, 212, 255); + + private static readonly GUIContent[] XZLabels = {new GUIContent("X"), new GUIContent("Z")}; + private static readonly GUIContent[] YZLabels = {new GUIContent("Y"), new GUIContent("Z")}; + + // ====================================== Fields + private readonly Texture2D convertAll2D; + private readonly Texture2D addPointIcon; + + private readonly SerializedProperty closedProperty; + private readonly SerializedProperty pointsModeProperty; + private readonly SerializedProperty controlTypeProperty; + private readonly SerializedProperty mode2DProperty; + private readonly SerializedProperty snapTypeProperty; + private readonly SerializedProperty snapDistanceProperty; + private readonly SerializedProperty snapAxisProperty; + private readonly SerializedProperty snapTriggerInteractionProperty; + private readonly SerializedProperty snapToBackFacesProperty; + private readonly SerializedProperty eventModeProperty; + private readonly SerializedProperty forceChangedEventModeProperty; + + //point + private readonly BGCurveEditorPoint editorPoint; + //painting a curve in the scene + private BGCurvePainterGizmo painter; + + private readonly BGSceneViewOverlay overlay; + private readonly BGCurveEditorPointsSelection editorSelection; + private readonly SerializedObject serializedObject; + private readonly List pointTransformTrackers = new List(); + + private GUIContent syncContent; + + + public BGCurveEditorPoints(BGCurveEditor editor, SerializedObject serializedObject, BGCurveEditorPointsSelection editorSelection) + : base(editor, serializedObject, BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGPoints123)) + { + this.serializedObject = serializedObject; + this.editorSelection = editorSelection; + + //textures + convertAll2D = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGConvertAll123); + addPointIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGAdd123); + + //point + editorPoint = new BGCurveEditorPoint(() => Editor.Math, editorSelection); + + //closed or not + closedProperty = serializedObject.FindProperty("closed"); + + //how points are stored + pointsModeProperty = serializedObject.FindProperty("pointsMode"); + + //2d mode + mode2DProperty = serializedObject.FindProperty("mode2D"); + + //snapping + snapTypeProperty = serializedObject.FindProperty("snapType"); + snapAxisProperty = serializedObject.FindProperty("snapAxis"); + snapDistanceProperty = serializedObject.FindProperty("snapDistance"); + snapTriggerInteractionProperty = serializedObject.FindProperty("snapTriggerInteraction"); + snapToBackFacesProperty = serializedObject.FindProperty("snapToBackFaces"); + + //force update + forceChangedEventModeProperty = serializedObject.FindProperty("forceChangedEventMode"); + + //event type + eventModeProperty = serializedObject.FindProperty("eventMode"); + + //settings + controlTypeProperty = serializedObject.FindProperty("settings").FindPropertyRelative("controlType"); + + //Context menu + overlay = new BGSceneViewOverlay(this, editorSelection); + + //for GameObjects points which use transforms + UpdatePointsTrackers(); + } + + + // ================================================================================ Inspector + public override void OnInspectorGui() + { + var settings = Settings; + + editorSelection.Reset(); + + // ======================================== Top section + InspectorTopSection(); + + // ======================================== Points + GUILayout.Space(5); + + if (Curve.PointsCount > 0) + { + BGEditorUtility.VerticalBox(() => + { + var temp = BGCurveSettingsForEditor.DisableInspectorPointMenu; + BGCurveSettingsForEditor.DisableInspectorPointMenu = BGEditorUtility.ButtonOnOff(ref temp, "Points menu [" + Curve.PointsCount + "]", "Show points in Editor inspector", + HiddenPointMenuColor, + new GUIContent("Show", "Click to show points menu"), + new GUIContent("Hide", "Click to hide points menu"), () => + { + const string title = "Reverse points"; + + if (!GUILayout.Button(new GUIContent(title, "Reverse all points, but keep curve intact"))) return; + + if (Curve.PointsCount < 2) + { + BGEditorUtility.Inform(title, "There should be at least 2 points. Curve has " + Curve.PointsCount); + return; + } + if (!BGEditorUtility.Confirm(title, "Are you sure you want to reverse the order of " + Curve.PointsCount + " points? Curve will remain intact.", "Reverse")) return; + + Curve.Reverse(); + }); + + //show points! + if (!BGCurveSettingsForEditor.DisableInspectorPointMenu) + SwapVector2Labels(Curve.Mode2D, () => Curve.ForEach((point, index, count) => editorPoint.OnInspectorGui(point, index, settings))); + }); + + // ======================================== Selections operations + editorSelection.InspectorSelectionOperations(); + + //warning + BGEditorUtility.HelpBox("Selection mode is on", MessageType.Warning, !editorSelection.Changed && editorSelection.HasSelected()); + } + else + { + BGEditorUtility.HorizontalBox(() => + { + EditorGUILayout.LabelField("No points!"); + + if (BGEditorUtility.ButtonWithIcon(addPointIcon, "Add new point at (0,0,0) local coordinates")) + BGCurveEditor.AddPoint(Curve, new BGCurvePoint(Curve, Vector3.zero, settings.ControlType, Vector3.right, Vector3.left), 0); + }); + } + + if (!editorSelection.Changed) return; + + Editor.Repaint(); + SceneView.RepaintAll(); + } + + + private void InspectorTopSection() + { + if (Curve.PointsCount == 0) + EditorGUILayout.HelpBox( + "1) Ctrl + LeftClick in scene view to add a point and snap it to " + + "\r\n a) 3D mode: mesh with collider" + + "\r\n b) 2D mode: curve's 2D plane." + + "\r\n" + + "\r\n2) Ctrl + Shift + LeftClick in Scene View to add a point unconditionally at some distance, specified in the settings." + + "\r\n" + + "\r\n3) Hold control over existing point or selection to access Scene View menu" + + "\r\n" + + "\r\n4) Hold shift + drag to use rectangular selection in Scene View" + , MessageType.Info); + + + try + { + // Curve's block + BGEditorUtility.VerticalBox(() => + { + //closed + EditorGUILayout.PropertyField(closedProperty); + + + //point's store mode + BGEditorUtility.Horizontal(() => + { + EditorGUILayout.PropertyField(pointsModeProperty); + + BGEditorUtility.DisableGui(() => + { + BGEditorUtility.Assign(ref syncContent, () => new GUIContent("Sync", "Sort points Game Objects and update names")); + + if (!GUILayout.Button(syncContent)) return; + + BGPrivateField.Invoke(Curve, BGCurve.MethodSetPointsNames); + }, !BGCurve.IsGoMode(Curve.PointsMode)); + }); + + + //2D mode + BGEditorUtility.Horizontal(() => + { + EditorGUILayout.PropertyField(mode2DProperty); + BGEditorUtility.DisableGui(() => + { + if (!GUILayout.Button("Apply", GUI.skin.button, GUILayout.Width(80))) return; + + Curve.FireBeforeChange(BGCurve.Event2D); + Curve.Apply2D(Curve.Mode2D); + Curve.FireChange(BGCurveChangedArgs.GetInstance(Curve, BGCurveChangedArgs.ChangeTypeEnum.Points, BGCurve.Event2D)); + }, mode2DProperty.enumValueIndex == 0); + }); + + //snapping + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.Horizontal(() => + { + EditorGUILayout.PropertyField(snapTypeProperty); + + BGEditorUtility.DisableGui(() => + { + if (!GUILayout.Button("Apply", GUI.skin.button, GUILayout.Width(80))) return; + + Curve.FireBeforeChange(BGCurve.EventSnapType); + Curve.ApplySnapping(); + Curve.FireChange(BGCurveChangedArgs.GetInstance(Curve, BGCurveChangedArgs.ChangeTypeEnum.Snap, BGCurve.EventSnapType)); + }, snapTypeProperty.enumValueIndex == 0); + }); + + if (snapTypeProperty.enumValueIndex == 0) return; + + EditorGUILayout.PropertyField(snapAxisProperty); + EditorGUILayout.PropertyField(snapDistanceProperty); + EditorGUILayout.PropertyField(snapTriggerInteractionProperty); + EditorGUILayout.PropertyField(snapToBackFacesProperty); + + BGEditorUtility.LayerMaskField("Snap Layer Mask", Curve.SnapLayerMask, i => + { + Curve.FireBeforeChange(BGCurve.EventSnapTrigger); + Curve.SnapLayerMask = i; + Curve.ApplySnapping(); + Curve.FireChange(BGCurveChangedArgs.GetInstance(Curve, BGCurveChangedArgs.ChangeTypeEnum.Snap, BGCurve.EventSnapTrigger)); + }); + }); + + //event mode + EditorGUILayout.PropertyField(eventModeProperty); + + //force update + EditorGUILayout.PropertyField(forceChangedEventModeProperty); + + //convert control type + BGEditorUtility.Horizontal(() => + { + EditorGUILayout.PropertyField(controlTypeProperty); + + if (!BGEditorUtility.ButtonWithIcon(convertAll2D, "Convert control types for all existing points ", 44)) return; + + var settings = Settings; + + foreach (var point in Curve.Points.Where(point => point.ControlType != settings.ControlType)) point.ControlType = settings.ControlType; + }); + }); + } + catch (BGEditorUtility.ExitException) + { + GUIUtility.ExitGUI(); + } + } + + // ================================================================================ Scene + public override void OnSceneGui(Plane[] frustum) + { + var settings = Settings; + + var curveRotation = GetRotation(Curve.transform); + + if (Curve.PointsCount != 0 && settings.VRay) + { + painter = painter ?? new BGCurvePainterHandles(Editor.Math); + painter.DrawCurve(); + } + + Curve.ForEach((point, index, count) => editorPoint.OnSceneGUI(point, index, settings, curveRotation, frustum)); + + //tangents + if (settings.ShowCurve && settings.ShowTangents && Editor.Math.SectionsCount > 0 && Editor.Math.IsCalculated(BGCurveBaseMath.Field.Tangent)) + { + BGEditorUtility.SwapHandlesColor(settings.TangentsColor, () => + { + var math = Editor.Math; + var sectionsCount = math.SectionsCount; + var sections = math.SectionInfos; + + for (var i = 0; i < sectionsCount; i++) + { + var section = sections[i]; + var points = section.Points; + ShowTangent(points[0].Position, points[0].Tangent, settings.TangentsSize); + if (settings.TangentsPerSection > 1) + { + var sectionLength = section.Distance; + var part = sectionLength/settings.TangentsPerSection; + for (var j = 1; j < settings.TangentsPerSection; j++) + { + var distanceWithinSection = part*j; + Vector3 position; + Vector3 tangent; + section.CalcByDistance(distanceWithinSection, out position, out tangent, true, true); + ShowTangent(position, tangent, settings.TangentsSize); + } + } + } + }); + } + + + editorSelection.Scene(curveRotation); + + overlay.Process(Event.current); + + CheckPointsTransforms(); + } + + private void CheckPointsTransforms() + { + var skipAction = false; + foreach (var tracker in pointTransformTrackers) skipAction |= tracker.CheckForChange(skipAction); + } + + private static void ShowTangent(Vector3 position, Vector3 tangent, float size) + { + if (tangent.sqrMagnitude > 0.0001f) Handles.ArrowCap(0, position, Quaternion.LookRotation(tangent), BGEditorUtility.GetHandleSize(position, size)); + } + + public static Quaternion GetRotation(Transform transform) + { + return Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : transform.rotation; + } + + + public override void OnApply() + { + var curve = Editor.Curve; + var settings = Settings; + + // ============================================== Closed + if (curve.Closed != closedProperty.boolValue) + { + Curve.FireBeforeChange(BGCurve.EventClosed); + serializedObject.ApplyModifiedProperties(); + Curve.FireChange(BGCurveChangedArgs.GetInstance(Curve, BGCurveChangedArgs.ChangeTypeEnum.Points, BGCurve.EventClosed)); + } + + if ((int) curve.ForceChangedEventMode != forceChangedEventModeProperty.enumValueIndex) + { + Curve.FireBeforeChange(BGCurve.EventForceUpdate); + serializedObject.ApplyModifiedProperties(); + Curve.FireChange(BGCurveChangedArgs.GetInstance(Curve, BGCurveChangedArgs.ChangeTypeEnum.Curve, BGCurve.EventForceUpdate)); + } + + // ============================================== Points store mode + if ((int) Curve.PointsMode != pointsModeProperty.enumValueIndex) + { + var newPointsMode = (BGCurve.PointsModeEnum) pointsModeProperty.enumValueIndex; + + //ask for confirmation in case changes may affect something else + if ((Curve.PointsMode == BGCurve.PointsModeEnum.Components) && !BGEditorUtility.Confirm("Convert Points", + "Are you sure you want to convert points? All existing references to these points will be lost.", "Convert")) return; + + if ((Curve.PointsMode == BGCurve.PointsModeEnum.GameObjectsNoTransform && newPointsMode != BGCurve.PointsModeEnum.GameObjectsTransform || + Curve.PointsMode == BGCurve.PointsModeEnum.GameObjectsTransform && newPointsMode != BGCurve.PointsModeEnum.GameObjectsNoTransform) + && !BGEditorUtility.Confirm("Convert Points", "Are you sure you want to convert points? All existing GameObjects for points will be deleted.", "Convert")) return; + + editorSelection.Clear(); + + //invoke convert + BGPrivateField.Invoke(Curve, BGCurve.MethodConvertPoints, newPointsMode, + BGCurveEditor.GetPointProvider(newPointsMode, Curve), + BGCurveEditor.GetPointDestroyer(Curve.PointsMode, Curve)); + + //this call is not required + // serializedObject.ApplyModifiedProperties(); + } + + // ============================================== 2D mode + if ((int) curve.Mode2D != mode2DProperty.enumValueIndex) + { + Curve.FireBeforeChange(BGCurve.Event2D); + serializedObject.ApplyModifiedProperties(); + + var oldEventMode = Curve.EventMode; + Curve.EventMode = BGCurve.EventModeEnum.NoEvents; + + //force points recalc + Curve.Apply2D(Curve.Mode2D); + + if (BGEditorUtility.Confirm("Editor handles change", "Do you want to adjust configurable Editor handles (in Scene View) to chosen mode? This affects only current curve.", "Yes")) + { + if (Curve.Mode2D != BGCurve.Mode2DEnum.Off) + { + Apply2D(settings.HandlesSettings); + Apply2D(settings.ControlHandlesSettings); + } + else + { + Apply3D(settings.HandlesSettings); + Apply3D(settings.ControlHandlesSettings); + } + } + + Curve.EventMode = oldEventMode; + + Curve.FireChange(BGCurveChangedArgs.GetInstance(Curve, BGCurveChangedArgs.ChangeTypeEnum.Points, BGCurve.Event2D)); + } + + // ============================================== Snapping + if ((int) curve.SnapType != snapTypeProperty.enumValueIndex) SnappingChanged(BGCurve.EventSnapType); + + if ((int) curve.SnapAxis != snapAxisProperty.enumValueIndex) SnappingChanged(BGCurve.EventSnapAxis); + + if (Math.Abs((int) curve.SnapDistance - snapDistanceProperty.floatValue) > BGCurve.Epsilon) SnappingChanged(BGCurve.EventSnapDistance); + + if ((int) curve.SnapTriggerInteraction != snapTriggerInteractionProperty.enumValueIndex) SnappingChanged(BGCurve.EventSnapTrigger); + + if (curve.SnapToBackFaces != snapToBackFacesProperty.boolValue) SnappingChanged(BGCurve.EventSnapBackfaces); + + // ============================================== Event mode + if ((int) curve.EventMode != eventModeProperty.enumValueIndex) serializedObject.ApplyModifiedProperties(); + + // ============================================== Control Type + if ((int) settings.ControlType != controlTypeProperty.enumValueIndex) serializedObject.ApplyModifiedProperties(); + } + + private void SnappingChanged(string eventMessage) + { + Curve.FireBeforeChange(eventMessage); + + serializedObject.ApplyModifiedProperties(); + + Curve.ApplySnapping(); + + Curve.FireChange(BGCurveChangedArgs.GetInstance(Curve, BGCurveChangedArgs.ChangeTypeEnum.Snap, eventMessage)); + } + + private void Apply3D(BGCurveSettings.SettingsForHandles handlesSettings) + { + handlesSettings.RemoveX = handlesSettings.RemoveY = handlesSettings.RemoveZ = handlesSettings.RemoveXY = handlesSettings.RemoveXZ = handlesSettings.RemoveYZ = false; + } + + private void Apply2D(BGCurveSettings.SettingsForHandles handlesSettings) + { + handlesSettings.RemoveX = Curve.Mode2D == BGCurve.Mode2DEnum.YZ; + handlesSettings.RemoveY = Curve.Mode2D == BGCurve.Mode2DEnum.XZ; + handlesSettings.RemoveZ = Curve.Mode2D == BGCurve.Mode2DEnum.XY; + + handlesSettings.RemoveXY = Curve.Mode2D == BGCurve.Mode2DEnum.XZ || Curve.Mode2D == BGCurve.Mode2DEnum.YZ; + handlesSettings.RemoveXZ = Curve.Mode2D == BGCurve.Mode2DEnum.XY || Curve.Mode2D == BGCurve.Mode2DEnum.YZ; + handlesSettings.RemoveYZ = Curve.Mode2D == BGCurve.Mode2DEnum.XZ || Curve.Mode2D == BGCurve.Mode2DEnum.XY; + } + + + public override string GetStickerMessage(ref MessageType type) + { + return "" + Curve.PointsCount; + } + + public override void OnUndoRedo() + { + editorSelection.OnUndoRedo(); + } + + public override void OnCurveChanged(BGCurveChangedArgs args) + { + if (args == null || string.IsNullOrEmpty(args.Message) || Curve.PointsMode != BGCurve.PointsModeEnum.GameObjectsTransform) return; + + if (args.ChangeType != BGCurveChangedArgs.ChangeTypeEnum.Point && args.ChangeType != BGCurveChangedArgs.ChangeTypeEnum.Points) return; + + if (!( + args.Message.Equals(BGCurve.EventAddPoint) || args.Message.Equals(BGCurve.EventAddPoints) + || args.Message.Equals(BGCurve.EventClearAllPoints) || args.Message.Equals(BGCurve.EventDeletePoints) + )) return; + + UpdatePointsTrackers(); + } + + private void UpdatePointsTrackers() + { + if (pointTransformTrackers.Count > 0) foreach (var tracker in pointTransformTrackers) tracker.Release(); + + pointTransformTrackers.Clear(); + + //for GameObjectsTransform mode + if (Curve.PointsMode == BGCurve.PointsModeEnum.GameObjectsTransform) + Curve.ForEach((point, index, count) => pointTransformTrackers.Add(BGTransformMonitor.GetMonitor(((BGCurvePointGO) point).transform, transform => Curve.FireChange(null)))); + + //for points transforms + Curve.ForEach((point, index, count) => + { + if (point.PointTransform != null) pointTransformTrackers.Add(BGTransformMonitor.GetMonitor(point.PointTransform, transform => Curve.FireChange(null))); + }); + } + + public static void SwapVector2Labels(BGCurve.Mode2DEnum mode2D, Action action) + { + var needToSwap = mode2D != BGCurve.Mode2DEnum.Off && mode2D != BGCurve.Mode2DEnum.XY; + GUIContent[] oldLabels = null; + if (needToSwap) + { + oldLabels = BGPrivateField.Get(typeof(EditorGUI), "s_XYLabels"); + GUIContent[] newLabels; + switch (mode2D) + { + case BGCurve.Mode2DEnum.XZ: + newLabels = XZLabels; + break; + case BGCurve.Mode2DEnum.YZ: + newLabels = YZLabels; + break; + default: + throw new ArgumentOutOfRangeException("mode2D", mode2D, null); + } + BGPrivateField.Set(typeof(EditorGUI), "s_XYLabels", newLabels); + } + + try + { + action(); + } + finally + { + if (needToSwap) BGPrivateField.Set(typeof(EditorGUI), "s_XYLabels", oldLabels); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoints.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoints.cs.meta new file mode 100644 index 0000000..3503252 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPoints.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5efec0dbdba6a2a4e94b0ac6db243cc6 +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPointsSelection.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPointsSelection.cs new file mode 100644 index 0000000..6878da7 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPointsSelection.cs @@ -0,0 +1,617 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + //helper class for points selection inside editor + public class BGCurveEditorPointsSelection + { + private static readonly Color SelectedBackgroundColor = new Color32(157, 246, 246, 40); + + + private readonly Texture2D tickNoTexture; + private readonly Texture2D tickYesTexture; + private readonly Texture2D deleteTexture; + private readonly Texture2D selectAllTexture; + private readonly Texture2D deselectAllTexture; + private readonly Texture2D convertAllTexture; + + + private readonly List points = new List(); + + private bool groupSelectionStarted; + private bool groupSelectionIsSelecting; + + private BGCurveSettings settings; + + public bool Changed { get; private set; } + + public int CountSelected + { + get { return points.Count; } + } + + private readonly BGCurve curve; + private readonly BGRectangularSelection selectionRectangle; + + private BGCurvePoint.ControlTypeEnum controlType = BGCurvePoint.ControlTypeEnum.Absent; + + private BGEditorUtility.EventCanceller eventCanceller; + + //do not want to use events + private int lastCurveCount; + private readonly PointsContainer pointsContainer; + + public BGCurveEditorPointsSelection(BGCurve curve, BGCurveEditor editor) + { + this.curve = curve; + selectionRectangle = new BGRectangularSelection(editor, this); + + tickNoTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGTickNo123); + tickYesTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGTickYes123); + deleteTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGDelete123); + selectAllTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGSelectAll123); + deselectAllTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGDeSelectAll123); + convertAllTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGConvertAll123); + pointsContainer = new PointsContainer(this); + } + + public bool HasSelected() + { + return CountSelected > 0; + } + + internal void Clear() + { + Changed = Changed || HasSelected(); + points.Clear(); + } + + public bool Contains(BGCurvePointI point) + { + return points.Contains(point); + } + + //if we selecting or removing selection + public void GroupSelection(BGCurvePointI point) + { + if (groupSelectionIsSelecting) Add(point); + else Remove(point); + } + + public bool Add(BGCurvePointI point) + { + if (Contains(point)) return false; + + Changed = true; + points.Add(point); + return true; + } + + public bool Remove(BGCurvePointI point) + { + if (!Contains(point)) return false; + Changed = true; + points.Remove(point); + return true; + } + + private void SetX(float x) + { + foreach (var point in points) + { + var positionWorld = point.PositionWorld; + point.PositionWorld = new Vector3(x, positionWorld.y, positionWorld.z); + } + } + + private void SetY(float y) + { + foreach (var point in points) + { + var positionWorld = point.PositionWorld; + point.PositionWorld = new Vector3(positionWorld.x, y, positionWorld.z); + } + } + + private void SetZ(float z) + { + foreach (var point in points) + { + var positionWorld = point.PositionWorld; + point.PositionWorld = new Vector3(positionWorld.x, positionWorld.y, z); + } + } + + public void Reset() + { + Changed = false; + settings = BGPrivateField.GetSettings(curve); + } + + //draw interactible selection icon control + public void InspectorSelectionRect(BGCurvePointI point) + { + var currentEvent = Event.current; + var rect = GUILayoutUtility.GetRect(24, 24, 24, 24, new GUIStyle {fixedWidth = 24, fixedHeight = 24, stretchWidth = false, stretchHeight = false}); + if (currentEvent.isMouse) + { + if (currentEvent.type == EventType.mouseDown) + { + if (rect.Contains(currentEvent.mousePosition)) + { + groupSelectionStarted = true; + groupSelectionIsSelecting = !Contains(point); + GroupSelection(point); + } + } + else if (groupSelectionStarted) + { + switch (currentEvent.type) + { + case EventType.MouseUp: + groupSelectionStarted = false; + break; + case EventType.MouseDrag: + if (rect.Contains(currentEvent.mousePosition)) GroupSelection(point); + break; + } + } + } + + var selected = Contains(point); + var selectedTexture = selected ? tickYesTexture : tickNoTexture; + var labelStyle = selected ? new GUIStyle("Label") {normal = new GUIStyleState {textColor = settings.LabelColorSelected}} : EditorStyles.label; + EditorGUI.LabelField(rect, new GUIContent(selectedTexture, "Click to (de)select a point, or click and drag to (de)select multiple points. " + + "Hold shift to use rectangular selection"), labelStyle); + } + + //OnInspectorGui for selection + public void InspectorSelectionOperations() + { + BGEditorUtility.VerticalBox(() => + { + // ================================================ Global operations + BGEditorUtility.HorizontalBox(() => + { + BGEditorUtility.SwapLabelWidth(80, () => EditorGUILayout.LabelField("Selected (" + points.Count + ")")); + + if (BGEditorUtility.ButtonWithIcon(deleteTexture, "Delete selected points")) if (!DeleteSelected()) return; + + GUILayout.Space(4); + if (BGEditorUtility.ButtonWithIcon(selectAllTexture, "Select all points", 35)) + { + Changed = Changed || points.Count != curve.PointsCount; + + points.Clear(); + + foreach (var point1 in curve.Points) points.Add(point1); + } + + GUILayout.Space(4); + + if (BGEditorUtility.ButtonWithIcon(deselectAllTexture, "Deselect all points", 35)) Clear(); + }); + + + // ================================================ Selections operations + // skip mouse buttons events which change selection + if (Changed) return; + + GUILayout.Space(5); + if (HasSelected()) + { + BGEditorUtility.SwapGuiBackgroundColor(SelectedBackgroundColor, () => + { + BGEditorUtility.VerticalBox(() => + { + var averagePositionSelected = GetAveragePosition(); + + // ===================================================== Control handles + BGEditorUtility.Horizontal(() => + { + controlType = (BGCurvePoint.ControlTypeEnum) EditorGUILayout.EnumPopup("Controls", controlType); + if (!BGEditorUtility.ButtonWithIcon(convertAllTexture, "Set control type for all selected points", 44)) return; + + SetControlTypeForSelected(controlType); + }); + + // ===================================================== Average positions & delete + BGEditorUtility.Vector3Field("Average position", "Average points position. Change several points positions at once, keeping distance difference intact", + averagePositionSelected, + newAverage => + { + var delta = newAverage - averagePositionSelected; + curve.Transaction(() => + { + foreach (var point in points) point.PositionWorld += delta; + }); + }); + // ===================================================== Set position directly + BGEditorUtility.Vector3Field("Set position", "Set points position directly", + averagePositionSelected, + newPosition => + { + curve.Transaction(() => + { + if (BGEditorUtility.AnyChange(averagePositionSelected.x, newPosition.x)) SetX(newPosition.x); + if (BGEditorUtility.AnyChange(averagePositionSelected.y, newPosition.y)) SetY(newPosition.y); + if (BGEditorUtility.AnyChange(averagePositionSelected.z, newPosition.z)) SetZ(newPosition.z); + }); + }); + + // ===================================================== Set control positions directly + var count = 0; + var averageControl1Sum = Vector3.zero; + var averageControl2Sum = Vector3.zero; + foreach (var point in points.Where(point => point.ControlType != BGCurvePoint.ControlTypeEnum.Absent)) + { + count++; + averageControl1Sum += point.ControlFirstLocal; + averageControl2Sum += point.ControlSecondLocal; + } + + if (count != 0) + { + //has points with bezier controls + BGEditorUtility.Vector3Field("Set Control 1", "Set 1st control position directly", + averageControl1Sum/count, + newPosition => + { + curve.Transaction( + () => + { + foreach (var point in points.Where(point => point.ControlType != BGCurvePoint.ControlTypeEnum.Absent)) point.ControlFirstLocal = newPosition; + }); + }); + + BGEditorUtility.Vector3Field("Set Control 2", "Set 2nd control position directly", + averageControl2Sum/count, + newPosition => + { + curve.Transaction( + () => + { + foreach (var point in points.Where(point => point.ControlType != BGCurvePoint.ControlTypeEnum.Absent)) point.ControlSecondLocal = newPosition; + }); + }); + } + + + // ===================================================== Custom fields + if (curve.FieldsCount > 0) + { + var fields = curve.Fields; + pointsContainer.UpdateFields(); + foreach (var field in fields) BGCurveEditorPoint.ShowField(pointsContainer, field, pointsContainer.AnimationCurveChanged); + } + }); + }); + } + else BGEditorUtility.HelpBox("Hold shift to use rectangular selection\r\nClick or click+drag over tick icons to (de)select points", MessageType.Info, curve.PointsCount > 0); + }); + } + + public void SetControlTypeForSelected(BGCurvePoint.ControlTypeEnum controlType) + { + curve.Transaction(() => + { + foreach (var point in points) point.ControlType = controlType; + }); + } + + public bool DeleteSelected() + { + if (points.Count == 0) + { + BGEditorUtility.Inform("Error", "Chose at least one point to delete"); + return false; + } + + if (!BGEditorUtility.Confirm("Delete points confirmation", "Are you sure you want to remove " + points.Count + " point(s)?", "Delete")) return false; + + BGCurveEditor.DeletePoints(curve, points.ToArray()); + + Clear(); + return true; + } + + public Vector3 GetAveragePosition() + { + return points.Aggregate(Vector3.zero, (current, point) => current + point.PositionWorld)/points.Count; + } + + // OnSceneGui + public void Scene(Quaternion rotation) + { + if (lastCurveCount != curve.PointsCount) + { + lastCurveCount = curve.PointsCount; + OnUndoRedo(); + } + + if (!HasSelected()) return; + + BGEditorUtility.Assign(ref settings, () => BGPrivateField.GetSettings(curve)); + + //group operation for selected points + var text = " Selected [" + points.Count + "]"; + var average = GetAveragePosition(); + Handles.Label(average + BGEditorUtility.GetHandleSize(average)*Vector3.up*.25f, text, new GUIStyle("Label") {normal = new GUIStyleState {textColor = settings.LabelColorSelected}}); + + var newAverage = BGEditorUtility.Handle(-10, settings.HandlesType, average, rotation, settings.HandlesSettings); + + if (BGEditorUtility.AnyChange(average, newAverage)) + { + curve.Transaction(() => + { + var delta = newAverage - average; + foreach (var selectedPoint in points) selectedPoint.PositionWorld += delta; + }); + } + } + + public bool SingleSelected(BGCurvePointI point) + { + return points.Count == 1 && Contains(point); + } + + public void Process(Event currentEvent) + { + if (currentEvent.type == EventType.mouseDown) + { + if (currentEvent.button == 0) + { + if ((!currentEvent.control && currentEvent.shift) || BGCurveSettingsForEditor.LockView) + { + var cancelEvent = Tools.viewTool != ViewTool.FPS && Tools.current != Tool.View /*&& Tools.current != Tool.None*/ && !currentEvent.isKey; + if (cancelEvent) eventCanceller = new BGEditorUtility.EventCanceller(); + + if (currentEvent.shift && !BGCurveSettingsForEditor.DisableRectangularSelection) selectionRectangle.On(); + else if (cancelEvent) BGCurveEditor.OverlayMessage.Display("The Scene view is locked.\r\n Set 'Lock View' (in the BGCurve Editor) to false to unlock."); + } + } + else if (currentEvent.button == 1 && selectionRectangle.IsOn) + { + //glitch with right click + GUIUtility.hotControl = GUIUtility.GetControlID(FocusType.Passive); + } + } + else if (currentEvent.type == EventType.mouseUp) + { + SceneView.RepaintAll(); + selectionRectangle.Off(); + BGEditorUtility.Release(ref eventCanceller); + } + + + selectionRectangle.Process(currentEvent); + } + + public void OnUndoRedo() + { + if (CountSelected == 0) return; + + for (var i = points.Count - 1; i >= 0; i--) if (curve.IndexOf(points[i]) < 0) points.RemoveAt(i); + } + + public void ForEach(Func action) + { + if (CountSelected == 0) return; + + //not sure if it can be converted to LINQ + foreach (var point in points) if (action(point)) return; + } + + private sealed class PointsContainer : BGCurvePointI + { + private readonly Dictionary name2Value = new Dictionary(); + private readonly BGCurveEditorPointsSelection selection; + //we reuse the list to reduce GC + private readonly List existingKeys = new List(); + + public BGCurve Curve { get; private set; } + public Vector3 PositionLocal { get; set; } + public Vector3 PositionLocalTransformed { get; set; } + public Vector3 PositionWorld { get; set; } + public Vector3 ControlFirstLocal { get; set; } + public Vector3 ControlFirstLocalTransformed { get; set; } + public Vector3 ControlFirstWorld { get; set; } + public Vector3 ControlSecondLocal { get; set; } + public Vector3 ControlSecondLocalTransformed { get; set; } + public Vector3 ControlSecondWorld { get; set; } + public BGCurvePoint.ControlTypeEnum ControlType { get; set; } + public Transform PointTransform { get; set; } + + public PointsContainer(BGCurveEditorPointsSelection selection) + { + this.selection = selection; + Curve = selection.curve; + +// var animationCurve = new AnimationCurve(); + } + + public T GetField(string name) + { + var type = typeof(T); + var value = GetField(name, type); + var field = (T) value; + return field; + } + + public void SetField(string name, T value) + { + SetField(name, value, typeof(T)); + } + + + public object GetField(string name, Type type) + { + return name2Value[name]; + } + + public void SetField(string name, object value, Type type) + { + name2Value[name] = value; + + selection.ForEach(p => + { + p.SetField(name, value, type); + return false; + }); + } + + public float GetFloat(string name) + { + throw new NotImplementedException(); + } + + public bool GetBool(string name) + { + throw new NotImplementedException(); + } + + public int GetInt(string name) + { + throw new NotImplementedException(); + } + + public Vector3 GetVector3(string name) + { + throw new NotImplementedException(); + } + + public Bounds GetBounds(string name) + { + throw new NotImplementedException(); + } + + public Quaternion GetQuaternion(string name) + { + throw new NotImplementedException(); + } + + public Color GetColor(string name) + { + throw new NotImplementedException(); + } + + public void SetFloat(string name, float value) + { + throw new NotImplementedException(); + } + + public void SetBool(string name, bool value) + { + throw new NotImplementedException(); + } + + public void SetInt(string name, int value) + { + throw new NotImplementedException(); + } + + public void SetVector3(string name, Vector3 value) + { + throw new NotImplementedException(); + } + + public void SetQuaternion(string name, Quaternion value) + { + throw new NotImplementedException(); + } + + public void SetBounds(string name, Bounds value) + { + throw new NotImplementedException(); + } + + public void SetColor(string name, Color value) + { + throw new NotImplementedException(); + } + + public void AnimationCurveChanged(string name, AnimationCurve animationCurve) + { + selection.ForEach(p => + { + var pointCurve = p.GetField(name); + pointCurve.keys = animationCurve.keys; + pointCurve.postWrapMode = animationCurve.postWrapMode; + pointCurve.preWrapMode = animationCurve.preWrapMode; + return false; + }); + } + + // make sure all fields are present + public void UpdateFields() + { + var fields = Curve.Fields; + + existingKeys.Clear(); + + if (name2Value.Count > 0) foreach (var key in name2Value.Keys) existingKeys.Add(key); + + if (fields.Length != 0) + { + foreach (var field in fields) + { + var fieldName = field.FieldName; + + existingKeys.Remove(fieldName); + + if (name2Value.ContainsKey(field.FieldName)) continue; + + //add new value + switch (field.Type) + { + case BGCurvePointField.TypeEnum.Bool: + name2Value[fieldName] = false; + break; + case BGCurvePointField.TypeEnum.Int: + name2Value[fieldName] = 0; + break; + case BGCurvePointField.TypeEnum.Float: + name2Value[fieldName] = 0f; + break; + case BGCurvePointField.TypeEnum.String: + name2Value[fieldName] = ""; + break; + case BGCurvePointField.TypeEnum.Vector3: + name2Value[fieldName] = new Vector3(); + break; + case BGCurvePointField.TypeEnum.Bounds: + name2Value[fieldName] = new Bounds(); + break; + case BGCurvePointField.TypeEnum.Color: + name2Value[fieldName] = new Color(); + break; + case BGCurvePointField.TypeEnum.Quaternion: + name2Value[fieldName] = Quaternion.identity; + break; + case BGCurvePointField.TypeEnum.AnimationCurve: + name2Value[fieldName] = new AnimationCurve(); + break; + case BGCurvePointField.TypeEnum.GameObject: + case BGCurvePointField.TypeEnum.Component: + case BGCurvePointField.TypeEnum.BGCurve: + case BGCurvePointField.TypeEnum.BGCurvePointComponent: + case BGCurvePointField.TypeEnum.BGCurvePointGO: + name2Value[fieldName] = null; + break; + default: + throw new ArgumentOutOfRangeException("field.Type"); + } + } + } + + //remove unused keys + if (existingKeys.Count > 0) foreach (var key in existingKeys) name2Value.Remove(key); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPointsSelection.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPointsSelection.cs.meta new file mode 100644 index 0000000..f38ba27 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorPointsSelection.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 441a0da564bef264fb9baaada36283ea +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorSettings.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorSettings.cs new file mode 100644 index 0000000..6699a19 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorSettings.cs @@ -0,0 +1,166 @@ +using System.Collections.Generic; +using System.Linq; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGCurveEditorSettings : BGCurveEditorTab + { + private static bool showSaveLoad; + private string newAssetName; + private string lastOperation; + + //anim props + private readonly BGEditorUtility.BoolAnimatedProperty showCurveProp; + private SerializedProperty settings; + + + public BGCurveEditorSettings(BGCurveEditor editor, SerializedObject serializedObject) + : base(editor, serializedObject, BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGSettings123)) + { + //anim props + showCurveProp = new BGEditorUtility.BoolAnimatedProperty(editor, serializedObject.FindProperty("settings"), "showCurve"); + } + + public override void OnInspectorGui() + { + settings = SerializedObject.FindProperty("settings"); + var settingsObj = Settings; + + // Save & Load + showSaveLoad = EditorGUILayout.Foldout(showSaveLoad, "Save and load settings"); + if (showSaveLoad) + { + BGEditorUtility.VerticalBox(() => + { + var path = BGCurveSettingsOperations.GetPath(); + + BGEditorUtility.HelpBox("Folder is not set", MessageType.Info, path == null, () => + { + EditorGUILayout.LabelField("Folder", path); + + BGEditorUtility.HelpBox("Folder is not found", MessageType.Warning, !BGCurveSettingsOperations.IsValid(path), () => + { + // ================================= Load settings + var all = BGCurveSettingsOperations.GetAll(); + + BGEditorUtility.HelpBox("Folder does not have any settings", MessageType.Warning, all == null || all.Length == 0, () => + { + BGEditorUtility.Horizontal(() => + { + var options = new List {new GUIContent("")}; + options.AddRange(all.Select(setting => new GUIContent(setting))); + var selected = EditorGUILayout.Popup(new GUIContent("Load", "Load a specified settings for current object"), 0, options.ToArray()); + if (selected > 0) + { + var newSettings = BGCurveSettingsOperations.Load(options[selected].text); + if (newSettings != null) + { + BGPrivateField.SetSettings(Curve, newSettings); + EditorUtility.SetDirty(Curve); + lastOperation = options[selected].text + " was loaded"; + } + else lastOperation = "Unable to load a settings " + options[selected].text; + } + + if (GUILayout.Button(new GUIContent("Reload", "Reload settings from disk. This operation does not change settings for the curent object."))) + { + BGCurveSettingsOperations.Reload(BGCurveSettingsOperations.GetPath()); + lastOperation = "Settings was reloaded from disk"; + } + }); + }); + + // ================================= Save settings + BGEditorUtility.Horizontal(() => + { + newAssetName = EditorGUILayout.TextField(new GUIContent("Save", "Save current setting on disk"), newAssetName); + if (!GUILayout.Button(new GUIContent("Save", "Save current setting on disk"))) return; + + if (newAssetName == null || newAssetName.Trim().Equals("")) BGEditorUtility.Inform("Invalid asset name", "Please, enter the name for new asset"); + else lastOperation = BGCurveSettingsOperations.Save(settingsObj, newAssetName) ? newAssetName + " was saved on disk" : "Unable to save " + newAssetName + " on disk"; + }); + + BGEditorUtility.HelpBox(lastOperation, MessageType.Info, lastOperation != null); + }); + }); + + BGEditorUtility.Horizontal(() => + { + if (GUILayout.Button(new GUIContent("Save as default", "Save current settings as default for future curves"))) + { + lastOperation = BGCurveSettingsOperations.SaveDefault(settingsObj) ? "Current settings was saved as default" : "Unable to save settings on disk as default"; + } + + if (GUILayout.Button(new GUIContent("Chose a folder", "Chose a folder where to store settings files"))) BGCurveSettingsOperations.ChoseDir(); + }); + }); + } + + EditorGUILayout.HelpBox("All fields settings are under Fields tab", MessageType.Warning); + + BGEditorUtility.ChangeCheck(() => + { + //Points + BGEditorUtility.VerticalBox(() => + { + //Hide handles + EditorGUILayout.PropertyField(Find("hideHandles")); + + EditorGUILayout.PropertyField(Find("newPointDistance")); + EditorGUILayout.PropertyField(Find("showPointMenu")); + }); + + var tangentProp = Find("showTangents"); + + //curve + BGEditorUtility.FadeGroup(showCurveProp, () => + { + EditorGUILayout.PropertyField(Find("showCurveMode")); + EditorGUILayout.PropertyField(Find("sections")); + EditorGUILayout.PropertyField(Find("vRay")); + BGEditorUtility.HelpBox("VRay will work only if object is selected.", MessageType.Warning, Find("vRay").boolValue && Find("showCurveMode").enumValueIndex != 0); + EditorGUILayout.PropertyField(Find("lineColor")); + + //tangents + BGEditorUtility.VerticalBox(() => + { + EditorGUILayout.PropertyField(tangentProp); + if (settingsObj.ShowTangents) + { + BGEditorUtility.Indent(1, () => + { + EditorGUILayout.PropertyField(Find("tangentsSize")); + EditorGUILayout.PropertyField(Find("tangentsPerSection")); + EditorGUILayout.PropertyField(Find("tangentsColor")); + }); + } + }); + }); + }, () => + { + //if any change + SerializedObject.ApplyModifiedProperties(); + SceneView.RepaintAll(); + }); + } + + private SerializedProperty Find(string name) + { + return settings.FindPropertyRelative(name); + } + + + public override void OnEnable() + { + Tools.hidden = Settings.HideHandles; + } + + + public override void OnApply() + { + Tools.hidden = Settings.HideHandles; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorSettings.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorSettings.cs.meta new file mode 100644 index 0000000..a4d2c24 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorSettings.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e1df90c7c52e81b44be91984d29ff247 +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorTab.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorTab.cs new file mode 100644 index 0000000..576258b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorTab.cs @@ -0,0 +1,79 @@ +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + public abstract class BGCurveEditorTab + { + public readonly BGCurveEditor Editor; + public readonly SerializedObject SerializedObject; + public readonly BGCurve Curve; + + private readonly Texture2D header2D; + + public Texture2D Header2D + { + get { return header2D; } + } + + public BGCurveSettings Settings + { + get { return BGPrivateField.GetSettings(Curve); } + } + + protected BGCurveEditorTab(BGCurveEditor editor, SerializedObject serializedObject, Texture2D header2D) + { + Editor = editor; + Curve = editor.Curve; + SerializedObject = serializedObject; + this.header2D = header2D; + } + + + // standard onInspector call + public abstract void OnInspectorGui(); + + //standard onscene + public virtual void OnSceneGui(Plane[] frustum) + { + } + + + // standard onEnable + public virtual void OnEnable() + { + } + + //editor disabled callback + public virtual void OnDisable() + { + } + + //editor removed callback + public virtual void OnDestroy() + { + } + + + //after applying the changes + public virtual void OnApply() + { + } + + + //sticker message (on toolbar) + public virtual string GetStickerMessage(ref MessageType type) + { + return null; + } + + public virtual void OnUndoRedo() + { + } + + public virtual void OnCurveChanged(BGCurveChangedArgs args) + { + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorTab.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorTab.cs.meta new file mode 100644 index 0000000..3d03904 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveEditorTab.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0d58f9d2731617f47a5feea3ca370779 +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointComponentDrawer.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointComponentDrawer.cs new file mode 100644 index 0000000..788d0f2 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointComponentDrawer.cs @@ -0,0 +1,49 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomPropertyDrawer(typeof(BGCurvePointComponent), true)] + public class BGCurvePointComponentDrawer : BGPropertyDrawer + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // idea.. partially copy/pasted from BGCcChoseDrawer + // this is a required startup call + SetUp(position, property, label, () => + { + if (!(property.objectReferenceValue != null)) DrawProperty(property); + else + { + var point = (BGCurvePointComponent) property.objectReferenceValue; + + var pointCount = point.Curve.PointsCount; + + if (pointCount < 2) DrawProperty(property); + else + { + var pointIndex = point.Curve.IndexOf(point); + var buttonContent = new GUIContent("" + pointIndex, "Object has multiple components attached. Click to chose."); + + var buttonWidth = GUI.skin.button.CalcSize(buttonContent).x; + + Rect.width -= buttonWidth; + EditorGUI.PropertyField(Rect, property); + + + if (GUI.Button(new Rect(Rect) {width = buttonWidth, x = Rect.xMax}, buttonContent)) + { + BGCurveChosePointWindow.Open(pointIndex, point.Curve, newPoint => + { + property.objectReferenceValue = newPoint; + property.serializedObject.ApplyModifiedProperties(); + EditorUtility.SetDirty(property.serializedObject.targetObject); + }); + } + } + } + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointComponentDrawer.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointComponentDrawer.cs.meta new file mode 100644 index 0000000..54d0e1b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointComponentDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 83b0dba0ac76f224da8f2bef4a936744 +timeCreated: 1475061550 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointGOEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointGOEditor.cs new file mode 100644 index 0000000..010426e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointGOEditor.cs @@ -0,0 +1,80 @@ +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using UnityEngine; +using UnityEngineInternal; + +namespace BansheeGz.BGSpline.Editor +{ + //bug in editor while curve is rotated in 2d mode (position overflow to super big values while being dragged in SceneView) + [CustomEditor(typeof(BGCurvePointGO))] + public class BGCurvePointGOEditor : UnityEditor.Editor + { + public static bool PointSelected; + + private BGCurvePointI point; + private BGCurveEditorPoint pointEditor; + + private BGCurveEditor curveEditor; + private BGTransition.SwayTransition pointIndicatorTransition; + private Texture2D pointSelectedTexture; + + protected virtual BGCurvePointI Point + { + get { return (BGCurvePointI) target; } + } + + protected virtual void OnEnable() + { + point = Point; + + pointEditor = new BGCurveEditorPoint(() => null, null); + + if (curveEditor != null) curveEditor.OnDestroy(); + + curveEditor = (BGCurveEditor) CreateEditor(point.Curve); + + pointSelectedTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGPointSelected123); + + PointSelected = true; + } + + + void OnDisable() + { + PointSelected = false; + if (curveEditor != null) curveEditor.OnDisable(); + } + + void OnDestroy() + { + PointSelected = false; + if (curveEditor != null) curveEditor.OnDestroy(); + } + + public override void OnInspectorGUI() + { + var curve = point.Curve; + + BGCurveEditorPoints.SwapVector2Labels(curve.Mode2D, () => pointEditor.OnInspectorGui(point, curve.IndexOf(point), BGPrivateField.GetSettings(curve))); + } + + public virtual void OnSceneGUI() + { + BGEditorUtility.Assign(ref pointIndicatorTransition, () => new BGTransition.SwayTransition(30, 30, 1)); + + BGSceneViewOverlay.DrawHandlesGuiTexture(BGEditorUtility.GetSceneViewPosition(point.PositionWorld), pointIndicatorTransition, pointSelectedTexture); + + + curveEditor.OnSceneGUI(); + + // animation is off for now +// SceneView.RepaintAll(); + } + + [DrawGizmo(GizmoType.Selected)] + public static void DrawGizmos(BGCurve curve, GizmoType gizmoType) + { + BGCurveEditor.DrawGizmos(curve, gizmoType); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointGOEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointGOEditor.cs.meta new file mode 100644 index 0000000..45e0020 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurvePointGOEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 252e4a88e6bc93a47ba0fce8ecbba329 +timeCreated: 1476925566 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveReferenceToPointEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveReferenceToPointEditor.cs new file mode 100644 index 0000000..c6ee651 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveReferenceToPointEditor.cs @@ -0,0 +1,87 @@ +using System.Linq; +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + [CustomEditor(typeof(BGCurveReferenceToPoint))] + public class BGCurveReferenceToPointEditor : BGCurvePointGOEditor + { + private BGCurveReferenceToPoint pointReference; + + private BGTransformMonitor transformMonitor; + + protected override BGCurvePointI Point + { + get { return pointReference.Point; } + } + + protected override void OnEnable() + { + pointReference = (BGCurveReferenceToPoint) target; + + var point = pointReference.Point; + if (!IsValid(point)) + { + //no need for it anymore + DestroyImmediate(pointReference); + return; + } + + var allComponents = pointReference.GetComponents(); + if (allComponents.Any(component => component != pointReference && component.Point == pointReference.Point)) + { + DestroyImmediate(pointReference); + return; + } + + transformMonitor = BGTransformMonitor.GetMonitor(pointReference.transform, transform => point.Curve.FireChange(null)); + + base.OnEnable(); + } + + public void OnDestroy() + { + if (transformMonitor != null) transformMonitor.Release(); + transformMonitor = null; + pointReference = null; + } + + + private static bool IsValid(BGCurvePointI point) + { + return point != null && point.Curve != null && point.Curve.IndexOf(point) >= 0; + } + + public override void OnInspectorGUI() + { + transformMonitor.CheckForChange(); + + var point = pointReference.Point; + + if (!IsValid(point)) return; + + BGEditorUtility.DisableGui(() => EditorGUILayout.TextField("BGCurve", point.Curve.gameObject.name)); + + base.OnInspectorGUI(); + } + + public override void OnSceneGUI() + { + var point = pointReference.Point; + + if (!IsValid(point)) return; + + transformMonitor.CheckForChange(); + + base.OnSceneGUI(); + } + + [DrawGizmo(GizmoType.Selected)] + public new static void DrawGizmos(BGCurve curve, GizmoType gizmoType) + { + BGCurvePointGOEditor.DrawGizmos(curve, gizmoType); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveReferenceToPointEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveReferenceToPointEditor.cs.meta new file mode 100644 index 0000000..c82ad65 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGCurveReferenceToPointEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 559b4471bb9f69d42b854d355126983a +timeCreated: 1477988941 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGNewPointPositionManager.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGNewPointPositionManager.cs new file mode 100644 index 0000000..70f08e3 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGNewPointPositionManager.cs @@ -0,0 +1,189 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Editor +{ + public static class BGNewPointPositionManager + { + //multiply tangent by this constant for new points, inserted after all points. + private const float DistanceToControlMultiplier = .2f; + + //multiply tangent by this constant for points, inserted between 2 existing points. + private const float DistanceToTangentMultiplier = .05f; + + //multiply tangent by this constant for points, which positions can not be derived + private const float DistanceToTangentNoDataMultiplier = 1.5f; + + private static BGCurvePoint point; + + public static BGCurvePoint CreatePoint(Vector3 position, BGCurve curve, BGCurvePoint.ControlTypeEnum controlType, int parts, bool ensureNew) + { + float distanceToPreviousPoint; + float distanceToNextPoint; + return CreatePoint(position, curve, controlType, parts, out distanceToPreviousPoint, out distanceToNextPoint, ensureNew); + } + + public static BGCurvePoint CreatePoint(Vector3 position, BGCurve curve, BGCurvePoint.ControlTypeEnum controlType, int parts, out float distanceToPreviousPoint, out float distanceToNextPoint, + bool ensureNew) + { + distanceToPreviousPoint = -1; + distanceToNextPoint = -1; + + if (curve.PointsCount == 0) + { + //first point + Vector3 control; + switch (curve.Mode2D) + { + case BGCurve.Mode2DEnum.YZ: + control = Vector3.forward; + break; + default: + // BGCurve.Mode2DEnum.XY: + // BGCurve.Mode2DEnum.Off: + // BGCurve.Mode2DEnum.XZ: + control = Vector3.right; + break; + } + return curve.CreatePointFromLocalPosition(curve.ToLocal(position), controlType, control, -control); + } + + parts = Mathf.Clamp(parts, 1, 50); + + //we no need no events (maybe check if point was actually added to a curve for events firing?) + var oldSuppress = curve.SupressEvents; + curve.SupressEvents = true; + + //create a point with no controls first + BGCurvePoint newPoint; + if (ensureNew) + { + newPoint = curve.CreatePointFromWorldPosition(position, BGCurvePoint.ControlTypeEnum.Absent); + } + else + { + if (point == null || point.Curve != curve) point = curve.CreatePointFromWorldPosition(position, BGCurvePoint.ControlTypeEnum.Absent); + newPoint = point; + newPoint.PositionWorld = position; + newPoint.ControlFirstLocal = Vector3.zero; + newPoint.ControlSecondLocal = Vector3.zero; + } + + if(curve.Mode2DOn) curve.Apply2D(newPoint); + + //adjacent points + var previousPoint = curve[curve.PointsCount - 1]; + var nextPoint = curve.Closed ? curve[0] : null; + + //direction + var tangent = BGEditorUtility.CalculateTangent(newPoint, previousPoint, nextPoint, 1/(float) parts); + if (tangent.sqrMagnitude < 0.0001f) + { + //whatever + switch (curve.Mode2D) + { + case BGCurve.Mode2DEnum.Off: + case BGCurve.Mode2DEnum.XY: + case BGCurve.Mode2DEnum.XZ: + tangent = Vector3.right; + break; + case BGCurve.Mode2DEnum.YZ: + tangent = Vector3.up; + break; + } + } + + //length + distanceToPreviousPoint = BGEditorUtility.CalculateDistance(previousPoint, newPoint, parts); + float minDistance; + if (nextPoint != null) + { + distanceToNextPoint = BGEditorUtility.CalculateDistance(newPoint, nextPoint, parts); + minDistance = Math.Min(distanceToPreviousPoint, distanceToNextPoint); + } + else + { + minDistance = distanceToPreviousPoint; + } + var length = minDistance*DistanceToControlMultiplier; + + + //we need local tangent for controls + tangent = curve.ToLocalDirection(tangent); + + + + newPoint.ControlSecondLocal = tangent*length; + + newPoint.ControlFirstLocal = -newPoint.ControlSecondLocal; + + + newPoint.ControlType = controlType; + + curve.SupressEvents = oldSuppress; + return newPoint; + } + + public static BGCurvePoint InsertBefore(BGCurve curve, int index, BGCurvePoint.ControlTypeEnum controlType, int parts) + { + var newPoint = CreatePointByPointsCount(curve, controlType); + if (newPoint != null) return newPoint; + + if (index == 0 && !curve.Closed) + return InsertNoData(curve, controlType, BGEditorUtility.CalculateTangent(curve[0], curve[1], 0f), curve[0].ControlFirstLocal, curve[0].PositionWorld, false); + + return CreatePointBetween(curve, index == 0 ? curve[curve.PointsCount - 1] : curve[index - 1], curve[index], parts, controlType); + } + + + public static BGCurvePoint InsertAfter(BGCurve curve, int index, BGCurvePoint.ControlTypeEnum controlType, int parts) + { + var newPoint = CreatePointByPointsCount(curve, controlType); + if (newPoint != null) return newPoint; + + var pointsCount = curve.PointsCount; + if (index == pointsCount - 1 && !curve.Closed) + { + var lastPoint = curve[pointsCount - 1]; + return InsertNoData(curve, controlType, BGEditorUtility.CalculateTangent(curve[pointsCount - 2], lastPoint, 1f), lastPoint.ControlSecondLocal, lastPoint.PositionWorld, true); + } + + return CreatePointBetween(curve, curve[index], index == pointsCount - 1 ? curve[0] : curve[index + 1], parts, controlType); + } + + private static BGCurvePoint CreatePointByPointsCount(BGCurve curve, BGCurvePoint.ControlTypeEnum controlType) + { + var pointsCount = curve.PointsCount; + + switch (pointsCount) + { + case 0: + throw new UnityException("You can not use this method with no points on the curve. pointsCount==0"); + case 1: + return curve.CreatePointFromLocalPosition(Vector3.forward, controlType, Vector3.right, Vector3.left); + } + return null; + } + + private static BGCurvePoint InsertNoData(BGCurve curve, BGCurvePoint.ControlTypeEnum controlType, Vector3 tangent, Vector3 control, Vector3 positionWorld, bool inverseTangent) + { + var controlMagnitude = control.magnitude; + if (controlMagnitude < 1) controlMagnitude = 1; + + var pos = positionWorld - tangent*controlMagnitude*DistanceToTangentNoDataMultiplier*(inverseTangent ? -1 : 1); + + return curve.CreatePointFromWorldPosition(pos, controlType, pos - tangent, pos + tangent); + } + + private static BGCurvePoint CreatePointBetween(BGCurve curve, BGCurvePointI previousPoint, BGCurvePointI nextPoint, int parts, BGCurvePoint.ControlTypeEnum controlType) + { + var newPos = BGEditorUtility.CalculatePosition(previousPoint, nextPoint, .5f); + var tangent = BGEditorUtility.CalculateTangent(previousPoint, nextPoint, .5f); + + var scaledTangent = tangent*DistanceToTangentMultiplier*BGEditorUtility.CalculateDistance(previousPoint, nextPoint, parts); + + return curve.CreatePointFromLocalPosition(curve.ToLocal(newPos), controlType, curve.ToLocalDirection(-scaledTangent), curve.ToLocalDirection(scaledTangent)); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGNewPointPositionManager.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGNewPointPositionManager.cs.meta new file mode 100644 index 0000000..9a921a4 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGNewPointPositionManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: aec4164ed8f499945a786507eac50af5 +timeCreated: 1472342782 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGRectangularSelection.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGRectangularSelection.cs new file mode 100644 index 0000000..75e76ab --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGRectangularSelection.cs @@ -0,0 +1,174 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGRectangularSelection + { + private const int BorderTextureSize = 8; + private static readonly Color BorderColor = new Color32(255, 255, 255, 100); + + private Texture2D back; + private readonly Texture2D borderHorizontal; + private readonly Texture2D borderVertical; + + private readonly BGCurve curve; + private readonly BGCurveEditorPointsSelection selection; + private readonly BGCurveEditor editor; + + private Vector2 start; + private bool selectionWasMade; + public bool IsOn { get; private set; } + + private Color backColor = BGCurveSettingsForEditor.ColorForRectangularSelection; + + public BGRectangularSelection(BGCurveEditor editor, BGCurveEditorPointsSelection selection) + { + this.editor = editor; + this.selection = selection; + curve = editor.Curve; + + borderHorizontal = CreateBorder(false); + borderVertical = CreateBorder(true); + } + + private Texture2D CreateBorder(bool vertical) + { + var texture = vertical ? new Texture2D(1, BorderTextureSize) : new Texture2D(BorderTextureSize, 1); + + var noColor = new Color(); + for (var i = 0; i < BorderTextureSize; i++) + { + var color = i > 3 ? noColor : BorderColor; + + if (vertical) texture.SetPixel(0, i, color); + else texture.SetPixel(i, 0, color); + } + texture.Apply(false); + return texture; + } + + + public void On() + { + IsOn = true; + selectionWasMade = false; + start = Event.current.mousePosition; + SceneView.RepaintAll(); + + //colors and texture + if (back == null || backColor != BGCurveSettingsForEditor.ColorForRectangularSelection) + { + backColor = BGCurveSettingsForEditor.ColorForRectangularSelection; + back = BGEditorUtility.Texture1X1(backColor); + } + } + + public void Off() + { + if (!IsOn) return; + IsOn = false; + + if (selectionWasMade) return; + + if (selection.HasSelected()) + { + selection.Clear(); + SceneView.RepaintAll(); + } + } + + public void Process(Event currentEvent) + { + if (!IsOn) return; + + var end = currentEvent.mousePosition; + + //we check if mouse pointer was moved + if (!selectionWasMade && (end - start).sqrMagnitude > 1) selectionWasMade = true; + + if (!selectionWasMade) return; + + var rect = new Rect(Math.Min(start.x, end.x), Math.Min(start.y, end.y), Math.Abs(start.x - end.x), Math.Abs(start.y - end.y)); + + //========================= Model + //update points + UpdatePoints(rect); + + //========================= UI + Ui(rect); + + SceneView.RepaintAll(); + editor.Repaint(); + } + + private void UpdatePoints(Rect rect) + { + var sceneViewHeight = BGEditorUtility.GetSceneViewHeight(); + + var math = editor.Math; + + curve.ForEach((point, index, count) => + { + //add or remove from selection + if (rect.Contains(BGEditorUtility.GetSceneViewPosition(math.GetPosition(index), sceneViewHeight))) selection.Add(point); + else selection.Remove(point); + }); + + if (!selection.Changed) return; + + selection.Reset(); + } + + + private void Ui(Rect rect) + { + Handles.BeginGUI(); + + var size = rect.size; + var width = Mathf.FloorToInt(Math.Abs(size.x)); + var height = Mathf.FloorToInt(Math.Abs(size.y)); + if (width == 0 || height == 0) return; + + //------ back + GUI.DrawTexture(rect, back, ScaleMode.StretchToFill); + + //------ borders + //top + DrawBorder(new Rect(rect) {width = width, height = height == 1 ? 1 : 2}, false); + if (height <= 2) return; + + //bottom + DrawBorder(new Rect(rect) {y = rect.yMax - 2, width = width, height = 2}, false); + + if (width <= 4 || height <= 4) return; + + //left + DrawBorder(new Rect(rect) {width = 2}, true); + //right + DrawBorder(new Rect(rect) {x = rect.xMax - 2, width = 2}, true); + + Handles.EndGUI(); + } + + private void DrawBorder(Rect rect, bool vertical) + { + float widthScale = 1, heightScale = 1; + Texture2D texture; + if (vertical) + { + texture = borderVertical; + heightScale = rect.height/BorderTextureSize; + } + else + { + texture = borderHorizontal; + widthScale = rect.width/BorderTextureSize; + } + + GUI.DrawTextureWithTexCoords(rect, texture, new Rect(0, 0, widthScale, heightScale)); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGRectangularSelection.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGRectangularSelection.cs.meta new file mode 100644 index 0000000..68f8ff0 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Curve/BGRectangularSelection.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 16379b7aa6eabc740a4a2086e6c30bff +timeCreated: 1472269887 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra.meta new file mode 100644 index 0000000..e44154d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b5ef7e0d16af7b04b9ae146bb3d792c6 +folderAsset: yes +timeCreated: 1473056753 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcAddWindow.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcAddWindow.cs new file mode 100644 index 0000000..2e2bfb5 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcAddWindow.cs @@ -0,0 +1,340 @@ +using System; +using UnityEngine; +using System.Collections.Generic; +using System.Linq; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGCcAddWindow : EditorWindow + { + private const int IconSize = 48; + private const int HeaderHeight = 12; + + private static readonly Vector2 WindowSize = new Vector2(700, 400); + + + private static Tree tree; + + private static Texture2D headerImage; + private static Texture2D noImage; + private static Texture2D boxWithBorderImage; + private static GUIStyle nameStyle; + private static GUIStyle disabledStyle; + private static GUIStyle filterStyle; + + private static Action action; + private static BGCcAddWindow instance; + + private static int tab; + private Vector2 scrollPos; + + internal static void Open(BGCurve curve, Action action, Type dependsOnType = null) + { + BGCcAddWindow.action = action; + + noImage = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGCcNoImage123); + + tree = new Tree(curve, dependsOnType); + + instance = BGEditorUtility.ShowPopupWindow(WindowSize); + } + + private void OnGUI() + { + //styles + AssighSyles(); + + + //draw header + DrawHeader(); + + + if (tree.Roots.Count == 0) + { + Message("Did not find any component"); + } + else + { + BGEditorUtility.VerticalBox(() => + { + scrollPos = EditorGUILayout.BeginScrollView(scrollPos); + tree.OnInspectorGui(); + EditorGUILayout.EndScrollView(); + + }); + } + } + + private static void Message(string message) + { + EditorGUILayout.LabelField(message, new GUIStyle("Label") + { + fontSize = 22, + wordWrap = true + }, GUILayout.Height(200)); + } + + private static void DrawHeader() + { + BGEditorUtility.HorizontalBox(() => { GUILayout.Label(" "); }); + GUI.DrawTexture(GUILayoutUtility.GetLastRect(), boxWithBorderImage); + + var rect = new Rect(new Vector2(40, 10), new Vector2(headerImage.width*HeaderHeight/(float) headerImage.height, HeaderHeight)); + GUI.DrawTexture(rect, headerImage); + + if (tree.DependsOnType != null) + GUI.Label(new Rect(rect) {x = rect.xMax + 10, height = 16, width = 400, y = rect.y - 2}, "Filter: Dependent on [" + tree.DependsOnType.Name + "]", filterStyle); + } + + private static void AssighSyles() + { + BGEditorUtility.Assign(ref nameStyle, () => new GUIStyle("Label") + { + alignment = TextAnchor.MiddleCenter, + clipping = TextClipping.Clip, + wordWrap = true, + fontStyle = FontStyle.Bold, + normal = + { + textColor = Color.black, + background = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGBoxWithBorder123) + } + }); + BGEditorUtility.Assign(ref disabledStyle, () => new GUIStyle("Label") + { + alignment = TextAnchor.MiddleCenter, + normal = + { + textColor = Color.red, + background = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGBoxWithBorder123) + } + }); + BGEditorUtility.Assign(ref filterStyle, () => new GUIStyle("Label") + { + fontStyle = FontStyle.Bold, + normal = + { + textColor = Color.red + } + }); + BGEditorUtility.Assign(ref headerImage, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGCurveComponents123)); + BGEditorUtility.Assign(ref boxWithBorderImage, () => BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGBoxWithBorder123)); + } + + + //thanks to Bunny83 + public static Type[] GetAllSubTypes(Type targetType) + { + var result = new List(); + var assemblies = AppDomain.CurrentDomain.GetAssemblies(); + foreach (var assembly in assemblies) result.AddRange(from type in assembly.GetTypes() where type.IsClass where !type.IsAbstract where type.IsSubclassOf(targetType) select type); + return result.ToArray(); + } + + //=================================================================== Inner classes + + //================================================= Tree + private sealed class Tree : BGTreeView + { + private readonly Dictionary type2Node = new Dictionary(); + + public BGCurve Curve { get; private set; } + + public Type DependsOnType { get; private set; } + + public Tree(BGCurve curve, Type dependsOnType) + : base(new Config(0, (int) (IconSize*.9f), (int) (IconSize*.5f), 2, 16)) + { + Curve = curve; + DependsOnType = dependsOnType; + + //------------- load all BGCc subclasses + var typesList = GetAllSubTypes(typeof (BGCc)); + foreach (var node in from type in typesList + let descriptor = BGCc.GetDescriptor(type) + let single = BGCc.IsSingle(type) + select new CcNode(this, descriptor != null ? new CcData(type, single, descriptor) : new CcData(type, single, type.Name))) + { + try + { + node.CcData.ParentType = BGCc.GetParentClass(node.CcData.Type); + } + catch (Exception e) + { + Debug.LogException(e); + continue; + } + type2Node[node.CcData.Type] = node; + } + + foreach (var node in type2Node.Values) if (!node.Processed) node.ProcessStructure(); + } + + public CcNode this[Type type] + { + get { return type2Node[type]; } + } + + public override void OnInspectorGui() + { + if (DependsOnType == null) base.OnInspectorGui(); + else + { + var node = type2Node[DependsOnType]; + if (node == null) + { + Message("Error: Can not find component " + DependsOnType); + } + else if (!node.HasChildren) + { + Message("Component [" + node.CcData.Name + "] does not have any children"); + } + else + { + node.OnInspectorGui(); + } + } + } + } + + //================================================= Tree node + private sealed class CcNode : BGTreeNode + { + private readonly CcData ccData; + private readonly bool singleAndAdded; + private Texture2D addIcon; + + + private GUIStyle nameStyle; + private GUIStyle descriptionStyle; + private GUIStyle addedStyle; + + + public CcData CcData + { + get { return ccData; } + } + + public bool Processed { get; private set; } + + private Tree MyTree + { + get { return (Tree) Tree; } + } + + public CcNode(Tree tree, CcData ccData) + : base(tree) + { + this.ccData = ccData; + singleAndAdded = ccData.Single && tree.Curve.GetComponent(ccData.Type) != null; + } + + public override void OnInspectorGuiInternal(int level) + { + const int offset = 2; + + if (singleAndAdded) GUI.enabled = false; + if (GUILayout.Button("", GUILayout.Height(IconSize + offset*2))) + { + action(ccData.Type); + instance.Close(); + } + if (singleAndAdded) GUI.enabled = true; + + // Draw on top of the button (no more Layout stuff) + var buttonRect = GUILayoutUtility.GetLastRect(); + + + var iconRect = new Rect(buttonRect.x + offset, buttonRect.y + offset, IconSize, IconSize); + GUI.DrawTexture(iconRect, ccData.Icon); + +/* + //already added + if (singleAndAdded) GUI.DrawTexture(new Rect(iconRect) {x = iconRect.xMax + offset, width = offset*8}, + BGEUtil.Assign(ref addIcon, () => BGEUtil.LoadTexture2D(BGEUtil.Image.BGCcAdded123))); +*/ + if (singleAndAdded) + { + var oldMatrix = GUI.matrix; + BGEditorUtility.Assign(ref addedStyle, () => new GUIStyle("Box") + { + fontSize = 14, + fontStyle = FontStyle.Bold, + normal = {textColor = Color.red, background = BGEditorUtility.Texture1X1(new Color(1,0,0,.2f))} + }); + var content = new GUIContent("added"); + var labelSize = addedStyle.CalcSize(content); + var pivotPoint = new Vector2(iconRect.xMax, iconRect.center.y) + new Vector2(labelSize.y*.5f, 0); + GUIUtility.RotateAroundPivot(-90, pivotPoint); + GUI.Label(new Rect(pivotPoint - labelSize*.5f, labelSize), content, addedStyle); + GUI.matrix = oldMatrix; + } + + + //name + var nameStartX = iconRect.xMax + offset*12; + var nameRect = new Rect(nameStartX, iconRect.y, buttonRect.width - nameStartX, IconSize/3f); + EditorGUI.LabelField(nameRect, ccData.Name, BGEditorUtility.Assign(ref nameStyle, () => new GUIStyle("Label") {fontStyle = FontStyle.Bold})); + + //description + var descriptionRect = new Rect(nameStartX, nameRect.yMax + offset, nameRect.width, IconSize*2/3f); + EditorGUI.LabelField(descriptionRect, ccData.Description, BGEditorUtility.Assign(ref descriptionStyle, () => new GUIStyle("Label") {wordWrap = true})); + } + + + public override void ProcessStructure() + { + if (ccData.ParentType == null) + { + MyTree.Roots.Add(this); + } + else + { + Parent = MyTree[CcData.ParentType]; + } + Processed = true; + } + } + + //================================================= CC data + private sealed class CcData + { + public Type Type { get; private set; } + + public Type ParentType { get; set; } + + public string Description { get; private set; } + + public string Name { get; private set; } + + public Texture2D Icon { get; private set; } + + public bool Single { get; private set; } + + public CcData(Type type, bool single, BGCc.CcDescriptor ccDescriptor) + : this(type, single, ccDescriptor.Name) + { + Description = ccDescriptor.Description; + if (!string.IsNullOrEmpty(ccDescriptor.Image)) Icon = BGEditorUtility.LoadCcTexture2D(ccDescriptor.Image) ?? noImage; + } + + public CcData(Type type, bool single, string name) + { + Type = type; + + Name = name; + Icon = noImage; + Single = single; + + if (string.IsNullOrEmpty(Name)) Name = Type.Name; + } + + public override string ToString() + { + return Type.Name + ": " + Name; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcAddWindow.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcAddWindow.cs.meta new file mode 100644 index 0000000..2d35f25 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcAddWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a20bb7d90ed1356459501898772114a8 +timeCreated: 1472483253 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChangeNameWindow.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChangeNameWindow.cs new file mode 100644 index 0000000..2a40676 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChangeNameWindow.cs @@ -0,0 +1,54 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + + +namespace BansheeGz.BGSpline.Editor +{ + public class BGCcChangeNameWindow : EditorWindow + { + private static readonly Vector2 WindowSize = new Vector2(400, 50); + + private static BGCc current; + private static string ccName; + private static BGCcChangeNameWindow instance; + + + private Vector2 scrollPos; + private GUIStyle boxStyle; + + + internal static void Open(BGCc current) + { + BGCcChangeNameWindow.current = current; + + ccName = current.CcName; + + instance = BGEditorUtility.ShowPopupWindow(WindowSize); + } + + private void OnGUI() + { + BGEditorUtility.SwapLabelWidth(60, () => + { + BGEditorUtility.Horizontal(BGEditorUtility.Assign(ref boxStyle, () => new GUIStyle("Box") {padding = new RectOffset(8, 8, 8, 8)}), () => + { + ccName = EditorGUILayout.TextField("Name", ccName); + + GUILayout.Space(8); + + if (GUILayout.Button("Save and Close")) + { + if (!string.Equals(ccName, current.CcName)) + { + Undo.RecordObject(current, "Change name"); + current.CcName = ccName; + EditorUtility.SetDirty(current); + } + instance.Close(); + } + }); + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChangeNameWindow.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChangeNameWindow.cs.meta new file mode 100644 index 0000000..210ac3a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChangeNameWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ec708301478213148abdd926189518ae +timeCreated: 1473063970 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseDrawer.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseDrawer.cs new file mode 100644 index 0000000..0217c41 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseDrawer.cs @@ -0,0 +1,53 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public abstract class BGCcChoseDrawer : BGPropertyDrawer where T : BGCc + { + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // this is a required startup call + SetUp(position, property, label, () => + { + if (!(property.objectReferenceValue != null)) + { + DrawProperty(property); + } + else + { + var cc = (T) property.objectReferenceValue; + + var allPossibleCcList = cc.GetComponents(cc.GetType()); + + if (allPossibleCcList.Length < 2) + { + DrawProperty(property); + } + else + { + var buttonContent = new GUIContent(BGEditorUtility.Trim(cc.CcName, 16), "Object has multiple components attached. Click to chose."); + + var buttonWidth = GUI.skin.button.CalcSize(buttonContent).x; + + Rect.width -= buttonWidth; + EditorGUI.PropertyField(Rect, property); + + + if (GUI.Button(new Rect(Rect) {width = buttonWidth, x = Rect.xMax}, buttonContent)) + { + BGCcChoseWindow.Open(cc, allPossibleCcList, newCc => + { + Undo.RecordObject(property.serializedObject.targetObject, "Cc changed"); + property.objectReferenceValue = newCc; + property.serializedObject.ApplyModifiedProperties(); + EditorUtility.SetDirty(property.serializedObject.targetObject); + }); + } + } + } + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseDrawer.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseDrawer.cs.meta new file mode 100644 index 0000000..16c5a51 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 58d3f7af09907cf429f8934b2cb7eb35 +timeCreated: 1473062560 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseWindow.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseWindow.cs new file mode 100644 index 0000000..f850246 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseWindow.cs @@ -0,0 +1,60 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGCcChoseWindow : EditorWindow + { + private static readonly Vector2 WindowSize = new Vector2(400, 200); + + private static Action action; + private static BGCcChoseWindow instance; + private static BGCc current; + private static Component[] availableList; + private static GUIStyle boxStyle; + + + private Vector2 scrollPos; + + + internal static void Open(BGCc current, Component[] availableList, Action action) + { + BGCcChoseWindow.action = action; + BGCcChoseWindow.current = current; + BGCcChoseWindow.availableList = availableList; + + instance = BGEditorUtility.ShowPopupWindow(WindowSize); + } + + private void OnGUI() + { + scrollPos = EditorGUILayout.BeginScrollView(scrollPos); + + ShowButtons(); + + EditorGUILayout.EndScrollView(); + } + + private static void ShowButtons() + { + BGEditorUtility.Vertical(BGEditorUtility.Assign(ref boxStyle, () => new GUIStyle("Box") {padding = new RectOffset(8, 8, 8, 8)}), () => + { + for (var i = 0; i < availableList.Length; i++) + { + var cc = (BGCc) availableList[i]; + + BGEditorUtility.DisableGui(() => + { + if (!GUILayout.Button(cc.CcName)) return; + + + action(cc); + instance.Close(); + }, cc == current); + } + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseWindow.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseWindow.cs.meta new file mode 100644 index 0000000..d56fa59 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCcChoseWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3afdd426232a2c34f8f50115b9d5c751 +timeCreated: 1473060319 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGChoseComponentWindow.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGChoseComponentWindow.cs new file mode 100644 index 0000000..4edfc0f --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGChoseComponentWindow.cs @@ -0,0 +1,54 @@ +using System; +using UnityEngine; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + // idea.. partially copy/pasted from BGCcChoseWindow + public class BGChoseComponentWindow : EditorWindow + { + private static readonly Vector2 WindowSize = new Vector2(400, 400); + + private static Action action; + private static BGChoseComponentWindow instance; + private static Component current; + private static GUIStyle boxStyle; + + + private Vector2 scrollPos; + + + internal static void Open(Component current, Action action) + { + BGChoseComponentWindow.action = action; + BGChoseComponentWindow.current = current; + + instance = BGEditorUtility.ShowPopupWindow(WindowSize); + } + + private void OnGUI() + { + scrollPos = EditorGUILayout.BeginScrollView(scrollPos); + + BGEditorUtility.VerticalBox(() => + { + var allComponents = current.GetComponents(typeof (Component)); + foreach (var component in allComponents) + { + var comp = component; + BGEditorUtility.DisableGui(() => + { + if (GUILayout.Button(comp.ToString(), GUILayout.Width(380))) + { + action(comp); + instance.Close(); + } + }, current == component); + } + }); + + EditorGUILayout.EndScrollView(); + + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGChoseComponentWindow.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGChoseComponentWindow.cs.meta new file mode 100644 index 0000000..595189b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGChoseComponentWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3164790b79db83d40a1b9a2746cf9b6a +timeCreated: 1475286949 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurveChosePointWindow.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurveChosePointWindow.cs new file mode 100644 index 0000000..7d1d7a8 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurveChosePointWindow.cs @@ -0,0 +1,43 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + // idea.. partially copy/pasted from BGCcChoseWindow + public class BGCurveChosePointWindow : EditorWindow + { + private static readonly Vector2 WindowSize = new Vector2(400, 40); + + private static Action action; + private static BGCurveChosePointWindow instance; + private static BGCurve curve; + private static int current; + + internal static void Open(int current, BGCurve curve, Action action) + { + BGCurveChosePointWindow.action = action; + BGCurveChosePointWindow.current = current; + BGCurveChosePointWindow.curve = curve; + + instance = BGEditorUtility.ShowPopupWindow(WindowSize); + } + + private void OnGUI() + { + BGEditorUtility.HorizontalBox(() => + { + EditorGUILayout.LabelField("Point index", GUILayout.Width(100)); + var newValue = EditorGUILayout.IntSlider(current, 0, curve.PointsCount - 1, GUILayout.Width(200)); + if (current != newValue) + { + current = newValue; + action((BGCurvePointComponent) curve[newValue]); + } + + if (GUILayout.Button("Close", GUILayout.Width(50))) instance.Close(); + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurveChosePointWindow.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurveChosePointWindow.cs.meta new file mode 100644 index 0000000..0466a3b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurveChosePointWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 47003328321ae5a4d8ceaf8ab44b555e +timeCreated: 1475061925 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterGizmo.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterGizmo.cs new file mode 100644 index 0000000..24b00ce --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterGizmo.cs @@ -0,0 +1,82 @@ +using BansheeGz.BGSpline.Curve; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + //draws a curve in editor + public class BGCurvePainterGizmo + { + public BGCurveBaseMath Math { get; private set; } + + private readonly BGTransformMonitor transformMonitor; + + public BGCurvePainterGizmo(BGCurveBaseMath math, bool monitorTransform = false) + { + Math = math; + if (monitorTransform) transformMonitor = BGTransformMonitor.GetMonitor(math.Curve); + } + + public virtual void DrawCurve() + { + if (transformMonitor != null) transformMonitor.CheckForChange(); + + var settings = BGPrivateField.GetSettings(Math.Curve); + + BGEditorUtility.SwapGizmosColor(settings.LineColor, () => + { + //======================================== Draw section + for (var i = 0; i < Math.SectionsCount; i++) DrawSection(Math[i]); + }); + + + //======================================== Draw spheres + if (settings.ShowSpheres) + { + BGEditorUtility.SwapGizmosColor(settings.SphereColor, () => + { + BeforeDrawingSpheres(settings); + for (var i = 0; i < Math.Curve.PointsCount; i++) DrawSphere(settings, Math.GetPosition(i), settings.SphereRadius); + AfterDrawingSpheres(); + }); + } + } + + public void Dispose() + { + if (Math != null) Math.Dispose(); + if (transformMonitor != null) transformMonitor.Release(); + } + + protected virtual void BeforeDrawingSpheres(BGCurveSettings settings) + { + } + + protected virtual void AfterDrawingSpheres() + { + } + + public virtual void DrawSphere(BGCurveSettings settings, Vector3 pos, float sphereRadius) + { + Gizmos.DrawSphere(pos, sphereRadius); + } + + protected void DrawSection(BGCurveBaseMath.SectionInfo section) + { + if (section.PointsCount < 2) return; + + var points = section.Points; + var prevPoint = points[0]; + for (var i = 1; i < points.Count; i++) + { + var nexPoint = points[i]; + DrawLine(prevPoint.Position, nexPoint.Position); + prevPoint = nexPoint; + } + } + + protected virtual void DrawLine(Vector3 from, Vector3 to) + { + Gizmos.DrawLine(from, to); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterGizmo.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterGizmo.cs.meta new file mode 100644 index 0000000..42988a0 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterGizmo.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 61f851c212ea4794cb98000e86717feb +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterHandles.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterHandles.cs new file mode 100644 index 0000000..f3d18fd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterHandles.cs @@ -0,0 +1,42 @@ +using BansheeGz.BGSpline.Curve; +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGCurvePainterHandles : BGCurvePainterGizmo + { + private Color tempColorBeforeSpheresDraw; + + public BGCurvePainterHandles(BGCurveBaseMath math) + : base(math) + { + } + + public override void DrawCurve() + { + BGEditorUtility.SwapHandlesColor(BGPrivateField.GetSettings(Math.Curve).LineColor, () => base.DrawCurve()); + } + + protected override void BeforeDrawingSpheres(BGCurveSettings settings) + { + tempColorBeforeSpheresDraw = Handles.color; + Handles.color = settings.SphereColor; + } + + protected override void AfterDrawingSpheres() + { + Handles.color = tempColorBeforeSpheresDraw; + } + + public override void DrawSphere(BGCurveSettings settings, Vector3 pos, float sphereRadius) + { + Handles.SphereCap(0, pos, Quaternion.identity, sphereRadius*2); + } + + protected override void DrawLine(Vector3 @from, Vector3 to) + { + Handles.DrawLine(from, to); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterHandles.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterHandles.cs.meta new file mode 100644 index 0000000..1fac635 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGCurvePainterHandles.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: aee191ffbacf6ee47aab2ecea5833778 +timeCreated: 1458655215 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGHandlesSettingsDrawer.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGHandlesSettingsDrawer.cs new file mode 100644 index 0000000..0101c04 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGHandlesSettingsDrawer.cs @@ -0,0 +1,70 @@ +using BansheeGz.BGSpline.Curve; +using UnityEngine; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + // Currently this file is not used + // custom drawer for handles settings + // idea.. code is still messy after refactoring + [CustomPropertyDrawer(typeof (BGCurveSettings.SettingsForHandles))] + public class BGHandlesSettingsDrawer : BGPropertyDrawer + { + //do not remove. It indicates 5 lines are used + public override float GetPropertyHeight(SerializedProperty property, GUIContent label) + { + return base.GetPropertyHeight(property, label)*5; + } + + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + // this is required startup call + SetUp(position, property, label, () => + { + //occupy 2 lines + SetHeight(Height*2); + + //this call will set controlRect=space for control itself (without label) + PrefixLabel("Remove"); + + //set cursor to the start of just allocated space for control + SetCursor(ControlRect.x, ControlRect.y); + + //this block will draw checkboxes for Remove options + Indent(0, () => + { + //------------------------------------------- first line + LineWithRemoveControls(property, Height, 15, new[] {"X", "Y", "Z"}, new[] {"RemoveX", "RemoveY", "RemoveZ"}); + + //------------------------------------------- second line + SetCursor(ControlRect.x, CursorY + Height); + LineWithRemoveControls(property, Height, 20, new[] {"XZ", "XY", "YZ"}, new[] {"RemoveXZ", "RemoveXY", "RemoveYZ"}); + }); + + //------------------------------------------- third line (Scale Axis) + //reset height to standard 1 line + SetHeight(Height); + //skip 2 lines, used for checkboxes + NextLine(2); + DrawRelativeProperty(property, "Scale Axis", "AxisScale"); + + //------------------------------------------- forth line (Scale Planes) + NextLine(); + DrawRelativeProperty(property, "Scale Planes", "PlanesScale"); + + //------------------------------------------- fifth line (Alpha) + NextLine(); + DrawRelativeProperty(property, "Alpha", "Alpha"); + }); + } + + private void LineWithRemoveControls(SerializedProperty property, float height, int labelWidth, string[] labels, string[] fields) + { + for (var i = 0; i < labels.Length; i++) + { + RelativePropertyByCursor(10, height, property, fields[i]); + LabelByCursor(labelWidth, height, labels[i]); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGHandlesSettingsDrawer.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGHandlesSettingsDrawer.cs.meta new file mode 100644 index 0000000..4cb9c81 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGHandlesSettingsDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 595f24c0eb8112744bbf9d8d45b91e06 +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGPropertyDrawer.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGPropertyDrawer.cs new file mode 100644 index 0000000..ce34edd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGPropertyDrawer.cs @@ -0,0 +1,102 @@ +using System; +using UnityEngine; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + //idea.. code is very messy even after refactoring + //there are currently 2 strategies to draw- 1) by using labelRect + controlRect. 2) By using cursors. This is a total mess. + public class BGPropertyDrawer : PropertyDrawer + { + private const int Space = 5; + + //one line height + protected float Height; + + //space to use for property GUI + protected Rect Rect; + //space used for show Control calls + protected Rect ControlRect; + + //additional cursors for *ByCursor calls. + protected float CursorX; + protected float CursorY; + + // startUp (Required!) + protected void SetUp(Rect position, SerializedProperty property, GUIContent label, Action action) + { + Rect = position; + //do not remove base ref + Height = base.GetPropertyHeight(property, label); + EditorGUI.BeginProperty(position, label, property); + action(); + EditorGUI.EndProperty(); + } + + //helper with indents + protected void Indent(int indent, Action action) + { + var oldIndent = EditorGUI.indentLevel; + EditorGUI.indentLevel = indent; + action(); + EditorGUI.indentLevel = oldIndent; + } + + + //======================================================= By labelRect + controlRect + + protected void PrefixLabel(string message, string tooltip = null) + { + ControlRect = EditorGUI.PrefixLabel(Rect, GUIUtility.GetControlID(FocusType.Passive), new GUIContent(message, tooltip)); + } + + protected void DrawProperty(SerializedProperty property) + { +// PrefixLabel(property.displayName, property.tooltip); + EditorGUI.PropertyField(Rect, property); + } + + + protected bool RelativeProperty(SerializedProperty property, string name) + { + return EditorGUI.PropertyField(ControlRect, property.FindPropertyRelative(name), GUIContent.none); + } + + protected void DrawRelativeProperty(SerializedProperty property, string label, string propertyName, string tooltip = null) + { + PrefixLabel(label, tooltip); + Indent(0, () => RelativeProperty(property, propertyName)); + } + + + protected void SetHeight(float height) + { + Rect.height = height; + } + + protected void NextLine(int linesToSkip = 1) + { + Rect.y += Height*linesToSkip; + } + + + //======================================================= By Cursor + protected void RelativePropertyByCursor(int width, float height, SerializedProperty property, string name) + { + EditorGUI.PropertyField(new Rect(CursorX, CursorY, width, height), property.FindPropertyRelative(name), GUIContent.none); + CursorX += width + Space; + } + + protected void LabelByCursor(int width, float height, string label) + { + EditorGUI.LabelField(new Rect(CursorX, CursorY, width, height), label); + CursorX += width + Space; + } + + protected void SetCursor(float x, float y) + { + CursorX = x; + CursorY = y; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGPropertyDrawer.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGPropertyDrawer.cs.meta new file mode 100644 index 0000000..fc663ef --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGPropertyDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5b27947e37c1b494cbcf1ac8331c96a9 +timeCreated: 1471778173 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGTransformMonitor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGTransformMonitor.cs new file mode 100644 index 0000000..6a652a3 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGTransformMonitor.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGTransformMonitor + { + private static readonly Queue Pool = new Queue(); + + private Vector3 position; + private Quaternion rotation; + private Vector3 scale; + + private Transform transform; + private Action changed; + + private BGTransformMonitor(Transform transform, Action changed) + { + Update(transform, changed); + } + + public static BGTransformMonitor GetMonitor(Transform transform, Action changed) + { + if (Pool.Count == 0) return new BGTransformMonitor(transform, changed); + + var monitor = Pool.Dequeue(); + monitor.transform = transform; + monitor.changed = changed; + + return monitor; + } + + public static BGTransformMonitor GetMonitor(BGCurve curve) + { + return GetMonitor(curve.transform, transform1 => { curve.FireChange(null); }); + } + + + public bool CheckForChange(bool skipAction = false) + { + if (Application.isPlaying || changed == null || transform == null) return false; + + if (position == transform.position && rotation == transform.rotation && scale == transform.lossyScale) return false; + + Update(); + + if (!skipAction) changed(transform); + + return true; + } + + public void Release() + { + transform = null; + changed = null; + + Pool.Enqueue(this); + } + + + private void Update(Transform transform, Action changed) + { + this.transform = transform; + this.changed = changed; + Update(); + } + + private void Update() + { + position = transform.position; + rotation = transform.rotation; + scale = transform.lossyScale; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGTransformMonitor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGTransformMonitor.cs.meta new file mode 100644 index 0000000..0356d94 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Infra/BGTransformMonitor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 82b8689fcf20fad4dac3b2732079ad96 +timeCreated: 1474230021 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay.meta new file mode 100644 index 0000000..fd0c658 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2e55235c43bc9794398e45f589fe1c1a +folderAsset: yes +timeCreated: 1472482844 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGOverlayMessage.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGOverlayMessage.cs new file mode 100644 index 0000000..a260e04 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGOverlayMessage.cs @@ -0,0 +1,52 @@ +using UnityEditor; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGOverlayMessage + { + private const float ShowTime = 1.5f; + + private string message; + private double started; + private bool showing; + + private GUIStyle style; + private readonly Rect rect = new Rect(10, 10, 400, 60); + + + //indicates the message should be shown + public void Display(string message) + { + this.message = message; + started = EditorApplication.timeSinceStartup; + showing = true; + } + + // call this every frame to find out if the message expired + public void Check() + { + if (showing && EditorApplication.timeSinceStartup - started > ShowTime) SceneView.RepaintAll(); + } + + // shows a message in the scene view + public void OnSceneGui() + { + if (!showing) return; + + if (EditorApplication.timeSinceStartup - started > ShowTime) showing = false; + + BGEditorUtility.Assign(ref style, () => new GUIStyle("Label") + { + alignment = TextAnchor.MiddleCenter, + richText = true, + normal = {textColor = Color.white, background = BGEditorUtility.Texture1X1(new Color32(0, 0, 0, 100))} + }); + + + Handles.BeginGUI(); + GUI.Label(rect, message, style); + Handles.EndGUI(); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGOverlayMessage.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGOverlayMessage.cs.meta new file mode 100644 index 0000000..8bf5800 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGOverlayMessage.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3fe7d907a5ebe0b4e8b4d4ed3a46608e +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGPopupMenu.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGPopupMenu.cs new file mode 100644 index 0000000..27ce19a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGPopupMenu.cs @@ -0,0 +1,226 @@ +using System; +using UnityEngine; +using System.Collections.Generic; +using System.Linq; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + //popup menu in SceneView + public class BGPopupMenu + { + private const int HeaderHeight = 16; + + + private readonly Texture2D menuItemBackgroundTexture; + private readonly Texture2D backTexture; + private readonly Texture2D selectedTexture; + private readonly Texture2D currentTexture; + + private readonly string title; + + + public Vector2 Point2DPosition; + public Vector3 Point3DPosition; + public bool Active; + public MenuItem ActiveItem; + + private float height; + private float width; + private Rect targetRect; + private BGTransition.SimpleTransition onTransition; + + private readonly List items = new List(); + private GUIStyle titleStyle; + + public BGPopupMenu(string title) + { + this.title = title; + menuItemBackgroundTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGMenuItemBackground123); + backTexture = BGEditorUtility.Texture1X1(new Color32(46, 144, 168, 80)); + selectedTexture = BGEditorUtility.Texture1X1(new Color32(0, 255, 0, 100)); + currentTexture = BGEditorUtility.Texture1X1(new Color32(200, 200, 200, 200)); + } + + public void Add(MenuItem item) + { + items.Add(item); + } + + public MenuItem Get(int index) + { + return items[index]; + } + + public virtual void On(Vector3 position) + { + if (Active) return; + + Active = true; + + onTransition = new BGTransition.SimpleTransition(.2, false); + Point3DPosition = position; + Point2DPosition = BGEditorUtility.GetSceneViewPosition(Point3DPosition); + + //target size (go first) + height = width = 0; + foreach (var size in items.Where(item => !item.Disabled).Select(item => item.Size)) + { + if (height < size.y*2) height = size.y*2; + width += size.x; + } + targetRect.size = new Vector2(width, height + HeaderHeight); + + + //target position (go second) + targetRect.x = Point2DPosition.x - targetRect.size.x*.5f; + targetRect.y = Point2DPosition.y - targetRect.size.y*.75f; + } + + public void OnGui(Event currentEvent) + { + if (!Active) return; + + var mousePosition = currentEvent.mousePosition; + + if (onTransition == null && !targetRect.Contains(mousePosition)) + { + Active = false; + SceneView.RepaintAll(); + return; + } + + BGEditorUtility.Assign(ref titleStyle, () => new GUIStyle("Label") + { + fontStyle = FontStyle.Bold, + alignment = TextAnchor.MiddleCenter, + normal = + { + textColor = Color.white, + background = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGBoxWithBorder123) + }, + }); + + Handles.BeginGUI(); + + if (onTransition != null && !onTransition.Tick()) + { + //animating transition + GUI.DrawTexture(new Rect(Vector2.Lerp(Point2DPosition, targetRect.position, onTransition.Ratio), targetRect.size*onTransition.Ratio), backTexture, ScaleMode.StretchToFill); + } + else + { + //ready + onTransition = null; + + GUI.DrawTexture(targetRect, backTexture, ScaleMode.StretchToFill); + GUI.Label(new Rect(targetRect) {height = HeaderHeight}, title, titleStyle); + + ActiveItem = null; + var cursor = targetRect.x; + + foreach (var item in items.Where(item => !item.Disabled)) + { + var itemRect = new Rect(cursor, targetRect.y + HeaderHeight, item.Size.x, item.Size.y); + var selected = itemRect.Contains(mousePosition); + + //if not separator + if (selected && item.Description != null) + { + ActiveItem = item; + + if (!currentEvent.control && item is MenuItemButton) ((MenuItemButton) item).Action(); + } + + //icon + if (item.Icon != null) + { + GUI.DrawTexture(itemRect, menuItemBackgroundTexture, ScaleMode.StretchToFill); + + if (selected) GUI.DrawTexture(itemRect, selectedTexture, ScaleMode.StretchToFill); + + GUI.DrawTexture(itemRect, item.Icon, ScaleMode.StretchToFill); + } + + if (item.Current) + { + GUI.DrawTexture(itemRect, currentTexture, ScaleMode.StretchToFill); + } + + cursor += itemRect.width; + } + } + + Handles.EndGUI(); + + if (!currentEvent.control) Active = false; + } + + //=================================================================================== menu items + //---------------------- abstract + public abstract class MenuItem + { + public abstract string Description { get; } + public abstract Texture2D Icon { get; } + public abstract Vector2 Size { get; } + + public bool Disabled; + + public bool Current; + } + + //---------------------- separator + public class MenuSeparator : MenuItem + { + private readonly Vector2 size = new Vector2(16, 32); + + public override string Description + { + get { return null; } + } + + public override Texture2D Icon + { + get { return null; } + } + + public override Vector2 Size + { + get { return size; } + } + } + + //---------------------- menu item + public class MenuItemButton : MenuItem + { + public readonly Action Action; + + private readonly Texture2D iconTexture; + private readonly string description; + private readonly Vector2 size = new Vector2(32, 32); + + + public override string Description + { + get { return description; } + } + + public override Texture2D Icon + { + get { return iconTexture; } + } + + public override Vector2 Size + { + get { return size; } + } + + public MenuItemButton(Texture2D iconTexture, string description, Action action) + { + this.iconTexture = iconTexture; + this.description = description; + Action = action; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGPopupMenu.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGPopupMenu.cs.meta new file mode 100644 index 0000000..da7e8b4 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGPopupMenu.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5da84aced639ead46b938408b8bc6a0c +timeCreated: 1472295379 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlay.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlay.cs new file mode 100644 index 0000000..e448905 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlay.cs @@ -0,0 +1,143 @@ +using UnityEngine; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + //scene view context actions (Ctrl pressed) + //idea.. whole BGSceneViewOverlay thing needs to be refactored + public sealed class BGSceneViewOverlay + { + private static readonly string HeaderColor = BGEditorUtility.ToHex(new Color32(255, 255, 255, 255)); +// private static readonly string ErrorColor = ToHex(new Color32(122, 0, 0, 255)); + private static readonly string ErrorColor = BGEditorUtility.ToHex(new Color32(250, 207, 207, 255)); +// private static readonly string OkColor = ToHex(new Color32(0, 122, 0, 255)); + private static readonly string OkColor = BGEditorUtility.ToHex(new Color32(207, 250, 209, 255)); +// private static readonly string ActionColor = ToHex(new Color32(46, 143, 168, 255)); + private static readonly string ActionColor = BGEditorUtility.ToHex(Color.white); + + internal readonly BGCurveEditorPoints Editor; + private GUIStyle style; + + private readonly SceneAction[] actions; + + //some kind of standard trick + public BGEditorUtility.EventCanceller EventCanceller; + + public BGSceneViewOverlay(BGCurveEditorPoints editor, BGCurveEditorPointsSelection editorSelection) + { + Editor = editor; + + actions = new SceneAction[] + { + new BGSceneViewOverlayMenuSelection(this, editorSelection), + new BGSceneViewOverlayMenuPoint(this, editorSelection), + new BGSceneViewOverlayPointAddAtDistance(this), + new BGSceneViewOverlayPointAddSnap3D(this), + new BGSceneViewOverlayPointAddSnap2D(this) + }; + } + + private void Message(SceneAction action, Vector3 position, string message) + { + BGEditorUtility.SwapHandlesColor(new Color32(46, 143, 168, 255), () => + { + // idea.. some hacker's work that needs to be redone + var error = message.IndexOf(ErrorColor) != -1; + + Handles.Label(position, " " + + "" + + BGEditorUtility.ColorIt("Action[", HeaderColor) + + BGEditorUtility.ColorIt(action.Name, ActionColor) + + BGEditorUtility.ColorIt("] ", HeaderColor) + + (error ? ToError("Error") : ToOk("Ok")) + + "\r\n" + + message, style); + }); + } + + + public void Process(Event currentEvent) + { + if (currentEvent.type == EventType.mouseUp) BGEditorUtility.Release(ref EventCanceller); + + if (currentEvent.shift && !currentEvent.control) return; + + Vector3 mousePosition = Event.current.mousePosition; + + var pixelHeight = SceneView.currentDrawingSceneView.camera.pixelHeight; + var pixelWidth = SceneView.currentDrawingSceneView.camera.pixelWidth; + mousePosition.y = pixelHeight - mousePosition.y; + if (mousePosition.x < 0 || mousePosition.y < 0 || mousePosition.x > pixelWidth || mousePosition.y > pixelHeight) return; + + + BGEditorUtility.Assign(ref style, () => new GUIStyle("Label") + { + padding = new RectOffset(4, 4, 4, 4), + border = new RectOffset(4, 4, 4, 4), + fontStyle = FontStyle.Bold, + richText = true, + normal = new GUIStyleState + { + textColor = Color.white, + background = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGBoxWithBorder123) + } + }); + + + foreach (var action in actions) + { + var position = Vector3.zero; + string message = null; + + var seized = action.Seize(currentEvent, ref position, ref message); + if (!seized) continue; + + if (message != null) Message(action, position, message); + break; + } + + if (currentEvent.control && currentEvent.type != EventType.Repaint) SceneView.RepaintAll(); + } + + public static string ToError(string error) + { + return BGEditorUtility.ColorIt(error, ErrorColor); + } + + public static string ToOk(string okMessage) + { + return BGEditorUtility.ColorIt(okMessage, OkColor); + } + + //identify particular action + public abstract class SceneAction + { + protected readonly BGSceneViewOverlay overlay; + + public abstract string Name { get; } + + protected SceneAction(BGSceneViewOverlay overlay) + { + this.overlay = overlay; + } + + //return true if event is seized by this action. if seized, Position and message should also be set in this case + internal abstract bool Seize(Event currentEvent, ref Vector3 position, ref string message); + } + + public static void DrawHandlesGuiTexture(Vector2 screenPoint, BGTransition.SwayTransition pointIndicatorTransition, Texture2D pointSelectedTexture) + { + pointIndicatorTransition.Tick(); + + var shift = pointIndicatorTransition.Value*.5f; + + Handles.BeginGUI(); + + GUI.DrawTexture( + new Rect(screenPoint - new Vector2(shift, shift), new Vector2(pointIndicatorTransition.Value, pointIndicatorTransition.Value)), + pointSelectedTexture, ScaleMode.StretchToFill); + + Handles.EndGUI(); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlay.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlay.cs.meta new file mode 100644 index 0000000..5907bdd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlay.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 91d24c95cb2b3554fa3ab77739c350f2 +timeCreated: 1472269855 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenu.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenu.cs new file mode 100644 index 0000000..0283a1a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenu.cs @@ -0,0 +1,131 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public abstract class BGSceneViewOverlayMenu : BGSceneViewOverlay.SceneAction where T : BGSceneViewOverlayMenu.AbstractMenu + { + protected const float DistanceTolerance = 100; + + private readonly Texture2D pointSelectedTexture; + + protected T menu; + protected BGCurveEditorPointsSelection editorSelection; + + private BGTransition.SwayTransition pointIndicatorTransition; + + protected BGSceneViewOverlayMenu(BGSceneViewOverlay overlay, BGCurveEditorPointsSelection editorSelection) + : base(overlay) + { + this.editorSelection = editorSelection; + pointSelectedTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGPointSelected123); + } + + internal override bool Seize(Event currentEvent, ref Vector3 position, ref string message) + { + if (menu.Active) + { + menu.OnGui(currentEvent); + + BGEditorUtility.Assign(ref pointIndicatorTransition, () => new BGTransition.SwayTransition(20, 30, .4f)); + BGSceneViewOverlay.DrawHandlesGuiTexture(menu.Point2DPosition, pointIndicatorTransition, pointSelectedTexture); + + var okMessage = menu.ActiveItem != null && menu.ActiveItem.Description != null + ? "Release Ctrl to " + menu.ActiveItem.Description + : "Hover over an option and release Ctrl."; + + //out params + position = menu.Point3DPosition; + message = BGSceneViewOverlay.ToOk(okMessage) + "\r\n" + menu.Details; + //============== Ok + return true; + } + + if (!(currentEvent.type == EventType.Repaint && currentEvent.control || currentEvent.type == EventType.MouseMove && currentEvent.control)) return false; + + if (Process(currentEvent, overlay.Editor.Editor.Math, BGEditorUtility.GetSceneViewHeight(), ref position, ref message)) return true; + + pointIndicatorTransition = null; + + //============== No luck + return false; + } + + protected abstract bool Process(Event @event, BGCurveBaseMath math, float sceneViewHeight, ref Vector3 position, ref string message); + + + + protected static string SuccessMessage(string message) + { + return BGSceneViewOverlay.ToOk("Hover over an option and release Ctrl.\r\n") + message; + } + + + //========================================================== Abstract menu + public abstract class AbstractMenu : BGPopupMenu + { + public readonly BGCurveEditorPointsSelection EditorSelection; + public readonly BGSceneViewOverlay Overlay; + + public abstract string Details { get; } + + protected AbstractMenu(BGSceneViewOverlay overlay, BGCurveEditorPointsSelection editorSelection, string title) + : base(title) + { + EditorSelection = editorSelection; + Overlay = overlay; + + Add(new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGControlAbsent123), "Convert point control to Absent", + () => { SetControl(BGCurvePoint.ControlTypeEnum.Absent); })); + + Add(new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGControlBezierSymmetrical123), "Convert point control to Bezier Symmetrical", + () => { SetControl(BGCurvePoint.ControlTypeEnum.BezierSymmetrical); })); + + Add(new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGControlBezierIndependent123), "Convert point control to Bezier Independent", + () => { SetControl(BGCurvePoint.ControlTypeEnum.BezierIndependant); })); + + + AdditionalMenuItems(); + + + Add(new LockMenuItem(() => + { + BGCurveSettingsForEditor.LockView = !BGCurveSettingsForEditor.LockView; + EditorUtility.SetDirty(overlay.Editor.Curve); + })); + + Add(new MenuSeparator()); + + Add(new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGPointDelete123), "Delete a point", Delete)); + } + + protected virtual void AdditionalMenuItems() + { + } + + protected abstract void SetControl(BGCurvePoint.ControlTypeEnum controlType); + protected abstract void Delete(); + } + + //========================================================== Lock menu + private sealed class LockMenuItem : BGPopupMenu.MenuItemButton + { + public LockMenuItem(Action action) + : base(null, null, action) + { + } + + public override string Description + { + get { return BGCurveSettingsForEditor.LockView ? "Switch 'Lock View' mode off" : "Switch 'Lock View' mode on"; } + } + + public override Texture2D Icon + { + get { return BGEditorUtility.LoadTexture2D(BGCurveSettingsForEditor.LockView ? BGEditorUtility.Image.BGLockOn123 : BGEditorUtility.Image.BGLockOff123); } + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenu.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenu.cs.meta new file mode 100644 index 0000000..f6f8347 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenu.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 25d2d1299235bef4fbddaea4c0a46414 +timeCreated: 1472984624 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuPoint.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuPoint.cs new file mode 100644 index 0000000..73b1df5 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuPoint.cs @@ -0,0 +1,146 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + //point's menu + public class BGSceneViewOverlayMenuPoint : BGSceneViewOverlayMenu + { + public override string Name + { + get { return "Point menu"; } + } + + public BGSceneViewOverlayMenuPoint(BGSceneViewOverlay overlay, BGCurveEditorPointsSelection editorSelection) : base(overlay, editorSelection) + { + menu = new PointMenu(overlay, editorSelection); + } + + + protected override bool Process(Event @event, BGCurveBaseMath math, float sceneViewHeight, ref Vector3 position, ref string message) + { + if (BGCurveSettingsForEditor.DisableSceneViewPointMenu) return false; + + var minDistanceToCamera = float.MaxValue; + var mousePosition = @event.mousePosition; + var cameraPos = SceneView.currentDrawingSceneView.camera.transform.position; + + var index = -1; + var pointsCount = math.Curve.PointsCount; + + for (var i = 0; i < pointsCount; i++) + { + var pointPos = math.GetPosition(i); + + var sqrMagnitude = (mousePosition - BGEditorUtility.GetSceneViewPosition(pointPos, sceneViewHeight)).sqrMagnitude; + if (sqrMagnitude > DistanceTolerance) continue; + + var sqrtMagnitude = Vector3.SqrMagnitude(cameraPos - pointPos); + + if (minDistanceToCamera < sqrtMagnitude) continue; + + //found a target + minDistanceToCamera = sqrMagnitude; + index = i; + } + + if (index < 0) return false; + + + //menu active + var point = math.Curve[index]; + position = math.GetPosition(index); + message = SuccessMessage("Point " + index); + menu.On(point, index); + + //============== Ok + return true; + } + + + //========================================================== Point menu + public sealed class PointMenu : AbstractMenu + { + public int PointIndex; + private BGCurvePointI point; + private MenuItemButton addToSelectionItem; + private MenuItemButton removeFromSelectionItem; + + public PointMenu(BGSceneViewOverlay overlay, BGCurveEditorPointsSelection editorSelection) + : base(overlay, editorSelection, "Point menu") + { + } + + public override string Details + { + get { return "Point " + PointIndex; } + } + + protected override void AdditionalMenuItems() + { + Add(new MenuSeparator()); + + //add before + Add(new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGPointInsertBefore123), "Insert a point before this point", + () => + { + var curve = point.Curve; + var settings = BGPrivateField.GetSettings(curve); + var index = curve.IndexOf(point); + + BGCurveEditor.AddPoint(curve, BGNewPointPositionManager.InsertBefore(curve, index, settings.ControlType, settings.Sections), index); + })); + + //add after + Add(new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGPointInsertAfter123), "Insert a point after this point", + () => + { + var curve = point.Curve; + var settings = BGPrivateField.GetSettings(curve); + var index = curve.IndexOf(point); + BGCurveEditor.AddPoint(curve, BGNewPointPositionManager.InsertAfter(curve, index, settings.ControlType, settings.Sections), index + 1); + })); + + + //add remove to selection + addToSelectionItem = new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGSelectionAdd123), "Add this point to selection", + () => EditorSelection.Add(point)); + + removeFromSelectionItem = new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGSelectionRemove123), "Remove this point from selection", + () => EditorSelection.Remove(point)); + + Add(addToSelectionItem); + Add(removeFromSelectionItem); + } + + protected override void SetControl(BGCurvePoint.ControlTypeEnum type) + { + point.ControlType = type; + } + + public void On(BGCurvePointI point, int index) + { + PointIndex = index; + this.point = point; + On(point.PositionWorld); + + Get(0).Current = point.ControlType == BGCurvePoint.ControlTypeEnum.Absent; + Get(1).Current = point.ControlType == BGCurvePoint.ControlTypeEnum.BezierSymmetrical; + Get(2).Current = point.ControlType == BGCurvePoint.ControlTypeEnum.BezierIndependant; + } + + protected override void Delete() + { + BGCurveEditor.DeletePoint(point.Curve, point.Curve.IndexOf(point)); + } + + public override void On(Vector3 position) + { + addToSelectionItem.Disabled = EditorSelection.Contains(point); + removeFromSelectionItem.Disabled = !addToSelectionItem.Disabled; + base.On(position); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuPoint.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuPoint.cs.meta new file mode 100644 index 0000000..3614bd9 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuPoint.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f64ca4438c929b04e8da2bfe20525440 +timeCreated: 1472274459 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuSelection.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuSelection.cs new file mode 100644 index 0000000..0fc132a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuSelection.cs @@ -0,0 +1,105 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGSceneViewOverlayMenuSelection : BGSceneViewOverlayMenu + { + public override string Name + { + get { return "Selection menu"; } + } + + public BGSceneViewOverlayMenuSelection(BGSceneViewOverlay overlay, BGCurveEditorPointsSelection editorSelection) + : base(overlay, editorSelection) + { + menu = new SelectionMenu(overlay, editorSelection); + } + + protected override bool Process(Event @event, BGCurveBaseMath math, float sceneViewHeight, ref Vector3 position, ref string message) + { + if (BGCurveSettingsForEditor.DisableSceneViewSelectionMenu || !menu.EditorSelection.HasSelected()) return false; + + + var selectedPos = menu.EditorSelection.GetAveragePosition(); + if (!(DistanceTolerance > (@event.mousePosition - BGEditorUtility.GetSceneViewPosition(selectedPos, sceneViewHeight)).sqrMagnitude)) return false; + + + //out params + position = selectedPos; + message = SuccessMessage("Selected " + menu.EditorSelection.CountSelected + " point(s)."); + + //turn on the menu + menu.On(position); + + //check if all points share the same control type + BGCurvePoint.ControlTypeEnum singleType = BGCurvePoint.ControlTypeEnum.Absent; + bool first = true, single=true; + menu.EditorSelection.ForEach(point => + { + if (first) + { + first = false; + singleType = point.ControlType; + } + else if (singleType != point.ControlType) + { + single = false; + return true; + } + + return false; + }); + + if (single) + { + menu.Get(0).Current = singleType == BGCurvePoint.ControlTypeEnum.Absent; + menu.Get(1).Current = singleType == BGCurvePoint.ControlTypeEnum.BezierSymmetrical; + menu.Get(2).Current = singleType == BGCurvePoint.ControlTypeEnum.BezierIndependant; + } + else menu.Get(0).Current = menu.Get(1).Current = menu.Get(2).Current = false; + + + return true; + } + + //========================================================== Selection menu + public sealed class SelectionMenu : AbstractMenu + { + public SelectionMenu(BGSceneViewOverlay overlay, BGCurveEditorPointsSelection editorSelection) + : base(overlay, editorSelection, "Selection menu") + { + } + + protected override void SetControl(BGCurvePoint.ControlTypeEnum type) + { + EditorSelection.SetControlTypeForSelected(type); + } + + protected override void Delete() + { + EditorSelection.DeleteSelected(); + } + + public override string Details + { + get { return "Selected " + EditorSelection.CountSelected + " point(s)."; } + } + + protected override void AdditionalMenuItems() + { + Add(new MenuSeparator()); + Add(new MenuItemButton(BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGSelectionRemove123), "Remove this point from selection", + () => + { + EditorSelection.Clear(); + EditorUtility.SetDirty(Overlay.Editor.Curve); + })); + } + + + } + + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuSelection.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuSelection.cs.meta new file mode 100644 index 0000000..8712ccd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayMenuSelection.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a24e39d345905a74eb25e8f16f456c30 +timeCreated: 1472984950 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAdd.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAdd.cs new file mode 100644 index 0000000..f5260ec --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAdd.cs @@ -0,0 +1,166 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public abstract class BGSceneViewOverlayPointAdd : BGSceneViewOverlay.SceneAction + { + protected const float ScalePreviewPoint = .18f; + + + private static readonly BGTransition.SwayTransition swayTransition = new BGTransition.SwayTransition(.8f, 1.2f, .6); + + + protected BGSceneViewOverlayPointAdd(BGSceneViewOverlay overlay) : base(overlay) + { + } + + protected static void PreviewControls(BGCurveSettings settings, Vector3 position, Vector3 control1World, Vector3 control2World) + { + BGEditorUtility.SwapHandlesColor(settings.ControlHandlesColor, () => + { + PreviewControl(settings, position, control1World); + PreviewControl(settings, position, control2World); + }); + } + + protected static void PreviewControl(BGCurveSettings settings, Vector3 position, Vector3 controlWorld) + { + var size = BGEditorUtility.GetHandleSize(position, ScalePreviewPoint*.8f); + + Handles.SphereCap(0, controlWorld, Quaternion.identity, size); + Handles.DrawLine(position, controlWorld); + } + + protected static void DrawSection(BGCurvePointI from, BGCurvePointI to, int parts) + { + BGEditorUtility.Split(@from, to, parts, (fromPos, toPos) => Handles.DrawDottedLine(fromPos, toPos, 2)); + } + + + // preview + protected void Preview(Vector3 position, BGCurve curve, ref float toLast, ref float toFirst) + { + var settings = overlay.Editor.Settings; + + //show point + BGEditorUtility.SwapHandlesColor(settings.SphereColor, () => Handles.SphereCap(0, position, Quaternion.identity, BGEditorUtility.GetHandleSize(position, ScalePreviewPoint))); + + //create a point + var newPoint = BGNewPointPositionManager.CreatePoint(position, curve, settings.ControlType, settings.Sections, out toLast, out toFirst, false); + + //show controls + if (newPoint.ControlType != BGCurvePoint.ControlTypeEnum.Absent) PreviewControls(settings, position, newPoint.ControlFirstWorld, newPoint.ControlSecondWorld); + + if (curve.PointsCount == 0) return; + + BGEditorUtility.SwapHandlesColor(BGCurveSettingsForEditor.ColorForNewSectionPreview, () => + { + // last To new + DrawSection(curve[curve.PointsCount - 1], newPoint, settings.Sections); + + AdditionalPreview(newPoint); + + // new To zero + if (curve.Closed) DrawSection(newPoint, curve[0], settings.Sections); + }); + } + + protected virtual void AdditionalPreview(BGCurvePoint newPoint) + { + } + + + //see base class for description + internal override bool Seize(Event currentEvent, ref Vector3 position, ref string message) + { + if (!Comply(currentEvent)) return false; + + + Vector3 intersectionPosition; + Plane plane; + + + if (currentEvent.type == EventType.mouseDown && currentEvent.control && currentEvent.button == 0) + { + //Mouse down for some action + var curve = overlay.Editor.Curve; + var settings = overlay.Editor.Settings; + + Cast(currentEvent, HandleUtility.GUIPointToWorldRay(currentEvent.mousePosition), out intersectionPosition, out message, out plane); + + if (message != null) BGCurveEditor.OverlayMessage.Display(message); + else + { + position = intersectionPosition; + BGCurveEditor.AddPoint(curve, + BGNewPointPositionManager.CreatePoint(intersectionPosition, curve, settings.ControlType, settings.Sections, true), + curve.PointsCount); + } + overlay.EventCanceller = new BGEditorUtility.EventCanceller(); + return true; + } + + + if (!(currentEvent.type == EventType.Repaint && currentEvent.control || currentEvent.type == EventType.MouseMove && currentEvent.control)) return false; + + var ray = HandleUtility.GUIPointToWorldRay(currentEvent.mousePosition); + Cast(currentEvent, ray, out intersectionPosition, out message, out plane); + + position = intersectionPosition; + + if (message != null) return true; + + Animation(plane, ray, swayTransition); + + //preview + float toLast = -1, toFirst = -1; + Preview(intersectionPosition, overlay.Editor.Curve, ref toLast, ref toFirst); + + //distance + message = BGSceneViewOverlay.ToOk("MouseClick to add a point\r\n") + + //to last + (toLast < 0 ? "First point is ready to go!" : "Distance to last=" + toLast) + + //to first + (toFirst < 0 ? "" : ", to first=" + toFirst); + return true; + } + + protected virtual void Animation(Plane plane, Ray ray, BGTransition.SwayTransition transition) + { + float enter; + if (plane.Raycast(ray, out enter)) + { + swayTransition.Tick(); + + Animate(transition, ray.GetPoint(enter), enter, plane); + } + } + + + protected virtual bool Comply(Event currentEvent) + { + return true; + } + + protected static Vector3[] GetVertsByPlaneAndDistance(Vector3 scale, Vector3 point, float distanceToCamera, Plane plane) + { + var m = Matrix4x4.TRS(point, Quaternion.LookRotation(plane.normal), scale); + var verts = new[] + {GetRectVector(-1, -1, distanceToCamera, m), GetRectVector(-1, 1, distanceToCamera, m), GetRectVector(1, 1, distanceToCamera, m), GetRectVector(1, -1, distanceToCamera, m)}; + return verts; + } + + private static Vector3 GetRectVector(float x, float y, float distance, Matrix4x4 matrix) + { + return matrix.MultiplyPoint(new Vector3(x, y)*distance/18); + } + + + //abstract + protected abstract void Animate(BGTransition.SwayTransition swayTransition, Vector3 point, float distanceToCamera, Plane plane); + + protected abstract void Cast(Event @event, Ray ray, out Vector3 position, out string error, out Plane plane); + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAdd.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAdd.cs.meta new file mode 100644 index 0000000..7d27621 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAdd.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4bcec5eb8d6d6af48bacbcf49bee822e +timeCreated: 1472345427 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddAtDistance.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddAtDistance.cs new file mode 100644 index 0000000..50c768f --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddAtDistance.cs @@ -0,0 +1,74 @@ +using BansheeGz.BGSpline.Curve; +using UnityEngine; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGSceneViewOverlayPointAddAtDistance : BGSceneViewOverlayPointAdd + { + private static readonly Color32 PointersColor = Color.white; + private Vector3 lastPosition; + + public BGSceneViewOverlayPointAddAtDistance(BGSceneViewOverlay overlay) : base(overlay) + { + } + + public override string Name + { + get { return "Add point at Distance"; } + } + + + protected override bool Comply(Event currentEvent) + { + return currentEvent.shift; + } + + protected override void Cast(Event @event, Ray ray, out Vector3 position, out string error, out Plane plane) + { + var settings = overlay.Editor.Settings; + + lastPosition = position = ray.GetPoint(settings.NewPointDistance); + + var curve = overlay.Editor.Curve; + if (curve.Mode2DOn) + { + BGSceneViewOverlayPointAddSnap2D.Get2DPlane(out plane, curve); + position = position - Vector3.Project(position, plane.normal.normalized); + } + else plane = new Plane(ray.direction.normalized, lastPosition); + + error = null; + } + + protected override void AdditionalPreview(BGCurvePoint newPoint) + { + var curve = overlay.Editor.Curve; + if (!curve.Mode2DOn) return; + + Handles.DrawLine(lastPosition, newPoint.PositionWorld); + } + + protected override void Animation(Plane plane, Ray ray, BGTransition.SwayTransition transition) + { + var curve = overlay.Editor.Curve; + + if (!curve.Mode2DOn) base.Animation(plane, ray, transition); + else + { + var settings = overlay.Editor.Settings; + transition.Tick(); + Animate(transition, lastPosition, settings.NewPointDistance, plane); + } + } + + protected override void Animate(BGTransition.SwayTransition swayTransition, Vector3 point, float distanceToCamera, Plane plane) + { + var verts = GetVertsByPlaneAndDistance(new Vector3(swayTransition.Value, swayTransition.Value, swayTransition.Value), point, distanceToCamera, plane); + + var size = swayTransition.Value*ScalePreviewPoint*distanceToCamera/5; + + BGEditorUtility.SwapHandlesColor(PointersColor, () => { foreach (var position in verts) Handles.ConeCap(0, position, Quaternion.LookRotation(point - position), size); }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddAtDistance.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddAtDistance.cs.meta new file mode 100644 index 0000000..c1eb169 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddAtDistance.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 13e1047830cfadc46929d3f713cdca63 +timeCreated: 1472280829 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap2D.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap2D.cs new file mode 100644 index 0000000..c9d1754 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap2D.cs @@ -0,0 +1,75 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGSceneViewOverlayPointAddSnap2D : BGSceneViewOverlayPointAdd + { + private static readonly BGTransition.SwayTransition rectTransition = new BGTransition.SwayTransition(1.1f, 1.3f, 2); + + public BGSceneViewOverlayPointAddSnap2D(BGSceneViewOverlay overlay) : base(overlay) + { + } + + public override string Name + { + get { return "Add point and Snap to Curve's 2D Plane"; } + } + + protected override void Cast(Event @event, Ray ray, out Vector3 position, out string error, out Plane plane) + { + var curve = overlay.Editor.Curve; + + Get2DPlane(out plane, curve); + + float distance; + if (!plane.Raycast(ray, out distance)) + { + error = BGSceneViewOverlay.ToError("Curve is in 2D mode! \r\n Curve's plane does not intersect with the current point.") + + "\r\nUse Ctrl+Shift+Click to spawn a point at the distance,\r\n which is set in settings"; + + position = ray.GetPoint(10); + } + else + { + error = null; + position = ray.GetPoint(distance); + } + } + + public static void Get2DPlane(out Plane plane, BGCurve curve) + { + switch (curve.Mode2D) + { + case BGCurve.Mode2DEnum.XY: + plane = new Plane(curve.ToWorldDirection(Vector3.forward), curve.transform.position); + break; + case BGCurve.Mode2DEnum.XZ: + plane = new Plane(curve.ToWorldDirection(Vector3.up), curve.transform.position); + break; + default: +// case BGCurve.Mode2DEnum.YZ: + plane = new Plane(curve.ToWorldDirection(Vector3.right), curve.transform.position); + break; + } + } + + protected override bool Comply(Event currentEvent) + { + return overlay.Editor.Curve.Mode2D != BGCurve.Mode2DEnum.Off; + } + + protected override void Animate(BGTransition.SwayTransition swayTransition, Vector3 point, float distanceToCamera, Plane plane) + { + rectTransition.Tick(); + + var verts = GetVertsByPlaneAndDistance(new Vector3(rectTransition.Value, rectTransition.Value, rectTransition.Value), point, distanceToCamera, plane); + + + var color = BGCurveSettingsForEditor.HandleColorForAddAndSnap2D; + Handles.DrawSolidRectangleWithOutline(verts, color, new Color32(color.r, color.g, color.b, 255)); + Handles.DrawWireDisc(point, Vector3.Cross(verts[1] - verts[0], verts[2] - verts[0]), swayTransition.Value*distanceToCamera/24); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap2D.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap2D.cs.meta new file mode 100644 index 0000000..48c8bab --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap2D.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cd91011407f1abc41ae27e638529e479 +timeCreated: 1472950363 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap3D.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap3D.cs new file mode 100644 index 0000000..a9cf2f2 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap3D.cs @@ -0,0 +1,51 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + //add point and snap to the mesh (or curve's 2D plane) + public class BGSceneViewOverlayPointAddSnap3D : BGSceneViewOverlayPointAdd + { + public BGSceneViewOverlayPointAddSnap3D(BGSceneViewOverlay overlay) + : base(overlay) + { + } + + public override string Name + { + get { return "Add point and Snap to a Mesh"; } + } + + protected override void Animate(BGTransition.SwayTransition swayTransition, Vector3 point, float distanceToCamera, Plane plane) + { + //show rect + var verts = GetVertsByPlaneAndDistance(new Vector3(swayTransition.Value, swayTransition.Value, swayTransition.Value), point, distanceToCamera, plane); + var color = BGCurveSettingsForEditor.HandleColorForAddAndSnap3D; + Handles.DrawSolidRectangleWithOutline(verts, color, new Color32(color.r, color.g, color.b, 255)); + } + + + protected override void Cast(Event @event, Ray ray, out Vector3 position, out string error, out Plane plane) + { + RaycastHit hit; + if (Physics.Raycast(ray, out hit)) + { + position = hit.point; + plane = new Plane(hit.normal, hit.point); + error = null; + } + else + { + error = BGSceneViewOverlay.ToError("No mesh (or collider) to snap a point to!") + " \r\n Use Ctrl+Shift+Click to spawn a point at the distance,\r\n which is set in settings"; + position = ray.GetPoint(10); + plane = new Plane(); + } + } + + protected override bool Comply(Event currentEvent) + { + return overlay.Editor.Curve.Mode2D == BGCurve.Mode2DEnum.Off; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap3D.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap3D.cs.meta new file mode 100644 index 0000000..c7e50d5 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Overlay/BGSceneViewOverlayPointAddSnap3D.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ef3acc6fea76e7b449cac399c8e0f891 +timeCreated: 1472273229 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings.meta new file mode 100644 index 0000000..85c7dd4 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1fa6dd41561b2464fbeac539fb6cbf34 +folderAsset: yes +timeCreated: 1472482812 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditor.cs new file mode 100644 index 0000000..638e6eb --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditor.cs @@ -0,0 +1,248 @@ +using System; +using UnityEngine; +using System.Linq; +using System.Reflection; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public static class BGCurveSettingsForEditor + { + public enum CoordinateSpaceEnum + { + Local = 0, + LocalTransformed = 1, + World = 2, + } + + + //Keys + private const string InspectorPointsCoordinatesKey = "BansheeGZ.BGCurve.inspectorPointsCoordinates"; + private const string InspectorControlsCoordinatesKey = "BansheeGZ.BGCurve.inspectorControlsCoordinates"; + + private const string DisableRectangularSelectionKey = "BansheeGZ.BGCurve.disableRectangularSelection"; + private const string DisableSceneViewPointMenuKey = "BansheeGZ.BGCurve.disableSceneViewPointMenu"; + private const string DisableSceneViewSelectionMenuKey = "BansheeGZ.BGCurve.disableSceneViewSelectionMenu"; + private const string DisableInspectorPointMenuKey = "BansheeGZ.BGCurve.disableInspectorPointMenu"; + private const string CcInspectorHandlesOffKey = "BansheeGZ.BGCurve.inspectorHandlesOff"; + + private const string LockViewKey = "BansheeGZ.BGCurve.lockView"; + private const string CurrentTabKey = "BansheeGZ.BGCurve.currentTab"; + + //colors + private const string HandleColorForAddAndSnap3DKey = "BansheeGZ.BGCurve.handleColorForAddAndSnap3D"; + private const string HandleColorForAddAndSnap2DKey = "BansheeGZ.BGCurve.handleColorForAddAndSnap2D"; + private const string ColorForRectangularSelectionKey = "BansheeGZ.BGCurve.colorForRectangularSelection"; + private const string ColorForLabelBackgroundKey = "BansheeGZ.BGCurve.colorForLabelBackground"; + private const string ColorForNewSectionPreviewKey = "BansheeGZ.BGCurve.colorForNewSectionPreview"; + + //Default values + private static readonly Color32 HandleColorForAddAndSnap3DDefault = new Color32(46, 143, 168, 20); + private static readonly Color32 HandleColorForAddAndSnap2DDefault = new Color32(255, 255, 255, 10); + private static readonly Color32 ColorForRectangularSelectionDefault = new Color32(46, 143, 168, 25); + private static readonly Color32 ColorForLabelBackgroundDefault = new Color32(255, 255, 255, 25); + private static readonly Color32 ColorForNewSectionPreviewDefault = new Color32(255, 0, 0, 255); + + private static CoordinateSpaceEnum inspectorPointCoordinateSpace; + private static CoordinateSpaceEnum inspectorControlCoordinateSpace; + + private static bool disableRectangularSelection; + private static bool disableSceneViewPointMenu; + private static bool disableSceneViewSelectionMenu; + private static bool disableInspectorPointMenu; + private static bool lockView; + private static bool ccInspectorHandlesOff; + + private static Color32 handleColorForAddAndSnap3D; + private static Color32 handleColorForAddAndSnap2D; + private static Color32 colorForRectangularSelection; + private static Color32 colorForLabelBackground; + private static Color32 colorForNewSectionPreview; + + private static int currentTab; + + public static int CurrentTab + { + get { return currentTab; } + set { SaveInt(ref currentTab, value, CurrentTabKey); } + } + + public static CoordinateSpaceEnum InspectorPointCoordinateSpace + { + get { return inspectorPointCoordinateSpace; } + set + { + if (value == inspectorPointCoordinateSpace) return; + + var val = (int) inspectorPointCoordinateSpace; + SaveInt(ref val, (int) value, InspectorPointsCoordinatesKey); + inspectorPointCoordinateSpace = value; + } + } + + public static CoordinateSpaceEnum InspectorControlCoordinateSpace + { + get { return inspectorControlCoordinateSpace; } + set + { + if (value == inspectorControlCoordinateSpace) return; + + var val = (int) inspectorControlCoordinateSpace; + SaveInt(ref val, (int) value, InspectorControlsCoordinatesKey); + inspectorControlCoordinateSpace = value; + } + } + + public static bool CcInspectorHandlesOff + { + get { return ccInspectorHandlesOff; } + set { SaveBool(ref ccInspectorHandlesOff, value, CcInspectorHandlesOffKey); } + } + + public static bool LockView + { + get { return lockView; } + set { SaveBool(ref lockView, value, LockViewKey); } + } + + + public static bool DisableRectangularSelection + { + get { return disableRectangularSelection; } + set { SaveBool(ref disableRectangularSelection, value, DisableRectangularSelectionKey); } + } + + public static bool DisableSceneViewPointMenu + { + get { return disableSceneViewPointMenu; } + set { SaveBool(ref disableSceneViewPointMenu, value, DisableSceneViewPointMenuKey); } + } + + public static bool DisableSceneViewSelectionMenu + { + get { return disableSceneViewSelectionMenu; } + set { SaveBool(ref disableSceneViewSelectionMenu, value, DisableSceneViewSelectionMenuKey); } + } + + public static bool DisableInspectorPointMenu + { + get { return disableInspectorPointMenu; } + set { SaveBool(ref disableInspectorPointMenu, value, DisableInspectorPointMenuKey); } + } + + + public static Color32 HandleColorForAddAndSnap3D + { + get { return handleColorForAddAndSnap3D; } + set { SaveColor(ref handleColorForAddAndSnap3D, value, HandleColorForAddAndSnap3DKey); } + } + + public static Color32 HandleColorForAddAndSnap2D + { + get { return handleColorForAddAndSnap2D; } + set { SaveColor(ref handleColorForAddAndSnap2D, value, HandleColorForAddAndSnap2DKey); } + } + + public static Color32 ColorForRectangularSelection + { + get { return colorForRectangularSelection; } + set { SaveColor(ref colorForRectangularSelection, value, ColorForRectangularSelectionKey); } + } + + public static Color32 ColorForLabelBackground + { + get { return colorForLabelBackground; } + set { SaveColor(ref colorForLabelBackground, value, ColorForLabelBackgroundKey); } + } + + public static Color32 ColorForNewSectionPreview + { + get { return colorForNewSectionPreview; } + set { SaveColor(ref colorForNewSectionPreview, value, ColorForNewSectionPreviewKey); } + } + + static BGCurveSettingsForEditor() + { + Init(); + } + + private static void SaveBool(ref bool oldValue, bool newValue, string key) + { + CheckAndSave(ref oldValue, newValue, () => EditorPrefs.SetBool(key, newValue)); + } + + private static void SaveInt(ref int oldValue, int newValue, string key) + { + CheckAndSave(ref oldValue, newValue, () => EditorPrefs.SetInt(key, newValue)); + } + + private static void SaveColor(ref Color32 oldValue, Color32 newValue, string key) + { + CheckAndSave(ref oldValue, newValue, () => EditorPrefs.SetString(key, ColorToString(newValue))); + } + + private static void CheckAndSave(ref T oldValue, T newValue, Action notEqualAction) + { + if (oldValue.Equals(newValue)) return; + oldValue = newValue; + notEqualAction(); + } + + private static void Init() + { + inspectorPointCoordinateSpace = (CoordinateSpaceEnum) EditorPrefs.GetInt(InspectorPointsCoordinatesKey, (int) CoordinateSpaceEnum.World); + inspectorControlCoordinateSpace = (CoordinateSpaceEnum) EditorPrefs.GetInt(InspectorControlsCoordinatesKey); + + disableRectangularSelection = EditorPrefs.GetBool(DisableRectangularSelectionKey); + disableSceneViewPointMenu = EditorPrefs.GetBool(DisableSceneViewPointMenuKey); + disableSceneViewSelectionMenu = EditorPrefs.GetBool(DisableSceneViewSelectionMenuKey); + disableInspectorPointMenu = EditorPrefs.GetBool(DisableInspectorPointMenuKey); + + lockView = EditorPrefs.GetBool(LockViewKey); + currentTab = EditorPrefs.GetInt(CurrentTabKey); + + + handleColorForAddAndSnap3D = StringToColor(EditorPrefs.GetString(HandleColorForAddAndSnap3DKey), HandleColorForAddAndSnap3DDefault); + handleColorForAddAndSnap2D = StringToColor(EditorPrefs.GetString(HandleColorForAddAndSnap2DKey), HandleColorForAddAndSnap2DDefault); + colorForRectangularSelection = StringToColor(EditorPrefs.GetString(ColorForRectangularSelectionKey), ColorForRectangularSelectionDefault); + colorForLabelBackground = StringToColor(EditorPrefs.GetString(ColorForLabelBackgroundKey), ColorForLabelBackgroundDefault); + colorForNewSectionPreview = StringToColor(EditorPrefs.GetString(ColorForNewSectionPreviewKey), ColorForNewSectionPreviewDefault); + } + + //resets to default + public static void Reset() + { + var constants = typeof(BGCurveSettingsForEditor).GetFields( + BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy) + .Where(c => c.IsLiteral && !c.IsInitOnly && c.Name.EndsWith("Key")).ToList(); + + foreach (var constant in constants) EditorPrefs.DeleteKey((string) constant.GetValue(null)); + + Init(); + } + + private static string ColorToString(Color32 color) + { + return color.r + "," + color.g + "," + color.b + "," + color.a; + } + + private static Color32 StringToColor(string colorString, Color32 defaultColor) + { + if (string.IsNullOrEmpty(colorString)) return defaultColor; + + var parts = colorString.Split(','); + if (parts.Length != 4) return defaultColor; + + + try + { + return new Color32(byte.Parse(parts[0]), byte.Parse(parts[1]), byte.Parse(parts[2]), byte.Parse(parts[3])); + } + catch (Exception e) + { + Debug.LogException(e); + return defaultColor; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditor.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditor.cs.meta new file mode 100644 index 0000000..e306f9c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9d802b133f80b6349ad532e4d415d660 +timeCreated: 1472973279 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditorWindow.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditorWindow.cs new file mode 100644 index 0000000..b5d8831 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditorWindow.cs @@ -0,0 +1,117 @@ +using UnityEngine; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGCurveSettingsForEditorWindow : EditorWindow + { + private const int Padding = 20; + private static readonly Vector2 WindowSize = new Vector2(600, 400); + + private Vector2 scrollPos; + + + internal static void Open() + { + BGEditorUtility.ShowPopupWindow(WindowSize); + } + + private void OnGUI() + { + scrollPos = EditorGUILayout.BeginScrollView(scrollPos); + ShowSettings(); + EditorGUILayout.EndScrollView(); + } + + private static void ShowSettings() + { + BGEditorUtility.SwapLabelWidth(300, () => + { + BGEditorUtility.Vertical(new GUIStyle("Box") {padding = new RectOffset(Padding, Padding, Padding, Padding)}, () => + { + EditorGUILayout.LabelField("BG Curve Editor Settings", new GUIStyle("Box") {fontSize = 22}); + + if (GUILayout.Button(new GUIContent("Reset to defaults", "Reset all editor settings to their defaults.")) + && BGEditorUtility.Confirm("Reset settings", "Reset All Editor settings to defaults? It does not affect curve's settings.", "Reset")) + { + BGCurveSettingsForEditor.Reset(); + } + + //coordinates for points and controls + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.PopupField(BGCurveSettingsForEditor.InspectorPointCoordinateSpace, "Point Coordinates", + b => BGCurveSettingsForEditor.InspectorPointCoordinateSpace = (BGCurveSettingsForEditor.CoordinateSpaceEnum) b); + EditorGUILayout.HelpBox("Coordinate Space for points (for Inspector's fields inder Points tab.)", MessageType.Info); + }); + + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.PopupField(BGCurveSettingsForEditor.InspectorControlCoordinateSpace, "Point Controls Coordinates", + b => BGCurveSettingsForEditor.InspectorControlCoordinateSpace = (BGCurveSettingsForEditor.CoordinateSpaceEnum)b); + EditorGUILayout.HelpBox("Coordinate Space for points controls (for Inspector's fields inder Points tab.)", MessageType.Info); + }); + + + // disable fields + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.ToggleField(BGCurveSettingsForEditor.DisableSceneViewPointMenu, "Disable SV Point Menu", b => BGCurveSettingsForEditor.DisableSceneViewPointMenu = b); + EditorGUILayout.HelpBox("Disable point's menu, which is activated in Scene View by holding Ctrl over a point.", MessageType.Info); + }); + + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.ToggleField(BGCurveSettingsForEditor.DisableSceneViewSelectionMenu, "Disable SV Selection Menu", b => BGCurveSettingsForEditor.DisableSceneViewSelectionMenu = b); + EditorGUILayout.HelpBox("Disable selection's menu, which is activated in Scene View by holding Ctrl over a selection handles.", MessageType.Info); + }); + +/* + BGEUtil.VerticalBox(() => + { + BGEUtil.ToggleField(BGCurveEditorSettings.DisableInspectorPointMenu, "Disable Inspector Points Menu", b => BGCurveEditorSettings.DisableInspectorPointMenu = b); + EditorGUILayout.HelpBox("Disable points menu, which is located under Points tab in Inspector.", MessageType.Info); + }); + */ + + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.ToggleField(BGCurveSettingsForEditor.DisableRectangularSelection, "Disable Rectangular Selection", b => BGCurveSettingsForEditor.DisableRectangularSelection = b); + EditorGUILayout.HelpBox("Disable rectangular selection in Scene View, which is activated by holding shift and mouse dragging.", MessageType.Info); + }); + + + // colors + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.ColorField("Rectangular Selection Color", BGCurveSettingsForEditor.ColorForRectangularSelection, b => BGCurveSettingsForEditor.ColorForRectangularSelection = b); + EditorGUILayout.HelpBox("Color for Rectangular Selection background", MessageType.Info); + }); + + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.ColorField("Add and Snap 3D Handles Color", BGCurveSettingsForEditor.HandleColorForAddAndSnap3D, b => BGCurveSettingsForEditor.HandleColorForAddAndSnap3D = b); + EditorGUILayout.HelpBox("Color for handles, shown for 3D curve in Scene View when new point is previewed.", MessageType.Info); + }); + + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.ColorField("Add and Snap 2D Handles Color", BGCurveSettingsForEditor.HandleColorForAddAndSnap2D, b => BGCurveSettingsForEditor.HandleColorForAddAndSnap2D = b); + EditorGUILayout.HelpBox("Color for handles, shown for 2D curve in Scene View when new point is previewed.", MessageType.Info); + }); + + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.ColorField("Points labels back color", BGCurveSettingsForEditor.ColorForLabelBackground, b => BGCurveSettingsForEditor.ColorForLabelBackground = b); + EditorGUILayout.HelpBox("Background color for points labels in Scene View.", MessageType.Info); + }); + BGEditorUtility.VerticalBox(() => + { + BGEditorUtility.ColorField("New section preview color", BGCurveSettingsForEditor.ColorForNewSectionPreview, b => BGCurveSettingsForEditor.ColorForNewSectionPreview = b); + EditorGUILayout.HelpBox("Color for new section preview in Scene View.", MessageType.Info); + }); + }); + }); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditorWindow.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditorWindow.cs.meta new file mode 100644 index 0000000..864abd2 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsForEditorWindow.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cd56b8c2c4cb03b41a910f6f1281b6bc +timeCreated: 1472981091 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsOperations.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsOperations.cs new file mode 100644 index 0000000..0ae8a3e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsOperations.cs @@ -0,0 +1,144 @@ +using System.Collections.Generic; +using System.IO; +using BansheeGz.BGSpline.Curve; +using UnityEngine; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public static class BGCurveSettingsOperations + { + private const string DefaultFileName = "BGDefaultSettings123"; + + private const string EditorKey = "BansheeGZ.BGCurve.settingsDir"; + + private static string[] allSettings; + private static bool dirty; + + public static BGCurveSettings LoadDefault() + { + return Load(DefaultFileName); + } + + public static BGCurveSettings Load(string asset) + { + var dir = GetPath(); + if (dir == null || !IsValid(dir)) return null; + + var loaded = AssetDatabase.LoadAssetAtPath(GetFullPath(dir, asset)); + return loaded == null ? null : Object.Instantiate(loaded).Settings; + } + + + public static bool SaveDefault(BGCurveSettings settings) + { + return Save(settings, DefaultFileName); + } + + public static bool Save(BGCurveSettings settings, string name) + { + var dir = GetPath(); + if (!IsValid(dir)) dir = null; + + if (dir == null) dir = ChoseFolder(); + + if (dir == null) return false; + + var settingsSo = ScriptableObject.CreateInstance(); + settingsSo.Settings = settings; + + var fullPath = GetFullPath(dir, name); + AssetDatabase.CreateAsset(settingsSo, fullPath); + AssetDatabase.SaveAssets(); + dirty = true; + return true; + } + + private static string GetFullPath(string dir, string asset) + { + return dir + Path.DirectorySeparatorChar + asset + ".asset"; + } + + private static string ChoseFolder() + { + var dir = EditorUtility.OpenFolderPanel("Chose a folder to store default settings", Application.dataPath, ""); + + if (dir == null || dir.Equals("")) return null; + + + if (!dir.StartsWith(Application.dataPath)) + { + Debug.Log("Failed. Path should be relative to project folder"); + dir = null; + } + else + { + //this was a stupid idea to include "Assets" to the path + dir = "Assets" + dir.Substring(Application.dataPath.Length); + EditorPrefs.SetString(EditorKey, dir); + dirty = true; + } + return dir; + } + + public static void ChoseDir() + { + ChoseFolder(); + } + + public static string GetPath() + { + var path = EditorPrefs.GetString(EditorKey); + return path == null || path.Equals("") ? null : path; + } + + public static bool IsValid(string dir) + { + //this was a stupid idea to include "Assets" to the path + return dir != null && !dir.Equals("") && Directory.Exists(Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) + dir); + } + + public static string[] GetAll() + { + var path = GetPath(); + if (!IsValid(path)) return new string[0]; + + if (allSettings == null || dirty) + { + dirty = false; + Reload(path); + } + + return allSettings; + } + + public static void Reload(string path) + { + var guids = AssetDatabase.FindAssets("t:BGCurveSettingsSO", new[] {path}); + if (guids != null && guids.Length > 0) + { + var pathes = new List(); + foreach (var guid in guids) + { + var assetPath = AssetDatabase.GUIDToAssetPath(guid); + var separatorIndex = assetPath.LastIndexOf(Path.DirectorySeparatorChar); + + if (separatorIndex > 0) assetPath = assetPath.Substring(separatorIndex + 1); + + separatorIndex = assetPath.LastIndexOf(Path.AltDirectorySeparatorChar); + + if (separatorIndex > 0) assetPath = assetPath.Substring(separatorIndex + 1); + + if (assetPath.EndsWith(".asset")) assetPath = assetPath.Substring(0, assetPath.Length - 6); + + pathes.Add(assetPath); + } + allSettings = pathes.ToArray(); + } + else + { + allSettings = new string[0]; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsOperations.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsOperations.cs.meta new file mode 100644 index 0000000..ce2f47e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsOperations.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3961a72ccd7952343b4cee470a7c51cb +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsSO.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsSO.cs new file mode 100644 index 0000000..a4e7c98 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsSO.cs @@ -0,0 +1,12 @@ +using System; +using BansheeGz.BGSpline.Curve; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + [Serializable] + public class BGCurveSettingsSO : ScriptableObject + { + public BGCurveSettings Settings; + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsSO.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsSO.cs.meta new file mode 100644 index 0000000..53a14f5 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Settings/BGCurveSettingsSO.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 363780417ece4f1439ee477913bf05e3 +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils.meta new file mode 100644 index 0000000..ef4fac6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5d766538e07f6b44595f6f99251584c2 +folderAsset: yes +timeCreated: 1472482870 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGEditorUtility.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGEditorUtility.cs new file mode 100644 index 0000000..55c2d90 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGEditorUtility.cs @@ -0,0 +1,1207 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using BansheeGz.BGSpline.Curve; +using UnityEngine; +using UnityEditor; +using UnityEditor.AnimatedValues; + +namespace BansheeGz.BGSpline.Editor +{ + public static class BGEditorUtility + { + private const string DefaultIconPath = "Assets/BansheeGz/BGCurve/Icons/"; + + //exact names for icons + public enum Image + { + BGCurveLogo123, + BGDelete123, + BGAdd123, + BGMoveUp123, + BGMoveDown123, + BGPoints123, + BGConvertAll123, + BGTickNo123, + BGTickYes123, + BGSelectAll123, + BGDeSelectAll123, + BGSettings123, + BGComponents123, + BGFields123, + BGTableHeader123, + BGTableCell123, + BGTableTitle123, + BGBoxWithBorder123, + BGPointSelected123, + BGPointMenu123, + BGControlAbsent123, + BGControlBezierSymmetrical123, + BGControlBezierIndependent123, + BGPointDelete123, + BGLockOff123, + BGLockOn123, + BGCcNoImage123, + BGCurveComponents123, + BGHelp123, + BGBoxRed123, + BGBoxWhite123, + BGCollapseAll123, + BGExpandAll123, + BGHierarchyIcon123, + BGHierarchySelectedIcon123, + BGHierarchyErrorIcon123, + BGHierarchyErrorSelectedIcon123, + BGOn123, + BGOff123, + BGHierarchyWarningSelectedIcon123, + BGHierarchyWarningIcon123, + BGMenuItemBackground123, + BGPointInsertAfter123, + BGPointInsertBefore123, + BGSelectionAdd123, + BGSelectionRemove123, + BGExpanded123, + BGCollapsed123, + BGSettingsIcon123, + BGCcEditName123, + BGHandlesOn123, + BGHandlesOff123, + BGCopy123, + BGPaste123 + } + + private static readonly DragSession dragSession = new DragSession(); + private static Texture2D whiteTexture1x1; + + private static float xSnap = EditorPrefs.GetFloat("MoveSnapX", 1f); + private static float ySnap = EditorPrefs.GetFloat("MoveSnapY", 1f); + private static float zSnap = EditorPrefs.GetFloat("MoveSnapZ", 1f); + + private static string currentIconPath = DefaultIconPath; + private static string additionalCcIconPath; + + private static readonly List layers = new List(); + private static readonly List layerNumbers = new List(); + private static readonly List optionsList = new List(); + private static readonly List fieldsList = new List(); + private static bool vertexSnappingOn; + + static BGEditorUtility() + { + ReloadSnapSettings(); + } + + public static void ReloadSnapSettings() + { + xSnap = EditorPrefs.GetFloat("MoveSnapX", 1f); + ySnap = EditorPrefs.GetFloat("MoveSnapY", 1f); + zSnap = EditorPrefs.GetFloat("MoveSnapZ", 1f); + } + + // ============================================== OnSceneGui utils + + public static void SwapHandlesColor(Color color, Action action) + { + var oldColor = Handles.color; + Handles.color = color; + action(); + Handles.color = oldColor; + } + + public static void SwapGizmosColor(Color color, Action action) + { + var oldColor = Gizmos.color; + Gizmos.color = color; + action(); + Gizmos.color = oldColor; + } + + public static Vector2 GetSceneViewPosition(Vector3 position, float sceneViewHeight) + { + var screenPoint = SceneView.currentDrawingSceneView.camera.WorldToScreenPoint(position); + return new Vector2(screenPoint.x, sceneViewHeight - screenPoint.y); + } + + public static Vector2 GetSceneViewPosition(Vector3 position) + { + var screenPoint = SceneView.currentDrawingSceneView.camera.WorldToScreenPoint(position); + return new Vector2(screenPoint.x, GetSceneViewHeight() - screenPoint.y); + } + + public static float GetSceneViewHeight() + { + return SceneView.currentDrawingSceneView.camera.pixelHeight; + } + + public static float GetHandleSize(Vector3 position, float scale = 1) + { + return HandleUtility.GetHandleSize(position)*scale; + } + + // ============================================== OnInspectorGui utils + public static void SwapGuiBackgroundColor(Color color, Action action) + { + var oldColor = GUI.backgroundColor; + GUI.backgroundColor = color; + + Assign(ref whiteTexture1x1, () => Texture1X1(Color.white)); + + try + { + var temp = whiteTexture1x1.width; + temp.Equals(1); + } + catch (MissingReferenceException) + { + //have no darn idea about any other way to reload the texture + whiteTexture1x1 = Texture1X1(Color.white); + } + + Horizontal(new GUIStyle(GUIStyle.none) {normal = {background = whiteTexture1x1}}, action); + GUI.backgroundColor = oldColor; + } + + public static void FadeGroup(BoolAnimatedProperty boolProperty, Action callback) + { + VerticalBox(() => + { + boolProperty.Property.boolValue = boolProperty.AnimBool.target = EditorGUILayout.ToggleLeft(boolProperty.Property.displayName, boolProperty.Property.boolValue); + if (EditorGUILayout.BeginFadeGroup(boolProperty.AnimBool.faded)) Indent(1, callback); + EditorGUILayout.EndFadeGroup(); + }); + } + + public static void Indent(int steps, Action action) + { + StartIndent(steps); + action(); + EndIndent(steps); + } + + public static void EndIndent(int steps = 2) + { + EditorGUI.indentLevel -= steps; + } + + public static void StartIndent(int steps = 2) + { + EditorGUI.indentLevel += steps; + } + + public static bool ButtonOnOff(ref bool value, string name, string tooltip, Color onColor, GUIContent onContent, GUIContent offContent, Action additionalAction = null) + { + var myValue = value; + Action action = () => + { + EditorGUILayout.PrefixLabel(new GUIContent(name, tooltip)); + if (GUILayout.Button(myValue ? onContent : offContent)) myValue = !myValue; + + if (additionalAction != null) additionalAction(); + }; + + if (myValue) SwapGuiBackgroundColor(onColor, action); + else HorizontalBox(action); + + value = myValue; + return myValue; + } + + + // ============================================== Layout + public static void Vertical(Action callback) + { + Vertical(GUIStyle.none, callback); + } + + public static void Vertical(GUIStyle style, Action callback) + { + EditorGUILayout.BeginVertical(style); + callback(); + EditorGUILayout.EndVertical(); + } + + public static void VerticalBox(Action callback) + { + Vertical("Box", callback); + } + + public static void Horizontal(Action callback) + { + Horizontal(GUIStyle.none, callback); + } + + public static void Horizontal(GUIStyle style, Action callback) + { + EditorGUILayout.BeginHorizontal(style); + callback(); + EditorGUILayout.EndHorizontal(); + } + + public static void HorizontalBox(Action callback) + { + Horizontal("Box", callback); + } + + + // ============================================== Fields + public static void TextField(Rect rect, string value, Action action, bool isDelayed) + { + var newValue = !isDelayed ? EditorGUI.TextField(rect, value) : EditorGUI.DelayedTextField(rect, value); + if (!String.Equals(newValue, value)) action(newValue); + } + + public static void TextField(string value, Action action, bool isDelayed) + { + var newValue = !isDelayed ? EditorGUILayout.TextField(value) : EditorGUILayout.DelayedTextField(value); + if (!String.Equals(newValue, value)) action(newValue); + } + + public static void TextField(string label, string value, Action action, bool isDelayed) + { + var newValue = !isDelayed ? EditorGUILayout.TextField(label, value) : EditorGUILayout.DelayedTextField(label, value); + if (!String.Equals(newValue, value)) action(newValue); + } + + public static void BoolField(Rect rect, bool value, Action action) + { + var newValue = EditorGUI.Toggle(rect, value); + if (value != newValue) action(newValue); + } + + public static void BoolField(string label, bool value, Action action) + { + var newValue = EditorGUILayout.Toggle(label, value); + if (value != newValue) action(newValue); + } + + public static void Vector3Field(string name, string tooltip, Vector3 value, Action action) + { + var newValue = EditorGUILayout.Vector3Field(new GUIContent(name, tooltip), value); + if (AnyChange(newValue, value)) action(newValue); + } + + public static void Vector2Field(string name, string tooltip, Vector2 value, Action action) + { + var newValue = EditorGUILayout.Vector2Field(new GUIContent(name, tooltip), value); + if (AnyChange(newValue, value)) action(newValue); + } + + public static void ToggleField(bool value, string label, Action action) + { + var newValue = EditorGUILayout.Toggle(label, value); + if (value != newValue) action(newValue); + } + + public static void ToggleField(Rect rect, bool value, Action action) + { + var newValue = EditorGUI.Toggle(rect, value); + if (value ^ newValue && action != null) action(newValue); + } + + public static void IntField(string label, int value, Action action) + { + var newValue = EditorGUILayout.IntField(label, value); + if (value != newValue) action(newValue); + } + + public static void FloatField(string label, float value, Action action) + { + var newValue = EditorGUILayout.FloatField(label, value); + if (Math.Abs(value - newValue) > BGCurve.Epsilon) action(newValue); + } + + public static void BoundsField(string label, Bounds value, Action action) + { + var newValue = EditorGUILayout.BoundsField(label, value); + if (value != newValue) action(newValue); + } + + public static void AnimationCurveField(string label, AnimationCurve value, Action action) + { + if (value == null) value = new AnimationCurve(); + var newValue = EditorGUILayout.CurveField(label, value); + if (value != newValue) action(newValue); + } + + public static void QuaternionField(string label, Quaternion value, Action action) + { + var oldValue = new Vector4(value.x, value.y, value.z, value.w); + var newValue = EditorGUILayout.Vector4Field(label, oldValue); + if (oldValue != newValue) action(new Quaternion(newValue.x, newValue.y, newValue.z, newValue.w)); + } + + public static void GameObjectField(string label, GameObject value, Action action) + { + var newValue = EditorGUILayout.ObjectField(label, value, typeof(GameObject), true); + if (value != newValue) action((GameObject) newValue); + } + + public static void ComponentField(string label, T value, Action action) where T : Component + { + var newValue = EditorGUILayout.ObjectField(label, value, typeof(T), true); + if (value != newValue) action((T) newValue); + } + + + public static void ComponentChoosableField(string label, Component value, Action action) + { + Horizontal(() => + { + var newValue = EditorGUILayout.ObjectField(label, value, typeof(Component), true); + if (value != newValue) action((Component) newValue); + + if (newValue != null && GUILayout.Button("...", GUILayout.Width(40))) BGChoseComponentWindow.Open((Component) newValue, action); + }); + } + + public static void BGCurveField(string label, BGCurve value, Action action) + { + var newValue = EditorGUILayout.ObjectField(label, value, typeof(BGCurve), true); + if (value != newValue) action((BGCurve) newValue); + } + + public static void BGCurvePointComponentField(string label, BGCurvePointComponent value, Action action) + { + var newValue = EditorGUILayout.ObjectField(label, value, typeof(BGCurvePointComponent), true); + if (value != newValue) action((BGCurvePointComponent) newValue); + } + + public static void BGCurvePointGOField(string label, BGCurvePointGO value, Action action) + { + var newValue = EditorGUILayout.ObjectField(label, value, typeof(BGCurvePointGO), true); + if (value != newValue) action((BGCurvePointGO) newValue); + } + + + public static void ColorField(Rect rect, Color color, Action action) + { + var newValue = EditorGUI.ColorField(rect, color); + if (AnyChange(color, newValue)) action(newValue); + } + + public static void ColorField(string label, Color32 color, Action action) + { + var newValue = EditorGUILayout.ColorField(label, color); + if (AnyChange(color, newValue)) action(newValue); + } + + public static void SliderField(Rect rect, float value, float min, float max, Action action) + { + var newValue = GUI.HorizontalSlider(rect, value, min, max); + if (AnyChange(value, newValue)) action(newValue); + } + + public static void SliderField(int value, int min, int max, Action action) + { + var newValue = EditorGUILayout.IntSlider(value, min, max); + if (AnyChange(value, newValue)) action(newValue); + } + + public static void SliderField(float value, float min, float max, Action action) + { + var newValue = GUILayout.HorizontalSlider(value, min, max); + if (AnyChange(value, newValue)) action(newValue); + } + + + public static void PopupField(Rect rect, Enum value, Enum[] allOptions, Action action) + { + var options = new string[allOptions.Length]; + var selected = 0; + for (var i = 0; i < allOptions.Length; i++) + { + var val = allOptions.GetValue(i); + + options[i] = val.ToString(); + if (Equals(value, val)) selected = i; + } + var newIndex = EditorGUI.Popup(rect, selected, options); + + if (newIndex != selected) action((Enum) allOptions.GetValue(newIndex)); + } + + public static void PopupField(Rect rect, Enum value, Action action) + { + PopupField(rect, value, Enum.GetValues(value.GetType()).Cast().ToArray(), action); + } + + public static void PopupField(Enum value, string label, Enum[] allOptions, Action action) + { + var options = new string[allOptions.Length]; + var selected = 0; + for (var i = 0; i < allOptions.Length; i++) + { + var val = allOptions.GetValue(i); + + options[i] = val.ToString(); + if (Equals(value, val)) selected = i; + } + var newIndex = EditorGUILayout.Popup(label, selected, options); + + if (newIndex != selected) action((Enum) allOptions.GetValue(newIndex)); + } + + public static void PopupField(Enum value, string label, Action action) + { + PopupField(value, label, Enum.GetValues(value.GetType()).Cast().ToArray(), action); + } + + + public static void LayerMaskField(string label, LayerMask layer, Action action) + { +/* + var newValue = EditorGUILayout.LayerField(label, layer.value); + if (newValue != layer.value) action(newValue); + */ + //thanks to FlyingOstriche + //I have no time to figure out what's going on here + layers.Clear(); + layerNumbers.Clear(); + + for (var i = 0; i < 32; i++) + { + var layerName = LayerMask.LayerToName(i); + if (String.IsNullOrEmpty(layerName)) continue; + + layers.Add(layerName); + layerNumbers.Add(i); + } + + var mask = 0; + for (var i = 0; i < layerNumbers.Count; i++) + if (((1 << layerNumbers[i]) & layer.value) > 0) + { + mask |= (1 << i); + } + + var newValue = EditorGUILayout.MaskField(label, mask, layers.ToArray()); + + //do not convert to LINQ + var newMask = 0; + var newMaskCheck = 0; + for (var i = 0; i < layerNumbers.Count; i++) + if ((newValue & (1 << i)) > 0) + { + newMask |= (1 << layerNumbers[i]); + newMaskCheck |= (1 << i); + } + + if (newMaskCheck == mask) return; + + + action(newMask); + } + + public static void CustomField(GUIContent label, BGCurve curve, BGCurvePointField value, BGCurvePointField.TypeEnum type, Action action) + { + //idea.. this is a nasty hack to get rid of weak reference object.. not sure how to get rid of it properly + if (value == null) action(null); + + optionsList.Clear(); + fieldsList.Clear(); + + optionsList.Add(new GUIContent("None")); + + var fields = curve.Fields; + var selectedIndex = 0; + if (fields != null && fields.Length > 0) + { + var cursor = 1; + foreach (var field in fields) + { + if (field.Type != type) continue; + + var b = value != null; + var @equals = b && String.Equals(value.FieldName, field.FieldName); + if (b && @equals) selectedIndex = cursor; + + optionsList.Add(new GUIContent(field.FieldName)); + fieldsList.Add(field); + cursor++; + } + } + var newIndex = EditorGUILayout.Popup(label, selectedIndex, optionsList.ToArray()); + if (newIndex != selectedIndex) action(newIndex == 0 ? null : fieldsList[newIndex - 1]); + } + + + // ============================================== Textures + //loads a texture2d + public static Texture2D LoadTexture2D(Image image, string path = DefaultIconPath, string ext = ".png", bool critical = true) + { + if (String.Equals(path, DefaultIconPath)) path = currentIconPath; + + var icon = LoadTexture(path + image + ext); + if (icon != null) return icon; + + //try to find in assets + var newPath = FindByName(Image.BGDelete123.ToString()); + if (newPath == null) + { + if (critical) + { + // no luck + Debug.LogException(new UnityException( + "Can not find BGCurve Editors icons folder. The icons folder, located by default at '" + DefaultIconPath + + "', should be included in your assets, otherwise the package will not work correctly in Editor.")); + } + return null; + } + + currentIconPath = FolderFromFullPath(newPath); + return LoadTexture(currentIconPath + image + ext); + } + + public static Texture2D LoadCcTexture2D(string path) + { + if (String.IsNullOrEmpty(path)) return null; + + var icon = LoadTexture(path); + + if (icon == null) + { + string fileName; + string fileNameNoExtension; + try + { + fileName = FileFromFullPath(path); + fileNameNoExtension = StripExtension(fileName); + } + catch (Exception) + { + return null; + } + + if (String.IsNullOrEmpty(fileName) || String.IsNullOrEmpty(fileNameNoExtension)) return null; + + //try to find in another place + if (additionalCcIconPath != null) icon = LoadTexture(additionalCcIconPath + fileName); + + if (icon == null) + { + var newPath = FindByName(fileNameNoExtension); + if (newPath != null) + { + var newFolder = FolderFromFullPath(newPath); + if (additionalCcIconPath == null) additionalCcIconPath = newFolder; + icon = LoadTexture(newFolder + fileName); + } + } + } + return icon; + } + + public static Texture2D LoadTexture(string path) + { + //we do hope LoadAssetAtPath is optimized by Unity + return AssetDatabase.LoadAssetAtPath(path); + } + + private static string FindByName(string fileName) + { + var files = AssetDatabase.FindAssets(fileName); + return files == null || files.Length == 0 ? null : AssetDatabase.GUIDToAssetPath(files[0]); + } + + private static string FolderFromFullPath(string path) + { + try + { + var maxSlashIndex = Mathf.Max(path.LastIndexOf('/'), path.LastIndexOf('\\')); + return maxSlashIndex >= 0 ? path.Substring(0, maxSlashIndex + 1) : path; + } + catch (Exception) + { + return null; + } + } + + private static string FileFromFullPath(string path) + { + try + { + var maxSlashIndex = Mathf.Max(path.LastIndexOf('/'), path.LastIndexOf('\\')); + return maxSlashIndex >= 0 ? path.Substring(maxSlashIndex + 1, path.Length - maxSlashIndex - 1) : path; + } + catch (Exception) + { + return null; + } + } + + private static string StripExtension(string fileName) + { + try + { + var dotIndex = Mathf.Max(fileName.LastIndexOf('.')); + return dotIndex >= 0 ? fileName.Substring(0, dotIndex) : fileName; + } + catch (Exception) + { + return null; + } + } + + + // texture is not getting scaled! + public static bool ButtonWithIcon(Texture2D icon, string tooltip, int width = 16, int height = 16) + { + return GUI.Button( + GUILayoutUtility.GetRect(width, width, height, height, + new GUIStyle {fixedWidth = width, fixedHeight = height, stretchWidth = false, stretchHeight = false}), + new GUIContent(icon, tooltip), GUIStyle.none); + } + + public static Texture2D Texture1X1(Color color) + { + var texture = new Texture2D(1, 1, TextureFormat.ARGB32, false); + texture.SetPixel(0, 0, color); + texture.Apply(false); + return texture; + } + + public static Texture2D TextureWithBorder(int size, int borderSize, Color color, Color borderColor) + { + if (size < 4) size = 4; + else if (size > 1024) size = 1024; + if (!Mathf.IsPowerOfTwo(size)) size = Mathf.ClosestPowerOfTwo(size); + + if (borderSize < 1) borderSize = 1; + else if (borderSize > size/2) borderSize = Mathf.CeilToInt(size/2f); + + var texture = new Texture2D(size, size, TextureFormat.ARGB32, false); + + //idea... setPixels works faster + //left + for (var i = 0; i < borderSize; i++) for (var j = 0; j < size; j++) texture.SetPixel(i, j, borderColor); + //right + for (var i = size - borderSize; i < size; i++) for (var j = 0; j < size; j++) texture.SetPixel(i, j, borderColor); + for (var i = borderSize; i < size - borderSize; i++) + { + //top + for (var j = 0; j < borderSize; j++) texture.SetPixel(i, j, borderColor); + //bottom + for (var j = size - borderSize; j < size; j++) texture.SetPixel(i, j, borderColor); + } + + //back + for (var i = borderSize; i < size - borderSize; i++) for (var j = borderSize; j < size - borderSize; j++) texture.SetPixel(i, j, color); + + texture.Apply(false); + return texture; + } + + // ============================================== Dialogs + public static void Inform(string title, string message) + { + EditorUtility.DisplayDialog(title, message, "Ok"); + } + + public static bool Confirm(string title, string message, string ok) + { + return EditorUtility.DisplayDialog(title, message, ok, "Cancel"); + } + + public static void HelpBox(string message, MessageType messageType, bool condition = true, Action elseAction = null) + { + if (condition) EditorGUILayout.HelpBox(message, messageType); + else if (elseAction != null) elseAction(); + } + + + // ============================================== Custom handles + + public static Vector3 ControlHandleCustom(int number, Vector3 position, Quaternion rotation, BGCurveSettings.SettingsForHandles handlesSettings) + { + var handleSize = GetHandleSize(position); + + if (vertexSnappingOn) + { + Handles.color = Handles.centerColor; + GUI.SetNextControlName("FreeMoveAxis"); + return Handles.FreeMoveHandle(position, rotation, handleSize*0.15f, new Vector3(xSnap, ySnap, zSnap), Handles.RectangleCap); + } + + var axisSize = handleSize*handlesSettings.AxisScale; + + var color = Handles.color; + + if (!handlesSettings.RemoveX) position = AxisHandle(position, rotation, axisSize, Handles.xAxisColor, "xAxis", Vector3.right, xSnap, handlesSettings.Alpha); + + if (!handlesSettings.RemoveY) position = AxisHandle(position, rotation, axisSize, Handles.yAxisColor, "yAxis", Vector3.up, ySnap, handlesSettings.Alpha); + + if (!handlesSettings.RemoveZ) position = AxisHandle(position, rotation, axisSize, Handles.zAxisColor, "zAxis", Vector3.forward, zSnap, handlesSettings.Alpha); + + if (!handlesSettings.RemoveXZ) position = PlanarHandle("xz" + number, position, rotation, handleSize*.3f*handlesSettings.PlanesScale, Vector3.right, Vector3.forward, Handles.yAxisColor); + + if (!handlesSettings.RemoveYZ) position = PlanarHandle("yz" + number, position, rotation, handleSize*.3f*handlesSettings.PlanesScale, Vector3.up, Vector3.forward, Handles.xAxisColor); + + if (!handlesSettings.RemoveXY) position = PlanarHandle("xy" + number, position, rotation, handleSize*.3f*handlesSettings.PlanesScale, Vector3.up, Vector3.right, Handles.zAxisColor); + + Handles.color = color; + return position; + } + + private static Vector3 AxisHandle(Vector3 position, Quaternion rotation, float handleSize, Color color, string controlName, Vector3 direction, float snap, float alpha) + { + Handles.color = new Color(color.r, color.g, color.b, alpha); + GUI.SetNextControlName(controlName); + return Handles.Slider(position, rotation*direction, handleSize, Handles.ArrowCap, snap); + } + + // ======================================================================================= + // This is a hell lot of a hackery & bad code & probably bugs. + // idea.. to rewrite + // ======================================================================================= + private static Vector3 PlanarHandle(string name, Vector3 position, Quaternion rotation, float size, Vector3 direction1, Vector3 direction2, Color color) + { + var c = Handles.color; + Handles.color = color; + var v1 = rotation*(direction1*size); + var v2 = rotation*(direction2*size); + var verts = new[] {position + v1 + v2, position + v1 - v2, position - v1 - v2, position - v1 + v2}; + + //adjustments + var cameraPos = Camera.current.transform.position; + var min = Single.MaxValue; + + + var minIndex = -1; + var dragCheck = dragSession.Active(name); + + if (dragCheck > 0) minIndex = dragCheck; + else + { + for (var i = 0; i < verts.Length; i++) + { + var magnitude = (cameraPos - verts[i]).sqrMagnitude; + if ((min < magnitude)) continue; + + minIndex = i; + min = magnitude; + } + + dragSession.NextMin(minIndex, name); + } + + for (var i = 0; i < verts.Length; i++) if (i != minIndex) verts[i] = Vector3.Lerp(verts[i], verts[minIndex], .5f); + + var center = (verts[0] + verts[1] + verts[2] + verts[3])*.25f; + + Handles.DrawSolidRectangleWithOutline(verts, new Color(color.r, color.g, color.r, .1f), new Color(0.0f, 0.0f, 0.0f, 0.0f)); + + GUI.SetNextControlName(name); + + var newCenter = Handles.Slider2D(center, rotation*Vector3.Cross(direction1, direction2), rotation*direction1, rotation*direction2, size*.5f, Handles.RectangleCap, 0); + + if (AnyChange(center, newCenter)) position = position + (newCenter - center); + + Handles.color = c; + return position; + } + + + // ============================================= Misc functions + + public static string ToHex(Color c) + { + return String.Format("#{0:X2}{1:X2}{2:X2}", ToByte(c.r), ToByte(c.g), ToByte(c.b)); + } + + private static byte ToByte(float f) + { + f = Mathf.Clamp01(f); + return (byte) (f*255); + } + + public static string ColorIt(string message, string color) + { + return "" + message + ""; + } + + public static bool AnyChange(Vector3 vector1, Vector3 vector2) + { + return !Mathf.Approximately(vector1.x, vector2.x) || !Mathf.Approximately(vector1.y, vector2.y) || !Mathf.Approximately(vector1.z, vector2.z); + } + + public static bool AnyChange(float value1, float value2) + { + return !Mathf.Approximately(value1, value2); + } + + private static bool AnyChange(Color32 color1, Color32 color2) + { + return color1.r != color2.r || color1.g != color2.g || color1.b != color2.b || color1.a != color2.a; + } + + public static T Assign(ref T nullable, Func valueProvider) where T : class + { + return nullable ?? (nullable = valueProvider()); + } + + public static void Iterate(T[] array, Action action) + { + if (array == null || array.Length == 0) return; + for (var i = 0; i < array.Length; i++) action(i, array[i]); + } + + public static bool IterateInterruptable(T[] array, Func action) + { + if (array == null || array.Length == 0) return false; + if (array.Where((t, i) => action(i, t)).Any()) return true; + return false; + } + + public static TV Ensure(Dictionary key2Value, TK key, Func valueProvider) + { + if (key2Value.ContainsKey(key)) return key2Value[key]; + + var newValue = valueProvider(); + key2Value[key] = newValue; + return newValue; + } + + public static List Ensure(Dictionary> key2Value, TK key) + { + if (key2Value.ContainsKey(key)) return key2Value[key]; + + var newValue = new List(); + key2Value[key] = newValue; + return newValue; + } + + public static bool ChangeCheck(Action action, Action changeCallback = null) + { + EditorGUI.BeginChangeCheck(); + action(); + var changed = EditorGUI.EndChangeCheck(); + if (changed && changeCallback != null) changeCallback(); + return changed; + } + + + public static void SwapGuiColor(Color color, Action action) + { + var oldColor = GUI.color; + GUI.color = color; + action(); + GUI.color = oldColor; + } + + public static void SwapLabelWidth(int width, Action action) + { + var oldValue = EditorGUIUtility.labelWidth; + EditorGUIUtility.labelWidth = width; + action(); + EditorGUIUtility.labelWidth = oldValue; + } + + public static void DisableGui(Action action, bool condition = true) + { + var oldValue = false; + if (condition) + { + oldValue = GUI.enabled; + GUI.enabled = false; + } + action(); + if (condition) GUI.enabled = oldValue; + } + + public static bool Empty(T[] array) + { + return array == null || array.Length == 0; + } + + public static bool Empty(List list) + { + return list == null || list.Count == 0; + } + + public static string Trim(string value, int maxWidth) + { + if (value == null) return null; + + string result; + + if (value.Length < maxWidth) + { + result = value.Substring(0, value.Length); + } + else + { + result = value.Substring(0, maxWidth - "..".Length) + ".."; + } + return result; + } + + public static T ShowPopupWindow(Vector2 size) where T : EditorWindow + { + // var window = EditorWindow.GetWindow(); + var window = ScriptableObject.CreateInstance(); + + var screenPoint = GUIUtility.GUIToScreenPoint(Event.current.mousePosition); + window.ShowAsDropDown(new Rect(screenPoint.x, screenPoint.y, 16, 16), size); + return window; + } + + public static void DrawBound(Bounds bounds, Color color, Color borderColor) + { + var min = bounds.min; + var max = bounds.max; + + var xMin = min.x; + var xMax = max.x; + var yMin = min.y; + var yMax = max.y; + var zMin = min.z; + var zMax = max.z; + + var p1 = new Vector3(xMin, yMin, zMin); + var p2 = new Vector3(xMin, yMax, zMin); + var p3 = new Vector3(xMax, yMax, zMin); + var p4 = new Vector3(xMax, yMin, zMin); + var p5 = new Vector3(xMin, yMin, zMax); + var p6 = new Vector3(xMin, yMax, zMax); + var p7 = new Vector3(xMax, yMax, zMax); + var p8 = new Vector3(xMax, yMin, zMax); + + DrawRect(p1, p2, p3, p4, color, borderColor); + DrawRect(p1, p5, p6, p2, color, borderColor); + DrawRect(p2, p6, p7, p3, color, borderColor); + DrawRect(p3, p7, p8, p4, color, borderColor); + DrawRect(p4, p8, p5, p1, color, borderColor); + DrawRect(p5, p6, p7, p8, color, borderColor); + } + + + public static void DrawRect(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, Color color, Color bColor) + { + var verts = new[] {v1, v2, v3, v4}; + Handles.DrawSolidRectangleWithOutline(verts, color, bColor); + } + + // ============================================= Curve related + //this is very slow + public static void Split(BGCurvePointI @from, BGCurvePointI to, int parts, Action action) + { + var noControls = @from.ControlType == BGCurvePoint.ControlTypeEnum.Absent && to.ControlType == BGCurvePoint.ControlTypeEnum.Absent; + if (noControls) + { + action(@from.PositionWorld, to.PositionWorld); + } + else + { + var fromPos = @from.PositionWorld; + var toPos = to.PositionWorld; + var control1 = @from.ControlSecondWorld; + var control2 = to.ControlFirstWorld; + var bothControls = @from.ControlType != BGCurvePoint.ControlTypeEnum.Absent && to.ControlType != BGCurvePoint.ControlTypeEnum.Absent; + if (!bothControls && @from.ControlType == BGCurvePoint.ControlTypeEnum.Absent) control1 = control2; + + + var prev = fromPos; + for (var i = 1; i < parts + 1; i++) + { + var ratio = i/(float) parts; + + var currentPosition = bothControls + ? BGCurveFormulas.BezierCubic(ratio, fromPos, control1, control2, toPos) + : BGCurveFormulas.BezierQuadratic(ratio, fromPos, control1, toPos); + action(prev, currentPosition); + prev = currentPosition; + } + } + } + + //copy paste from math, not sure how to refactor it + public static Vector3 CalculatePosition(BGCurvePointI @from, BGCurvePointI to, float t) + { + if (@from.ControlType == BGCurvePoint.ControlTypeEnum.Absent && to.ControlType == BGCurvePoint.ControlTypeEnum.Absent) + { + return Vector3.Lerp(@from.PositionWorld, to.PositionWorld, t); + } + if (@from.ControlType != BGCurvePoint.ControlTypeEnum.Absent && to.ControlType != BGCurvePoint.ControlTypeEnum.Absent) + { + return BGCurveFormulas.BezierCubic(t, @from.PositionWorld, @from.ControlSecondWorld, to.ControlFirstWorld, to.PositionWorld); + } + + return BGCurveFormulas.BezierQuadratic(t, @from.PositionWorld, @from.ControlType == BGCurvePoint.ControlTypeEnum.Absent ? to.ControlFirstWorld : @from.ControlSecondWorld, + to.PositionWorld); + } + + /// Tangent in World coordinates + public static Vector3 CalculateTangent(BGCurvePointI @from, BGCurvePointI to, float t) + { + if (@from.ControlType == BGCurvePoint.ControlTypeEnum.Absent && to.ControlType == BGCurvePoint.ControlTypeEnum.Absent) + { + return (to.PositionWorld - @from.PositionWorld).normalized; + } + if (@from.ControlType != BGCurvePoint.ControlTypeEnum.Absent && to.ControlType != BGCurvePoint.ControlTypeEnum.Absent) + { + return BGCurveFormulas.BezierCubicDerivative(t, @from.PositionWorld, @from.ControlSecondWorld, to.ControlFirstWorld, to.PositionWorld).normalized; + } + + return BGCurveFormulas.BezierQuadraticDerivative(t, @from.PositionWorld, @from.ControlType == BGCurvePoint.ControlTypeEnum.Absent ? to.ControlFirstWorld : @from.ControlSecondWorld, + to.PositionWorld).normalized; + } + + /// Tangent in World coordinates + public static Vector3 CalculateTangent(BGCurvePointI point, BGCurvePointI previous, BGCurvePointI next, float precision) + { + var prevTangent = previous != null ? CalculateTangent(previous, point, 1 - precision) : Vector3.zero; + var nextTangent = next != null ? CalculateTangent(point, next, precision) : Vector3.zero; + + var tangent = (previous != null && next != null) + ? Vector3.Lerp(prevTangent, nextTangent, .5f) + : next == null ? prevTangent : nextTangent; + + return tangent.normalized; + } + +/* + public static Vector3 CalculateTangent(BGCurvePoint point, float precision) + { + var curve = point.Curve; + + //not enough points + if (curve.PointsCount < 2) return Vector3.zero; + + var myIndex = curve.IndexOf(point); + + //have no idea why it can happen + if (myIndex < 0) return Vector3.zero; + + //prev point + BGCurvePoint prev = null; + if (myIndex != 0 || curve.Closed) + { + prev = myIndex == 0 ? curve[curve.PointsCount - 1] : curve[myIndex - 1]; + } + + //next point + BGCurvePoint next = null; + if (myIndex != curve.PointsCount - 1 || curve.Closed) + { + next = myIndex == curve.PointsCount - 1 ? curve[0] : curve[myIndex + 1]; + } + return CalculateTangent(point, prev, next, precision); + } + */ + + public static float CalculateDistance(BGCurvePointI from, BGCurvePointI to, int parts) + { + var distance = 0f; + Split(@from, to, parts, (fromPos, toPos) => distance += Vector3.Distance(fromPos, toPos)); + return distance; + } + + // ============================================= Helper classes + public class BoolAnimatedProperty + { + public readonly SerializedProperty Property; + public readonly AnimBool AnimBool = new AnimBool(); + + public BoolAnimatedProperty(UnityEditor.Editor editor, SerializedProperty obj, string name) + { + Property = obj.FindPropertyRelative(name); + AnimBool.target = Property.boolValue; + AnimBool.valueChanged.AddListener(editor.Repaint); + } + } + + private sealed class DragSession + { + private int minIndex; + private bool needtoRecalculate; + private string lastActiveName; + + + public int Active(string name) + { + var currentEvent = Event.current; + + if (currentEvent.type == EventType.MouseUp || currentEvent.type == EventType.MouseDown) needtoRecalculate = true; + + if (needtoRecalculate || GUIUtility.hotControl == 0 || !String.Equals(lastActiveName, name) || !String.Equals(GUI.GetNameOfFocusedControl(), name)) return -1; + + return minIndex; + } + + public void NextMin(int minIndex, string name) + { + if (GUIUtility.hotControl == 0 || !String.Equals(GUI.GetNameOfFocusedControl(), name)) return; + + lastActiveName = name; + needtoRecalculate = false; + this.minIndex = minIndex; + } + } + + public static void Release(ref EventCanceller eventCanceller) + { + if (eventCanceller != null) + { + eventCanceller.Release(); + //bye + eventCanceller = null; + } + } + + public class EventCanceller + { + public EventCanceller() + { + Event.current.Use(); + GUIUtility.hotControl = GUIUtility.GetControlID(FocusType.Passive); + } + + internal void Release() + { + GUIUtility.hotControl = 0; + } + } + + public class ExitException : Exception + { + //get me outta of here + } + + //handles + public static Vector3 Handle(int number, BGCurveSettings.HandlesTypeEnum type, Vector3 position, Quaternion rotation, BGCurveSettings.SettingsForHandles handlesSettings) + { + switch (type) + { + case BGCurveSettings.HandlesTypeEnum.FreeMove: + position = Handles.FreeMoveHandle(position, rotation, GetHandleSize(position, .2f), Vector3.zero, Handles.CircleCap); + break; + case BGCurveSettings.HandlesTypeEnum.Standard: + position = Handles.PositionHandle(position, rotation); + break; + case BGCurveSettings.HandlesTypeEnum.Configurable: + + var dragging = GUIUtility.hotControl != 0; + var current = Event.current; + switch (current.type) + { + case EventType.KeyDown: + if (current.keyCode == KeyCode.V && !dragging) vertexSnappingOn = true; + break; + case EventType.KeyUp: + if (current.keyCode == KeyCode.V && !current.shift && !dragging) vertexSnappingOn = false; + break; + case EventType.Layout: + var vertexDragging = BGPrivateField.Get(typeof(Tools), "vertexDragging"); + if (!dragging && !vertexDragging) vertexSnappingOn = current.shift; + break; + } + + + position = ControlHandleCustom(number, position, rotation, handlesSettings); + break; + } + return position; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGEditorUtility.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGEditorUtility.cs.meta new file mode 100644 index 0000000..9d9a69d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGEditorUtility.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2e1efa288be0969499190391b84444b4 +timeCreated: 1458400607 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGPrivateField.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGPrivateField.cs new file mode 100644 index 0000000..469c247 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGPrivateField.cs @@ -0,0 +1,113 @@ +using System; +using System.Reflection; +using BansheeGz.BGSpline.Curve; +using UnityEngine; + +namespace BansheeGz.BGSpline.Editor +{ + // access private members + public static class BGPrivateField + { + //--------------------------------------- Settings + public static void SetSettings(BGCurve curve, BGCurveSettings settings) + { + Set(curve, "settings", settings); + } + + public static BGCurveSettings GetSettings(BGCurve curve) + { + return Get(curve, "settings"); + } + + //--------------------------------------- Fields + public static bool GetShowHandles(BGCurvePointField field) + { + return Get(field, "showHandles"); + } + + public static int GetHandlesType(BGCurvePointField field) + { + return Get(field, "handlesType"); + } + + public static Color GetHandlesColor(BGCurvePointField field) + { + return Get(field, "handlesColor"); + } + + public static bool GetShowInPointsMenu(BGCurvePointField field) + { + return Get(field, "showInPointsMenu"); + } + + public static void SetShowHandles(BGCurvePointField field, bool value) + { + Set(field, "showHandles", value); + } + + public static void SetHandlesType(BGCurvePointField field, int value) + { + Set(field, "handlesType", value); + } + + public static void SetHandlesColor(BGCurvePointField field, Color value) + { + Set(field, "handlesColor", value); + } + + public static void SetShowInPointsMenu(BGCurvePointField field, bool value) + { + Set(field, "showInPointsMenu", value); + } + + //--------------------------------------- Cc + public static bool GetShowHandles(BGCc cc) + { + return Get(cc, "showHandles"); + } + + // == utility + public static T Get(object obj, string name) + { + return (T) GetField(obj, name).GetValue(obj); + } + + public static void Set(object obj, string name, T value) + { + GetField(obj, name).SetValue(obj, value); + } + + private static FieldInfo GetField(object obj, string name) + { + var isStatic = obj is Type; + var type = isStatic ? (Type) obj : obj.GetType(); + + var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + + if (isStatic) bindingFlags |= BindingFlags.Static; + + var targetField = type.GetField(name, bindingFlags); + + if (targetField != null) return targetField; + + + var basetype = type.BaseType; + while (targetField == null && basetype != null && basetype != typeof(object)) + { + targetField = basetype.GetField(name, bindingFlags); + basetype = basetype.BaseType; + } + return targetField; + } + + public static object Invoke(object obj, string methodName, params object[] parameters) + { + return obj.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance).Invoke(obj, parameters); + } + + public static object Invoke(object obj, string methodName, Type[] types, params object[] parameters) + { + return obj.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance, null, types, null).Invoke(obj, parameters); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGPrivateField.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGPrivateField.cs.meta new file mode 100644 index 0000000..dc29f49 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGPrivateField.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ad83a743d133b9043a076f918496f4a0 +timeCreated: 1458403127 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGStartUp.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGStartUp.cs new file mode 100644 index 0000000..61c39a0 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGStartUp.cs @@ -0,0 +1,69 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + [InitializeOnLoad] + public static class BGStartUp + { + private const int IconSize = 20; + + // Not selected + private static readonly Texture2D CurveIcon; + private static readonly Texture2D CurveWarningIcon; + private static readonly Texture2D CurveErrorIcon; + + // Selected + private static readonly Texture2D CurveSelectedIcon; + private static readonly Texture2D CurveWarningSelectedIcon; + private static readonly Texture2D CurveErrorSelectedIcon; + + + static BGStartUp() + { + CurveIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHierarchyIcon123, critical:false); + if (CurveIcon!=null) + { + CurveWarningIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHierarchyWarningIcon123); + CurveErrorIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHierarchyErrorIcon123); + + CurveSelectedIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHierarchySelectedIcon123); + CurveWarningSelectedIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHierarchyWarningSelectedIcon123); + CurveErrorSelectedIcon = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGHierarchyErrorSelectedIcon123); + EditorApplication.hierarchyWindowItemOnGUI += ShowIcon; + } + } + + //thanks to laurentlavigne + private static void ShowIcon(int instanceId, Rect selectionRect) + { + var go = EditorUtility.InstanceIDToObject(instanceId) as GameObject; + + if (go == null) return; + var curve = go.GetComponent(); + if (curve == null) return; + + var selected = Selection.Contains(instanceId); + bool hasError = false, hasWarning = false; + BGCurveEditorComponents.ComponentsStatus(curve, ref hasError, ref hasWarning); + + var icon = selected + //selected + ? hasError + ? CurveErrorSelectedIcon + : hasWarning + ? CurveWarningSelectedIcon + : CurveSelectedIcon + + // Not selected + : hasError + ? CurveErrorIcon + : hasWarning + ? CurveWarningIcon + : CurveIcon; + + GUI.Label(new Rect(selectionRect) {x = selectionRect.width - IconSize, width = IconSize}, icon); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGStartUp.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGStartUp.cs.meta new file mode 100644 index 0000000..6db4b16 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGStartUp.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bfc6ad0229c788e4eba29701126bfed0 +timeCreated: 1472626247 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTransition.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTransition.cs new file mode 100644 index 0000000..29a3972 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTransition.cs @@ -0,0 +1,84 @@ +using UnityEngine; +using UnityEditor; + +namespace BansheeGz.BGSpline.Editor +{ + public abstract class BGTransition + { + private readonly bool cycle; +// private readonly double startTime; + private readonly double period; + + private double cycleStartTime; + private float ratio; + + private bool completed; + + public float Ratio + { + get { return ratio; } + } + + + protected BGTransition(double period, bool cycle) + { + this.period = period; + this.cycle = cycle; +// startTime = cycleStartTime = EditorApplication.timeSinceStartup; + } + + public virtual bool Tick() + { + if (completed) return true; + + var elapsed = (float) (EditorApplication.timeSinceStartup - cycleStartTime); + var cycleEnded = elapsed > period; + + if (cycleEnded) + { + elapsed = 0; + cycleStartTime = EditorApplication.timeSinceStartup; + + if (!cycle) completed = true; + } + ratio = (float) (elapsed/period); + + return cycleEnded; + } + + public class SimpleTransition : BGTransition + { + public SimpleTransition(double period, bool cycle) + : base(period, cycle) + { + } + } + + public class SwayTransition : BGTransition + { + private readonly float from; + private readonly float to; + + private bool up = true; + + public float Value { get; set; } + + public SwayTransition(float @from, float to, double period) + : base(period, true) + { + this.from = from; + this.to = to; + Value = from; + } + + public override bool Tick() + { + if (base.Tick()) up = !up; + + Value = up ? Mathf.Lerp(from, to, Ratio) : Mathf.Lerp(to, from, Ratio); + + return true; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTransition.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTransition.cs.meta new file mode 100644 index 0000000..46acd06 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTransition.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c5d7571d642b2ea499ebf45bd0227fc5 +timeCreated: 1472289579 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTreeView.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTreeView.cs new file mode 100644 index 0000000..6cae669 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTreeView.cs @@ -0,0 +1,275 @@ +using System; +using UnityEngine; +using System.Collections.Generic; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Editor +{ + public class BGTreeView where T : BGTreeNode + { + public readonly List Roots = new List(); + + public Config Configuration { get; private set; } + + private Texture2D linkTexture; + private Texture2D expandedIconTexture; + private Texture2D collapsedIconTexture; + + public Texture2D ExpandedIconTexture + { + get { return expandedIconTexture ?? (expandedIconTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGExpanded123)); } + } + + public Texture2D CollapsedIconTexture + { + get { return collapsedIconTexture ?? (collapsedIconTexture = BGEditorUtility.LoadTexture2D(BGEditorUtility.Image.BGCollapsed123)); } + } + + public BGTreeView(Config config) + { + Configuration = config; + } + + public virtual void OnInspectorGui() + { + IterateRoots((i, root) => + { + if (i != 0) GUILayout.Space(Configuration.VerticalSpace*2); + root.OnInspectorGui(); + }); + } + + public void ExpandCollapseAll(bool collapsed) + { + IterateRoots((i, root) => root.ExpandCollapsed(collapsed, true)); + } + + protected void IterateRoots(Action action) + { + for (var i = 0; i < Roots.Count; i++) action(i, Roots[i]); + } + + public virtual Texture2D GetLinkTexture(int level) + { + BGEditorUtility.Assign(ref linkTexture, () => BGEditorUtility.Texture1X1(Color.black)); + return linkTexture; + } + + //========================================================= Config + public class Config + { + public int VerticalSpace { get; private set; } + public int HorizontalLinkOffset { get; private set; } + public int HorizontalSpace { get; private set; } + public int LinkLineSize { get; private set; } + + public int ExpandCollapseIconSize { get; private set; } + + public Config(int verticalSpace, int horizontalSpace, int horizontalLinkOffset, int linkLineSize, int expandCollapseIconSize) + { + VerticalSpace = verticalSpace; + HorizontalLinkOffset = horizontalLinkOffset; + HorizontalSpace = horizontalSpace; + LinkLineSize = linkLineSize; + ExpandCollapseIconSize = expandCollapseIconSize; + } + } + } + + + //========================================================= Node + //curiously recurring template pattern (something wrong here) + public abstract class BGTreeNode where T : BGTreeNode + { + private readonly BGTreeView tree; + private T parent; + private List children; + + private GUIStyle buttonStyle; + + public virtual bool Collapsed { get; set; } + + public Rect Rect { get; set; } + + public bool HasChildren + { + get { return !BGEditorUtility.Empty(children); } + } + + private List postActions; + + public T Parent + { + get { return parent; } + set + { + if (parent == value) return; + + //remove from old parent + if (parent != null && parent.children != null) parent.children.Remove((T) this); + + parent = value; + if (parent == null) return; + + //recursion check + var currentParent = parent; + var nestingLevel = 0; + while (currentParent != null) + { + if (currentParent == this) throw new BGCc.CcException("Recursion check fail!"); + if (nestingLevel > 10) throw new BGCc.CcException("Recursion check fail! Unacceptable Nesting Level " + nestingLevel); + + currentParent = currentParent.Parent; + nestingLevel++; + } + + //add to parent + parent.children = parent.children ?? new List(); + if (!parent.children.Contains((T) this)) parent.children.Add((T) this); + } + } + + public int Level + { + get + { + if (Parent == null) return 0; + + var parentLevel = Parent.Level; + //just in case (recursion check) + if (parentLevel > 10) throw new BGCc.CcException("Recursion check fail! Unacceptable Nesting Level " + parentLevel); + return parentLevel + 1; + } + } + + public BGTreeView Tree + { + get { return tree; } + } + + + protected BGTreeNode(BGTreeView tree) + { + if (tree == null) throw new BGCc.CcException("tree can not be null!"); + this.tree = tree; + } + + public void ExpandCollapsed(bool collapsed, bool recursive) + { + Collapsed = collapsed; + if (recursive) IterateChildren(child => child.ExpandCollapsed(collapsed, true)); + } + + protected void IterateChildren(Action action) + { + if (BGEditorUtility.Empty(children)) return; + + foreach (var child in children) action(child); + } + + + public virtual Rect OnInspectorGui() + { + var level = Level; + + var myRect = new Rect(); + BGEditorUtility.Vertical(() => + { + BGEditorUtility.Horizontal(() => + { + if (level > 0 && tree.Configuration.HorizontalSpace > 0) GUILayout.Space(tree.Configuration.HorizontalSpace*level); + + BGEditorUtility.Vertical(() => { OnInspectorGuiInternal(level); }); + + myRect = GUILayoutUtility.GetLastRect(); + }); + }); + + if (Event.current.type == EventType.Repaint) Rect = myRect; + + if (children == null || children.Count == 0 || Collapsed) return myRect; + + + //Children + var texture = tree.GetLinkTexture(level); + + var linkStartX = myRect.x + tree.Configuration.HorizontalLinkOffset; + + var childRect = new Rect(); + + var linkSize = tree.Configuration.LinkLineSize; + + if (postActions != null) postActions.Clear(); + foreach (var child in children) + { + if (tree.Configuration.VerticalSpace > 0) GUILayout.Space(tree.Configuration.VerticalSpace); + + childRect = child.OnInspectorGui(); + + //horizontal link + var linkWidth = childRect.x - linkStartX; + + if (!(linkWidth > 0)) continue; + + //child Y Center + var childCenterY = childRect.y + childRect.size.y*.5f; + + //link + var horizontalLink = new Rect( + linkStartX, + childCenterY - linkSize*.5f, + linkWidth, + linkSize); + + GUI.DrawTexture(horizontalLink, texture, ScaleMode.StretchToFill); + + //icon + var iconSize = tree.Configuration.ExpandCollapseIconSize; + if (iconSize > 0 && child.HasChildren) + { + BGEditorUtility.Assign(ref buttonStyle, () => new GUIStyle("Button") + { + margin = new RectOffset(), + padding = new RectOffset(), + border = new RectOffset() + }); + + postActions = postActions ?? new List(); + var childRef = child; + postActions.Add(() => + { + var iconSizeHalf = iconSize*.5f; + if (GUI.Button(new Rect( + linkStartX - iconSizeHalf + linkSize*.5f, + childCenterY - iconSizeHalf + linkSize*.5f, + iconSize, + iconSize), + childRef.Collapsed ? tree.CollapsedIconTexture : tree.ExpandedIconTexture, buttonStyle)) + { + childRef.Collapsed = !childRef.Collapsed; + } + }); + } + } + + if (linkStartX < childRect.x) + { + //vertical link + GUI.DrawTexture(new Rect( + linkStartX, + myRect.yMax, + linkSize, + childRect.center.y - myRect.yMax + ), texture, ScaleMode.StretchToFill); + } + + + if (postActions != null && postActions.Count > 0) foreach (var postAction in postActions) postAction(); + + return myRect; + } + + public abstract void OnInspectorGuiInternal(int level); + public abstract void ProcessStructure(); + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTreeView.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTreeView.cs.meta new file mode 100644 index 0000000..19beb63 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Editor/Utils/BGTreeView.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4fecf1343b9858f4a8c2a2f8c22e15d2 +timeCreated: 1472892209 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/readme.txt b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/readme.txt new file mode 100644 index 0000000..edd35b7 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/readme.txt @@ -0,0 +1,62 @@ +BG Curve v.1.2.2 by BancheeGz (12/2016) +Bezier spline editor for Unity +License: MIT License + +www.bansheegz.com/BGCurve +support email: banshee.gzzz@gmail.com + +===================================================== + +----------------------------------------------------- +Package structure: +----------------------------------------------------- +Curve - basic curve's classes + math (distance, positions, tangents, position by closest point). +Components - components are meant to add some functions to curve without any scripting. +Examples - examples and tests for different use-cases. + +----------------------------------------------------- +Quick tips: +----------------------------------------------------- +1) To create a curve chose GameObjecty->Create Other->BG Curve or AddComponent and search "BGCurve". +2) You can learn a lot by looking at fields tooltips and contextual tips in the editor. Example scene could also be helpfull. +3) You can save & load curve settings on/from disk. +4) You can select several points and perform group operations. Hold shift to use rectangular selection. +5) Use components- they are meant to work without any additional scripting. +5) BGCurve class does not contain any Math operations- to use Math- add BGCcMath component +6) Use 2D mode if needed, it helps with 2d curves. +7) Use Lock view to disable selecting of any object except curve's points. +8) Use point's and selection menus in Scene View (hold Ctrl and hover over a point or selection's center). +9) Use standard Unity's AnimationView to animate splines +10) View demo video. + + + +===================================================== +Versions History: +----------------------------------------------------- +Version 1.2 changes: +----------------------------------------------------- +Animation support +Custom fields for points +Snapping (to terrain etc.) +New components (Scale and Triangulate) +New approximation type (Adaptive) +Base math switched to fastest algorithm available for approximation (25% faster) +Components (ChangeCursor and Rotate) are upgraded to support custom points fields +Points store options (inlined, component, gameobjects) + +----------------------------------------------------- +Version 1.1 changes: +----------------------------------------------------- +Components are added (for using without scripting) +Rectangular selection for points. +Context menu for points and selections in SceneView. +BGCurveBaseMath optimization. +New points now has preview in Scene View before adding. +Point creation now respect tangents, controls are scaled properly, in 2D mode Ctrl+Click now respects curve's 2D plane, rather than some mesh. +Show tangents option in SceneView +Examples are reworked. +Minor bugs fixing. +code cleanup and refactoring. +Unity 5.4 compatibility + diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/readme.txt.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/readme.txt.meta new file mode 100644 index 0000000..5860c96 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/readme.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 291a61797e7bab64195fb6be8d006b4d +timeCreated: 1458544744 +licenseType: Store +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/Fonts.meta b/IronToad_UnityProject/Assets/Fonts.meta new file mode 100644 index 0000000..79d6b53 --- /dev/null +++ b/IronToad_UnityProject/Assets/Fonts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e993c1c70630f4e33ad8dc005f5d4acc +folderAsset: yes +timeCreated: 1484957599 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/Fonts/Gang of Three.ttf b/IronToad_UnityProject/Assets/Fonts/Gang of Three.ttf new file mode 100755 index 0000000000000000000000000000000000000000..23d266d3d2a580f00748427ab3b98287716d3136 GIT binary patch literal 21872 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%0DBO;nn^fh&% zY0ZJ;m>}N$ef|q$jopqomcg+|Sj<)oouH|XB*u|`G%%!xvTZJ1n^XFPAsy0o&-QS} zL^2vVy{b8%_efK5J>QVDG5XMAhZE=pjeF#9-ZH8IJ+_Q(hhW5=xKvq*um-B*K>e(V z=2NmPLrpvmha+m;QWY)h>04ZX&e*tARYn}2SS{BW%Ea{-q=$^AuW&@f?(?2X$8=*w zmZeDL(e@d=F4;^M9Mm&z@6f1{eB5(Ra%A9=CNV{IVm)1P_;SS1lEorqmmYb@K4Hzk zUpctGgD}$Ha9p#;76>ccY&z!rQ z`aY&TnJlJ~)%z*G-QT07B(G!qP!T5we8*;?=JalhB`l0l@$|SOn9fPFl-0!&F-XcZ zAzIp)La>ZpV=o1U&>YS?t|oI%`xw*fX4p>Di>)Lc+QHhD*4iW z<;oAxGAG@ZIBkG)4*AIoQMG}n4T9yAv))mum@XMng@w0u5SK6x4VsSY>1(9)n9T)& zan{d&p&0i*g)UT=UW2mk;807*qo IM6N<$fF-b{U5F2M=-`GRPGttaAI1-Cl zA;F#v?WR>;=w$Bw?wK>^F=O8` zQO`A^-AhFDFwrA?AUfJV&_A$pgf_Rfwk(Um9@ej~-#U2r*1pE=rMWv7_g~msV3y&< zJRc#)h+?+il9QOo;=jvTihr^w?qUc(N-f&K<3E@`z{iZ_u+Gq5?Bfv6VV_O$e)jVc z&wG+JSmW=D48kOs+bZc(W3HJXz`$7D;h85$SjCF+Lfr2AuYXm$i z<2=CUAkJQJsaZPBwx68#Lz=5Nr+JQexLbTBX>Y`d z7PgCX7r0b2&PO#@{rZ^a$ZIz%1hqpwt2_pO43Gu<4)f1>jCgR5w2S9)&CR;)1!qA$ z4{;w+H~85H7=w4ozMN0^e$8`6zE3b$`R0wj8~~S^H~R9V=E{FB_Yv1U$Xs35^#2s> zN8ro!kNdQp|GtE0c=byjUtop*r}>!FN7n61!k^JRYvlE;=3Pc!&w;a`KIytW4;X{z z=qnyI>-K`?d0Ee^JV!h)YTj*J7tfi>x5v2d%ivObjC#JJd5(VJG3tpLzsd?h-G1c$ z{>Ee6`>z4ASkx{3H=p;{B~v_o|MzR2r$5>E?>xsddYF}{Px`sY`CjK)7wa3qDSm@z z;CKcVSAK5t41V4OPT4p847Bj3pSLv6$UffYIqG>7JVyLxAK%v8>?40(N@?xmJKEmt zL>_`NT?b7^w6bw$5oyZR+8oRAT1cK<6Y3mA)KXLr1Wqg2 zuAm03^LTD$C6vCVT;GmlAinDdAq7;SWwKEaqQ0GdI7nH_s;$NzzQH8G-aw1|!b@g> z2>p6c65-)GqAxDj9XE2kqG&{cO?2t+%^z;wI5zt2#+A+EizmNhza8mRpi_ZP1v(Yz zRG?FV|5pKQ6{40{06?je@(fbupN(g z3iv9If5yv#l5hUCONUl}c_M`>$=rylTcGeNWb$u&udii;^U97wqsH&(dPrrg9v0mqpp%7K&-V zi(M59Toc!IO4F_%hTBeH3-cW0ivAQAg3_4F`$8VWMzV=8y2prL(%5di9{DRPFj6+n znlk9Uc4<)BeDYD?M1n~?Ec2DI@NE-@^1NRDUqp}97E#*ar-yqrUx)(XRiY})<6-=q z(AsN#DzD>bo#L6Z3!(&j;+F@W7yL3JfXG~$bx}y&XEWZ~6z`#N4QvbX^GdPV$8l^> b6JvcyuBF$SwNyu$*P`P^ZPqWJ-x&H2^Kmr} literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestLineRendererCheckerBox.mat.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestLineRendererCheckerBox.mat.meta new file mode 100644 index 0000000..eadccbd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestLineRendererCheckerBox.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ae3eb8adc3950cb4899d2a8dc3564602 +timeCreated: 1473155545 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestMoonMaterial.mat b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestMoonMaterial.mat new file mode 100644 index 0000000000000000000000000000000000000000..45403612d76fd64d9e76cd52f50c4876d71a35cd GIT binary patch literal 4916 zcmeI0OKcle6o!xO#7R>qlv3JKO2hk|Qqu4YO`60>L+d8RX+d3JCiaazF!n?<jjx@QJ6l^@nGC=|=$AKc9^1TmxP9xxrQ6q!Tsu?*%VIH) zBjq)b81`Fw5{qQ;_f1aXA2JdT0MbvQ8QFvJ@8I{~nAM!tS@|12j$=;yTo)gMpJy>2 zPSGtaSSsGCU(^;s0CsVf?&CCgwTW%t^#UC1=c;Y4V(o z^C-??oFn8~b8->3A3-_aYj{TBLrz1PFO|}p@4cEOygSZ)h9_|@V9t2ZEnG?4TXC|5 zyT!SmT&o@D1BNI4dLMJj}dLth}Bihp;}~b$g01CLfe9 zFzVFpX~Xlno$=a8YaO=g`MlwS@)O3aCu{ryl)}1wkN*CO zG4K5s2_YF7(*8To`%9W7y!-wiGdwSU!uM~O^BFw>6&cljt|Q+Ym<>Q*Chp>YVMfkp zFyV=xe=wt;SBSgpJATG{c*hUll!<*-_wg2Htmg!A%=qm-zG}GLN4zh!^!D*}V{iBI z4a4m|zG=AK$G5*FN3R=baH8$KwkC;P~{@x4Xi`-;yyROdTI81Kw?+HgDHGvtuo zd}jz_ay#Ey!|i+_yd<9xOiMtTdJibi~_e= zTXAYdXI(Be-DqPu@YhukZItRtMRe+1Rn-)_ie6S!yU@HEO4DhmgOHnIOJgwq* zO4_o4@zUB_sC~_Qz7y#{e9sR;38W^g;;J317ztG9 zw}OfaPqY|)d9~$wk=rb*b`&_qsz2ygpkIN01^N}}SD;^k|6c)q8qO@Ns4yz}e$#AN z^gnKH%PD)HR9alRfHD7Nb32TKUgH+KTy)$fb_-NN&l2~Hf zaf?=-Q<39(7yO{%cz3bqCkJ*=f#Z2j`!2Tp1TQaDDqf3wupP!&wPVq~3k^5i)!eq_ z&jD%NMJN0ivu?3%yK+3^t*WZOBNW?yKU|fIsEOyfl?Bfa!yPBU!aj$w>)w@u%8ZA- zp$;dW(rhk_wwd5V4gP0ak-xS^tHh>LQ-F~_zMj-JSKbTUNP)ytI$s@&+f-r5^Yl+8 zW%fAPCTct0W7{<^MS*J8qB^bPDgLC;+iPBWM5s literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestMoonMaterial.mat.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestMoonMaterial.mat.meta new file mode 100644 index 0000000..9d52cb7 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestMoonMaterial.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0eee3b445c49c204badd4329bcefe33f +timeCreated: 1476798409 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestSunMaterial.mat b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestSunMaterial.mat new file mode 100644 index 0000000000000000000000000000000000000000..21996d19cfb34ac714131c3d12c213734ebfbd2a GIT binary patch literal 4964 zcmeI0OKclO7{@<5&!$i)CA6iq4exhK3FTRuG>Maj)=i4jg1DHCJ+T+oyV34CI1-0F zA;Fy!y;MkCkPza;g#!{7u2hIac^sQ-uc&JH|7X_|j}xil?ukC_%x}K==6mdJW-T)O zv&ey}h}Et*xzG4qz1W<&B$1Z{IxB+Wc_w*0sY|4;I1lm>k5F z?KP1E`dfOCh~)71O`jw`e7 z5v-w~Bjj58Z%+~?|AzDs`wEgz;{-S0n@4WxV4Ih+0Vf#A9d`3?|M8>q8Yl!y-M*WbNh&%XS7?JZC zOnGYOAB-e_e1Hyc=j?5e1TWow^@p*^ncqa*yo$*c?ZpV9;9IZRv zX~Kluj(5gzJKkBt?RX2|yTv<4uEma*@6nVG$Q5|Nc=_%;2N4;=+@Q|GzZfwO3y@p~ zzn$@Sy7--ppYP(_jCL+$yy(O#bRAEYmg4Yqq3Xs#SZKw{kKDjNBaQN$>#2oVbe5dB zj*iwV)t#yeIi2=Q=e*kZBnYb!zy-Hfj~mX~oafXyo@qvL(0Et*Sb3?bno6QLbp6`0 zQ!6@aa@lv|jioSHQ(?SOsw)-KsI#uB8FUq`EUQ+*UysCh8Y*3rl5{F=hKkE7j;Ew0 z8|W{tu14C{oEJE;b|mnEFp^MevLX%>A~Lpjj2GRied$qS6gQX#S|gj}@x-)HML{#H zsOUtK-j`RJt{1z0S+(NOF{^fJ)PKraKm4E+BL?8lPn`DGQwrKWGrE9tR` z$8xqkkaD58P%14fUPPb&vUwcFMbGhwT`oGVkJAF#c1v)Aq@+#jO*b2BJd#+=*5eVa zJgZ{I^)3cs!}0E-&rc4VphCy-v&tN;0F>CvxZ5JADw5z(U%bx=> zzl%=vF-D!u*6oP#thb`7!46k!eb%X5L{2=*#v z+9Cs&MfQz|$Xz0LV+NCtmj=Oq3vBXJKP{Un-^T^Roceh0Q$&1s#LKjC8tbK2)x_$d55 zf%!nXkJkMAI4kkbsh{2!`&K`UFR{)_tDk8KZtEwA6>UgDSycDoR!zZhWA)`Jwgs)eOl}GC}B+A zE1zQ2tlMLT_vw26fH~uN-0*(uyu8nnd-H`B z`wPar_D2XI8R^&loA>)OnkBsT`X4pCPkx8*Uoq!BdJHNuto>{u-z%8)K%XUU;eTL8 z&U-N7iJ!kPqo3!9TkM;D#@l$)&+~?7bsw)`&Uzjvj~Tz+#}^E@`-tbImi9irWbExe zzHGSN$5#xu`}it&r#?=QYqk6Mn&G{|da{qK8=qSgKCgJcLv_BBgz?UNrwq6AJxLB} z&v%+ICb#pQG2G5~)^I!DJb0&k=g76%`SLlM@LoBO2$(OQou{B8!`RoS>+mmTtix$& zriI@~`Ri@`X3EdBah{BR7E)etA{DrfCre9FFp)32ksst6k*bBRUppby;+*TL)3X>X zIng=>+HQH>DXW0HlaU#mQJWw7K{*6ia4YLk)!CTyoC@bN^)T|QZ>k!OJX=?FC1Dh} zwaSW9DL5N)uI5IYOM$4-^k8 zIi8Y+Y+}5)wiaq%bDr-+IuPIUgHQsg$f`Ijh{*8nVQ#dHyRozWLp>#i5MwW4Z7fg`dtwsPt7J@4ed-~Z3w(dd^$@Y|Jc1-cdJR-jvf zZUwp(_#`B8deGX8IOPD zivlIa%8{Cgwwtb3H@FnB#J1zotT?M8$MxRugR0}*#-6VlSUClb=Q)kr*z(o8xL7KA zb*{a37-O#;i}szbx?x9i+m@dJ(zpvw_yK0EV%xUlc+y){Wq(H~w*6kXDi%-^&vQ%j zo*$w;ZAFBIeGFq~e~QaNY1+e@5M$bCHXBB_nBWBsb~E+JUt6P5V$-ZCz~JStCbZ4F zZv}3oK;lWAua3p7sW8;X4dQ>1Jx-Q~+K!(cZqf7vV)-Kup2d3>M&;S4c literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeLeafsMaterial.mat.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeLeafsMaterial.mat.meta new file mode 100644 index 0000000..c14939e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeLeafsMaterial.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5f399b603419be14ba9bffcf786e93cd +timeCreated: 1476837719 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeTrunkMaterial.mat b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeTrunkMaterial.mat new file mode 100644 index 0000000000000000000000000000000000000000..99a5e26e7e9014286d2b2b3a81e4f13b5c654887 GIT binary patch literal 4908 zcmeI0%WvFN6vod?GD({93Z=B6l!o^!q?Ayep-J;>XosXEEr`wFOm1dOJ>$ssl!?T` zt4gqk4P8(n*dQSU8(1K*U;|r(x+sqoYBvZ~$_iBt-*@e~ojVz+`~h>K6W{yu@$q@s zo@}o7J4wS@{D#4q#6Et|mSL zKaXMFm+qrA|ITG4{xS8FYqD?l!}t>GtTg-SH9RB7;QtHwVf;KtCgw5O%pt@>C1=c; z3Gyx-=RO?6IQz-9cF9TDz60far{Nia4>-I2V zOrDbuFlyB85yN|QJ-@}A@jPmHuXSGDXGy+&)_ET%*V<>*^9jRq@;%0^Cu{s9l)}1w zh5r78F|Yk$LP$n>wg1Nb{*-13Z@&IV4DXTO;QJTMd5<21iVSH#7m)8I%(|gZ6F2eS zF(cJ$+J>Ln#?R<}t zLt68lB#g=Je5VYz^PM)_&UXg9UB0vATJ3!K98GvmP9p;5%V*~?sK^lZ_2@eMiy7-M z56v|3Ybk%VgvF2JD^-z7xIo<#VUb6 zxZZ1iP;tDQ*z;8bE2qHmJg0sWTfTZ1 z7K%l$#O40Jg)QAvA9(ghWfaE{4cP_$?{O!@w3B?nlD9xs+OWM&Es)?N@(r1ITZW( zNvCk?^pYylUhv|8dEQ@T1QeZ1qb>>3pPBe6rO@cx6c?lEPP0jUn|+PiCENc1#U?3+ literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeTrunkMaterial.mat.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeTrunkMaterial.mat.meta new file mode 100644 index 0000000..b409f3d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTreeTrunkMaterial.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4f8b792cce88f944e987ce9c635c0b6e +timeCreated: 1476824693 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTrunk.mat b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestTrunk.mat new file mode 100644 index 0000000000000000000000000000000000000000..f7ea09c3b75f1181a92fabe60a3086145a22be74 GIT binary patch literal 4896 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 lOm?Y~Pd`VWZ@;-l@xQ25Eqy!~A2 sequences = new List(10); + + // Use this for initialization + void Start() + { + var changeCursors = GetComponentsInChildren(true); + + // for this to work we need to rename curves +// Array.Sort(changeCursors, (o1, o2) => string.Compare(o1.gameObject.name, o2.gameObject.name)); + + for (var i = 0; i < changeCursors.Length; i++) Register(changeCursors[i]); + } + + private void Register(BGCcCursorChangeLinear curve) + { + sequences.Add(new Sequence(curve)); + } + + // Update is called once per frame + void Update() + { + foreach (var sequence in sequences) + if (sequence.Curve.gameObject.activeInHierarchy) + { + sequence.Check(); + } + } + + + // no luck here. There shoould be some way to pass curve's number and get rid of this? + /* + public void PointReached(int point, int curve) + { + Process(curve, point); + } + */ + + //Nigthmare start (idea.. we need to switch to non persistent events for this test, which send reference to a curve) + public void PointReached0(int point) + { + Process(0, point); + } + + public void PointReached1(int point) + { + Process(1, point); + } + + public void PointReached2(int point) + { + Process(2, point); + } + + public void PointReached3(int point) + { + Process(3, point); + } + + public void PointReached4(int point) + { + Process(4, point); + } + + public void PointReached5(int point) + { + Process(5, point); + } + + public void PointReached6(int point) + { + Process(6, point); + } + + public void PointReached7(int point) + { + Process(7, point); + } + + public void PointReached8(int point) + { + Process(8, point); + } + + public void PointReached9(int point) + { + Process(9, point); + } + + public void PointReached10(int point) + { + Process(10, point); + } + + public void PointReached11(int point) + { + Process(11, point); + } + + public void PointReached12(int point) + { + Process(12, point); + } + + public void PointReached13(int point) + { + Process(13, point); + } + + public void PointReached14(int point) + { + Process(14, point); + } + + public void PointReached15(int point) + { + Process(15, point); + } + + public void PointReached16(int point) + { + Process(16, point); + } + + public void PointReached17(int point) + { + Process(17, point); + } + + public void PointReached18(int point) + { + Process(18, point); + } + + public void PointReached19(int point) + { + Process(19, point); + } + + public void PointReached20(int point) + { + Process(20, point); + } + + public void PointReached21(int point) + { + Process(21, point); + } + + public void PointReached22(int point) + { + Process(22, point); + } + + public void PointReached23(int point) + { + Process(23, point); + } + + public void PointReached24(int point) + { + Process(24, point); + } + + public void PointReached25(int point) + { + Process(25, point); + } + + public void PointReached26(int point) + { + Process(26, point); + } + + public void PointReached27(int point) + { + Process(27, point); + } + + public void PointReached28(int point) + { + Process(28, point); + } + + public void PointReached29(int point) + { + Process(29, point); + } + + public void PointReached30(int point) + { + Process(30, point); + } + + public void PointReached31(int point) + { + Process(31, point); + } + + public void PointReached32(int point) + { + Process(32, point); + } + + + private void Process(int curve, int pointIndex) + { + var sequence = sequences[curve]; + if (!sequence.Curve.gameObject.activeSelf) return; + +// print("Reached {" + pointIndex + "} for curve =" + curve); + + sequence.Reached(pointIndex); + } + + private sealed class Sequence + { + //precision does not matter too much idea.. lower the value, something wrong here + public const float Epsilon = 0.1f; + + private readonly List expectedPoints = new List(); + private BGCcCursorChangeLinear changeCursor; + + private int pointCursor; + private bool valid = true; + private float lastPoint; + + private float started; + + public BGCurve Curve; + + + private float Elapsed + { + get { return Time.time - started; } + } + + public Sequence(BGCcCursorChangeLinear changeCursor) + { + this.changeCursor = changeCursor; + var cursor = changeCursor.Cursor; + var curve = changeCursor.Curve; + Curve = curve; + started = Time.time; + + + if (!Curve.gameObject.activeInHierarchy) return; + + ThrowIf("Stop overflow control is not supported", changeCursor.OverflowControl == BGCcCursorChangeLinear.OverflowControlEnum.Stop); + + + var pointsCount = curve.PointsCount; + ThrowIf("Curve should have at least 2 points.", pointsCount < 2); + + var math = changeCursor.Cursor.Math.Math; + + var sectionIndex = cursor.CalculateSectionIndex(); + var speed = changeCursor.CurrentSpeed; + var speedPositive = speed > 0; + + if (speedPositive) + { + //=================================== Positive speed + //first point + if (curve.Closed && sectionIndex == pointsCount - 1) + { + expectedPoints.Add(new ExpectedPoint(0, math.GetDistance() - cursor.Distance, speed, 0)); + } + else if (!curve.Closed && sectionIndex == pointsCount - 2) + { + expectedPoints.Add(new ExpectedPoint(pointsCount - 1, math.GetDistance() - cursor.Distance, speed, 0)); + } + else + { + expectedPoints.Add(new ExpectedPoint(sectionIndex + 1, math[sectionIndex + 1].DistanceFromStartToOrigin - cursor.Distance, speed, 0)); + } + + //go towards end + for (var i = sectionIndex + 2; i < pointsCount; i++) + { + expectedPoints.Add(new ExpectedPoint(i, math[i - 1].Distance, changeCursor.GetSpeedAtPoint(i - 1), changeCursor.GetDelayAtPoint(i - 1))); + } + + //add last point + if (curve.Closed && sectionIndex != pointsCount) + { + expectedPoints.Add(new ExpectedPoint(0, math[pointsCount - 1].Distance, changeCursor.GetSpeedAtPoint(pointsCount - 1), changeCursor.GetDelayAtPoint(pointsCount - 1))); + } + + + if (changeCursor.OverflowControl == BGCcCursorChangeLinear.OverflowControlEnum.PingPong) + { + if (curve.Closed) + expectedPoints.Add(new ExpectedPoint(pointsCount - 1, math[pointsCount - 1].Distance, + changeCursor.GetSpeedAtPoint(pointsCount - 1), changeCursor.GetDelayAtPoint(0))); + + //go all the way down + for (var i = pointsCount - 2; i >= 0; i--) + { + expectedPoints.Add(new ExpectedPoint(i, math[i].Distance, changeCursor.GetSpeedAtPoint(i), changeCursor.GetDelayAtPoint(i + 1))); + } + } + else + { + if (!curve.Closed) + { + expectedPoints.Add(new ExpectedPoint(0, math[pointsCount - 2].Distance, 0, changeCursor.GetDelayAtPoint(pointsCount - 1))); + } + } + + //go up to initial position + for (var i = 1; i <= sectionIndex; i++) + { + expectedPoints.Add(new ExpectedPoint(i, math[i - 1].Distance, changeCursor.GetSpeedAtPoint(i - 1), changeCursor.GetDelayAtPoint(i - 1))); + } + + //last point + expectedPoints.Add(new ExpectedPoint(-1, cursor.Distance - math[sectionIndex].DistanceFromStartToOrigin, speed, changeCursor.GetDelayAtPoint(sectionIndex))); + } + else + { + //=================================== Negative speed + //first point + expectedPoints.Add(new ExpectedPoint(sectionIndex, cursor.Distance - math[sectionIndex].DistanceFromStartToOrigin, speed, 0)); + + //go towards start + for (var i = sectionIndex - 1; i >= 0; i--) + { + expectedPoints.Add(new ExpectedPoint(i, math[i].Distance, changeCursor.GetSpeedAtPoint(i), changeCursor.GetDelayAtPoint(i + 1))); + } + + if (changeCursor.OverflowControl == BGCcCursorChangeLinear.OverflowControlEnum.PingPong) + { + for (var i = 1; i < pointsCount; i++) + { + expectedPoints.Add(new ExpectedPoint(i, math[i - 1].Distance, changeCursor.GetSpeedAtPoint(i - 1), changeCursor.GetDelayAtPoint(i - 1))); + } + + if (curve.Closed) + { + expectedPoints.Add(new ExpectedPoint(0, math[pointsCount - 1].Distance, changeCursor.GetSpeedAtPoint(pointsCount - 1), changeCursor.GetDelayAtPoint(pointsCount - 1))); + expectedPoints.Add(new ExpectedPoint(pointsCount - 1, math[pointsCount - 1].Distance, + changeCursor.GetSpeedAtPoint(pointsCount - 1), changeCursor.GetDelayAtPoint(0))); + } + } + else + { + if (curve.Closed) + { + expectedPoints.Add(new ExpectedPoint(pointsCount - 1, math[pointsCount - 1].Distance, + changeCursor.GetSpeedAtPoint(pointsCount - 1), changeCursor.GetDelayAtPoint(0))); + } + else + { + expectedPoints.Add(new ExpectedPoint(pointsCount - 1, 0, 0, changeCursor.GetDelayAtPoint(0))); + } + } + + + //go from end to initial section + for (var i = pointsCount - 2; i > sectionIndex; i--) + { + expectedPoints.Add(new ExpectedPoint(i, math[i].Distance, changeCursor.GetSpeedAtPoint(i), changeCursor.GetDelayAtPoint(i + 1))); + } + + //last point + expectedPoints.Add(new ExpectedPoint(-1, math[sectionIndex].DistanceFromEndToOrigin - cursor.Distance, changeCursor.GetSpeedAtPoint(sectionIndex), + changeCursor.GetDelayAtPoint(sectionIndex + 1))); + } + } + + private void ThrowIf(string message, bool condition) + { + if (condition) throw GetException(message); + } + + private UnityException GetException(string message) + { + return new UnityException(message + ". Curve=" + changeCursor.Curve.gameObject.name); + } + + public void Check() + { + if (!valid) return; + + var toCheck = expectedPoints[pointCursor]; + + if (toCheck.PointIndex == -1) + { + if (toCheck.ExpectedDelay < Elapsed) + { + MoveNext(); + } + } + else if (toCheck.ExpectedDelay < Elapsed - Epsilon) + { + valid = false; + Debug.LogException(GetException("Missing event: expected " + toCheck + " event did not occur")); + return; + } + } + + public void Reached(int point) + { + if (!valid) return; + + var toCompare = expectedPoints[pointCursor]; + if (toCompare.PointIndex >= 0 && toCompare.PointIndex != point) + { + valid = false; + Debug.LogException(GetException("Points indexes mismatch: expected " + toCompare.PointIndex + ", actual=" + point)); + return; + } + + var expectedDelay = toCompare.ExpectedDelay; + var actualDelay = Elapsed; + if (Math.Abs(expectedDelay - actualDelay) > Epsilon) + { + valid = false; + Debug.LogException(GetException("Timing mismatch at point {" + toCompare.PointIndex + "}: expected " + expectedDelay + ", actual=" + actualDelay)); + return; + } + + MoveNext(); + } + + private void MoveNext() + { + started = Time.time; + pointCursor = pointCursor == expectedPoints.Count - 1 ? 0 : pointCursor + 1; + } + } + + private sealed class ExpectedPoint + { + public readonly float Distance; + public readonly int PointIndex; + public readonly float Speed; + public readonly float Delay; + + public ExpectedPoint(int pointIndex, float distance, float speed, float delay) + { + Speed = speed; + Distance = distance; + PointIndex = pointIndex; + Delay = delay; + } + + public double ExpectedDelay + { + get + { + var speed = Math.Abs(Speed); + var delay = Mathf.Clamp(Delay, 0, float.MaxValue); + return delay + (speed < Sequence.Epsilon ? Sequence.Epsilon : Distance/speed); + } + } + + public override string ToString() + { + return "Point " + PointIndex + " after " + ExpectedDelay + " delay."; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCcChangeCursorLinear.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCcChangeCursorLinear.cs.meta new file mode 100644 index 0000000..15e7260 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCcChangeCursorLinear.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 9ae216fc3e845094f987bb267515c24f +timeCreated: 1477542371 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveChange.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveChange.cs new file mode 100644 index 0000000..1699a5c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveChange.cs @@ -0,0 +1,32 @@ +using UnityEngine; + +namespace BansheeGz.BGSpline.Example +{ + // rotate and scale an object + public class BGTestCurveChange : MonoBehaviour + { + private const float RotationSpeed = 40; + private const float ScaleUpperLimit = 1.25f; + private const float ScaleLowerLimit = .5f; + + private Vector3 scaleSpeed = Vector3.one*.1f; + + // Update is called once per frame + private void Update() + { + //rotate + transform.RotateAround(transform.position, Vector3.up, RotationSpeed*Time.deltaTime); + + //scale + var localScale = transform.localScale; + var upperLimit = localScale.x > ScaleUpperLimit; + var lowerLimit = localScale.x < ScaleLowerLimit; + if (upperLimit || lowerLimit) + { + scaleSpeed = -scaleSpeed; + localScale = upperLimit ? new Vector3(ScaleUpperLimit, ScaleUpperLimit, ScaleUpperLimit) : new Vector3(ScaleLowerLimit, ScaleLowerLimit, ScaleLowerLimit); + } + transform.localScale = localScale + scaleSpeed*Time.deltaTime; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveChange.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveChange.cs.meta new file mode 100644 index 0000000..e93daf2 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveChange.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 878d4ca641b7844418bd302124244337 +timeCreated: 1474194271 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveClosestPoint.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveClosestPoint.cs new file mode 100644 index 0000000..92fbfdc --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveClosestPoint.cs @@ -0,0 +1,321 @@ +using System; +using UnityEngine; +using BansheeGz.BGSpline.Components; +using BansheeGz.BGSpline.Curve; +using Random = UnityEngine.Random; + +namespace BansheeGz.BGSpline.Example +{ + //check math's CalcPositionByClosestPoint method. (this test can be automated with CheckResults set to true) + public class BGTestCurveClosestPoint : MonoBehaviour + { + [Tooltip("Line renderer material")] public Material LineRendererMaterial; + + [Tooltip("Object to use for point's indication")] public GameObject PointIndicator; + + [Range(1, 100)] [Tooltip("How much points to use with search")] public int NumberOfPointsToSeek = 10; + + [Range(2, 100)] [Tooltip("How much points to add to the curve")] public int NumberOfCurvePoints = 100; + + [Range(1, 30)] [Tooltip("How much sections to use for splitting each curve's segment")] public int NumberOfSplits = 30; + + [Range(1, 5)] [Tooltip("Transition period")] public int Period = 4; + + [Tooltip("Use slow check method to validate results")] public bool CheckResults = false; + + + private BGCurve curve; + private BGCcMath math; + + //this is an area, defined by camera frustum (so we could see curve and points) + private static Vector3 min = new Vector3(-10, 0, -2); + private static Vector3 max = new Vector3(10, 10, 2); + + + //indicator objects + private GameObject[] objects; + + //curve's points positions + private Vector3[] oldCurvePointPos; + private Vector3[] newCurvePointPos; + + //point's positions + private Vector3[] oldPointPos; + private Vector3[] newPointPos; + + //for transitions + private float startTime = -100000; + + private int ErrorPointIndex = -1; + private GUIStyle style; + + private bool HasError + { + get { return ErrorPointIndex >= 0; } + } + + // Use this for initialization + private void Start() + { + //init components + curve = gameObject.AddComponent(); + curve.Closed = true; + math = gameObject.AddComponent(); + gameObject.AddComponent(); + var lineRenderer = gameObject.GetComponent(); + lineRenderer.sharedMaterial = LineRendererMaterial; + var color = new Color(.2f, .2f, .2f, 1f); +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.startWidth = lineRenderer.endWidth = .03f; + lineRenderer.startColor = lineRenderer.endColor = color; +#else + lineRenderer.SetWidth(.03f, .03f); + lineRenderer.SetColors(color, color); +#endif + math.SectionParts = NumberOfSplits; + + //create curve's points + for (var i = 0; i < NumberOfCurvePoints; i++) + { + var controlRandom = Random.Range(0, 3); + var controlType = BGCurvePoint.ControlTypeEnum.Absent; + switch (controlRandom) + { + case 1: + controlType = BGCurvePoint.ControlTypeEnum.BezierIndependant; + break; + case 2: + controlType = BGCurvePoint.ControlTypeEnum.BezierSymmetrical; + break; + } + curve.AddPoint(new BGCurvePoint(curve, + Vector3.zero, + controlType, + RandomVector()*.3f, + RandomVector()*.3f)); + } + + //init arrays + oldPointPos = new Vector3[NumberOfPointsToSeek]; + newPointPos = new Vector3[NumberOfPointsToSeek]; + oldCurvePointPos = new Vector3[NumberOfCurvePoints]; + newCurvePointPos = new Vector3[NumberOfCurvePoints]; + + InitArray(newCurvePointPos, oldCurvePointPos); + InitArray(newPointPos, oldPointPos); + + //create objects + objects = new GameObject[NumberOfPointsToSeek]; + for (var i = 0; i < NumberOfPointsToSeek; i++) + { + var clone = Instantiate(PointIndicator); + clone.transform.parent = transform; + objects[i] = clone; + } + PointIndicator.SetActive(false); + + //init cycle + InitCycle(); + } + + private void OnGUI() + { + if (style == null) style = new GUIStyle(GUI.skin.label) {fontSize = 20}; + GUI.Label(new Rect(0, 30, 600, 30), "Turn on Gizmos to see Debug lines", style); + } + + + private void InitCycle() + { + InitArray(oldCurvePointPos, newCurvePointPos); + InitArray(oldPointPos, newPointPos); + } + + // Update is called once per frame + private void Update() + { + if (HasError) + { + //use it for debugging + Process(ErrorPointIndex, true); + } + else + { + Calculate(null, null); + + + var elapsed = Time.time - startTime; + if (elapsed > Period) + { + startTime = Time.time; + InitCycle(); + elapsed = 0; + } + + //lerp + var ratio = elapsed/Period; + for (var i = 0; i < NumberOfCurvePoints; i++) + { + curve[i].PositionLocal = Vector3.Lerp(oldCurvePointPos[i], newCurvePointPos[i], ratio); + } + for (var i = 0; i < NumberOfPointsToSeek; i++) + { + objects[i].transform.localPosition = Vector3.Lerp(oldPointPos[i], newPointPos[i], ratio); + } + } + } + + + private void Calculate(object sender, EventArgs e) + { + for (var i = 0; i < NumberOfPointsToSeek; i++) + { + Process(i); + if (HasError) break; + } + } + + private void Process(int i, bool suppressWarning = false) + { + var point = objects[i].transform.position; + float distanceUsingMath; + var posUsingMath = math.CalcPositionByClosestPoint(point, out distanceUsingMath); + + Debug.DrawLine(point, posUsingMath, Color.yellow); + + if (!CheckResults) return; + + float distanceUsingCheckMethod; + var posUsingCheckMethod = CalcPositionByClosestPoint(math, point, out distanceUsingCheckMethod); + Debug.DrawLine(point, posUsingCheckMethod, Color.blue); + + var distanceCheck = Math.Abs(distanceUsingMath - distanceUsingCheckMethod) > .01f; + var pointCheck = Vector3.Magnitude(posUsingMath - posUsingCheckMethod) > 0.001f; + if ((distanceCheck || pointCheck) && Mathf.Abs((point - posUsingMath).magnitude - (point - posUsingCheckMethod).magnitude) > BGCurve.Epsilon) + { + ErrorPointIndex = i; + if (!suppressWarning) + { + Debug.Log("Error detected. Simulation stopped, but erroneous iteration's still running. Use debugger to debug the issue."); + Debug.Log("!!! Discrepancy detected while calculating pos by closest point: 1) [Using math] pos=" + posUsingMath + ", distance=" + distanceUsingMath + + " 2) [Using check method] pos=" + posUsingCheckMethod + ", distance=" + distanceUsingCheckMethod); + + + if (pointCheck) + { + Debug.Log("Reason: Result points varies more than " + BGCurve.Epsilon + ". Difference=" + Vector3.Magnitude(posUsingMath - posUsingCheckMethod)); + } + if (distanceCheck) + { + Debug.Log("Reason: Distances varies more than 1cm. Difference=" + Math.Abs(distanceUsingMath - distanceUsingCheckMethod)); + } + + var mathPos = math.CalcByDistance(BGCurveBaseMath.Field.Position, distanceUsingMath); + var checkMethodPos = math.CalcByDistance(BGCurveBaseMath.Field.Position, distanceUsingCheckMethod); + Debug.Log("Distance check: 1) [Using math] check=" + (Vector3.SqrMagnitude(mathPos - posUsingMath) < BGCurve.Epsilon ? "passed" : "failed") + + " 2) [Using check method] check=" + (Vector3.SqrMagnitude(checkMethodPos - posUsingCheckMethod) < BGCurve.Epsilon ? "passed" : "failed")); + + + var actualDistUsingMath = Vector3.Distance(point, posUsingMath); + var actualDistanceUsingCheckMethod = Vector3.Distance(point, posUsingCheckMethod); + Debug.Log("Actual distance: 1) [Using math] Dist=" + actualDistUsingMath + + " 2) [Using check method] Dist=" + actualDistanceUsingCheckMethod + + + (Math.Abs(actualDistUsingMath - actualDistanceUsingCheckMethod) > BGCurve.Epsilon + ? (". And the winner is " + (actualDistUsingMath < actualDistanceUsingCheckMethod ? "math" : "check method")) + : "")); + } + } + } + + //Bruteforce method for checking results only. Do not use it. + private static Vector3 CalcPositionByClosestPoint(BGCcMath math, Vector3 targetPoint, out float distance) + { + var sections = math.Math.SectionInfos; + var sectionsCount = sections.Count; + var result = sections[0][0].Position; + var minDistance = Vector3.SqrMagnitude(sections[0][0].Position - targetPoint); + distance = 0; + for (var i = 0; i < sectionsCount; i++) + { + var currentSection = sections[i]; + + + var points = currentSection.Points; + var pointsCount = points.Count; + for (var j = 1; j < pointsCount; j++) + { + var point = points[j]; + float ratio; + + var closestPoint = CalcClosestPointToLine(points[j - 1].Position, point.Position, targetPoint, out ratio); + + var sqrMagnitude = Vector3.SqrMagnitude(targetPoint - closestPoint); + if (!(minDistance > sqrMagnitude)) continue; + + + minDistance = sqrMagnitude; + result = closestPoint; + + if (ratio == 1) + { + var sectionIndex = i; + var pointIndex = j; + if (j == pointsCount - 1 && i < sectionsCount - 1) + { + sectionIndex = i + 1; + pointIndex = 0; + } + distance = sections[sectionIndex].DistanceFromStartToOrigin + sections[sectionIndex][pointIndex].DistanceToSectionStart; + } + else + { + distance = sections[i].DistanceFromStartToOrigin + Mathf.Lerp(currentSection[j - 1].DistanceToSectionStart, point.DistanceToSectionStart, ratio); + } + } + } + return result; + } + + + private static Vector3 RandomVector() + { + return new Vector3(Random.Range(min.x, max.x), Random.Range(min.y, max.y), Random.Range(min.z, max.z)); + } + + private static void InitArray(Vector3[] oldArray, Vector3[] newArray) + { + for (var i = 0; i < oldArray.Length; i++) + { + oldArray[i] = newArray[i]; + newArray[i] = RandomVector(); + } + } + + private static Vector3 CalcClosestPointToLine(Vector3 a, Vector3 b, Vector3 p, out float ratio) + { + var ap = p - a; + var ab = b - a; + var sqrtMagnitude = ab.sqrMagnitude; + if (Math.Abs(sqrtMagnitude) < BGCurve.Epsilon) + { + ratio = 1; + return b; + } + + var distance = Vector3.Dot(ap, ab)/sqrtMagnitude; + if (distance < 0) + { + ratio = 0; + return a; + } + if (distance > 1) + { + ratio = 1; + return b; + } + ratio = distance; + return a + ab*distance; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveClosestPoint.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveClosestPoint.cs.meta new file mode 100644 index 0000000..9639075 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveClosestPoint.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e541fe02faf348f4a82165f3484dbb8c +timeCreated: 1474039391 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveDynamic.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveDynamic.cs new file mode 100644 index 0000000..d7381c1 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveDynamic.cs @@ -0,0 +1,77 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Example +{ + // This is old obsolete example class, left for compatibility only. + // DO NOT USE IT AS AN EXAMPLE PLEASE + // Use Cc components (BGCurveBaseMath -> BGCcMath, LineRenderer -> BGCcVisualizationLineRenderer) + [RequireComponent(typeof (BGCurve))] + [RequireComponent(typeof (LineRenderer))] + public class BGTestCurveDynamic : MonoBehaviour + { + private const int TimeToMoveUp = 3; + + public GameObject ObjectToMove; + + private BGCurve curve; + private BGCurveBaseMath curveBaseMath; + + private float started; + private float ratio; + private LineRenderer lineRenderer; + + + // Use this for initialization + private void Start() + { + curve = GetComponent(); +// curve.TraceChanges = true; + + lineRenderer = GetComponent(); + +// curveBaseMath = new BGCurveBaseMath(curve, true); + curveBaseMath = new BGCurveBaseMath(curve); + started = Time.time; + + ResetLineRenderer(); + curve.Changed += (sender, args) => ResetLineRenderer(); + } + + private void ResetLineRenderer() + { + const int points = 50; + + var positions = new Vector3[points]; + for (var i = 0; i < points; i++) + { + positions[i] = curveBaseMath.CalcPositionByDistanceRatio(((float) i/(points - 1))); + } + +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.numPositions = points; +#else + lineRenderer.SetVertexCount(points); +#endif + + lineRenderer.SetPositions(positions); + } + + // Update is called once per frame + private void Update() + { + transform.RotateAround(Vector3.zero, Vector3.up, 40*Time.deltaTime); + + ratio = (Time.time - started)/TimeToMoveUp; + if (ratio >= 1) + { + started = Time.time; + ratio = 0; + } + else + { + ObjectToMove.transform.position = curveBaseMath.CalcPositionByDistanceRatio(ratio); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveDynamic.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveDynamic.cs.meta new file mode 100644 index 0000000..6ca7b9a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveDynamic.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 14e1aa9c8356b444eb28ff9fadb1e98e +timeCreated: 1473297298 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveMath.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveMath.cs new file mode 100644 index 0000000..4b0314a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveMath.cs @@ -0,0 +1,324 @@ +using System; +using UnityEngine; +using System.Collections.Generic; +using BansheeGz.BGSpline.Curve; +using Random = UnityEngine.Random; + +namespace BansheeGz.BGSpline.Example +{ + // math visual testing (for internal use) + public class BGTestCurveMath : MonoBehaviour + { + [Tooltip("Material to use with LineRenderer")] public Material LineRendererMaterial; + + [Tooltip("Object to move along a curve")] public MeshRenderer ObjectToMove; + + private const float Period = 3; + private const int ObjectsCount = 4; + private const float ObjectsSpeed = .3f; + + private TestCurves testCurves; + + private GUIStyle style; + + // Use this for initialization + private void Start() + { + testCurves = new TestCurves(GetComponent(), new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.PositionAndTangent), ObjectToMove, LineRendererMaterial); + + //Base, OptimizeStraightLines + testCurves.Add(new CurveData(testCurves, "BGBaseStraightLines", "Base, OptimizeStraightLines = true", transform.position + new Vector3(-4, 1), + new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.PositionAndTangent) {OptimizeStraightLines = true}, CurveData.MathTypeEnum.Base)); + + //Base, UsePointPositionsToCalcTangents + testCurves.Add(new CurveData(testCurves, "BGBasePos2Tangents", "Base, UsePointPositionsToCalcTangents = true", transform.position + new Vector3(-4, 4), + new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.PositionAndTangent) {UsePointPositionsToCalcTangents = true}, CurveData.MathTypeEnum.Base)); + + //Adaptive + testCurves.Add(new CurveData(testCurves, "BGAdaptive", "Adaptive", transform.position + new Vector3(4, 4), + new BGCurveAdaptiveMath.ConfigAdaptive(BGCurveBaseMath.Fields.PositionAndTangent) /* { Tolerance = .2f }*/, CurveData.MathTypeEnum.Adaptive)); + + //Formula + testCurves.Add(new CurveData(testCurves, "BGFormula", "Formula", transform.position + new Vector3(4, 1), + new BGCurveBaseMath.Config(BGCurveBaseMath.Fields.PositionAndTangent), CurveData.MathTypeEnum.Formula)); + } + + + // Update is called once per frame + private void Update() + { + testCurves.Update(); + if (Input.GetKeyDown(KeyCode.LeftArrow)) testCurves.MoveLeft(); + if (Input.GetKeyDown(KeyCode.RightArrow)) testCurves.MoveRight(); + } + + private void OnGUI() + { + if (style == null) style = new GUIStyle(GUI.skin.label) {fontSize = 18}; + GUI.Label(new Rect(0, 24, 800, 30), "Left Arrow - move left, Right Arrow - move right", style); + GUI.Label(new Rect(0, 48, 800, 30), "Comparing with: " + testCurves.CurrentToString(), style); + } + + + //==================================== abstract curve's data + private abstract class CurveDataAbstract + { + private readonly List objectsToMove = new List(); + private readonly Material objectToMoveMaterial; + private readonly LineRenderer lineRenderer; + public readonly Material LineRendererMaterial; + protected readonly GameObject GameObject; + + protected BGCurveBaseMath Math; + + private BGCurve curve; + + public BGCurve Curve + { + get { return curve; } + protected set + { + curve = value; + curve.Changed += (sender, args) => UpdateLineRenderer(); + } + } + + + protected CurveDataAbstract(GameObject gameObject, Material lineRendererMaterial, Color color) + { + GameObject = gameObject; + LineRendererMaterial = lineRendererMaterial; + + //change material + objectToMoveMaterial = Instantiate(lineRendererMaterial); + objectToMoveMaterial.SetColor("_TintColor", color); + + + //add lineRenderer + lineRenderer = gameObject.AddComponent(); + lineRenderer.material = lineRendererMaterial; +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.startWidth = lineRenderer.endWidth = 0.05f; + lineRenderer.startColor = lineRenderer.endColor = color; +#else + lineRenderer.SetWidth(0.05f, 0.05f); + lineRenderer.SetColors(color, color); +#endif + + } + + //=================== line renderer + private void UpdateLineRenderer() + { + const int count = 100; + var positions = new Vector3[100]; + const float countMinusOne = count - 1; + for (var i = 0; i < 100; i++) + { + var distanceRatio = i/countMinusOne; + positions[i] = Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, distanceRatio); + } +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.numPositions = count; +#else + lineRenderer.SetVertexCount(count); +#endif + lineRenderer.SetPositions(positions); + } + + //=================== objects + protected void AddObjects(int count, MeshRenderer pattern, Transform parent) + { + for (var i = 0; i < count; i++) + { + var clone = Instantiate(pattern.gameObject); + clone.transform.parent = parent; + AddObject(clone); + } + } + + protected void AddObject(GameObject obj) + { + obj.GetComponent().sharedMaterial = objectToMoveMaterial; + objectsToMove.Add(obj.gameObject); + } + + protected void UpdateObjects(List distanceRatios) + { + for (var i = 0; i < objectsToMove.Count; i++) + { + var position = Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, distanceRatios[i]); + var tangent = Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Tangent, distanceRatios[i]); + + objectsToMove[i].transform.position = position; + objectsToMove[i].transform.LookAt(position + tangent); + } + } + + public abstract void Update(); + } + + //==================================== Reference Curve + private sealed class TestCurves : CurveDataAbstract + { + public readonly List DistanceRatios = new List(); + public readonly MeshRenderer ObjectToMove; + private readonly List curves = new List(); + + private float startTime = -Period*2; + private Quaternion fromRotation; + private Quaternion toRotation; + private int currentCurveIndex = -1; + + + public TestCurves(BGCurve curve, BGCurveBaseMath.Config config, MeshRenderer objectToMove, Material lineRendererMaterial) + : base(curve.gameObject, lineRendererMaterial, Color.green) + { + Curve = curve; + Math = new BGCurveBaseMath(curve, config); + ObjectToMove = objectToMove; + + AddObject(objectToMove.gameObject); + AddObjects(ObjectsCount - 1, objectToMove, curve.transform); + + const float offset = 1/(float) ObjectsCount; + for (var i = 0; i < ObjectsCount; i++) DistanceRatios.Add(i*offset); + } + + public void MoveRight() + { + currentCurveIndex++; + if (currentCurveIndex == curves.Count) currentCurveIndex = 0; + } + + public void MoveLeft() + { + currentCurveIndex--; + if (currentCurveIndex < 0) currentCurveIndex = curves.Count - 1; + } + + public override void Update() + { + if (Time.time - startTime > Period) + { + startTime = Time.time; + + fromRotation = Curve.transform.rotation; + toRotation = Quaternion.Euler(Random.Range(0.0f, 360.0f), Random.Range(0.0f, 360.0f), Random.Range(0.0f, 360.0f)); + } + + var ratio = (Time.time - startTime)/Period; + Curve.transform.rotation = Quaternion.Lerp(fromRotation, toRotation, ratio); + for (var i = 0; i < DistanceRatios.Count; i++) + { + DistanceRatios[i] += ObjectsSpeed*Time.deltaTime; + if (DistanceRatios[i] > 1) DistanceRatios[i] = 0; + } + UpdateObjects(DistanceRatios); + + foreach (var data in curves) data.Update(); + } + + public bool IsCurrent(CurveData curve) + { + return currentCurveIndex >= 0 && currentCurveIndex < curves.Count && curves[currentCurveIndex] == curve; + } + + public void Add(CurveData curveData) + { + curves.Add(curveData); + } + + public string CurrentToString() + { + return currentCurveIndex < 0 ? "None" : curves[currentCurveIndex].Description; + } + } + + //==================================== Some Curve + private sealed class CurveData : CurveDataAbstract + { + public enum MathTypeEnum + { + Base, + Formula, + Adaptive + } + + private readonly Vector3 origin; + private readonly TestCurves testCurves; + private readonly Vector3 originalScale = new Vector3(.7f, .7f, .7f); + + private readonly string description; + + public string Description + { + get { return description; } + } + + public CurveData(TestCurves testCurves, string name, string description, Vector3 position, BGCurveBaseMath.Config config, MathTypeEnum mathType) + : base(new GameObject(name), testCurves.LineRendererMaterial, Color.magenta) + { + this.testCurves = testCurves; + this.description = description; + + //game object + GameObject.transform.position = position; + origin = position; + + //curve + Curve = GameObject.AddComponent(); + Curve.Closed = testCurves.Curve.Closed; + + //add points + for (var i = 0; i < testCurves.Curve.PointsCount; i++) + { + var point = testCurves.Curve[i]; + var clonePoint = new BGCurvePoint(Curve, point.PositionLocal, point.ControlType, point.ControlFirstLocal, point.ControlSecondLocal); + Curve.AddPoint(clonePoint); + } + + //init math after points are added + switch (mathType) + { + case MathTypeEnum.Base: + Math = new BGCurveBaseMath(Curve, config); + break; + case MathTypeEnum.Formula: +#pragma warning disable 0618 + Math = new BGCurveFormulaMath(Curve, config); +#pragma warning restore 0618 + + break; + case MathTypeEnum.Adaptive: + Math = new BGCurveAdaptiveMath(Curve, (BGCurveAdaptiveMath.ConfigAdaptive) config); + break; + default: + throw new ArgumentOutOfRangeException("mathType", mathType, null); + } + + AddObjects(ObjectsCount, testCurves.ObjectToMove, GameObject.transform); + + //scale down + GameObject.transform.localScale = originalScale; + } + + public override void Update() + { + var curveTransform = Curve.gameObject.transform; + + var referenceTransform = testCurves.Curve.transform; + + curveTransform.rotation = referenceTransform.rotation; + + var moveTime = 10*Time.deltaTime; + + var current = testCurves.IsCurrent(this); + curveTransform.position = Vector3.MoveTowards(curveTransform.position, current ? referenceTransform.position : origin, moveTime); + curveTransform.localScale = Vector3.MoveTowards(curveTransform.localScale, current ? referenceTransform.transform.localScale : originalScale, moveTime/4); + + UpdateObjects(testCurves.DistanceRatios); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveMath.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveMath.cs.meta new file mode 100644 index 0000000..45eeaa0 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveMath.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: f583c3c12fc27e84e93751f76bb81bc5 +timeCreated: 1471388845 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntime.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntime.cs new file mode 100644 index 0000000..638651c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntime.cs @@ -0,0 +1,120 @@ +using BansheeGz.BGSpline.Components; +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Example +{ + // test class for example only (adding moving deleting points at runtime) + [RequireComponent(typeof (BGCcMath))] + public class BGTestCurveRuntime : MonoBehaviour + { + // the height between 2 points + private const float OneTierHeight = 2; + //number of points to add (so total is 9). Should be even. + private const int PointsCountToAdd = 8; + //point's move time + private const float PointMoveTime = 1.5f; + //spread for control points + private const int MaximumControlSpread = 4; + + + public GameObject ObjectToMove; + + private BGCurve curve; + + private BGCcMath math; + + // section spawn start time + private float started; + + // current point's pointer (index) + private int counter; + // position for new point. The point will be moved slowly towards it. + private Vector3 nextPosition; + // position for new point's 1st control + private Vector3 nextControl1; + // position for previous point's 2nd control. + private Vector3 nextControl2; + + // Use this for initialization + private void Start() + { + curve = GetComponent(); + math = GetComponent(); + Reset(); + } + + //new cycle + private void Reset() + { + //delete all points (use curve.Delete to remove a single point) + curve.Clear(); + + //add very first point + curve.AddPoint(new BGCurvePoint(curve, Vector3.zero) {ControlType = BGCurvePoint.ControlTypeEnum.BezierIndependant}); + + started = Time.time; + counter = 0; + } + + // Update is called once per frame + private void Update() + { + var elapsed = Time.time - started; + + if (elapsed >= PointMoveTime || curve.PointsCount < 2) + { + if (counter == PointsCountToAdd) + { + //=========================================== Reset (end of cycle) + Reset(); + } + else + { + //=========================================== New point spawning + //spawn new point at the same position as the last one + var position = curve[curve.PointsCount - 1].PositionLocal; + curve.AddPoint(new BGCurvePoint(curve, position) + { + ControlType = BGCurvePoint.ControlTypeEnum.BezierIndependant, + //unfortunately by default ControlFirstLocal and ControlSecondLocal are not equal to Vector3.zero. That was a mistake. + ControlFirstLocal = Vector3.zero, + ControlSecondLocal = Vector3.zero + }); + + // are we going up or down + var up = counter < (PointsCountToAdd >> 1); + + //assign next positions to drag a point (and controls) to + nextPosition = position + new Vector3(0, up ? OneTierHeight : -OneTierHeight, 0); + var controlPosition = new Vector3( + Random.Range(-MaximumControlSpread, MaximumControlSpread), + (up ? OneTierHeight : -OneTierHeight)*.5f, + Random.Range(-MaximumControlSpread, MaximumControlSpread)); + nextControl1 = Vector3.Lerp(position - nextPosition, controlPosition, .8f); + nextControl2 = Vector3.Lerp(nextPosition - position, controlPosition, .8f); + started = Time.time; + + counter++; + if (curve.PointsCount > 2) curve.Delete(0); + } + } + else + { + var ratio = elapsed/PointMoveTime; + //=========================================== Moving a current point (and adjacent controls) slowly to their future positions + // changing curve's attributes, like point's positions or controls fires curve.Changed event (in curve's LateUpdate) + // math object uses this event to recalculate it's cached data (and it's relatively expensive operation). + // we also use this event to call UpdateLineRenderer to update UI. + var lastPoint = curve[curve.PointsCount - 1]; + lastPoint.PositionLocal = Vector3.Lerp(lastPoint.PositionLocal, nextPosition, ratio); + lastPoint.ControlFirstLocal = Vector3.Lerp(lastPoint.PositionLocal, nextControl1, ratio); + lastPoint.ControlFirstLocal = Vector3.Lerp(lastPoint.PositionLocal, nextControl2, ratio); + + // move particles. we can use math's cached data directly, if we want to + var section = math.Math[0]; + ObjectToMove.transform.position = math.Math.CalcByDistance(BGCurveBaseMath.Field.Position, section.DistanceFromStartToOrigin + section.Distance*ratio); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntime.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntime.cs.meta new file mode 100644 index 0000000..8c4dbc9 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntime.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4b89742ecd879a046849644e458dc278 +timeCreated: 1471249888 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntimeCustomFields.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntimeCustomFields.cs new file mode 100644 index 0000000..0032cba --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntimeCustomFields.cs @@ -0,0 +1,65 @@ +using BansheeGz.BGSpline.Components; +using BansheeGz.BGSpline.Curve; +using UnityEngine; + +namespace BansheeGz.BGSpline.Example +{ + // Testing creating custom fields from scratch at runtime + public class BGTestCurveRuntimeCustomFields : MonoBehaviour + { + private const string SpeedFieldName = "speed"; + private const string DelayFieldName = "delay"; + private const float Width = .02f; + + + public Transform ObjectToMove; + public Material LineRendererMaterial; + + // Use this for initialization + void Start() + { + //move object + var translateObject = gameObject.AddComponent(); + translateObject.ObjectToManipulate = ObjectToMove; + + //move cursor + var changeCursor = gameObject.AddComponent(); + + //add line renderer + gameObject.AddComponent(); + var lineRenderer = gameObject.GetComponent(); + lineRenderer.sharedMaterial = LineRendererMaterial; +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.startWidth = lineRenderer.endWidth = Width; +#else + lineRenderer.SetWidth(Width, Width); +#endif + + //set up curve + var curve = changeCursor.Curve; + curve.Closed = true; + curve.Mode2D = BGCurve.Mode2DEnum.XY; + curve.PointsMode = BGCurve.PointsModeEnum.GameObjectsTransform; + + //add points + curve.AddPoint(new BGCurvePoint(curve, new Vector2(-5, 0))); + curve.AddPoint(new BGCurvePoint(curve, new Vector2(0, 5), BGCurvePoint.ControlTypeEnum.BezierSymmetrical, new Vector2(-5, 0), new Vector2(5, 0))); + curve.AddPoint(new BGCurvePoint(curve, new Vector2(5, 0))); + + //setup custom fields + //---speed + changeCursor.SpeedField = NewFloatField(changeCursor, SpeedFieldName, 5, 10, 15); + //---delay + changeCursor.DelayField = NewFloatField(changeCursor, DelayFieldName, 3, 1, 2); + } + + //Add field with values + private static BGCurvePointField NewFloatField(BGCcCursorChangeLinear changeCursor, string fieldName, params float[] values) + { + var curve = changeCursor.Curve; + var field = curve.AddField(fieldName, BGCurvePointField.TypeEnum.Float); + for (var i = 0; i < values.Length; i++) curve[i].SetFloat(fieldName, values[i]); + return field; + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntimeCustomFields.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntimeCustomFields.cs.meta new file mode 100644 index 0000000..8bdee64 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveRuntimeCustomFields.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 69984b3a12156f746b3c5b5c83d103c6 +timeCreated: 1480534479 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveShowcase.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveShowcase.cs new file mode 100644 index 0000000..55f13fe --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveShowcase.cs @@ -0,0 +1,416 @@ +using UnityEngine; +using System.Collections.Generic; +using BansheeGz.BGSpline.Components; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Example +{ + //for 1.1 version Demo scene + public class BGTestCurveShowcase : MonoBehaviour + { + [Header("Light")] public Light Light; + + [Header("Logo parts")] public BGCcCursorObjectTranslate B; + public BGCcCursorObjectTranslate G; + public BGCcMath Curve; + + [Header("Projectiles")] public GameObject ProjectileFolder; + public TrailRenderer Projectile1; + public TrailRenderer Projectile2; + public BGCcCursor ProjectileCurve1; + + [Header("Particles")] public ParticleSystem BParticles; + public ParticleSystem GParticles; + public ParticleSystem CurveParticles1; + public ParticleSystem CurveParticles2; + + //============== dynamic + [Header("Dynamic")] public GameObject DynamicCurve; + public Light Light1; + public Light Light2; + public Light Light3; + + //============== some useless stuff + private readonly List effects = new List(); + + + //============== misc + private const float ScaleMin = 0.85f; + private const float ScaleMax = 1.15f; + private static readonly Vector3 FromScale = new Vector3(ScaleMin, ScaleMin, ScaleMin); + private static readonly Vector3 ToScale = new Vector3(ScaleMax, ScaleMax, ScaleMax); + private const float ScalePeriodMin = 1; + private const float ScalePeriodMax = 2; + + + //============== Unity callbacks + // Use this for initialization + private void Start() + { + //comment the effect to disable it + // scale the whole thing + effects.Add(new EffectScale(gameObject, ScalePeriodMin, ScalePeriodMax, FromScale, ToScale)); + + // scale parts + effects.Add(new EffectScale(B.gameObject, ScalePeriodMin, ScalePeriodMax, FromScale, ToScale)); + effects.Add(new EffectScale(G.gameObject, ScalePeriodMin, ScalePeriodMax, FromScale, ToScale)); + effects.Add(new EffectScale(Curve.gameObject, ScalePeriodMin, ScalePeriodMax, FromScale, ToScale)); + + //rotate letters + effects.Add(new EffectRotate(EffectRotate.CycleType.Random, B.gameObject, 1f, Vector3.zero, new Vector3(0, 360, 0), 2, 3)); + effects.Add(new EffectRotate(EffectRotate.CycleType.Random, G.gameObject, 1.6f, Vector3.zero, new Vector3(0, 360, 0), 4, 6)); + + //particles + // particles movements are done with Cc components + + //change tiling (on shared material) + effects.Add(new EffectChangeTiling(2, B.GetComponent().sharedMaterial, 0, 0, .2f, 1)); + + //rotate light + effects.Add(new EffectRotate(EffectRotate.CycleType.Swing, Light.gameObject, 3f, new Vector3(70, -90, 0), new Vector3(110, -90, 0))); + + //projectiles + effects.Add(new EffectRotate(EffectRotate.CycleType.FirstToLast, ProjectileFolder, 10, Vector3.zero, new Vector3(360, 0, 0))); + effects.Add(new EffectMoveAndRotateAlongCurve(ProjectileCurve1, Projectile1.gameObject, 3, 5, .1f)); + effects.Add(new EffectMoveAndRotateAlongCurve(ProjectileCurve1, Projectile2.gameObject, 3, 5, .1f, Mathf.PI)); + + //dynamic + effects.Add(new EffectDynamicCurve(DynamicCurve, 4, Light1, Light2, Light3)); + } + + // Update is called once per frame + private void Update() + { + foreach (var effect in effects) effect.Update(); + } + + + //========================================== Abstract Phase + private abstract class Phase + { + private readonly float periodMin; + private readonly float periodMax; + + internal float period = -10000; + internal float startTime; + + protected Phase(float periodMin, float periodMax) + { + this.periodMin = periodMin; + this.periodMax = periodMax; + } + + protected internal virtual void PhaseStart() + { + startTime = Time.time; + period = Random.Range(periodMin, periodMax); + } + + public abstract void Update(); + } + + private sealed class PhaseDelay : Phase + { + public PhaseDelay(float periodMin, float periodMax) : base(periodMin, periodMax) + { + } + + public override void Update() + { + } + } + + //========================================== Abstract Effect (compound phase) + private abstract class Effect : Phase + { + private readonly List phases = new List(); + + private int currentPhaseIndex; + + protected Effect(float periodMin, float periodMax) : base(periodMin, periodMax) + { + phases.Add(this); + } + + protected void AddPhase(Phase phase) + { + phases.Add(phase); + } + + protected void AddPhase(Phase phase, int index) + { + phases.Insert(index, phase); + } + + public override void Update() + { + var phase = phases[currentPhaseIndex]; + + var newPhase = false; + if (Time.time - phase.startTime > phase.period) + { + //next phase + newPhase = true; + currentPhaseIndex++; + if (currentPhaseIndex == phases.Count) currentPhaseIndex = 0; + + phase = phases[currentPhaseIndex]; + phase.PhaseStart(); + } + + if (phase is Effect) + { + var effect = (Effect) phase; + + if (newPhase) effect.Start(); + + effect.Update((Time.time - phase.startTime)/phase.period); + } + } + + protected float CheckReverse(float ratio, bool reverse) + { + return reverse ? (1 - ratio) : ratio; + } + + protected abstract void Update(float ratio); + + protected virtual void Start() + { + } + + //remap ratio value to new range (for example, if count=2, .25 and 0.75 will become 0.5) + protected static float Scale(float ratio, float count) + { + var smallPeriod = 1f/count; + return (ratio - Mathf.FloorToInt(ratio/smallPeriod)*smallPeriod)/smallPeriod; + } + } + + + //========================================== Change Scale + private sealed class EffectScale : Effect + { + private readonly GameObject target; + + private Vector3 min; + private Vector3 max; + private Vector3 oldScale; + private Vector3 newScale; + + public EffectScale(GameObject target, float periodMin, float periodMax, Vector3 min, Vector3 max) + : base(periodMin, periodMax) + { + this.target = target; + newScale = target.transform.localScale; + this.min = min; + this.max = max; + } + + protected override void Update(float ratio) + { + target.transform.localScale = Vector3.Lerp(oldScale, newScale, ratio); + } + + protected override void Start() + { + oldScale = newScale; + newScale = new Vector3(Random.Range(min.x, max.x), Random.Range(min.y, max.y), Random.Range(min.z, max.z)); + } + } + + //========================================== Change Rotate + private sealed class EffectRotate : Effect + { + internal enum CycleType + { + FirstToLast, + Swing, + Random + } + + private readonly GameObject target; + private readonly Vector3 min; + private readonly Vector3 max; + private readonly CycleType cycleType; + + private bool reverse; + + //full 360 on y + public EffectRotate(CycleType cycleType, GameObject target, float period, Vector3 min, Vector3 max, float delayMin, float delayMax) + : this(cycleType, target, period, min, max) + { + AddPhase(new PhaseDelay(delayMin, delayMax), 0); + } + + public EffectRotate(CycleType cycleType, GameObject target, float period, Vector3 min, Vector3 max) + : base(period, period) + { + this.target = target; + this.cycleType = cycleType; + this.min = min; + this.max = max; + } + + protected override void Update(float ratio) + { + target.transform.eulerAngles = Vector3.Lerp(min, max, CheckReverse(ratio, reverse)); + } + + protected override void Start() + { + switch (cycleType) + { + case CycleType.FirstToLast: + reverse = false; + break; + case CycleType.Swing: + reverse = !reverse; + break; + default: + reverse = Random.Range(0, 2) == 0; + break; + } + } + } + + //========================================== Change tiling + private sealed class EffectChangeTiling : Effect + { + private readonly float tileXMin; + private readonly float tileXMax; + private readonly float tileYMin; + private readonly float tileYMax; + private readonly Material material; + + private bool reverse; + + public EffectChangeTiling(float period, Material material, float tileXMin, float tileXMax, float tileYMin, float tileYMax) + : base(period, period) + { + this.material = material; + this.tileXMin = tileXMin; + this.tileXMax = tileXMax; + this.tileYMin = tileYMin; + this.tileYMax = tileYMax; + } + + protected override void Update(float ratio) + { + ratio = CheckReverse(ratio, reverse); + material.mainTextureScale = new Vector2(Mathf.Lerp(tileXMin, tileXMax, ratio), Mathf.Lerp(tileYMin, tileYMax, ratio)); + } + + protected override void Start() + { + reverse = !reverse; + } + } + + + //============================================================================================================== + // Working with BGCurve + //============================================================================================================== + //========================================== Move object along and rotate around tangent + private sealed class EffectMoveAndRotateAlongCurve : Effect + { + private readonly GameObject target; + private readonly BGCcCursor cursor; + private readonly float rotateCount; + private readonly float rotationDistance; + private readonly float initialRotationRadians; + + public EffectMoveAndRotateAlongCurve(BGCcCursor cursor, GameObject target, float period, int rotateCount, float rotationDistance, float initialRotationRadians = 0) + : base(period, period) + { + this.target = target; + this.cursor = cursor; + this.rotateCount = rotateCount; + this.rotationDistance = rotationDistance; + this.initialRotationRadians = initialRotationRadians; + } + + protected override void Update(float ratio) + { + var position = cursor.CalculatePosition(); + //Tangent should be included in Math calculation + var tangent = cursor.CalculateTangent(); + + var angle = initialRotationRadians + Mathf.Lerp(0, Mathf.PI*2, Scale(ratio, rotateCount)); + var pos = position + Quaternion.LookRotation(tangent)*(new Vector3(Mathf.Sin(angle), Mathf.Cos(angle))*rotationDistance); + + target.transform.position = pos; + } + } + + //========================================== creating BGCurve at runtime + private sealed class EffectDynamicCurve : Effect + { + private const int PointsCount = 3; + private const float SpanX = 8; + private const float SpanZ = 4; + + private readonly BGCcMath math; + private readonly Light[] lights; + private readonly float[] fromDistanceRatios; + private readonly float[] toDistanceRatios; + + public EffectDynamicCurve(GameObject target, float period, params Light[] lights) + : base(period, period) + { + target.AddComponent(); + math = target.AddComponent(); + math.Curve.Closed = true; + this.lights = lights; + fromDistanceRatios = new float[lights.Length]; + toDistanceRatios = new float[lights.Length]; + } + + protected override void Update(float ratio) + { + for (var i = 0; i < lights.Length; i++) + { + var light = lights[i]; + + //move + light.gameObject.transform.position = math.Math.CalcByDistanceRatio(BGCurveBaseMath.Field.Position, Mathf.Lerp(fromDistanceRatios[i], toDistanceRatios[i], ratio)); + + if (ratio < .1) + { + //lights on + light.intensity = Mathf.Lerp(0, 3, ratio*10); + } + else if (ratio > .9) + { + //lights off + light.intensity = Mathf.Lerp(3, 0, (ratio - .9f)*10); + } + } + } + + protected override void Start() + { + var curve = math.Curve; + curve.Clear(); + for (var i = 0; i < PointsCount; i++) AddPoint(curve); + + for (var i = 0; i < fromDistanceRatios.Length; i++) + { + fromDistanceRatios[i] = Random.Range(0f, 1); + toDistanceRatios[i] = Random.Range(0f, 1); + } + } + + private void AddPoint(BGCurve curve) + { + var control = RandomVector(); + curve.AddPoint(new BGCurvePoint(curve, RandomVector(), BGCurvePoint.ControlTypeEnum.BezierSymmetrical, control, -control)); + } + + private Vector3 RandomVector() + { + return new Vector3(Random.Range(-SpanX, SpanX), 0, Random.Range(-SpanZ, SpanZ)); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveShowcase.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveShowcase.cs.meta new file mode 100644 index 0000000..61f53e9 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveShowcase.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7958ebe98960fcd45a797f75226031f5 +timeCreated: 1472366315 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveStatic.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveStatic.cs new file mode 100644 index 0000000..ee7d9d8 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveStatic.cs @@ -0,0 +1,70 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Example +{ + // This is old obsolete example class, left for compatibility only. + // DO NOT USE IT AS AN EXAMPLE PLEASE + // Use Cc components (BGCurveBaseMath -> BGCcMath, LineRenderer -> BGCcVisualizationLineRenderer) + [RequireComponent(typeof (BGCurve))] + [RequireComponent(typeof (LineRenderer))] + public class BGTestCurveStatic : MonoBehaviour + { + private const int TimeToMoveUp = 3; + + public GameObject ObjectToMove; + + private BGCurve curve; + private BGCurveBaseMath curveBaseMath; + + private float started; + private float ratio; + private LineRenderer lineRenderer; + + + // Use this for initialization + private void Start() + { + curve = GetComponent(); + lineRenderer = GetComponent(); + +// curveBaseMath = new BGCurveBaseMath(curve, false, 30); + curveBaseMath = new BGCurveBaseMath(curve); + started = Time.time; + + ResetLineRenderer(); + } + + private void ResetLineRenderer() + { + const int points = 100; + + var positions = new Vector3[points]; + for (var i = 0; i < 100; i++) + { + positions[i] = curveBaseMath.CalcPositionByDistanceRatio(((float) i/(points - 1))); + } +#if UNITY_5_5 || UNITY_5_6 + lineRenderer.numPositions = points; +#else + lineRenderer.SetVertexCount(points); +#endif + lineRenderer.SetPositions(positions); + } + + // Update is called once per frame + private void Update() + { + ratio = (Time.time - started)/TimeToMoveUp; + if (ratio >= 1) + { + started = Time.time; + ratio = 0; + } + else + { + ObjectToMove.transform.position = curveBaseMath.CalcPositionByDistanceRatio(ratio); + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveStatic.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveStatic.cs.meta new file mode 100644 index 0000000..0b1adb5 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestCurveStatic.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0e58e9b269669674fb2020bb632d196f +timeCreated: 1473297298 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestDirector.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestDirector.cs new file mode 100644 index 0000000..74cae35 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestDirector.cs @@ -0,0 +1,96 @@ +using UnityEngine; +using System.Collections; + +namespace BansheeGz.BGSpline.Example +{ + //for 1.2 version demo scene + public class BGTestDirector : MonoBehaviour + { + private static readonly Color NightColor = Color.black; + private static readonly Color DayColor = new Color32(176, 224, 240, 255); + + //Day + public Light SunLight; + public Light DirectionalLight; + public ParticleSystem SunParticles; + + //Night + public Animator MoonAnimator; + public Light MoonLight; + public ParticleSystem StarsParticles; + + //Stars + public GameObject Stars; + + //callback for sun, reaching particular point + public void Sun(int point) + { + switch (point) + { + case 0: + StartCoroutine(ChangeBackColor(NightColor, DayColor)); + StartCoroutine(ChangeDirectLightIntensity(0, .8f)); + SunParticles.Play(); + break; + case 1: + SunLight.intensity = 1; + Stars.transform.localPosition += new Vector3(0, -20); + break; + case 3: + Stars.transform.localPosition -= new Vector3(0, -20); + SunLight.intensity = 0; + SunParticles.Stop(); + break; + } + } + + //callback for moon, reaching particular point + public void Moon(int point) + { + switch (point) + { + case 0: + StartCoroutine(ChangeBackColor(DayColor, NightColor)); + StartCoroutine(ChangeDirectLightIntensity(.8f, 0)); + StarsParticles.Play(); + break; + case 1: + MoonAnimator.SetBool("play", true); + MoonLight.intensity = 1; + break; + case 2: + StarsParticles.Stop(); + break; + case 3: + MoonAnimator.SetBool("play", false); + MoonLight.intensity = 0; + break; + } + } + + + private IEnumerator ChangeBackColor(Color from, Color to) + { + var started = Time.time; + const float changeTime = 1; + + while (Time.time - started < changeTime) + { + Camera.main.backgroundColor = Color.Lerp(from, to, (Time.time - started)/changeTime); + yield return null; + } + } + + private IEnumerator ChangeDirectLightIntensity(float from, float to) + { + var started = Time.time; + const float changeTime = 1; + + while (Time.time - started < changeTime) + { + DirectionalLight.intensity = Mathf.Lerp(from, to, (Time.time - started)/changeTime); + yield return null; + } + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestDirector.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestDirector.cs.meta new file mode 100644 index 0000000..eb74c8b --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestDirector.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: dbe40e6961ee5c74cb358876bec697f9 +timeCreated: 1476809059 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestMainMenu.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestMainMenu.cs new file mode 100644 index 0000000..fc9610f --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestMainMenu.cs @@ -0,0 +1,24 @@ +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace BansheeGz.BGSpline.Example +{ + //for main menu scene + public class BGTestMainMenu : MonoBehaviour + { + //to let know that scenes are loaded via menu + public static bool Inited; + + // Use this for initialization + void Start() + { + Inited = true; + } + + //for loading scenes + public void LoadScene(string scene) + { + SceneManager.LoadScene(scene); + } + } +} \ No newline at end of file diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestMainMenu.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestMainMenu.cs.meta new file mode 100644 index 0000000..0ed9afd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestMainMenu.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1bfad38550106584c93e18ad90e98703 +timeCreated: 1477523840 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestPerformance.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestPerformance.cs new file mode 100644 index 0000000..7025c50 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestPerformance.cs @@ -0,0 +1,166 @@ +using UnityEngine; +using BansheeGz.BGSpline.Components; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Example +{ + //for testing performance + //DO NOT USE Unity Handles (for curve's points) with this test class! + [RequireComponent(typeof (BGCcMath))] + public class BGTestPerformance : MonoBehaviour + { + public enum ControlTypeForNewPoints + { + Random, + Absent, + Bezier + } + + //speed range for objects + private const float SpeedRange = 5f; + //transition period for points + private const int Period = 10; + + //===========================Public + [Tooltip("Object's prefab")] public GameObject ObjectToMove; + [Tooltip("Limits for points positions and transitions")] public Bounds Bounds = new Bounds(Vector3.zero, Vector3.one); + [Tooltip("Number of points to spawn")] [Range(2, 2000)] public int PointsCount = 100; + [Tooltip("Number of objects to spawn")] [Range(1, 500)] public int ObjectsCount = 100; + [Tooltip("Control Type")] public ControlTypeForNewPoints ControlType; + + //===========================Private + + private float startTime = -1000; + private BGCurve curve; + private BGCurveBaseMath math; + + //points + private Vector3[] oldPos; + private Vector3[] newPos; + + //objs + private GameObject[] objects; + private float[] speed; + private float[] distances; + + private float oldDistance; + + //Unity callback + private void Start() + { + curve = GetComponent(); + var ccMath = GetComponent(); + math = ccMath.Math; + curve = ccMath.Curve; + + //init arrays + oldPos = new Vector3[PointsCount]; + newPos = new Vector3[PointsCount]; + speed = new float[ObjectsCount]; + distances = new float[ObjectsCount]; + objects = new GameObject[ObjectsCount]; + + + //--------------------------- init from points + for (var i = 0; i < PointsCount; i++) + { + var controlTypeEnum = BGCurvePoint.ControlTypeEnum.BezierIndependant; + switch (ControlType) + { + case ControlTypeForNewPoints.Absent: + controlTypeEnum = BGCurvePoint.ControlTypeEnum.Absent; + break; + case ControlTypeForNewPoints.Random: + controlTypeEnum = (BGCurvePoint.ControlTypeEnum) Random.Range(0, 3); + break; + } + curve.AddPoint(new BGCurvePoint(curve, RandomVector(), controlTypeEnum, RandomVector(), RandomVector())); + } + + //Recalculate manually after points were added (normally you would not do it) + math.Recalculate(); + + //---------------------------- init objects + if (ObjectToMove != null) + { + var totalDistance = oldDistance = math.GetDistance(); + for (var i = 0; i < ObjectsCount; i++) + { + var obj = Instantiate(ObjectToMove, Vector3.zero, Quaternion.identity) as GameObject; + obj.transform.parent = transform; + objects[i] = obj; + distances[i] = Random.Range(0, totalDistance); + } + ObjectToMove.SetActive(false); + //--------------------------- init speed + for (var i = 0; i < ObjectsCount; i++) + { + speed[i] = Random.Range(0, 2) == 0 ? Random.Range(-SpeedRange, -SpeedRange*0.3f) : Random.Range(SpeedRange*0.3f, SpeedRange); + } + } + } + + //Unity callback + private void Update() + { + //reset transitions + if (Time.time - startTime > Period) + { + startTime = Time.time; + for (var i = 0; i < PointsCount; i++) + { + oldPos[i] = newPos[i]; + newPos[i] = RandomVector(); + } + } + + //move points + var ratio = (Time.time - startTime)/Period; + var points = curve.Points; + for (var i = 0; i < PointsCount; i++) points[i].PositionLocal = Vector3.Lerp(oldPos[i], newPos[i], ratio); + + //move objects + var totalDistance = math.GetDistance(); + if (ObjectToMove != null) + { + var remapRatio = totalDistance/oldDistance; + for (var i = 0; i < ObjectsCount; i++) + { + var distance = distances[i]; + + //since curve's length changed-remap + distance = distance*remapRatio; + + distance = distance + speed[i]*Time.deltaTime; + if (distance < 0) + { + speed[i] = -speed[i]; + distance = 0; + } + else if (distance > totalDistance) + { + speed[i] = -speed[i]; + distance = totalDistance; + } + distances[i] = distance; + + objects[i].transform.position = math.CalcByDistance(BGCurveBaseMath.Field.Position, distance); + } + } + oldDistance = totalDistance; + } + + //misc utility methods + private Vector3 RandomVector() + { + return new Vector3(Range(0), Range(1), Range(2)); + } + + private float Range(int index) + { + return Random.Range(Bounds.min[index], Bounds.max[index]); + } + } +} + + diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestPerformance.cs.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestPerformance.cs.meta new file mode 100644 index 0000000..475c152 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Scripts/BGTestPerformance.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6fd365c04f9bb4241803aced3a970a79 +timeCreated: 1473296685 +licenseType: Store +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain.meta new file mode 100644 index 0000000..4c47095 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: d8330cb9504691b4795df7a28fd10477 +folderAsset: yes +timeCreated: 1476659936 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestDemoTerrain.asset b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestDemoTerrain.asset new file mode 100644 index 0000000000000000000000000000000000000000..9fe26ea76cada02ea9617bca35bad8a9e0987445 GIT binary patch literal 11040 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 Q{URIv#&;ea(*8yN1_}R$#Q*>R literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestDemoTerrain.asset.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestDemoTerrain.asset.meta new file mode 100644 index 0000000..d25782c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestDemoTerrain.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 737d7a849d554e141aa574ee80ee3fce +timeCreated: 1476659987 +licenseType: Store +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestSnappingTerrain.asset b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Terrain/BGTestSnappingTerrain.asset new file mode 100644 index 0000000000000000000000000000000000000000..76d797099a1ff9d287268e8edadb40fb48b142f4 GIT binary patch literal 8020 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 B#83bL literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGAdd123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGAdd123.png.meta new file mode 100644 index 0000000..1c5f3c6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGAdd123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 03ce3b24581c7414eaca31c2b196ecc6 +timeCreated: 1458521116 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWhite123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWhite123.png new file mode 100644 index 0000000000000000000000000000000000000000..2ea0724a995a6c2d9fa9ffe96c159acf74c98e7f GIT binary patch literal 214 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ zFbaY&s8!_c+Y zAnU*iMjoCOnt?*I4s|e2y1_G{HE9yV(KrT%-b~&TqE@xffW|X;y85}Sb4q9e0IyF& AZU6uP literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWhite123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWhite123.png.meta new file mode 100644 index 0000000..3f59db8 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWhite123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: ded8bd90f16890a408091013c9b03b43 +timeCreated: 1472605753 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWithBorder123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGBoxWithBorder123.png new file mode 100644 index 0000000000000000000000000000000000000000..5142b78ab5449532286905a1324e4ca837c2719c GIT binary patch literal 250 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8wRq zm@+|_@#(JE`9ML*64!{5;QX|b^2DN4hVt@qz0ADq;^f4FRK5J7^x5xhq=1UbJzX3_ zB3j>GH)L!M5NLiF^DD)M&7i@o=ZgDV1%@^y<|3XobJu$(J@|j^$e({YPJTZQcifnz z2?- zJs`|@URFg8$dD{?jVKAuPb(=;EJ|f4FE7{2%*!rLPAo{(%P&fw{mw=TsOYVyi(`mI z@6yZry_g*Zj(_xTD)Y)Y634W!>6_qDFP9@u8@|ZaFug9hW@gvgs>H}Gcv^eSS{A{c z6$0JSse9hc3}$cpYkpte*m}3_o=4~I=LmMiGiYbDmtI`geddPQxx%KE6&F;Rb@wDr z`6F_9{u`A>->0^{T6H&E5_t6`e=r$OW(hMqb6`5>zocR&TbuL;jA_m>VF`@>l0UfS zdcBE|e!iiZc~ARa={1ix&dLf+5U(xSINc>L*pvV9)HbV0yiTXwZyczR?NHjcLRDw^ z&%K+N(@&XQixRnU+_Z1%`O+W4KXiLd%4Rc7%>DVi{2#;OTCY@=9lI5Q9%t}$^>bP0 Hl+XkK6wZ!> literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcEditName123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcEditName123.png.meta new file mode 100644 index 0000000..d9441ad --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcEditName123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: e087ffb98e49ae34eb43f2f4d66da109 +timeCreated: 1473063659 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcNoImage123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcNoImage123.png new file mode 100644 index 0000000000000000000000000000000000000000..1e2fd872008766b21267c4fb36a4468c34cb6a61 GIT binary patch literal 824 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEX7WqAsj$Z!;#Vf2>u z`$3q|>)wt>Ktah8*NBqf{Irtt#G+J&^73-M%)IR4eY_xb0_H->7f!x;Me z`xAG@d^7dd?^?9Ovf*cqTwGjS)w~tanoA2TWTe)w7d`M_@AM{v`R9+zEuQxJ>#eN4 z-x&(n7}CimCjU(h@X~xzdGFWzDXEgDHtl(NYmvsGr$w22!g~yL#JZ2YK5lT6!Ebr+ zjU2P)_rL%ByH}ArE%o8ouUiji{(2tGFo*GgBmp93?R(~sP|YkkMds|$_`hI(I;q+4>J9~Tf zo838^)Z6Q7Yg^xzS)YiD?KEurT4noUp61dG_uose|9*Hu-`TXyj^95&3D}y1H;l}0 z`ZLd;Ki|6YLs8_k#O=55mb^{c$g%qBs*iDo$BtzmH@eB-^yBlFx7(6>%>O4R^~`-! z=^wE^?7sol7{(UsIK)=h7G=zPUVHXZ_o`LLwZt{>&fSyqHJ66H rR{#6@!NSnc(sK3sZBKEA%U`B@U2Q8JPRnQlQ#pgDtDnm{r-UW|usA{N literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcNoImage123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcNoImage123.png.meta new file mode 100644 index 0000000..93bbe89 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCcNoImage123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: a414723b197ce2f4a9fd841e965f138e +timeCreated: 1472488893 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapseAll123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapseAll123.png new file mode 100644 index 0000000000000000000000000000000000000000..0d419680749c83c96401410108dc825d25ccf1f9 GIT binary patch literal 464 zcmV;>0WbcEP)9>|5+LKXruw3@i zg_;Yq9e`U)uhj|mKnYKFHLGS`(8?QNl?m^CTcU2TP$7BrNH_!F1LX920c>@|Ayn(( zVaxG|6{;15C6d;Q9yPerRR`M3CAMu-FN@o-#m+ z_j3`{fZ>$)@j%QBv4A->i_k0r#C-4nJ zFq(oeraH86j!&t`Ps_WJubBUpA?)V04@d1^xPfmPkx=WTj0DW>|R+2Pmg?@LMm z!IB>p5`VT#-LUF#=7IP1|0U}F{p3#k|F`?HsLv5gG4lmC7{u7v*xKgT|2KNG_bZ3% zqr>0l7ks;&Z!fVec7MOp`*jN&3?96{|DR|3{h9-rr@!B?H+T~J|9^Ty!h&hyGbAJ> zepucNRN43E&(ROx<&TJosj0E$m4%5^s--YnL_|sm`D_UgS+k>H^24Xk^Lao(Xip5! z!Kzgeu?8P5ddzh=!dA0oip0Nvf7t_%^xT%4_Wgd{hIKnjesfxG+yDPtGcUtV#{f?I T9Ttm$VZh+&>gTe~DWM4f^RAzY literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapsed123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapsed123.png.meta new file mode 100644 index 0000000..44686ff --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCollapsed123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: d576ae51c051b294d978d836848416bf +timeCreated: 1472909534 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGComponents123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGComponents123.png new file mode 100644 index 0000000000000000000000000000000000000000..deb194c446ac428bac929a68c60859c01666c6be GIT binary patch literal 810 zcmV+_1J(SAP)00004b3#c}2nYxW zdR$hCMk#?xbPzv5@tFog3gqqqmGV?b6)1< zcCQy_S^v%R+~=J4|NPI#b1s4R@Eh*pA+BPr|0!mo55HhKUdAkur2iV$;X*y9{h~9* z)v(XOQQX9F%+K?ea0<;hAi8Q5mf}wwD{;2s2W&zo_Ms_llhJ`2IENLbyF2omZ*dvz zXh_>UoWwP3#i%^rh`sm}7jYzYOvf!z{8M-hBe5+xE@8C{^k|J_G~sXjocng%PqMM- z&j6co20hq?FVnU>c@E#Mawi|3O>NEBFH64@R11oV4aJqVFF%B0aI~E%#2Pf#0Y#Sp3#9iT!#!i z-96YLx~U$zFdE}AM9i=2SSxMZuMg2jNzJr0d`XLFZaVm9wP z-TQsN@ALig@;vWBh!7$CkjWT*tCcNJ`PFMBRfSwB$3waS-wVDShTU*DAs$>@ci&2NKt&;#XKe%eXvp1dIO2rGU#O& zGr~ZmfU2};{cv;fD5@!k&`;FN(_T{VPT#$j0eRtKqU0(wfy}Qx8wS0P(_eMeIKlbx z@4*Aa;|&a*2EI6?ULjvT)Ye>8FdO%Poi1*cRP>eK5&v0F#Hy%q63`}NV)2l!rbTp$#N~XHj?P-#e26HBpze#re%>V!Z07*qoM6N<$f_r-`M*si- literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlAbsent123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlAbsent123.png.meta new file mode 100644 index 0000000..2dbf1ce --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlAbsent123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: ed1ce6f1c6c55454c8302d8c78840174 +timeCreated: 1472300443 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierIndependent123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierIndependent123.png new file mode 100644 index 0000000000000000000000000000000000000000..56f6f8b1adbca79eacf7e5d4bd8cdd729034cd8d GIT binary patch literal 987 zcmV<110?*3P)Bfc^|&nZ@-2A>%U&&at@DF^XEb{j#W$lgD0;`$~&>m zEQNpL!2OBhThkvSg#omhdBUv8@yK-j!O=jCi^fJ`V3XhA#NQ!#+D%}}%K@0u?Su)k{_Va9MO z2SC~ln(vD5TEzy+w}$HE!}0K{vj>mg1l(f8eIE=UdfZU;EdPGrssY65!QAR9Uj+k% zYGOdjaC%n_06oU%S)T1W5e)Ej=K`VzsXW5rk?OLe-#>N(u-$NuA)>`?ZU6waJ~Pyf zBvOx;4Un~V0W}3Jdep1U8z9>FIq<7N)Q_tBXS-A#Ibx%_+i+&MJT~mrT6*YU>;;5Z zjMhFZoyXy!fcPn${zN1zw6Z;Dmf-x^#Qre^Awg*-$MBac+NLo^;3inBRoMW z`*Epu?^giu%=U|*uNqD>(B~U|HL)GoU>FA(*pVzB0AOv+o4{m2E5T=jaI>K%xV$jr z*X|GSWM>MCoxoyXu)CHJ=TTnn%d8#%U{CiX%EQ1?8R2Qv>SJ%u>7d4I-dgKp=im6_ zr*r%A*{uIS+t#L*wyFB2rh6xDlS@H!gI54(ji(3d*KgQY*U;cP&5Fwo*~4qrt!vDu zGGE^sUu@bqs?oL|mYPxZ%<|lZt?~4L!c!AB13*hW{g}dQz$Sz?5qed5@$8n!0URzNO#5Ft zJF_)%M(o@U5vM^Q`uFI&L;3K*YgvH@iVd;kDs_MNA>feT3KX8nRn@9EE52ib+)>=; zS^>@@MyW=W^EnUa1z!|-z66+ne*?hzW|zG7QioIemejF002ov JPDHLkV1iTs*Mk56 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierIndependent123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierIndependent123.png.meta new file mode 100644 index 0000000..0d7f106 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierIndependent123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 7a229d4c49ec7a04e9772d939231a8ad +timeCreated: 1472300443 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierSymmetrical123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGControlBezierSymmetrical123.png new file mode 100644 index 0000000000000000000000000000000000000000..a7614b6a5b2c60ca06f4db1d3ce2df6ecc1728a4 GIT binary patch literal 983 zcmV;|11S87P)A*gK)4U}|%P*a*}<3^H- z(l(7TLJTf+V@NPSnP}|Fv^x?6rVv*~O^gdQBra-O&>${MZ72h6;{-85Tu5v+Mmi~F z+L^h>#dO}h*Un7;On3BK&3DeZ-}lXZ_r5$>!@~}-f2j)R2SOOBLQNH7jnc7yxMYV@ zm&);{UIqOV!#E!6caF8pWZPbQu)AB>(0CQJ91&3M0ZI?xHM>#y93=C1Q?vuU*|ud5 zc6Axxmd%A7C7T0Srq;z(Z@Jp;roS3`#kpg*iC@k8`~f@#g_>$&1S(pAr{*dlR8k0!7Y(3VjmQQ^L_PtY1o^;+n9qS+vy3RI%2Y#Y)?Rpd*cB2(99zww_2prfS|B#f$Ag84sK)?UJ`*LKD@*tFrTeg~wPgk1^LuBDWzx!+bBb8ZVUqer7 z=1$t{OF3(Z{)XzuS!!mJhk=^H0fgD5zHk7DPfQHN4>f$0<)LWeUqvEwUVj+~yCcuTw$bTIE9u)3 z@Of{H)ye&0W=qBPk?9IjzG`2YcOU)m(t z3_n=0Q(OBaWiPOdY%-$KO>~O1FPk6c7-zaBC=riZf~(FfGY+xBR2U^^3_Rx1;kM%` z@#wkwaE`<2dGdv5{o(oWJlA#quitfZ-xrT?hHo%=6yg6Z1&WyFpTU%RwgM)*AB@OOpJ5Ta1b$m>O z*m_{=>+7E~P4jeRWn}^Jy<9Ef5HV660GLEnHRSbrPYw(WWG*f)+IH%8ySInK;bW>= zlhpTf*@nUE9ODHh*{$_@buHkwwzlIlGc!5G#l>aa-QBfGea}e@A?8TDn*gdRJv}`~ z$H&J{+nKktwEU{74!bxpQZRsA9^?T=sPS87Uw92khwS1eRV-kjD4;0H7Bbn9NOEG5&k1UIS!!gDex$co`h>&bQ|;~T z-;a!poNH=odaty!v>tfhuI{FR5gsC&!|Td@oTr&$LOu|WHfYzoRRotxq{;5Gp_Tt zs@__P`+UBw3kwT1b8~ZjU0q$zSeB)#s-|h`l5%o#n3$LtEh;KH4?Ld?coCqtx3?}7 z3KavXcEG^pP$=|+Z8XRnm-(6tGyr`on+gVlPx$@*`HYN=qQ1VqJgog#8Sa53?$sYJe=UQ7U_iLCmo`VDwwJvHvC)q;UyI1rS>?8m|0jhOuB vN@E8G^TIw}V+I!n(RASX_c!+rGdlfn zX;B#)jG#y~@<3Z6mPZ1hi}@hqvmZLwMwi{}7`U0+>S5B;S!=KKX8Qo2GV^`7PaM>%s=jSH3X2zW&o;@UZU>cQSH3zE$$n^@diNdvDF_PtS*4CZGeuc zJ`%w2uK=ZNek8!S`3gW8c4aMUr}p+&qqgui>d!wgdDkm>S54O?&Z>B`9r^1do!y}N zWRuDl0uOW?kV47Ijt}iX?lG6`+{weA0ly;D3^b?U+Zg`nMAm-LJ3`+}oQSeDZ{=cA z_1^cyv?)4Atla%<-kTl(*i#n2)3mWZ%-;uyr~?=N7aSxJ^*@9nj_oRRTqytm002ov JPDHLkV1kR=<@f*q literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCopy123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCopy123.png.meta new file mode 100644 index 0000000..d9371b6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCopy123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: ee35c284a32612c429d5fa9be3a4a535 +timeCreated: 1477995243 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveComponents123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveComponents123.png new file mode 100644 index 0000000000000000000000000000000000000000..f70d7e5897202f01da83d4abf93e28a3ab370d9b GIT binary patch literal 6834 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveComponents123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveComponents123.png.meta new file mode 100644 index 0000000..24dba01 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveComponents123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: a5b7666fd68eee74ea8390d47cb34a42 +timeCreated: 1472489767 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveLogo123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGCurveLogo123.png new file mode 100644 index 0000000000000000000000000000000000000000..8633937f9c439613e85a0816abd7048625a7923f GIT binary patch literal 7586 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 O!rS6g0#F3`;?H1|va2W$6P@ z&=4zVEP%p_WO)K9sH~vXf(Nj+Fcc&tCWeYac9$%B|8po7SfhKJo$4lM&fJ+fT5NpT zQ^6HOz)L2hqd&q=hY~<pj%JqPDDww9!6fES_r zb&}hjz*M@qxQfp=lCy#bJ6Gi+*k2J8&KUpDk=6k!vcoCw{5G^00Af_PKGNQbvJ<4x zGCq}|n0r`nQM~K8)&Z|l?$>D^{MSL~CR+&YoeF-06q2)iZ=Zx#ako)ycV4ZdY>6`S zx~})D*a18=Ab@hLNZWI29uF+>U(Bm{_>=L84nJ zFq(oe=rSPESa7c)IYk|I8B?J9yd}8FhGoAin;8 z;*7e7a-LG$J)weZfBt=+|M17k>aKJ%V-@w?&prg2W!V0WbcEP)6ve+F!68Bg1u??SL2zkF z5JX!A$t}>q>kuJQn^Ta3aFwerwgfroAP72&gP>5^5G6z;I($dGetg%(2M+If-{(2! zygVm|qT4vf3_jp5CR9fr7kF1icZ^*OW)&Ck8VA@&aXa{b$KZRT5a%wYQd}$kRoq`- zNaD=<_*_=MNp#{X9;CPlbVrY+d=M>o9?=wUgBXZ>6dzH-4{V}7V|WqMSc{K0RB+>% z!!kbM*Y)rxQCLKKM$-{|M;-p)A-XbjFYyJ7SirXm?q{6C$YJYx_&T0Oe9mZEi<-z! zFowgFCWlA(oly@<=nY*Nr9u^98fCnZ>}pkF=VeNBi9I}%tgi#j75roDqhI1qPaa2- zJ*IJj)5vErkGG*Mqb;~2HX%G}d$l}(Prfr&}ZyGl-Y78idx842jp1b2tG@9opB1@ki zSQJv15yCmxT3;>c`es@|tJ6KSd(QX`fY^}$h9=kYn%qbO6!n4zPAn$hJEK71s(B({ z*<9Q+7wYb4>RFwq=k_PSz*qGBSt7vDbNc{VCVK|70WxW0rvg6oEa!4Y z)th?BfQbsRdZQ$Hw`?xCo^5x3y}~~MG_UWDPcLs8FJt%O&nJjo!Jh^9nMjlXd^N8C zsqY;F+*%JUpaoE@Raf$b+EG%W3WG-gDTpe-_Q!4nJ zFq(oe*?^OwHW^~BYF?{<|X3pJK*_%NmGo%jw$o}PC) zJV3y7-){BCy8mg8Cm0T%zaMe&Xv73dYa0m(y;qOT5uYu;xaiMSirn#H@h z1Ckowc0UMZYpb^bIq`qI=cm7^2?{gz1o8w#UfkE!*qA8F%*=fFb* literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHandlesOn123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHandlesOn123.png.meta new file mode 100644 index 0000000..26b400a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHandlesOn123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: b6b3c686fb07aa0448eb20914ba73271 +timeCreated: 1476159626 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHelp123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHelp123.png new file mode 100644 index 0000000000000000000000000000000000000000..4637694732f3a08f1e245452e78764d7a11fc5c5 GIT binary patch literal 456 zcmV;(0XP1MP)_Krn}$R?UiPB(MUe4M%W%F@a8p*XxV zf;42xRpe99`;h?1mK$wWjW=7h?p}x~sxkvKjo3=caxrIWcTvBIHvG0JwAE~@k_VE& zgjKWbi#dG>QyT*TVx;AwrAck?6sWJJ)$VuC>c&}*`g>N$FYrvR_Jb7EkE z-wGs=`M^8qR2pWmx3K|DOtPY>a|?@rrqSb^_>Zvx&y4R{Wd$Iq;n}>@uKM|U?%+qN zt|L4EK%p18bFqyn8bed^Zok@ar9?`F~V|7%`1S@ yY=yWo9AH6$%kF2w^dAOr1%dn4 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHelp123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHelp123.png.meta new file mode 100644 index 0000000..dcae7fd --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHelp123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 974c3f86d59ae4c4aaeb18abc1b04b7f +timeCreated: 1472530071 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorIcon123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorIcon123.png new file mode 100644 index 0000000000000000000000000000000000000000..97355cf8f12193431366c091a5f71227d8d58c86 GIT binary patch literal 885 zcmV-*1B(2KP)Vbg~qR zA}EWfpy)9pL<=|3BHGl;Lm zZ#nZ{-FyGv`F}qS=bm$~!cBMX_~@Ft1Z~O@762tcAut`73dCGS^&!$TulrMf+m-r- zKI1r+F?N=*V_A+9%XaKowjGOU5d*wZuoJ+Fi@4NMjH8e9NorAMCgO^hNHb8X$Y@3J z*Y2c+?+Oa%P=D<*MxN`7A)4x{vp!5Ij*Yyi0q=;T8u zR4@3J8yae;&Skc_fT$y!UT13}&1Jx{%r%Gn{_oucD<1=BMDNaIbAZCHU!ud;8d#cX z085NB5}-8G03&4q1xfr~;4GSZSSHGVm5a~hVPr0-#fVyhk~P4b{{i?3Xh zidQb)2cZ4W-Nm-~7<&_m@i%g{DKDJ>f4_*VoHN+Jb^)_S_<8)a zwgR_2Wc~u)r>OZjd=bCO!>zTzjZwu93HaA|0Pv)E01-v_{#}$*$5)v}oTz%44uJSQ zTPZ=*e&p{I4T7no>1Yn4XJA;7=H-a)1SStX8NfIt)NScX6(}$TxRj!-S3xi_06?g9 zJ&IN!XDB&B&>t8FKmqVMMOl}EB1m>@2K^nN4h&`jibGszDoh37RmsooKxHFva_DXn z+IKdy00061c|?u^2H3-e`ztaF01({VfRa6cjW*$lJSDvag=>{H{AI-Jz200000 LNkvXXu0mjfPm6`< literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorIcon123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorIcon123.png.meta new file mode 100644 index 0000000..c44a9cb --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorIcon123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 94ab056a92cf75c47ab8adcde965871f +timeCreated: 1472629649 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorSelectedIcon123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorSelectedIcon123.png new file mode 100644 index 0000000000000000000000000000000000000000..80522d41770a853d7231af01e7518f5a1ef7165b GIT binary patch literal 884 zcmV-)1B?8LP)|x-MCXwOwuAKDB_}(N^v1tia5CR;ZWxs&I1-&1~>zns(!gXET zWYTgRM;ylyXVQ_$Nk=@-1G)tc0t9AecrmQ2EQ@m_IOZ9a0BHJ=Q#HT}jG^+&=d6Lh z*RER`f7^3Qg?A=385`3RmPHqE5vGclN^WqWjc`VwCIAp0(cQouz+_)Kk5b-ih}Nls z7FWwzTmgi$5s{>cCA1D@Te*q@R16OeG==09fI&G@&f)--U;Fw~@5TsQ%MBo2(oF*> zY$!LtOa)MCv-m>-S44O!F8x|TmE#b!V6_;wDAXf_QC1cY0DpigA8*1F8h6^#?c;p{ zo~H(}F0eG1&fI<1-XDAHj zn`EYH@3jvU5^oUR_!*+CDh8lX89ZWshC-dHO348Rs)+*qK3;Wnr1;aFH^2cA7r5(Z z1}vIN4gg>*T7loQO@-#N05mR?euUfqxWb;d-!xcCfb@+hsay`gAz*3RRe}kdeZYeP za!vxhIbzaRri@eGF{;N@XrC3_*%Xp+0RROl13*=!Gr?np{TcJZ=7=p_r2xqIXN!nd zC?}b*MNf$urO`UF-$mbMwTC929PQg=w@^owy_o(rH*W$oLMYPlJregy4JAZNj zcsNI>3w+6u&aeCCr;dbfh$r;f%O7eNo#cP@dQd~rpSo*4a{UEtlk;f4nGN><0000< KMNUMnLSTZtmvk=x literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorSelectedIcon123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorSelectedIcon123.png.meta new file mode 100644 index 0000000..c560bb1 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyErrorSelectedIcon123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 1621a394d1618b047a3fd6ddb5ee1a65 +timeCreated: 1472629649 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyIcon123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyIcon123.png new file mode 100644 index 0000000000000000000000000000000000000000..7b0ec9efad99a053538182fc111a7f6ad5eab99f GIT binary patch literal 840 zcmV-O1GoH%P)w#0K~z|Uy_ZW!R8bhmf8UuQZ76FIEesNppu$pmLtq7F##l;- zD~-rS^iUh=0YM-wq*lHXdh9}41QC&@6_h)vC|vZ=MGGyHh>0SyEa!YJa?){*4|3-I zclZ3i@BV-HaL>8t3NGEe>0>Z08)LVjtN}8CWx!$}4fyTo`i^QCF`p3)qZ$VJ2)qXw zKqCVLw4cL!hbJ~k%q=dpXAm(}s2%{8IN|25L7)$z534W60qQ#rBH9crNK&vva{4bo zL;Eg}PQZ8a&YelJ?r85763t*VP zTkK?YO%Wci%H6#{FVINygLER163}vB<5)#EU!GicwfYf#jY_)13(qP%4krHt&;&G5 z-=2d=1y-+8TWj3_m}j7Q4lm=s046FF>;WpLD>0~j>~w@IRK@8fP=@sHkAR^#M_EM6 zy_w(cIRliIMnGGgZp7?JJ^+CF>VY3|u4=J20HJ~*&}$AqpDT9*$p--NrqQhaT8HlQ(qYU)=Slth7 zWM!gfVfvHsi9M}A^vUOAe07NohnZ#|s`~b0h%^C$HCw4Ec$z4H+5HQIf-Q)a1EUz* zkjSs(?0-h8gEv6;16ee7lzI;Ua3a`-+ATl@7w;_e9snRz_y$7>sq;1`0^kpg5!S^0000|)XsY#*3Qgf z(V5bjKAWmDuV;7v=YQY%-JAFByCOxO+u_4ycGSePf+rlX4f6=l2NZyXlxcT>5-3zjV#>L1P#MVrQ25HF0EclaeI>!}hGg1z(I7bY^)ihuOT!oLRxR#939Db{88K z7U&M)Q3X6@*nt?vY*|BoxqikpDF^%oY)F|fUlT*4dHtB;{R~`e42rQI56nS}F<^+a zFG`#k?9r_ihc};S1P=Ocn#QHFJBqXGbpLn+MmPxgjNE0 z@m&Acs;}}SaI$#YI|K6;;*+%SMF8;)u)o!i+4^4qmTP3At^r3@>j|h)Ofw7vww30! zQ^D`OOaRj`_^jS{x0>UzcJIQfH{p?9ofbQS53IyLPGU zXVwRz>{p}Me@C&u&f+hbs$%RHqS*0d;#bxM0AMol_9*d%%QMce8^qO;3lq1!uN}|2 Y2YdwT%EcPD=>Px#07*qoM6N<$f~Eg~wEzGB literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchySelectedIcon123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchySelectedIcon123.png.meta new file mode 100644 index 0000000..3930e7a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchySelectedIcon123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: dceb510e1662d644a909812caca5b951 +timeCreated: 1472628860 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyWarningIcon123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGHierarchyWarningIcon123.png new file mode 100644 index 0000000000000000000000000000000000000000..ba81295955381ad7b9e3e0fe034e92a359133e3c GIT binary patch literal 878 zcmV-!1CjiRP)hIA1jR7ixI7QPa}B7zn{w8*leMTALF5s0PEz4vS3bH+Q5 zYkL21;hgjT&iQ`#a2_0mlNuX+^vvCWwzndz0rG(WFdvu;#2k9{Bl2^V@9UrTc~{o@ zuq*@H%+h8o3oDk58OtUX(@JchO9eRspyGz8ZOOyZ7ZEuQEOLZPqm{m|d{}TgWz2gk z(6{>cod#@qrN>&sZ6`6+8$_z7nmkkW%j{f)vnaj503gz`3#1;5}j1^~Z7}rDDDQjf#{XHyS4()GX>Bnd7H%hndu-Cbt0?d zyPJ3o`ehO?Zz=$8r4jpyqoXK9L^*oX3b3@l6X>1f2=l0Go$~6=9H64Y0%>q`Exmo_ z0RY4o2L4WRMGkla5Gv^fx#QsP=5|xgOad6=rCHZ7hmHb^C-^xG82f;SF2)=JKBkHJ zJX(lf<&oCoz`cavXH=CHxd3pbcmNSa+YqD~>>Q#1^w z&d)@0NSuLDMVmJx`YAAHq-7A>%BOm7Pr3o6o?QIYrViql3KB{V01$57iJ}#lHPR_c zsH`e2z2f(3j@^NsB$ z_kR*@EIP)o2a1LL<>Wr+O#VuoEe9}pokU~Mzn}9$vwR?`G6> zA)U57#}UtQgegbdDM#=;;Dbas1Q3{=q5GGvwJgq&VuxW$_-k2-C$&CD*F45l#!#2LR$Dx*NC$nEXqZP|7 z#no~aR{-HmSR`#?No_{iUasN*70%FLTTprd3`(S&#Q`c){R5eIV}xzx1`yJ27C@n? z+yJu`KxxS14+~ro;hDG$Xa!Y{L$w9##IRMN1tEm8X7K><2dMJ#COx6G-IfnN-WT9S zW)K_GjYiq4!U3R_BEF~qkYf55nhA3+n15m6C9x*>dp;=X>W_|v^$fP*3~(B)?a zEZRyA0AMVx0~2#ig#%>)XswX}guC-xVb7cIT3t$j?2Ra`Tn@ltU}e@-s*^VRfQLoo zoB}=@3SnLDI%syn5t3jq|XynQ=dCtU)U zW`@hGG*`+B01yhwH4)AN9&jWvsyoXH01&d}wkSt{v?ttH$}Slw95Mq@Cl6v{IwtTS zG0s8Yk#C^l0^bUx^Xt9~Q%_Qx;z@n}@~7I1PV&EcHKf7lxOOZ>uD_VG^+q5Ben|iT N002ovPDHLkV1n1Zp+;py;wec8?W^nEiMQx!E|?)P@`NsaV#Nnzo!xmNt3L^S4!)%nlgeZ~Ep z7(%`tI-}>jC-!RTTU`SVh8c|MulZb4GSjZ*~W0u=* zJh^^@VXohTRri<{Gk2WeT97&GF!LXdx*k4;XWQQhCfpYMBGt7>V%4jweLTqz7RK5$ z$sbr=oOdn#T`haaSI!gVEH7S(9yoKa;rG25!AXC-I29OG8dxSU^zm(Y7i?v^d3}Uu hNU5CmwfmRNCoM2ddA03+0Wi=QJYD@<);T3K0RWs4n8yGB literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOff123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOff123.png.meta new file mode 100644 index 0000000..edb81bf --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOff123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 45a92439e841a594ab7df00f55b18d91 +timeCreated: 1472306768 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOn123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGLockOn123.png new file mode 100644 index 0000000000000000000000000000000000000000..e4350e508322b51a907044c8a94b28fca76b1173 GIT binary patch literal 406 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8wRq z7`K2hqmPpB51^oAiEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$Qb5(ho-U3d z5v^~h8TuV|5OBS3A+}OL*H=T(x9SM*heRa{4%RPULP}gtabCK7si=YDVwD=}>x2_p z#)5qr-^{nId4BWx&5Nf3fd%D-dsT<^cZewRolg-3aXPhRg*l1ivQ_D7PNBO)oM`b5!1 zIddQOT}nc)8~TzK6*lq;YsY-GT442n$D@EPr2Ssgktck!V%+xfv9uZR-_cdO^48m_ z&v3Os=0Uqy#>X5FP43n!thwaHyZPB)^Lh5{M~+EcUiavFYX8k&ZvF;po(XfD`KwO3 w2C;NG2x>67D(DBij;-L1P+nfHmzkGcoSayYs+V7sKKq@G6j0G5PZ!6K zh}O5~47mu@?_@mZe#$fcxaC$Urp$x<13QA~ViZL!Vu1+l|j>7?^ zRQoRT#L<~U=Yb~C#Oo5}$K|G}cRs7@VI z$1ZW=B#D^WOCVEzfZ<9CxB*UqD#$eV%l>o*Az~O;+)~I**j`?hQ$w6UqK~y-6osvx}gkcnhuUj)|FtSjx@==pNAX!*b7CwG}SP3g- zHz{gXlCtrc6?RiTiXu^pVnHMuvmvsupqV6$=2&26yxtkcSv@`HzOQqiI${~)zqQGZ z2Y_*oh_RcKxsxuURD1wp?AoynI5nD;*San4=GUZ}0dHQW0Sc=HKMx9OB3lqwfEE?P z!wNnMsiRLLx==`^zXG(T0?liKA_fskHfjh^&W-xjo)Mt1d_*~?m?qb(rR3AVk~%c( zp1^~jLMmO&DGj{R<_>uK<2~4SU3!AVH{lDg#WPU{*fGXE!9EFs%rHqA)6}xZWfJd5 z;7Pu`B)H{?1x`4i%giF5onxR%t?H$LG3Q1pz$r0CskcWvbBX|L)utrP5unj^1sk$N zCUa6_7PkvqPyZ9k7+2im4nJ zFq(oe*!2gQu&X%Q~loCIE@QnXUi; literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOff123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOff123.png.meta new file mode 100644 index 0000000..4502fa6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOff123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: b1aef48490f4ed0428d5c198de902252 +timeCreated: 1472713091 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOn123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOn123.png new file mode 100644 index 0000000000000000000000000000000000000000..4ed7e0132f9e98e10496b5b0efb4dfa26a9b4b14 GIT binary patch literal 414 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf4nJ zFq(oeU-W_+4sp?f@_|2#Zvnp7pW$s~&%VS7?%+YZmmuXF|Oyi0l`+BFp$&+#P zI4aukp0`Hu*8C&d9V=?M68vo^DLwd*)>&`T zLXG(A-+T29AN{cu`nfYW=(F$t|J*F^m~Xsi65jEjyJBwi$t@pzT!3N8;OXk;vd$@? F2>^SLrk?-+ literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOn123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOn123.png.meta new file mode 100644 index 0000000..27e9e1e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGOn123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: ce573ece89da18f498539bf492e4fc89 +timeCreated: 1472713091 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPaste123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPaste123.png new file mode 100644 index 0000000000000000000000000000000000000000..e61bbe1220e9d8155b5cccac348f2d46fb9f3592 GIT binary patch literal 460 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 W4ECQnz`PLv00008bg=d#Wzp$PyK0ZTFf literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointDelete123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointDelete123.png.meta new file mode 100644 index 0000000..500cbaa --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointDelete123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 285c5dc0cef41774b99e38ea9a1dd9ab +timeCreated: 1472300690 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertAfter123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertAfter123.png new file mode 100644 index 0000000000000000000000000000000000000000..d99a061fddb8d1bd80258812303e3b865d616726 GIT binary patch literal 555 zcmV+`0@VG9P)>Zod4(W_n2cwOW3iX; z+{rK*Ayu6BX5Yqd_2!3~C7u9&%L$r!ii-X23`apoFqBNsr5LCifJHG9(!`k+btufo z@ypVL?*J0uPhmgU?z0wR?8URid0zp(>1&%C3h23>0M`H{05FgTl+jx~yi+FtIx>Vd zXa$c98p`SFX|>BQfUOp(rmXqD2^nVcPS>t#V%ksZ2VIc7=zcB@0f@Uf)JS;qT?hdw z0RT-}L^DNEe7f-*3uD{mu(F7lVgP2{0e;qdu{2%22>?t{LRBZK0BivNr{D(#00BS% zP#I8W!pg4d>TYY@0P&QoCtnD==KEkGoi@v1Wf2iE08y*P*4lw|%>%%4+Wm|wHT)9< t00BV50lfW~FkgV+yen8?$6TPlst@l|dPvLuL@NLQ002ovPDHLkV1igK_LJ%#) zCY2&0ArR0qWm4LS5Mr4^8?g&msURpMh#F9HDu{Aup_a zdGm(%`*wzT>_DgomUtyfPK_HkKddDG6~LN_AKp4F6nE=>O$QxgJc4z4KP~Z-M?l{RRl1c*Sb} R$$|g?002ovPDHLkV1lD+_kI8X literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertBefore123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertBefore123.png.meta new file mode 100644 index 0000000..5cc4c66 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointInsertBefore123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 6c4383b335fb4f84d8b4891eb8162aa5 +timeCreated: 1472739488 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointSelected123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGPointSelected123.png new file mode 100644 index 0000000000000000000000000000000000000000..cf1b00da702797903acd2b77f5cd3d3bc8e69a19 GIT binary patch literal 394 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8!2- zOF@{ixhZHCP*AeOHKHUqKdq!Zu_%?Hyu4g5GcUV1Ik6yBFTW^#_B$IX1_nlUPZ!6K zh}O5$4gH(~1zgW72yq@c<;A6~lgc{9EMjKHOT9bHya!z)vL11*h+x#cQWC=Q_`7hi zu8h#C|NC3*x^`YoDSCc(<}=mnD!vVN8y>n#et7uRdP4PHwrOeK92!+@nPnebiRNAK zv{cyQ<1SvG*LfApagB@j9!xfW=ZN^*eBsK8?EttVSRHGk9-(?sa%(?@sA*XSn&v%z&1 zdClJVG&XD2qhL;rv&*P%2P)CmiWY*|THI(`JQcUQ&uaA^uJQdQwc9_j5w)Fp(Q*5X z)MRh6OtT**f%GWpwj67bdK^(6m%qw9_c%NWBUW4BpyBFXQ7D*E z+nZub`(rKx0?X1zwFsml+!y67bWf4wf=A^k+g~`lx!XBL-b5d!d5cDeh z(0XMrW#*sbyhA$OZ;PW-`Udf)V~%?ihsJ+NQ^Hh=mh7>~I;{pL%!0kryS`KMY-av3 zMXf$--D#Kpn%!ZvIpvT?uzxy`NiY?lQ9oLx(<-Bt&4bc%Ta9=!GtW#_C^OTrqt?3D z!OFWghIaja@i>0Y%&9wGS^s=ZHKNQMiHKIc25_4pr;U0Zr~j>3W|kvjm)AX{sMVNs z)(ULR%&}>WmH%R~GH@CrqH&U_-#gBAFENUl<7d^h>#XhQtwdvJh=_)1^&comh48rn z$NZ{E-}z7ZpVnn=w%Vrfpyv#lr{J%P22;{tpKX5wY!(ZpQW!|f00000NkvXXu0mjf Db=08g literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectAll123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectAll123.png.meta new file mode 100644 index 0000000..9b5f002 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectAll123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: dede35dbc7af6e7489d42029b6b694f4 +timeCreated: 1458533499 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionAdd123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionAdd123.png new file mode 100644 index 0000000000000000000000000000000000000000..f96afb3239686731ae4a7eaac0c87f38310c4faf GIT binary patch literal 877 zcmV-z1CsoSP)u50);Ub*TTvV&5 zMN-i}NT(ud5hSz-qGl!|4092twlWKRgOM8{D+yOYR9KWyl0gzt=s54RP+#-jn;9i1 z-SmTj$9K=%`^|f2=H7w-S>lL~BznTAl)9Lqo0HYwi6wUtDXa!1UKGFox z&d-sRNXeayi9Z1I5Wr5NW*EZ+syfXk$7d$#09pNK&eX)rMJq_rEOf@Cq{XQfO>y0- zAZ@-84S)8p`>zvE?k8?3@t)h6*nbDES+y9}GL^p1ncA=a+RHCs6d z0u^ZB6Ah8qxdj>`Hw(J3lj0qywt?LW9Lg;aOCG>z89{B~M9nCPWHm~et44K$|2I@B zi6>XM>(c#mHKt!cIE)fvN-ba%)ssM#r^X+p4z$i)7dT4(#>C_sENtwLKsT77OuC5Q zf|`Dy-;1+7f+mzMCW}T2DsZD`Jt-4HWtdap!Q2A%k$WDaKCs7JNM$?XX-sqgc;|kr z{l>YTGTRVsL+n-{k3g*F6v9T*!ONVk8lfR_#a9!zy1*kKG*e&G=Bu3}{w5T&2jn=x zRB4v_f@krX(3UqCZ3gpXX#}PlZ_tagY{%M&Ev2M`?{m*4Pr+6fQaHh|z%UoOo zhVkbez+3Mk{(VhVXl$J37cbgAwoncrlH-2-&l2P}sj3qXGF7q(00000NkvXXu0mjf DWwVDU literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionAdd123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionAdd123.png.meta new file mode 100644 index 0000000..5904b7e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionAdd123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: cf5fc4a27a2691e4e8a4f7945b3328c8 +timeCreated: 1472746448 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionRemove123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionRemove123.png new file mode 100644 index 0000000000000000000000000000000000000000..208da0e0116621370ccb36a5bd5e6a4c445720a3 GIT binary patch literal 820 zcmV-41Izr0P)^U10Mwi;MJvY+qh8HMe+>04ZC7?srn&<<5$xxNX&9 zn_onN-@Lu0PAqwpn5D!9A7oJ~P+sEbbWsIjPj?``TGaQIw$S_h0&StYMJ;x-0L*wMUB|1SVH6n6#<~82PLzJ;%chDdaA$BgDHA|tlJ?+Oeu37|<1C{Q zaDJ?*RGbO-IBoVL+Ko5~pnyPhupMC!w*NZk>!)Z7-B?rkD&yURVh(|v#hGHkD$qGpL)s34c}pbtJikCoc(|y=OR=3g zgecevpnyQ!x`tANIv0sFek_ShMshqA%K^{;Vj75Amx+X9#FIBsJ(DqWoJgpTxb+C7 z+2tZlw1!5AS;N4-W$x@na|;x@7gQjNPr9mGfJ*mcoF(z{6g`h literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionRemove123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionRemove123.png.meta new file mode 100644 index 0000000..5a53e9a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSelectionRemove123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 433f6e35670079941910fc178f9bce4c +timeCreated: 1472746448 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettings123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettings123.png new file mode 100644 index 0000000000000000000000000000000000000000..56aa4ac83dbd99295b733fb22e5dd650e874ce08 GIT binary patch literal 600 zcmV-e0;m0nP)Ou@0{~J_ulV0 z_gt8Wljy)ztn~NTgQq>P&o{V(ix`7xnEjLd;ZjixveUnQIo`%TMb7 zbcS7sfBQUnR zi_>u<$fk&O;2zfDP;k|l5cU#Z(2nNJ|DM=I;Wy)9*oUJb-Dt_gPDLq-TZPK*F1BI{ zPGczs#R2be1$*PLH~t)@_?NR-S-P!W;rGe7OVaGOVk1rzuozY78w)F#JyLTCZYq$ZArn^E;UT*u5vE@B6s;U&&tSa6Ma z5j?5uZFmy?h7dx!v9@gAEjSZ)C3ZP)2La|2ts;UJ@pz0o0f`wvl*O7vhhxU{nKJ}R zD9$#XeqMrf2EbSUJ3v`U*)nFZtinYLkzh{%0H`5VXleTGld_VssQ``;kQ{*uZ*p+E z!HoCv3-UjztgK`)1Gro+iv(#S0}BvF&Jao-1n@y>dRjQao-mr1HzyyWEK2Py=eLgp zgKrChV9djAVXRTiQs3a>g zhKB+$nd3xJ{97Ihg%Au3gAf9X)e1?LFm@aOOr|&hfFw%#r2oLml`BQY*wb_GUmz$Z z1pr{NSx3h&ws)Ydr4@t_BqcdvFoyo#t1w&QQ80fV(x+yOY6k}fKnV@*_Uvw-G{A`y zC&CraR9x)uy_!31#&jC#S5*~19X*aIsi}D7wO8Rxc8<&QdcE+t_oCbD#iC_PK`DjB zVgchUuEJF@+wF0;MgySHIvHc{cVG7MF>M_G{xBXWT7eg~zW6V50LaYD#OrUp0ehky z4X5e>0M6tj*d2*s5bP>1FHf2@060Qpo6WyA;lA0kP_(Kjs(iEwM+FeLP;0iv&t14=5pgEpoU*~eK}^e> zHfi%nq^76Af8z#{Q&Rq}F9?Ky#EsRBPC;d5C1nOHoL9I&ikJfcXAGh!#S9?HA`Ii^ z{=}Gp<}*#)d$E%-&T1wCV3g1iUDL)Dinqk$YF}T>0R4Uauvl-dw{wkWSVw!i9~{qC zRabo$6#xJTAt%~f+w>l9*C>5jMh04&TfzC{4^BgVKZ3(SSS%Lknue}UF9+jW_f+q3 z|5G~-K;`O|fIm>vSl6H)JNSdHYdU0EMoLNw>QB~98lZMxE%Im20sssQ41h5v5QQ9! zrX2_1@pyiBd)zKA@)^U!!~MQj5%bYQWII|f=s~^IbpL~IaQ}t1&L)UeDxBmbR?5n}5M;=CG zN3=T%6B!nQrZWjZAKt?p52>}QpOXAFCRhDHX(ia~ej}@zmppJy# z^ZC$usS|_{SZy{Gmplbg6u~*i^*^sc(=|AqPF(T*j-IY=LOA(6CIHU(kgjRe@At!I zvjG4G2L>Tf3X9E(?A)AxKUdDo$r{xMhlBX}$d6&p_z}X%Ho+`h(MR+p+~9qC ztD~QW{uAKPp+oAHEnC(MT_4(hspCQ^GuTNcuuml>kx*#l+0zY;Zz*OINlQ-$0C+n) z!8z~MpcQ+*9X+BSo2dS60RUj<&Ye1dcW*soV@G*OdFtu<#!cC|IZ`MTLic5_&N%xz z*84%s_ku`Jg>F+rA=cj7wuEtZjWb?rbyz=*way&_xZQ3)fS2wxKN95D?f9NwP8|SN d-(>&*z+ZlDXR)uW7gGQL002ovPDHLkV1ibh`Mv-E literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettingsIcon123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettingsIcon123.png.meta new file mode 100644 index 0000000..439c2d2 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGSettingsIcon123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 94e25c1cd35aa4649ba3d4357982aeff +timeCreated: 1472983008 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableCell123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableCell123.png new file mode 100644 index 0000000000000000000000000000000000000000..d55413bdfd7244f38d80e30bf74cc1df32949c3d GIT binary patch literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8!2- zx**KhWPL3MC@5Lt8c`CQpH@mmtT}V`<;yxP*I|%i(^Pc zYx0^o_kMXrd3>=x%+Rp>eO&P-5AM#o@5aRwq&e7gtV$mUUUrD+;c=5Sc-0Wd-eZ+; zg>f;TMCpMQ%&0;MmA~GZK3^8hF2~#Q)c^k8XDkdA6Gc|c{@6boXc>d2tDnm{r-UW| D=6Om& literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableCell123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableCell123.png.meta new file mode 100644 index 0000000..c8b68e2 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableCell123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 59bb3d50c693c0b41b9ad2688737d022 +timeCreated: 1471855053 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableHeader123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableHeader123.png new file mode 100644 index 0000000000000000000000000000000000000000..4d78502d6cabfb8a21a5033a9638d615593a5166 GIT binary patch literal 228 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8!2- zvLMVD$^P63C@5Lt8c`CQpH@mmtT}V`<;yxP*I|%i(^Pc zYqHM#YoEM2;=foQW@spvk1yWD@v*yZ`-RPur8(H=>?nC5c-bMMhsRCU;8jB)dyiGZ z6~@JU5~T-LFrx}3RDSZq>3h3<&sZ307l~Y05Vgt^Xc>d2tDnm{r-UW| Dtrbcl literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableHeader123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableHeader123.png.meta new file mode 100644 index 0000000..14d350a --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableHeader123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 688c50e97be6de94c97dfebffc0232ef +timeCreated: 1471855053 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableTitle123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableTitle123.png new file mode 100644 index 0000000000000000000000000000000000000000..70538935b6335d7ddc4f06b60b217a5cf2e51826 GIT binary patch literal 1113 zcmV-f1g86mP)+tJoLY{&x4Ab5H*7|C0OeeIe{Zv)Sa;n)SGn&a4vBCXmrcEu*yr5i?i;fD~%Q ztj{4blq87*0K}w-n3yN#m>ejD+uKe-t)u&&1bGK^)0P2@~{_U%yq33_lI6gf!9M>EI@1^I! z`Qhj9e*fm%8y~+u_u^x_)ry@G&n&+h#eVU#b2AU!QOHG-`g`@iBJ>Nk>$qc$^Jly- zKKk@}zuFydX>7$G-Zy<=N=fzKE6jl5@@P=W4?X$v@M~+_{A|s0ir4zpZ21XXx^_v$Uj4l@<9F8fPg*uG3nXchZ`?oiWn#E| zZ1f*RYnV*m7nX4cMS-XeX$nTtJ%uR4%c?!Sk_&= z@vZ@ur5-JYrGv5A|CfYesW!jZ9N8G_Ua+m4VWPve`u9>F8msz_`^3f=1Hk-ZGxXe` zG#FXgk0DvW^?)(1H zSOM25b zg{|yJ{_@++=<6Gw{|Erum^O^j06&YiHxCk((3+UXpGSY=++4#+eD;$=cQ?? zjM3f4tu}gfLsu=OYW2=BIu)r-|Nbnk6SJ-l0Hl<+j3LuIFHPIsbxp%)7~R!pz^P=h f3IHpum0N!SB^b`V#{Fv)00000NkvXXu0mjf(zP6_ literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableTitle123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableTitle123.png.meta new file mode 100644 index 0000000..5fe0800 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTableTitle123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: d5ac72114a58e9a4a96233d3b26b7d50 +timeCreated: 1471859604 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 16 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickNo123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickNo123.png new file mode 100644 index 0000000000000000000000000000000000000000..59f79b9620be6cd82ade163ac313ac1537a5927f GIT binary patch literal 727 zcmV;|0x127P)~#0Pk)ub^6d5{GcElAOZcDmPp~8d$(DnRzEOvyxoJWV_uS?j;z;N7#!ma0!3m zeSBI$KfyXa$M2cBT3bJb#Fs-uLmRyWfhVwxKQePQGdFMzU*Qb?#%K7mzL^p6I`-i# z%82;?`l$=n@iva(V7Kp?xn8yFEzII(X0~ha2|SJS_-&_C^dC-Ct$MO1S;LLYyjAtP z3qOJ}T)^^H__^`Ux}Y06?U;>--CO5G#Irbx zA8;`<@AQKA6jYKneyRX75wWWV->-A#m#~zXxBJ1_=BmidwTM{2JNPgney&nuxQOpF zb7ebt-wJAyReX#qIG}UqT*8ISytNa2+X`xu+YxcL`kBB+X5M`e_yY+l$$iJ~p#+Ua zL$leOslP;z5~HJ|FKrSOMWOqK4mx6deEhvut2OpG;AL5Udk<1O;=ZPg)WHA%002ov JPDHLkV1kkEN>Ts- literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickNo123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickNo123.png.meta new file mode 100644 index 0000000..aa0bb49 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickNo123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 095ffc4f31a16bf4a931b1fe2f14b0f2 +timeCreated: 1458400542 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickYes123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/BGTickYes123.png new file mode 100644 index 0000000000000000000000000000000000000000..2d378de9f536cd9dc32800663df23b9ba4aacc58 GIT binary patch literal 716 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectRotate123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectRotate123.png.meta new file mode 100644 index 0000000..6637c50 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectRotate123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 5e55633039becc942bb8a380d8cf6d77 +timeCreated: 1472942522 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectScale123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectScale123.png new file mode 100644 index 0000000000000000000000000000000000000000..59d6c94e3d92b7b4d283fe4ba67641140afefe7d GIT binary patch literal 1766 zcmVufz+4 z2BbS@nw$0`-APKFjS0u#G&~+}34aCM&lKJ3IwT!J5BH{M%&Fs9_=#_->x|VE+HS{QscPh$avwprimgu?~MX zUJyfgSx)!OLVD3LF2mV{|0m<6LP#Gel)1D(Q!junA@qbzd0Ka&>?ay^c`QNzWldmM zXu(p^**^R>&+EkM{QY_PbI4e`d|cQ$EEg*LGodj>!E_&khcnQTzrPKC!S4(CJ*9dw z9;GzkgLqM0T88fn>3=Uz>o+&=#ixYRt=V~PR#;k+hkuLNgz=+&uc@yWN@>8oMn}3=sP3nQ zs{hjHI$(ZIlkjUX3tTH!bG44%pXVRI-NK>OM)qzYxU2D}Jnb=~PV*H)5DDw?8hlO& zzN^W8H?XVgUN`wx@yqC+gBD?_UquuM!>AE;S%qualMv0d$Z~6`jA4Y)>mKGChg7Nzd-tS&`cF+RnAitztfM=&Xlgl z<)iw3(hc|lP7*7$JA^j$=F?+KSh0fM-l>)C>toxt#&ona4Q3liJH&0!9vsBl+$>tg zS!c0)`P9nZa!YyI7S{pUJ*3^@czR=1oo^>9SO{g0;E~qrnHkKoBeCjH#Zve<#tUy2 zw^q*(!5W=LV~;TB1@PomVllQ~+++T&o??!hz=zKl+w~li2Atc`;j2A88jjBP?M@mRa+Qb+sNp;j26v^=2$4UF0L*@) z@kZz>8!=J|N}Isq#fG+Q(eQxd%rgz_+Jy*sS|vJuVV?b{h%@ZRADZNKS}+YhU}PR2 ze~$=dJ4Nge?-9GjpH$yoYp7fRDIMA)*l58#|ICVu6JuS?6n1BE=JB4pRXJhA2MW<7Mt~$_+q3MZLvmt zA2jDtFMzEg3j6R3@G>KqXcjnOI#1l{CMWR6(^(~3j#-TV0^xS=6Yq>{UjP6A07*qo IM6N<$f)(6Di2wiq literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectScale123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectScale123.png.meta new file mode 100644 index 0000000..fefed03 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectScale123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: d2786fd700db6304d82b0eb6badf912a +timeCreated: 1476113367 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectTranslate123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcCursorObjectTranslate123.png new file mode 100644 index 0000000000000000000000000000000000000000..933a1b9b77c7ad81f982983f404796ab7da54f50 GIT binary patch literal 1548 zcmV+n2J`ueP)Pbi4V(aL$}_=9%aG=RD{7Ooc2nhA}>cui|fIDpCTzgTqA&$d;9@ zP3Ms0NQLVSA)d*%Jb^b|gZw^F=H$`9qle4`-e0a5vz3u)gTUiBQ!5byzh zpW?IR&2TVmEySxGUj=)m_?8s*3UXmSPQ;gm{llh$oC^gZQ%#SN>{^ zGBZ+MkEraM>3+YIf35h!t8qH+P30bxuS=?^61Gj=cU1Ayg8c8J8_#3W2>RSw%6WHx)YAvF5=+Ib@LMIlzYk@Zz~}lef=WYK1niWr>Pkgf z1oUWp`Px$KA)uu9?!+##(#@dE7Vs%1mGu5T>>;3}_x6a@-dG?Y+rLI)k61VjARy}| z>uSGFIXck-ZY5hnzm;c?SQZy1L)m#^XXpJ6=+uW!5O5{l!*a6fzQ6zz$Sx3jif2&S zQbR`D&;bG}8I@ba_Sv7wri)>)7n8^qh>eU>scaooOqgn%bb#~JD7BXJPADqU+tWqTWuJW2>S zV3U|QJuO^vY8}irgi%7k@vHFbc1YfHI9j#>Wn&Kktrz+Fl-A2^A6iAgIN=BQ50;g{vS$qLz#A{Q!)cp1U00002$XITo80mcF~c;Ii42%M<1kN_ zfThO!6kjkCqtGw$Yz)4=f#YNJkBe?-2IYmzE->FHR{>XB?NfnQf$e$dOaRsa2T|;? z9oPqKK#DbGxeLu86Ca|b(9*1`237!n0l)iC)T|X+hy@-1KKIMt5v(&aXc~-+&RM`@ zny$xT7QH2CSq<^uy8*8o{U5SEDHhm3}#&0ww`hSarjV{{H}-jkZdQ-p~*kZ3WzHw5>Ag@3RNS4Tct@>6F7% zWE3YNCAgptcn>H;OKAj6*J&AWk|V7sd}@?`G0G=K4RCdY_5n`;GyV7RNFh7WN4cOD z*^|*g5%4GQx7DZ2kyaEMjPgOF+}ZA!LmXFlA+Xmk7bC;?sT@1cM zLi*l+2C5QmRU?4@e%l7*Dwm_}2B6gMGsvPd3^?5{e?{P< z_W>56U1NbYW~f1DH%$%iAfPKS&!;^IIK>)&hA;mxpu(uH@MSD&_O&6~;CX0zo6q!S z0|Qir^v^v%8T}>$jRafMm&hR6W9AxTu18DH1NNYq_X+x8=0)%v1FVi{D>c45uOHAF z=!Be-elf?KfM!QUp1#h=Dd1@50}cS26O7qTepfpY+I&W+T>)7OkTu#BkhK6=qg?@6 z3y?L!{D4ltz*ge7rIqL=MwkK)0<(Y{3e4+J1iv&WL#}%*O0E>4XmbVd4MAqA26!us zK$t)tN`VbTe)VCLX^9MStL1UzXM64~$AsUT|Aj zW1ML4T$Bpik1{)1pc4J!9$MS3M_@0abbK?!$qKJQ>E>dT$3NAPd7)4Wyo=WM9+XdP zbR4^hAhjO~S3lqt;6b1V@D8nWtTh;z9a29HWphATs5o2c4zygN5hEc|1iYjntV8Lk zLZJi+daYGoiE@J;I;ibZD27QhLM3RA_0V!CgeTbxcpD`?dRlGs2`u@X0`NM5G%2wP zbhzmOkEE1iHo-2_i1zPEep@k0islqBDkZNbNShO^0(O#qd+Y_=>eHF!zvoVIMiYE| zJq3UA@H%M<9vLkB+F4 zqA$u3tc++cA=qj5BB#g|{eU}L>X397n1;5kdUQ$AzTglCqtOgpjtuGjR{MT}rB#Zy zNf&hW$1Qg19b*PugMP6_bPAgmGsT`s=<>yBA$`h_+nw_VW)OD58=wXSKj-9Q9@i17 zMUmJc;HrGY9dQ$~{F`X`rbsX3Bjl8@7TpmTh@7SY=-%*i$Zm{uVID^Tg9&boPH`a~ z1FqJ+2n9;ZkkRz4XEVA97W=AfJ_YmuzW13t<4U}hQHG}a1t>m96q>szpcwc_eObo; z`)YkNxZDp|K#&3(OJTgRap=0tF@q=t+zs4jyrGCYNTzG$WINQ^dr tHrTF!tOdv#MV_{~Hv7-hIR&&?{0DzB`^K`orA+_;002ovPDHLkV1mmiB6t7* literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcMath123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcMath123.png.meta new file mode 100644 index 0000000..f7e976e --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcMath123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 913b0df64e0187e4e844d7fba6bd1e5f +timeCreated: 1472488522 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcSplitterPolyline123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcSplitterPolyline123.png new file mode 100644 index 0000000000000000000000000000000000000000..a445dea290da90106bcc7ed117889a896cbb0442 GIT binary patch literal 2138 zcmV-g2&MOlP)bD$b>P#Ew>5^4xpl&!LeKQaSWgAAE%eoh6r={2 z4NL#E6xDglteg?DymjlZH0Y5FXuLj@?;k^RRj9vR*Soct@ZVs>{{2b{Z z`=AN95-=V}VQ)JZ4+Hl*h}1%U0&WF10_Vo+z8-5k-r-q;1h|^O$ALOb^~VAKja|D1 z_)z$LCNM2_?OEWfz!>1~z|&B08U8Hr58(U2zOZfv&>U;i3iJT0fcMHBh${hoVR;O& z33w74%rn40!w(oi*JE!NU^UPMTm*aoSO{EM;5jD(HvtpFzSm%cPl~mf3G4#?gaZMt zCQuKoC!>b(&!5SD>)(l8J0q;SE><@?tQ*b*o(=1sj@2b*0A%8&>u@dI{Zws|5j0k{Iw3V;)UkLJ0jKc@sUqng2$fazqbDp_2a^FJMdDT`{sn@*FKgDs0uyAI%V;1|HVVO=*F|Kh`B z9HfQ7->`|XbX4dEya~(#j>c^LgW-Vg#U{n!*7i#NtKS$9<|Q4Xq2KzI151V>@J%->_So+xS=5E+eaWxXQp-o=*P z)@le*O9F1d%;V4!+AhaPI6i41-Y+4sC1H7S(j8ZefFp`GDGOcL5}LRfRD%E?+ne7} ztYMj`iWyXcfEJ*aOi(i^JRFvZnn5)PXu~!rPbA!L7gaEWqzUk`P0Slq!D*oiW{@-i zE!bA|k%aq=Fq|2D7srV=X#%RH{t>zuY6fG0FJkjf*+`OrYO8;QTr>DG@H^Mek|dy7 z>VE?kM~D#hADO{rz;9hUPm+LQ>VG@XRHToukjWuL_%)Uwc?>uX*n$OLF2KU?-MH;A z0e1r0fs#+EKA@yGaEN1u}=qG@0VWGA-dVp)Ou-kIrW-PSU0Q>+8#yZ25fC1oZ zvEOH4S(!rW{|8_#aA%%t$6&F&c7~tK)?g$z0as(Y$g?obaE2=Zk7LQohVXYAwhR@U z{cp!2$MFDW12&1>jHTHMp&yI>UV^O#zXA4^Blu9br^gpycIab4&G_3N3*3VROLK7; zmgipvynva-T!-h^VL@3pByd9HK`a~8f~kMBWo^Y&{blk;gZh9=$>aq0U}TkxG~z78 z6P~_ne=!eoQW-8qnw^B?nY>g#-wLymJZk9>2NFy zOT53L0}>Iw0sIF`h;#zym3hBgOj4YK2Q%2=)oP=;k2|rs;^)Alz+ZrW zVV-2vMfZ1+3*!QVl_a(n>2AO+iz@HeSWjZR3XR zF+l=Khwwaks}X8fyB2AY=4-wh)tL6=?Lo{4TONvee?P+Vekn3<^gZsU3!&9ooi+IN zS|5>mZwa#0gn;u9nya~4f_JDxb*c;K;APC=*+XW)-Pn?OJ?4G-h~s_v{o^%0y+SLr zUE8%%D>Ye@15e&w#K%gIr6vU2hR{ZB9HP3X=oIP$fbVuqocGHm_p`6*zoXJ8Yp-kJ8(4}cq1TKftNSQS^y)X z0keSnXrTw83w5FPY2V=6U#g|iTl{5}<;b8S6A*2PC5Yz{3lXR1Y1N2jhvNqyUg0@5 zAT(1mgL#^#HnqvOziu>w=Y^aJ5Dy|$uliu3CI-HIA<~F%hAo=0lN~#;LGQ-A!*j#? z8xY^~T~v9%2eADL0rr90^!9N~3~k@DbK&o%J$*@bL5}t15gFa3r8}s-_0HOIV-!te4)w z9pU~Dr|oc>*SBbkx0S6~)oWR6UmAHKDfvbYrE9?FY2_^f)EqRcQ=J;nfL3XhCTK$1 zm%j_`U*~@cq6`z5fCVE3>|!y`c=DpXcjSTfp{&sL{*Mv~xDt!X3X9tv8{YgW#19dR z5w{>FkBrm_q6h(FfL~z)e;Z3Z9at!^7np|pR1RS*ZKd3LdXJKU8 Qy#N3J07*qoM6N<$f^!Pz!2kdN literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcSplitterPolyline123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcSplitterPolyline123.png.meta new file mode 100644 index 0000000..966c3a1 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcSplitterPolyline123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 0def80e3c2695d345b205d3d2752e5b9 +timeCreated: 1474946153 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: 1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcTriangulate2D123.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcTriangulate2D123.png new file mode 100644 index 0000000000000000000000000000000000000000..cbafa42128f2a5729dd0ef1f0bc19b2ea81ce597 GIT binary patch literal 2300 zcmV@XvJtMN&pI8hi`2SW^_xQNdD6MN3dK zCr2DivzHmhW=Kb+vQoyv*G8KhvocC!8jY;U)KZHQ-|#I#QIP}{5K|Cj1!RHUr$5fQ z?&Wfq-FtVJ`v-hy?)>iWcb{|4^L)>9&UwyxezzcmZ5X}s^%Xo?Petm0&!CYI!fo}| zW~(FICd3Z))}!9o<_YLkcHa*_s35ly-!FT10H)w;Sl#`qeTcnqGa7JOJ2D0AhvjIh zrt)$R*clseEzZQq{C&4}%J!*HM|a~*EWyw%$n1y(IJer$%ROM3HV=cQlCHOop#RE7QlkqqPVLk4|S1}KF;m3FcKPl630`|qn zumYE1O#W>&Uc(Grm-XKV-@~hwDQJHcn1_c-?x$rkcERyD8i7$5D7oNZyog(KnO|ZJ zdgCAXyX3C_!*t1en(*r^|8M*yf1g|O{AXC0zYoIzoRr%?7CYtd7iO7@^Zl;4Pa?hC z?wVGC*YUo@a48PQY@9BQ)!j>eTP*d&Drt`CC-vT2Xq8;N6oq_kXh(+$co+xg`#mbi zH0HV|NFDh?dj?fYKx;eCPn3+DCiO-s$|KFyn2#Y68G}oHTOqmZ9+F2@!s(c0Q=>L! z-Fo8`JSExoduj51ubsLyxYCt)&SdwLJRg@UTwY?tFlmhUkyt%Pa?4$Dhcqr5@obiF z!Twkz%{2q@jx^6q!*Cpmk4xk8Uc7`)1vt{ufK%N82SAngCJEdXMfFq@evo5F?0dw=G z?%3u-;q3&}TY-9GI|21ppx)S8tH6%Za(65{9n6rSJij~oOVMBv@8WGKz?qMi@r)E) zt?voNdXj)XQdoMPwEOGJ7p2|x4jbv)!rT?i`7e*GU`7*b2S^d)Q8=Nbu61}?iUR*7 zZJN4?knWEJ`{5F)Cv!;rxu;pMkcg7c^0ND8;tAp=VjMS*l6HJoNV~bFTwh3G?VUJV z3dO5Ojs&}tfC4ViX80nGn8J!_L`(kML5#@;|0iE>A+8|qCsve^@-}e~aXITwWaOu% zz5SEYUM28>w6#9N<{PoCM!=r(_!P5Vz;LZcq1}Db_Ut3hehdQ-jvlJi$#R_Nqehj}jjc^Rn_+RjEU=^*co8XYo}2vRr-^(XV6q(xSB!(1(%BXbslQ zARZu!UhoHENEKQPEg>+73#uqPKDRrU7*K`&xp?gajAwZ1EZmxxxd-xnk%;{}sma5{ z`ZSxz3!NLoF_zenC(?bZ(7mLJ+6nk4hZNW5yNJJ*c)$#zI3YF@zaR#6pvjq8{;7QZ zYzOiqiPd?fIj{=7%c`l3fSvFGN6y@I;)+9aueavU6WKK*D|-!5DZPehAQnoYaSQS1 zEoeQIcsH*$qpGoY^Qvki;8+AFT$hczx~$epL=YGZ-MqTmGDCS>_n)8d%a)zO^AygK0;E4mySgFLc6KEuVF59T=vz|oSJLr#Kk1C( z!cD3bd*DGSQ+zIk%~M@9qdE`xE`kfbkbCUL4k{m3;t?&xbJ{}L#Zt7mW0t)&KYulQ zOAe-Dmy%WD+qIgxxoWj}K$dSV?!`L@JPLD4JmPLCqcaH4qc3j4E5tW(3qo50_B^7G zw9`8rlPTO(rM{g&bslh0QgZYuxkqm8u*9Z~4KMSEdAYZPcrj0e>xq@b{JhEp@$+iU z>R6T9JYZ?MyittXt2|LE%+4NhH13yDWBsJu;9x1M+*>*d`y|ei=8|t!sb{BAEde>3 zv!XHI_pYtk!Ym4>N<=(_Pe@DbJTyzhY?RXQ<0-V%)=tN$_Dpa-RbBBilk zmk8)DrMsWRHz-u~!c#4%>i4sW6B*$EJohO2^=(SS=a)vNUW4pG~}+!`5=SHF;gXgZK_{p|-=&$vtJ}X6WL9 z$k&+}EPN}+{FMw{O*~EfHix=niT!P|^28A0^}H-j>_+oCMi&WaVDwy86^(sUI^4LF zIE5Ij!)usWg#3COtNORRmLxR2Pm`|Ix_ zdY%As{zD0*yi67+fG2e6{t716Hspj>WxBL3%A`rPZtT;X7PW9 W=7_@pOA9Fg0000I6a|zfy-E-xC|9H@ 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 a33w*E%N$Qq=Kb|6z{J1|`AE+x;(q|o1%#{s literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcVisualizationLineRenderer123.png.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcVisualizationLineRenderer123.png.meta new file mode 100644 index 0000000..58c70aa --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Icons/Components/BGCcVisualizationLineRenderer123.png.meta @@ -0,0 +1,57 @@ +fileFormatVersion: 2 +guid: 7b4f1912d4b7c8841b28c9b596a7ace9 +timeCreated: 1473076361 +licenseType: Store +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 0 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -3 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: 1 + nPOTScale: 0 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 1 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 1 + textureType: 8 + buildTargetSettings: [] + spriteSheet: + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts.meta new file mode 100644 index 0000000..c82250c --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0843b6513bb58f147abafe88acbdf49b +folderAsset: yes +timeCreated: 1458400502 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc.meta new file mode 100644 index 0000000..6f1b0e8 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a25bc0e736a11d546bd0490d3cc13f88 +folderAsset: yes +timeCreated: 1471596338 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursor.cs b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursor.cs new file mode 100644 index 0000000..0184bc6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Scripts/Cc/BGCcCursor.cs @@ -0,0 +1,102 @@ +using UnityEngine; +using BansheeGz.BGSpline.Curve; + +namespace BansheeGz.BGSpline.Components +{ + ///

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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestClosestPoint.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestClosestPoint.unity.meta new file mode 100644 index 0000000..df7e1c3 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestClosestPoint.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce52d115c270eef42bc0891ccdb4d2e8 +timeCreated: 1476651640 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestComponents.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestComponents.unity new file mode 100644 index 0000000000000000000000000000000000000000..b8965a588ddd3a5b7c0188cff07c6e2ce83ff939 GIT binary patch literal 67881 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 b7UWgUHqJ{xj{i6gQ$MmVjPCJRZ{z;})wJcY literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestComponents.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestComponents.unity.meta new file mode 100644 index 0000000..358202d --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestComponents.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cfc6f54abf0c59a44a0e227bba8eee52 +timeCreated: 1476650452 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCustomFields.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCustomFields.unity new file mode 100644 index 0000000000000000000000000000000000000000..6d24a0e9c303b7147e86075d95f6a02f225b8899 GIT binary patch literal 43217 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCustomFields.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCustomFields.unity.meta new file mode 100644 index 0000000..34c7b27 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestCustomFields.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: bf8a28d06b5552f418492e2816f17f9a +timeCreated: 1477391785 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestMath.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestMath.unity new file mode 100644 index 0000000000000000000000000000000000000000..a27c54d2f76c24aa46b0168a4fb3c1ff5ce2de4d GIT binary patch literal 26569 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestMath.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestMath.unity.meta new file mode 100644 index 0000000..a7d2539 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestMath.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4a340a876dfa92848aa868ed979eff31 +timeCreated: 1476651353 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPerformance.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPerformance.unity new file mode 100644 index 0000000000000000000000000000000000000000..6ee0b2efaad8691ba646be29a501cdf0b6397c6e GIT binary patch literal 34785 zcmeHw37lL-wfF6;Ls*5d2ogFFSwjc}5riZ?Gg%=aLna9ci=k)c&PdH?@8b#B+a(}T%_@Av!Od$~~4 zxBgZ4)TvXaPMuorO%N>KCkW1ZJ_v#>gJ5|EzriOaOqwvMbN}EU>(;GHjRx>8ZtmZ= zXWQGBFM00X@r%B>Q{|qH;q#9;KfLm@|2TTl!;_Z2GVVt^Am5${DTI-!p!&%msN%78 zh~kcTD){!$pn5aXh5=$e4g4Dfj|1Nfze5n1H-)=r@Z@%gGyhNzp8z_$Al~58G=C~M zb4XCV$I%(?<@f1~@Nl2b$Oumb2ZGLWM~7uJ*5PLp5BKSeittph8hjoPI;`QQ2&qP` z8|82WaMp`;HaT>o+?QOrn*-;Sl*1N+Dejkx){E%O0{!bjhw|TwcvbSJ_J=$fh<}85 zhWJpC^GZCx;%bYLrRn?Ybd z{wM;CQnJtP2sq_%zt8Rz;o7HWBF?_~G5iK+3!PY>-I@7k5s&xTF~o&_ywB1`DxQ)) zek9`T<7outQ}M-!5+9qu+a12Ehf@w^#My^;Bktrt{L2m>=i&XZA74Y9^gm8q_)Gvi+sQy71h$)MWc5|cM{I8DX|I_W}Li7*Xsj&!V z*XV10+TlsNxePe_ly5itk^eN8e;j^|4(-voh%&#}O=o9G|2kkSSM4VAqypN&dl5Je z(QYc8xDTy%llg}P{y3y|Q|Ua7M_)zYI7GYY#-ZRJxZN7e5Er|7HuDb+#sPybD7e^7 z!H31hE&5?fXL!uloIt#RbcP48)#7WC{(e#Z5y7FLJsW}bni%CD8Jioxr*-4p$XLA& zi0~2Ov(9&XP9h!Qb7YK9j^#SOHpKY+L`0_{<`W+j;UgsfQqX6+d=f$HH6rK)R&nJX zOkB&AdR2k5UWX7DIcT{y=lK+19lsl5^*S`dM@qdebo37+9iiV4tJh@apM?-?606sg zh|VUldQFXRl{4mSQm+hf<#S}vkM_FD;f)^7xxqug*^W)b>+sVIxE?>#h>INJ{7jGV zk>ZCv5Bm5&n1P`FhsysAfRsP|DCKjA$mc!B4@BVj85)xhx|ZW-SWG^L6BmAl#pH8D zgr`IfBQaL8+&KtZuKG8lfz!X4D|i|_50U(1U4HswzJIfu!{;UNk2}02f$!mP%+nkl z^>6la_Z+f^4ZP zL?KJ(hL!GOhd6eK(5q`Kb@lZ~Dec`Ma#$RqTB-yL82~hv%VAGjeih~ENX{-)yzDdb z#jGEPXP7H=c^R6D#k?0K^YHg7g z9g`WhctUDPX<2D`Im0%KPtS=S81r+6ts{hbLfwcmzs#^<8EvM%+~J&I`*co4lyt@r zcjc1)c@F0c+wlG%sD2$$(oZ889nN&WgD6LWv4W>TbEu32^xBwzR|Fji6t|fxJw+e4 znd`U&{$s>Rhn}L1D9@nWH4d+NiYkYP9PWFHtQWmM)|YKz^&< zrl0C5ra@E7HT}#a@>}~hM!5ECdY0s;3BlTn{M_aEp{H1npJ{;W@uQyNKz`^c`uU9? zdWycjJ?i+G1>E@Q2S3jOr~DzZNS@^L6~`w%#d>_IruKx=Xxat4G z1aA5dS;gp>{vVydP5&2rct7~Bf>+9a330L8as59gft&sx8{tD_#c>|$OFchM@U+yI z^vw<*58Ri(wb!Q;xV6{P1a9qhLWHZHx4U-90{7di&*5zzPQCh~p9o^cle^&*3uu zz6hN8O9}iXhnExhD-N$jxYB>k(eI1!IQ``b+~}`J;6{ICge!e?OW}W2gvaThl)#Pt zXA`*5KRLpO1>1o3I7j~!!J%7_5ADWwh*LhFL(rM<@YqU(_(x98lR%@%(WxT8%0Eu$ zv_a^c9^u0{V-FT0P*2Vv9nq8FF+KTwgzL=Tb}zp`T=*FgTTwbQ%0DuA9Qx4a=$}RW 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsMode.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsMode.unity.meta new file mode 100644 index 0000000..18b34df --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsMode.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 73541577b3f697c44a11313a118a5cdf +timeCreated: 1477839477 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsTransforms.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestPointsTransforms.unity new file mode 100644 index 0000000000000000000000000000000000000000..59d742437ad26ffbd2103f02202553772dc29eff GIT binary patch literal 37412 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntime.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntime.unity.meta new file mode 100644 index 0000000..3c5c3ba --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntime.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2cc6fac9de9cc1c4198b9a986f2ced0e +timeCreated: 1476651544 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntimeCustomFields.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntimeCustomFields.unity new file mode 100644 index 0000000000000000000000000000000000000000..a25a2c56ba847def21d61ef27d8fa76ae307c543 GIT binary patch literal 57985 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 literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntimeCustomFields.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntimeCustomFields.unity.meta new file mode 100644 index 0000000..9d296bf --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestRuntimeCustomFields.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 069231f22cd3fdd4e80459175f290597 +timeCreated: 1480534258 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestSnapping.unity b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestSnapping.unity new file mode 100644 index 0000000000000000000000000000000000000000..fb50bb7197d2c6f99f90179af68059482e13988d GIT binary patch literal 40593 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 A!~g&Q literal 0 HcmV?d00001 diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestSnapping.unity.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestSnapping.unity.meta new file mode 100644 index 0000000..d124b75 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/BGCurveTestSnapping.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e960b8306460399409434b1280f8c9b0 +timeCreated: 1476935558 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials.meta b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials.meta new file mode 100644 index 0000000..1dc76f6 --- /dev/null +++ b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: dcbc0c43653154e41bc9880c9294d8b8 +folderAsset: yes +timeCreated: 1458645295 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestCheckerBoard.png b/IronToad_UnityProject/Assets/BansheeGz/BGCurve/Examples/Materials/BGTestCheckerBoard.png new file mode 100644 index 0000000000000000000000000000000000000000..1ec06e9203257692fe4d54c1d896ac8889e86577 GIT binary patch literal 1533 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