From b4bc8b044586cfd98f949c771bf61ce408a3a1b6 Mon Sep 17 00:00:00 2001 From: SepComet <202308010230@stu.csust.edu.cn> Date: Wed, 18 Feb 2026 22:53:33 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E8=B0=83=E6=95=B4=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BB=A5=E9=80=82=E5=BA=94=E6=89=93=E5=8C=85?= =?UTF-8?q?=E9=9C=80=E6=B1=82=20-=20=E6=B7=BB=E5=8A=A0=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=8F=B0=E4=BE=BF=E4=BA=8E=E5=9C=A8=E6=B8=B8=E6=88=8F=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E8=BF=87=E7=A8=8B=E4=B8=AD=E8=B0=83=E8=AF=95=E5=90=84?= =?UTF-8?q?=E9=A1=B9=E5=8A=9F=E8=83=BD=20-=20=E6=B7=BB=E5=8A=A0=20LevelRar?= =?UTF-8?q?ity=20=E8=A1=A8=EF=BC=8C=E5=A2=9E=E5=8A=A0=E4=BA=86=E9=9A=8F?= =?UTF-8?q?=E5=85=B3=E5=8D=A1=E6=95=B0=E5=8A=A8=E6=80=81=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=9A=84=E5=95=86=E5=93=81=E9=81=93=E5=85=B7=E5=93=81=E8=B4=A8?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E6=A6=82=E7=8E=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 + .../Inspector/BaseComponentInspector.cs | 2 +- ...buggerComponent.ScreenInformationWindow.cs | 2 +- Assets/GameMain/Configs/ResourceBuilder.xml | 6 +- .../GameMain/Configs/ResourceCollection.xml | 92 +++- Assets/GameMain/DataTables/Enemy.txt | 10 +- Assets/GameMain/DataTables/LevelRarity.txt | 7 + .../GameMain/DataTables/LevelRarity.txt.meta | 7 + Assets/GameMain/DataTables/LevelUpReward.txt | 30 +- Assets/GameMain/DataTables/Weapon.txt | 4 +- Assets/GameMain/Entities/MeleeEnemy.prefab | 2 +- Assets/GameMain/Entities/Player.prefab | 22 +- Assets/GameMain/Entities/RemoteEnemy.prefab | 2 +- .../StressTest.meta => Fonts/Shaders.meta} | 2 +- .../Shaders/TMP_Bitmap-Custom-Atlas.shader | 143 +++++ .../TMP_Bitmap-Custom-Atlas.shader.meta | 9 + .../Fonts/Shaders/TMP_Bitmap-Mobile.shader | 145 +++++ .../Shaders/TMP_Bitmap-Mobile.shader.meta | 9 + .../GameMain/Fonts/Shaders/TMP_Bitmap.shader | 143 +++++ .../Fonts/Shaders/TMP_Bitmap.shader.meta | 9 + .../Fonts/Shaders/TMP_SDF Overlay.shader | 317 +++++++++++ .../Fonts/Shaders/TMP_SDF Overlay.shader.meta | 9 + .../GameMain/Fonts/Shaders/TMP_SDF SSD.shader | 310 +++++++++++ .../Fonts/Shaders/TMP_SDF SSD.shader.meta | 9 + .../Shaders/TMP_SDF-Mobile Masking.shader | 247 +++++++++ .../TMP_SDF-Mobile Masking.shader.meta | 9 + .../Shaders/TMP_SDF-Mobile Overlay.shader | 240 +++++++++ .../TMP_SDF-Mobile Overlay.shader.meta | 9 + .../Fonts/Shaders/TMP_SDF-Mobile SSD.shader | 106 ++++ .../Shaders/TMP_SDF-Mobile SSD.shader.meta | 9 + .../Fonts/Shaders/TMP_SDF-Mobile.shader | 240 +++++++++ .../Fonts/Shaders/TMP_SDF-Mobile.shader.meta | 9 + .../Shaders/TMP_SDF-Surface-Mobile.shader | 138 +++++ .../TMP_SDF-Surface-Mobile.shader.meta | 9 + .../Fonts/Shaders/TMP_SDF-Surface.shader | 158 ++++++ .../Fonts/Shaders/TMP_SDF-Surface.shader.meta | 9 + Assets/GameMain/Fonts/Shaders/TMP_SDF.shader | 317 +++++++++++ .../Fonts/Shaders/TMP_SDF.shader.meta | 9 + .../GameMain/Fonts/Shaders/TMP_Sprite.shader | 116 ++++ .../Fonts/Shaders/TMP_Sprite.shader.meta | 9 + .../Fonts}/coin.asset | 0 .../Fonts}/coin.asset.meta | 0 Assets/GameMain/Materials/Blue.mat | 137 +++++ .../Blue.mat.meta} | 4 +- .../{Green.mat => InstancingGreen.mat} | 2 +- ...reen.mat.meta => InstancingGreen.mat.meta} | 0 Assets/GameMain/Materials/InstancingGrey.mat | 136 +++++ .../InstancingGrey.mat.meta} | 4 +- .../Materials/{Red.mat => InstancingRed.mat} | 2 +- .../{Red.mat.meta => InstancingRed.mat.meta} | 0 .../{Yellow.mat => InstancingYellow.mat} | 2 +- ...low.mat.meta => InstancingYellow.mat.meta} | 0 .../Game.meta} | 2 +- Assets/GameMain/Scenes/Game.unity | 3 +- .../GameMain/Scenes/Game/LightingData.asset | Bin 0 -> 18192 bytes .../Scenes/Game/LightingData.asset.meta | 8 + .../Scenes/Game/ReflectionProbe-0.exr | Bin 0 -> 163864 bytes .../Scenes/Game/ReflectionProbe-0.exr.meta | 127 +++++ Assets/GameMain/Scenes/MainSettings.lighting | 66 --- Assets/GameMain/Scenes/Menu.meta | 8 + .../GameMain/Scenes/Menu/LightingData.asset | Bin 0 -> 18256 bytes .../Scenes/Menu/LightingData.asset.meta | 8 + .../StressTest/GlobalVolumeProfile.asset | 104 ---- .../GameMain/Scripts/Base/GameEntry.Custom.cs | 17 + .../Scripts/Components/AbsorbComponent.cs | 101 ++++ .../AbsorbComponent.cs.meta} | 2 +- .../Scripts/Components/HealthComponent.cs | 8 +- .../Scripts/CustomComponent/DamageText.meta | 8 + .../DamageText/DamageTextComponent.cs | 67 +++ .../DamageText/DamageTextComponent.cs.meta} | 2 +- .../DamageText/DamageTextItem.cs | 80 +++ .../DamageText/DamageTextItem.cs.meta} | 2 +- .../DamageText/DamageTextItemObject.cs | 23 + .../DamageText/DamageTextItemObject.cs.meta} | 2 +- .../Scripts/CustomComponent/DebugPanel.meta | 8 + .../DebugPanel/RuntimeDebugPanelComponent.cs | 349 ++++++++++++ .../RuntimeDebugPanelComponent.cs.meta | 11 + .../EnemyManager/EnemyManagerComponent.cs | 84 ++- .../CustomComponent/HPBar/HPBarComponent.cs | 14 +- Assets/GameMain/Scripts/DataTable/DREnemy.cs | 4 +- .../Scripts/DataTable/DRLevelRarity.cs | 39 ++ .../Scripts/DataTable/DRLevelRarity.cs.meta | 11 + .../Scripts/DataTable/DRLevelUpReward.cs | 5 + .../Definition/DataStruct/StatModifier.cs | 4 +- .../Scripts/Definition/Enum/StatType.cs | 5 +- .../DataTableCodeGenerator.cs | 13 - .../DataTableGenerator/DataTableGenerator.cs | 412 --------------- .../DataTableGeneratorMenu.cs | 36 -- .../DataTableProcessor.BooleanProcessor.cs | 53 -- .../DataTableProcessor.ByteProcessor.cs | 52 -- .../DataTableProcessor.ByteProcessor.cs.meta | 11 - .../DataTableProcessor.CharProcessor.cs | 52 -- .../DataTableProcessor.CharProcessor.cs.meta | 11 - .../DataTableProcessor.Color32Processor.cs | 58 -- ...ataTableProcessor.Color32Processor.cs.meta | 11 - .../DataTableProcessor.ColorProcessor.cs | 58 -- .../DataTableProcessor.ColorProcessor.cs.meta | 11 - .../DataTableProcessor.CommentProcessor.cs | 71 --- ...ataTableProcessor.CommentProcessor.cs.meta | 11 - .../DataTableProcessor.DataProcessor.cs | 46 -- .../DataTableProcessor.DataProcessor.cs.meta | 11 - ...DataTableProcessor.DataProcessorUtility.cs | 61 --- ...ableProcessor.DataProcessorUtility.cs.meta | 11 - .../DataTableProcessor.DateTimeProcessor.cs | 53 -- ...taTableProcessor.DateTimeProcessor.cs.meta | 11 - .../DataTableProcessor.DecimalProcessor.cs | 52 -- ...ataTableProcessor.DecimalProcessor.cs.meta | 11 - .../DataTableProcessor.DoubleProcessor.cs | 52 -- ...DataTableProcessor.DoubleProcessor.cs.meta | 11 - ...DataTableProcessor.GenericDataProcessor.cs | 41 -- ...ableProcessor.GenericDataProcessor.cs.meta | 11 - .../DataTableProcessor.IdProcessor.cs | 70 --- .../DataTableProcessor.IdProcessor.cs.meta | 11 - .../DataTableProcessor.Int16Processor.cs | 53 -- .../DataTableProcessor.Int16Processor.cs.meta | 11 - .../DataTableProcessor.Int32Processor.cs | 53 -- .../DataTableProcessor.Int32Processor.cs.meta | 11 - .../DataTableProcessor.Int64Processor.cs | 53 -- .../DataTableProcessor.Int64Processor.cs.meta | 11 - .../DataTableProcessor.QuaternionProcessor.cs | 58 -- ...TableProcessor.QuaternionProcessor.cs.meta | 11 - .../DataTableProcessor.RectProcessor.cs | 58 -- .../DataTableProcessor.RectProcessor.cs.meta | 11 - .../DataTableProcessor.SByteProcessor.cs | 52 -- .../DataTableProcessor.SByteProcessor.cs.meta | 11 - .../DataTableProcessor.SingleProcessor.cs | 53 -- ...DataTableProcessor.SingleProcessor.cs.meta | 11 - .../DataTableProcessor.StringProcessor.cs | 52 -- ...DataTableProcessor.StringProcessor.cs.meta | 11 - .../DataTableProcessor.UInt16Processor.cs | 53 -- ...DataTableProcessor.UInt16Processor.cs.meta | 11 - .../DataTableProcessor.UInt32Processor.cs | 53 -- ...DataTableProcessor.UInt32Processor.cs.meta | 11 - .../DataTableProcessor.UInt64Processor.cs | 53 -- ...DataTableProcessor.UInt64Processor.cs.meta | 11 - .../DataTableProcessor.Vector2Processor.cs | 56 -- ...ataTableProcessor.Vector2Processor.cs.meta | 11 - .../DataTableProcessor.Vector3Processor.cs | 57 -- ...ataTableProcessor.Vector3Processor.cs.meta | 11 - .../DataTableProcessor.Vector4Processor.cs | 58 -- ...ataTableProcessor.Vector4Processor.cs.meta | 11 - .../DataTableGenerator/DataTableProcessor.cs | 498 ------------------ .../DataTableProcessor.cs.meta | 11 - .../Scripts/Editor/PlayerBuffConsoleWindow.cs | 278 ++++++++++ .../Editor/PlayerBuffConsoleWindow.cs.meta | 11 + .../Entity/EntityData/Enemy/EnemyData.cs | 7 +- .../Scripts/Entity/EntityLogic/CoinEntity.cs | 27 +- .../Scripts/Entity/EntityLogic/ExpEntity.cs | 27 +- .../Scripts/Entity/EntityLogic/Player.cs | 24 +- .../Entity/EntityLogic/Weapon/WeaponBase.cs | 12 +- .../Procedure/Base/ProcedurePreload.cs | 3 +- .../Scripts/Procedure/Game/GameStateBattle.cs | 1 - .../Scripts/Procedure/Game/ProcedureGame.cs | 1 + .../SpriteCache/SpriteCacheComponent.cs | 2 +- .../GameScene/UseCase/LevelUpFormUseCase.cs | 66 ++- .../UI/GameScene/UseCase/ShopFormUseCase.cs | 100 +++- .../GameMain/Scripts/Utility/RarityUtility.cs | 89 ++++ .../Scripts/Utility/RarityUtility.cs.meta | 11 + Assets/{ => GameMain}/Settings.meta | 0 .../Settings/SampleSceneProfile.asset | 0 .../Settings/SampleSceneProfile.asset.meta | 0 .../Settings/URP-Balanced-Renderer.asset | 0 .../Settings/URP-Balanced-Renderer.asset.meta | 0 .../Settings/URP-Balanced.asset | 48 +- .../Settings/URP-Balanced.asset.meta | 0 .../Settings/URP-HighFidelity-Renderer.asset | 0 .../URP-HighFidelity-Renderer.asset.meta | 0 .../Settings/URP-HighFidelity.asset | 48 +- .../Settings/URP-HighFidelity.asset.meta | 0 .../Settings/URP-Performant-Renderer.asset | 0 .../URP-Performant-Renderer.asset.meta | 0 .../Settings/URP-Performant.asset | 54 +- .../Settings/URP-Performant.asset.meta | 0 .../GameMain/UI/UIItems/DamageTextItem.prefab | 166 ++++++ .../UI/UIItems/DamageTextItem.prefab.meta | 7 + ...niversalRenderPipelineGlobalSettings.asset | 0 ...salRenderPipelineGlobalSettings.asset.meta | 0 Assets/Launcher.unity | 277 +++++----- Assets/StreamingAssets/.gitkeep | 0 .../BurstAotSettings_StandaloneWindows.json | 8 +- ProjectSettings/CommonBurstAotSettings.json | 2 +- ProjectSettings/GraphicsSettings.asset | 15 +- ProjectSettings/ProjectSettings.asset | 6 +- TodoList.md | 2 +- 数据表/Enemy.txt | 5 - 数据表/Enemy.xlsx | Bin 10479 -> 10531 bytes 数据表/Entity.txt | 11 - 数据表/Goods.txt | 9 - 数据表/Level.txt | 14 - 数据表/LevelRarity.xlsx | Bin 0 -> 10771 bytes 数据表/LevelUpReward.txt | 8 - 数据表/LevelUpReward.xlsx | Bin 10614 -> 11382 bytes 数据表/Music.txt | 7 - 数据表/Prop.txt | 24 - 数据表/Role.txt | 6 - 数据表/Scene.txt | 8 - 数据表/Sound.txt | 9 - 数据表/UIForm.txt | 14 - 数据表/UISound.txt | 6 - 数据表/Weapon.txt | 6 - 数据表/Weapon.xlsx | Bin 10992 -> 10991 bytes 数据表/convert.py | 10 +- 202 files changed, 5160 insertions(+), 3393 deletions(-) create mode 100644 Assets/GameMain/DataTables/LevelRarity.txt create mode 100644 Assets/GameMain/DataTables/LevelRarity.txt.meta rename Assets/GameMain/{Scenes/StressTest.meta => Fonts/Shaders.meta} (77%) create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Custom-Atlas.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Mobile.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Mobile.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_Bitmap.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_Bitmap.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF Overlay.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF Overlay.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF SSD.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF SSD.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Masking.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Masking.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Overlay.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Overlay.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile SSD.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile SSD.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface-Mobile.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface-Mobile.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_SDF.shader.meta create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_Sprite.shader create mode 100644 Assets/GameMain/Fonts/Shaders/TMP_Sprite.shader.meta rename Assets/{TextMesh Pro/Resources/Sprite Assets => GameMain/Fonts}/coin.asset (100%) rename Assets/{TextMesh Pro/Resources/Sprite Assets => GameMain/Fonts}/coin.asset.meta (100%) create mode 100644 Assets/GameMain/Materials/Blue.mat rename Assets/GameMain/{Scenes/StressTest/GlobalVolumeProfile.asset.meta => Materials/Blue.mat.meta} (64%) rename Assets/GameMain/Materials/{Green.mat => InstancingGreen.mat} (99%) rename Assets/GameMain/Materials/{Green.mat.meta => InstancingGreen.mat.meta} (100%) create mode 100644 Assets/GameMain/Materials/InstancingGrey.mat rename Assets/GameMain/{Scenes/MainSettings.lighting.meta => Materials/InstancingGrey.mat.meta} (60%) rename Assets/GameMain/Materials/{Red.mat => InstancingRed.mat} (99%) rename Assets/GameMain/Materials/{Red.mat.meta => InstancingRed.mat.meta} (100%) rename Assets/GameMain/Materials/{Yellow.mat => InstancingYellow.mat} (99%) rename Assets/GameMain/Materials/{Yellow.mat.meta => InstancingYellow.mat.meta} (100%) rename Assets/GameMain/{Scripts/Editor/DataTableGenerator.meta => Scenes/Game.meta} (77%) create mode 100644 Assets/GameMain/Scenes/Game/LightingData.asset create mode 100644 Assets/GameMain/Scenes/Game/LightingData.asset.meta create mode 100644 Assets/GameMain/Scenes/Game/ReflectionProbe-0.exr create mode 100644 Assets/GameMain/Scenes/Game/ReflectionProbe-0.exr.meta delete mode 100644 Assets/GameMain/Scenes/MainSettings.lighting create mode 100644 Assets/GameMain/Scenes/Menu.meta create mode 100644 Assets/GameMain/Scenes/Menu/LightingData.asset create mode 100644 Assets/GameMain/Scenes/Menu/LightingData.asset.meta delete mode 100644 Assets/GameMain/Scenes/StressTest/GlobalVolumeProfile.asset create mode 100644 Assets/GameMain/Scripts/Components/AbsorbComponent.cs rename Assets/GameMain/Scripts/{Editor/DataTableGenerator/DataTableCodeGenerator.cs.meta => Components/AbsorbComponent.cs.meta} (83%) create mode 100644 Assets/GameMain/Scripts/CustomComponent/DamageText.meta create mode 100644 Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextComponent.cs rename Assets/GameMain/Scripts/{Editor/DataTableGenerator/DataTableGenerator.cs.meta => CustomComponent/DamageText/DamageTextComponent.cs.meta} (83%) create mode 100644 Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItem.cs rename Assets/GameMain/Scripts/{Editor/DataTableGenerator/DataTableGeneratorMenu.cs.meta => CustomComponent/DamageText/DamageTextItem.cs.meta} (83%) create mode 100644 Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItemObject.cs rename Assets/GameMain/Scripts/{Editor/DataTableGenerator/DataTableProcessor.BooleanProcessor.cs.meta => CustomComponent/DamageText/DamageTextItemObject.cs.meta} (83%) create mode 100644 Assets/GameMain/Scripts/CustomComponent/DebugPanel.meta create mode 100644 Assets/GameMain/Scripts/CustomComponent/DebugPanel/RuntimeDebugPanelComponent.cs create mode 100644 Assets/GameMain/Scripts/CustomComponent/DebugPanel/RuntimeDebugPanelComponent.cs.meta create mode 100644 Assets/GameMain/Scripts/DataTable/DRLevelRarity.cs create mode 100644 Assets/GameMain/Scripts/DataTable/DRLevelRarity.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableCodeGenerator.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGenerator.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGeneratorMenu.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.BooleanProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ByteProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ByteProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CharProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CharProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Color32Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Color32Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ColorProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ColorProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CommentProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CommentProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessorUtility.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessorUtility.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DateTimeProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DateTimeProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DecimalProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DecimalProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DoubleProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DoubleProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.GenericDataProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.GenericDataProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.IdProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.IdProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int16Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int16Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int32Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int32Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int64Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int64Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.QuaternionProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.QuaternionProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.RectProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.RectProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SByteProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SByteProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SingleProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SingleProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.StringProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.StringProcessor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt16Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt16Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt32Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt32Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt64Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt64Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector2Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector2Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector3Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector3Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector4Processor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector4Processor.cs.meta delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.cs delete mode 100644 Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.cs.meta create mode 100644 Assets/GameMain/Scripts/Editor/PlayerBuffConsoleWindow.cs create mode 100644 Assets/GameMain/Scripts/Editor/PlayerBuffConsoleWindow.cs.meta create mode 100644 Assets/GameMain/Scripts/Utility/RarityUtility.cs create mode 100644 Assets/GameMain/Scripts/Utility/RarityUtility.cs.meta rename Assets/{ => GameMain}/Settings.meta (100%) rename Assets/{ => GameMain}/Settings/SampleSceneProfile.asset (100%) rename Assets/{ => GameMain}/Settings/SampleSceneProfile.asset.meta (100%) rename Assets/{ => GameMain}/Settings/URP-Balanced-Renderer.asset (100%) rename Assets/{ => GameMain}/Settings/URP-Balanced-Renderer.asset.meta (100%) rename Assets/{ => GameMain}/Settings/URP-Balanced.asset (76%) rename Assets/{ => GameMain}/Settings/URP-Balanced.asset.meta (100%) rename Assets/{ => GameMain}/Settings/URP-HighFidelity-Renderer.asset (100%) rename Assets/{ => GameMain}/Settings/URP-HighFidelity-Renderer.asset.meta (100%) rename Assets/{ => GameMain}/Settings/URP-HighFidelity.asset (76%) rename Assets/{ => GameMain}/Settings/URP-HighFidelity.asset.meta (100%) rename Assets/{ => GameMain}/Settings/URP-Performant-Renderer.asset (100%) rename Assets/{ => GameMain}/Settings/URP-Performant-Renderer.asset.meta (100%) rename Assets/{ => GameMain}/Settings/URP-Performant.asset (74%) rename Assets/{ => GameMain}/Settings/URP-Performant.asset.meta (100%) create mode 100644 Assets/GameMain/UI/UIItems/DamageTextItem.prefab create mode 100644 Assets/GameMain/UI/UIItems/DamageTextItem.prefab.meta rename Assets/{ => GameMain}/UniversalRenderPipelineGlobalSettings.asset (100%) rename Assets/{ => GameMain}/UniversalRenderPipelineGlobalSettings.asset.meta (100%) delete mode 100644 Assets/StreamingAssets/.gitkeep delete mode 100644 数据表/Enemy.txt delete mode 100644 数据表/Entity.txt delete mode 100644 数据表/Goods.txt delete mode 100644 数据表/Level.txt create mode 100644 数据表/LevelRarity.xlsx delete mode 100644 数据表/LevelUpReward.txt delete mode 100644 数据表/Music.txt delete mode 100644 数据表/Prop.txt delete mode 100644 数据表/Role.txt delete mode 100644 数据表/Scene.txt delete mode 100644 数据表/Sound.txt delete mode 100644 数据表/UIForm.txt delete mode 100644 数据表/UISound.txt delete mode 100644 数据表/Weapon.txt diff --git a/.gitignore b/.gitignore index f1f5e64..036465e 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,6 @@ crashlytics-build.properties /UI参考 /AGENTS.md +/bin + +~$*.xlsx diff --git a/Assets/GameFramework/Scripts/Editor/Inspector/BaseComponentInspector.cs b/Assets/GameFramework/Scripts/Editor/Inspector/BaseComponentInspector.cs index 65d3792..328d8be 100644 --- a/Assets/GameFramework/Scripts/Editor/Inspector/BaseComponentInspector.cs +++ b/Assets/GameFramework/Scripts/Editor/Inspector/BaseComponentInspector.cs @@ -104,7 +104,7 @@ namespace UnityGameFramework.Editor } EditorGUI.EndDisabledGroup(); - int frameRate = EditorGUILayout.IntSlider("Frame Rate", m_FrameRate.intValue, 1, 120); + int frameRate = EditorGUILayout.IntSlider("Frame Rate", m_FrameRate.intValue, 1, 240); if (frameRate != m_FrameRate.intValue) { if (EditorApplication.isPlaying) diff --git a/Assets/GameFramework/Scripts/Runtime/Debugger/DebuggerComponent.ScreenInformationWindow.cs b/Assets/GameFramework/Scripts/Runtime/Debugger/DebuggerComponent.ScreenInformationWindow.cs index 5c516c1..5f8b614 100644 --- a/Assets/GameFramework/Scripts/Runtime/Debugger/DebuggerComponent.ScreenInformationWindow.cs +++ b/Assets/GameFramework/Scripts/Runtime/Debugger/DebuggerComponent.ScreenInformationWindow.cs @@ -66,7 +66,7 @@ namespace UnityGameFramework.Runtime private string GetResolutionString(Resolution resolution) { - return Utility.Text.Format("{0} x {1} @ {2}Hz", resolution.width, resolution.height, resolution.refreshRate); + return Utility.Text.Format("{0} x {1} @ {2}Hz", resolution.width, resolution.height, resolution.refreshRateRatio); } private string GetCutoutsString(Rect[] cutouts) diff --git a/Assets/GameMain/Configs/ResourceBuilder.xml b/Assets/GameMain/Configs/ResourceBuilder.xml index 8e0b951..2a0c5c7 100644 --- a/Assets/GameMain/Configs/ResourceBuilder.xml +++ b/Assets/GameMain/Configs/ResourceBuilder.xml @@ -2,14 +2,14 @@ - 0 - 1 + 1 + 33 1 UnityGameFramework.Runtime.DefaultCompressionHelper True False StarForce.Editor.StarForceBuildEventHandler - + D:/Learn/GameLearn/UnityProjects/VampireLike/bin/AssetBundles True True True diff --git a/Assets/GameMain/Configs/ResourceCollection.xml b/Assets/GameMain/Configs/ResourceCollection.xml index b5987c3..5ad3660 100644 --- a/Assets/GameMain/Configs/ResourceCollection.xml +++ b/Assets/GameMain/Configs/ResourceCollection.xml @@ -16,43 +16,56 @@ + + + + + - - + + - - + + + + + + - + + + + + @@ -62,97 +75,120 @@ + + + - + - + + + - + + + + + + - + - + + + + - - - - - + + + - + - - - + - + + + + + - - + - - + + + + + + + - + + + + + + - + + + + - - \ No newline at end of file diff --git a/Assets/GameMain/DataTables/Enemy.txt b/Assets/GameMain/DataTables/Enemy.txt index 7ca14d2..2bcad84 100644 --- a/Assets/GameMain/DataTables/Enemy.txt +++ b/Assets/GameMain/DataTables/Enemy.txt @@ -1,5 +1,5 @@ -# 敌人基础属性表 -# Id MaxHealth Speed CoinDrop ExpDrop DropPercent -# int int float int int float -# 实体编号 策划备注 最大生命 移动速度 金币掉落 经验掉落 掉落概率 - 101 近战敌人 20 3 2 1 0.3 +# 敌人基础属性表 +# Id MaxHealth HpAddPerLevel Speed CoinDrop ExpDrop DropPercent +# int int int float int int float +# 实体编号 策划备注 最大生命 每关卡增加生命 移动速度 金币掉落 经验掉落 掉落概率 + 101 近战敌人 50 50 3 5 1 0.3 diff --git a/Assets/GameMain/DataTables/LevelRarity.txt b/Assets/GameMain/DataTables/LevelRarity.txt new file mode 100644 index 0000000..6cc8c8f --- /dev/null +++ b/Assets/GameMain/DataTables/LevelRarity.txt @@ -0,0 +1,7 @@ +# 关卡道具品质掉落概率表 +# Id LevelMin LevelMax WhiteWeight GreenWeight BlueWeight PurpleWeight RedWeight SumWeight +# int float float float float float float float float +# 概率编号 策划备注 关卡左区间 关卡右区间 白色掉落率 绿色掉落率 蓝色掉落率 紫色掉落率 红色掉落率 总掉落率(不需要读取) + 1 1 3 75 20 4 1 0 100 + 2 4 5 30 50 15 4 1 100 + 3 6 10 10 20 40 20 10 100 diff --git a/Assets/GameMain/DataTables/LevelRarity.txt.meta b/Assets/GameMain/DataTables/LevelRarity.txt.meta new file mode 100644 index 0000000..422c335 --- /dev/null +++ b/Assets/GameMain/DataTables/LevelRarity.txt.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0080b46050fc460cb6d6c7fc8d4e8c27 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/DataTables/LevelUpReward.txt b/Assets/GameMain/DataTables/LevelUpReward.txt index b2eb50e..a746f00 100644 --- a/Assets/GameMain/DataTables/LevelUpReward.txt +++ b/Assets/GameMain/DataTables/LevelUpReward.txt @@ -1,8 +1,22 @@ -# 道具表 -# Id Title IconAssetName Modifiers -# int string string StatModifier[] -# 奖励编号 策划备注 奖励名 图标资源名 道具属性 - 101 测试道具 肌肉 Almighty_Icon [{"StatType":"Attack","Value":0.05,"IsPercent":true}] - 102 牙齿 Almighty_Icon [{"StatType":"Attack","Value":0.05,"IsPercent":true}] - 103 脑 Almighty_Icon [{"StatType":"Attack","Value":0.05,"IsPercent":true}] - 104 鼻子 Almighty_Icon [{"StatType":"Attack","Value":0.05,"IsPercent":true}] +# 道具表 +# Id Title IconAssetName Rarity Modifiers +# int string string RarityType StatModifier[] +# 奖励编号 策划备注 奖励名 图标资源名 道具品质 道具属性 + 101 测试道具 肌肉 Almighty_Icon White [{"StatType":"Attack","Value":0.05,"IsPercent":true}] + 102 牙齿 Almighty_Icon White [{"StatType":"Attack","Value":0.05,"IsPercent":true}] + 103 脑 Almighty_Icon White [{"StatType":"Critical","Value":0.05,"IsPercent":true}] + 104 鼻子 Almighty_Icon White [{"StatType":"AbsorbRange","Value":0.05,"IsPercent":true}] + 105 腿 Almighty_Icon White [{"StatType":"MovementSpeed","Value":0.05,"IsPercent":true}] + 106 眼睛 Almighty_Icon White [{"StatType":"MaxHealth","Value":0.05,"IsPercent":true}] + 107 肌肉 Almighty_Icon Green [{"StatType":"Attack","Value":0.15,"IsPercent":true}] + 108 牙齿 Almighty_Icon Green [{"StatType":"Attack","Value":0.15,"IsPercent":true}] + 109 脑 Almighty_Icon Green [{"StatType":"Critical","Value":0.15,"IsPercent":true}] + 110 鼻子 Almighty_Icon Green [{"StatType":"AbsorbRange","Value":0.15,"IsPercent":true}] + 111 腿 Almighty_Icon Green [{"StatType":"MovementSpeed","Value":0.15,"IsPercent":true}] + 112 眼睛 Almighty_Icon Green [{"StatType":"MaxHealth","Value":0.15,"IsPercent":true}] + 113 肌肉 Almighty_Icon Blue [{"StatType":"Attack","Value":0.3,"IsPercent":true}] + 114 牙齿 Almighty_Icon Blue [{"StatType":"Attack","Value":0.3,"IsPercent":true}] + 115 脑 Almighty_Icon Blue [{"StatType":"Critical","Value":0.3,"IsPercent":true}] + 116 鼻子 Almighty_Icon Blue [{"StatType":"AbsorbRange","Value":0.3,"IsPercent":true}] + 117 腿 Almighty_Icon Blue [{"StatType":"MovementSpeed","Value":0.3,"IsPercent":true}] + 118 眼睛 Almighty_Icon Blue [{"StatType":"MaxHealth","Value":0.3,"IsPercent":true}] diff --git a/Assets/GameMain/DataTables/Weapon.txt b/Assets/GameMain/DataTables/Weapon.txt index 8e6d608..9e072dd 100644 --- a/Assets/GameMain/DataTables/Weapon.txt +++ b/Assets/GameMain/DataTables/Weapon.txt @@ -2,5 +2,5 @@ # Id Title IconAssetName Rarity Price PriceRandomPercent Attack Cooldown AttackRange AttackSoundId Pramas Modifiers # int string string RarityType int float int float float int string[] StatModifier[] # 武器编号 策划备注 武器名 图标资源名 道具品质 武器价格 价格浮动 伤害 冷却 范围 攻击音效编号 额外参数 额外属性 - 201 玩家武器 小刀 Almighty_Icon White 120 0.05 100 1.5 3 10000 [] [] - 202 手枪 Almighty_Icon White 130 0.05 120 1 10 10000 [] [] + 201 玩家武器 小刀 Almighty_Icon White 120 0.05 100 1.5 5 10000 [] [] + 202 手枪 Almighty_Icon White 130 0.05 120 1 15 10000 [] [] diff --git a/Assets/GameMain/Entities/MeleeEnemy.prefab b/Assets/GameMain/Entities/MeleeEnemy.prefab index d1f7662..4c3a5ed 100644 --- a/Assets/GameMain/Entities/MeleeEnemy.prefab +++ b/Assets/GameMain/Entities/MeleeEnemy.prefab @@ -65,7 +65,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 28c42f88cfe56e84e95c0d7545db8c1b, type: 2} + - {fileID: 2100000, guid: 83e5fce2d1e5b3e4ab6551de03cc9c22, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 diff --git a/Assets/GameMain/Entities/Player.prefab b/Assets/GameMain/Entities/Player.prefab index aeeb24a..a260094 100644 --- a/Assets/GameMain/Entities/Player.prefab +++ b/Assets/GameMain/Entities/Player.prefab @@ -369,6 +369,7 @@ GameObject: - component: {fileID: 582203051508165858} - component: {fileID: 4988822728923805024} - component: {fileID: 4321355627424240428} + - component: {fileID: 7894423710682551789} m_Layer: 7 m_Name: Player m_TagString: Player @@ -421,7 +422,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 31321ba15b8f8eb4c954353edc038b1d, type: 2} + - {fileID: 2100000, guid: c4f37184fcb9306428d7d002f7dca96d, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 @@ -566,3 +567,22 @@ MonoBehaviour: - {fileID: 4149661712638700245} - {fileID: 5429551983429523606} - {fileID: 2395797268595685132} +--- !u!114 &7894423710682551789 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8198962528757305497} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 46f46350fed64d8389ebb4ae72b65796, type: 3} + m_Name: + m_EditorClassIdentifier: + _absorbRangeBase: 3 + _absorbSpeed: 8 + _collectDistance: 0.35 + _maxDetectCount: 64 + _detectLayerMask: + serializedVersion: 2 + m_Bits: 8192 diff --git a/Assets/GameMain/Entities/RemoteEnemy.prefab b/Assets/GameMain/Entities/RemoteEnemy.prefab index 7bdd32a..06f7b4b 100644 --- a/Assets/GameMain/Entities/RemoteEnemy.prefab +++ b/Assets/GameMain/Entities/RemoteEnemy.prefab @@ -64,7 +64,7 @@ MeshRenderer: m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: - - {fileID: 2100000, guid: 2257393dd6ed51a49a6c3fd178382b59, type: 2} + - {fileID: 2100000, guid: 429ed03405bf8854eab46552b7470ac0, type: 2} m_StaticBatchInfo: firstSubMesh: 0 subMeshCount: 0 diff --git a/Assets/GameMain/Scenes/StressTest.meta b/Assets/GameMain/Fonts/Shaders.meta similarity index 77% rename from Assets/GameMain/Scenes/StressTest.meta rename to Assets/GameMain/Fonts/Shaders.meta index a8221dc..e6d5003 100644 --- a/Assets/GameMain/Scenes/StressTest.meta +++ b/Assets/GameMain/Fonts/Shaders.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: d278c30ab68ad1e4b8c981c2ffe9473e +guid: 9dc75a5d11c10e94c9d5ed1176388036 folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Custom-Atlas.shader b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Custom-Atlas.shader new file mode 100644 index 0000000..bab2b2c --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Custom-Atlas.shader @@ -0,0 +1,143 @@ +Shader "TextMeshPro/Bitmap Custom Atlas" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + [HDR]_FaceColor ("Text Color", Color) = (1,1,1,1) + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _Padding ("Padding", float) = 0 + + _StencilComp("Stencil Comparison", Float) = 8 + _Stencil("Stencil ID", Float) = 0 + _StencilOp("Stencil Operation", Float) = 0 + _StencilWriteMask("Stencil Write Mask", Float) = 255 + _StencilReadMask("Stencil Read Mask", Float) = 255 + + _CullMode("Cull Mode", Float) = 0 + _ColorMask("Color Mask", Float) = 15 +} + +SubShader{ + + Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull [_CullMode] + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + + struct appdata_t { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + float4 mask : TEXCOORD2; + }; + + uniform sampler2D _MainTex; + uniform sampler2D _FaceTex; + uniform float4 _FaceTex_ST; + uniform fixed4 _FaceColor; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + + float2 UnpackUV(float uv) + { + float2 output; + output.x = floor(uv / 4096); + output.y = uv - 4096 * output.x; + + return output * 0.001953125; + } + + v2f vert (appdata_t v) + { + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + + float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert)); + + fixed4 faceColor = v.color; + faceColor *= _FaceColor; + + v2f OUT; + OUT.vertex = vPosition; + OUT.color = faceColor; + OUT.texcoord0 = v.texcoord0; + OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex); + float2 pixelSize = vPosition.w; + pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : SV_Target + { + fixed4 color = tex2D(_MainTex, IN.texcoord0) * tex2D(_FaceTex, IN.texcoord1) * IN.color; + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + + CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta new file mode 100644 index 0000000..a0e6fef --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Custom-Atlas.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b6539f2b0fa989d4fb7e057799b9260d +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Mobile.shader b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Mobile.shader new file mode 100644 index 0000000..006a271 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Mobile.shader @@ -0,0 +1,145 @@ +Shader "TextMeshPro/Mobile/Bitmap" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + [HDR]_Color ("Text Color", Color) = (1,1,1,1) + _DiffusePower ("Diffuse Power", Range(1.0,4.0)) = 1.0 + + _VertexOffsetX("Vertex OffsetX", float) = 0 + _VertexOffsetY("Vertex OffsetY", float) = 0 + _MaskSoftnessX("Mask SoftnessX", float) = 0 + _MaskSoftnessY("Mask SoftnessY", float) = 0 + + _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + _StencilComp("Stencil Comparison", Float) = 8 + _Stencil("Stencil ID", Float) = 0 + _StencilOp("Stencil Operation", Float) = 0 + _StencilWriteMask("Stencil Write Mask", Float) = 255 + _StencilReadMask("Stencil Read Mask", Float) = 255 + + _CullMode("Cull Mode", Float) = 0 + _ColorMask("Color Mask", Float) = 15 +} + +SubShader { + + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull [_CullMode] + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma fragmentoption ARB_precision_hint_fastest + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + + struct appdata_t { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float4 mask : TEXCOORD2; + }; + + sampler2D _MainTex; + fixed4 _Color; + float _DiffusePower; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + + v2f vert (appdata_t v) + { + v2f OUT; + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + + OUT.vertex = UnityPixelSnap(UnityObjectToClipPos(vert)); + OUT.color = v.color; + OUT.color *= _Color; + OUT.color.rgb *= _DiffusePower; + OUT.texcoord0 = v.texcoord0; + + float2 pixelSize = OUT.vertex.w; + //pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : COLOR + { + fixed4 color = fixed4(IN.color.rgb, IN.color.a * tex2D(_MainTex, IN.texcoord0).a); + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + +SubShader { + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + Lighting Off Cull Off ZTest Always ZWrite Off Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + BindChannels { + Bind "Color", color + Bind "Vertex", vertex + Bind "TexCoord", texcoord0 + } + Pass { + SetTexture [_MainTex] { + constantColor [_Color] combine constant * primary, constant * texture + } + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Mobile.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Mobile.shader.meta new file mode 100644 index 0000000..51ef45d --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap-Mobile.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f06c2627a191cc1468383483fbafca04 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_Bitmap.shader b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap.shader new file mode 100644 index 0000000..8ce4937 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap.shader @@ -0,0 +1,143 @@ +Shader "TextMeshPro/Bitmap" { + +Properties { + _MainTex ("Font Atlas", 2D) = "white" {} + _FaceTex ("Font Texture", 2D) = "white" {} + [HDR]_FaceColor ("Text Color", Color) = (1,1,1,1) + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _ClipRect("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + _StencilComp("Stencil Comparison", Float) = 8 + _Stencil("Stencil ID", Float) = 0 + _StencilOp("Stencil Operation", Float) = 0 + _StencilWriteMask("Stencil Write Mask", Float) = 255 + _StencilReadMask("Stencil Read Mask", Float) = 255 + + _CullMode("Cull Mode", Float) = 0 + _ColorMask("Color Mask", Float) = 15 +} + +SubShader{ + + Tags { "Queue" = "Transparent" "IgnoreProjector" = "True" "RenderType" = "Transparent" } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + + Lighting Off + Cull [_CullMode] + ZTest [unity_GUIZTestMode] + ZWrite Off + Fog { Mode Off } + Blend SrcAlpha OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + + struct appdata_t { + float4 vertex : POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct v2f { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + float4 mask : TEXCOORD2; + }; + + uniform sampler2D _MainTex; + uniform sampler2D _FaceTex; + uniform float4 _FaceTex_ST; + uniform fixed4 _FaceColor; + + uniform float _VertexOffsetX; + uniform float _VertexOffsetY; + uniform float4 _ClipRect; + uniform float _MaskSoftnessX; + uniform float _MaskSoftnessY; + + float2 UnpackUV(float uv) + { + float2 output; + output.x = floor(uv / 4096); + output.y = uv - 4096 * output.x; + + return output * 0.001953125; + } + + v2f vert (appdata_t v) + { + float4 vert = v.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + vert.xy += (vert.w * 0.5) / _ScreenParams.xy; + + float4 vPosition = UnityPixelSnap(UnityObjectToClipPos(vert)); + + fixed4 faceColor = v.color; + faceColor *= _FaceColor; + + v2f OUT; + OUT.vertex = vPosition; + OUT.color = faceColor; + OUT.texcoord0 = v.texcoord0; + OUT.texcoord1 = TRANSFORM_TEX(UnpackUV(v.texcoord1), _FaceTex); + float2 pixelSize = vPosition.w; + pixelSize /= abs(float2(_ScreenParams.x * UNITY_MATRIX_P[0][0], _ScreenParams.y * UNITY_MATRIX_P[1][1])); + + // Clamp _ClipRect to 16bit. + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + OUT.mask = float4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + + return OUT; + } + + fixed4 frag (v2f IN) : SV_Target + { + fixed4 color = tex2D(_MainTex, IN.texcoord0); + color = fixed4 (tex2D(_FaceTex, IN.texcoord1).rgb * IN.color.rgb, IN.color.a * color.a); + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(IN.mask.xy)) * IN.mask.zw); + color *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(color.a - 0.001); + #endif + + return color; + } + ENDCG + } +} + + CustomEditor "TMPro.EditorUtilities.TMP_BitmapShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_Bitmap.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap.shader.meta new file mode 100644 index 0000000..f1e8c9b --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_Bitmap.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6a58ea03d3bd54e428d969b85afa5680 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF Overlay.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF Overlay.shader new file mode 100644 index 0000000..c50c593 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF Overlay.shader @@ -0,0 +1,317 @@ +Shader "TextMeshPro/Distance Field Overlay" { + +Properties { + _FaceTex ("Face Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 + [HDR]_SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularPower ("Specular", Range(0,4)) = 2.0 + _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 + _Diffuse ("Diffuse", Range(0,1)) = 0.5 + _Ambient ("Ambient", Range(1,0)) = 0.5 + + _BumpMap ("Normal map", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0 + _BumpFace ("Bump Face", Range(0,1)) = 0 + + _ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1) + _ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + + + [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + Tags + { + "Queue"="Overlay" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest Always + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma target 3.0 + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ BEVEL_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + #pragma shader_feature __ GLOW_ON + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 position : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 position : SV_POSITION; + fixed4 color : COLOR; + float2 atlas : TEXCOORD0; // Atlas + float4 param : TEXCOORD1; // alphaClip, scale, bias, weight + float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw) + float3 viewDir : TEXCOORD3; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 texcoord2 : TEXCOORD4; // u,v, scale, bias + fixed4 underlayColor : COLOR1; + #endif + float4 textures : TEXCOORD5; + }; + + // Used by Unity internally to handle Texture Tiling and Offset. + float4 _FaceTex_ST; + float4 _OutlineTex_ST; + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input,output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float bias =(.5 - weight) + (.5 / scale); + + float alphaClip = (1.0 - _OutlineWidth*_ScaleRatioA - _OutlineSoftness*_ScaleRatioA); + + #if GLOW_ON + alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); + #endif + + alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float bScale = scale; + bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale); + float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 bOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Support for texture tiling and offset + float2 textureUV = UnpackUV(input.texcoord1.x); + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + + output.position = vPosition; + output.color = input.color; + output.atlas = input.texcoord0; + output.param = float4(alphaClip, scale, bias, weight); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias); + output.underlayColor = underlayColor; + #endif + output.textures = float4(faceUV, outlineUV); + + return output; + } + + + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + float c = tex2D(_MainTex, input.atlas).a; + + #ifndef UNDERLAY_ON + clip(c - input.param.x); + #endif + + float scale = input.param.y; + float bias = input.param.z; + float weight = input.param.w; + float sd = (bias - c) * scale; + + float outline = (_OutlineWidth * _ScaleRatioA) * scale; + float softness = (_OutlineSoftness * _ScaleRatioA) * scale; + + half4 faceColor = _FaceColor; + half4 outlineColor = _OutlineColor; + + faceColor.rgb *= input.color.rgb; + + faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y); + outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y); + + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + + #if BEVEL_ON + float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); + float3 n = GetSurfaceNormal(input.atlas, weight, dxy); + + float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + n = normalize(n- bump); + + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0)); + + float3 col = GetSpecular(n, light); + faceColor.rgb += col*faceColor.a; + faceColor.rgb *= 1-(dot(n, light)*_Diffuse); + faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z); + + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + #endif + + #if UNDERLAY_ON + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); + #endif + + #if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + faceColor.rgb += glowColor.rgb * glowColor.a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + faceColor *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor * input.color.a; + } + + ENDCG + } +} + +Fallback "TextMeshPro/Mobile/Distance Field" +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF Overlay.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF Overlay.shader.meta new file mode 100644 index 0000000..4a454e0 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF Overlay.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1be7b5c5ed8a01f49b26f30ee2146240 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF SSD.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF SSD.shader new file mode 100644 index 0000000..ed48574 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF SSD.shader @@ -0,0 +1,310 @@ +Shader "TextMeshPro/Distance Field SSD" { + +Properties { + _FaceTex ("Face Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 + [HDR]_SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularPower ("Specular", Range(0,4)) = 2.0 + _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 + _Diffuse ("Diffuse", Range(0,1)) = 0.5 + _Ambient ("Ambient", Range(1,0)) = 0.5 + + _BumpMap ("Normal map", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0 + _BumpFace ("Bump Face", Range(0,1)) = 0 + + _ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1) + _ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + + + [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue" = "Transparent" + "IgnoreProjector" = "True" + "RenderType" = "Transparent" + } + + Stencil + { + Ref[_Stencil] + Comp[_StencilComp] + Pass[_StencilOp] + ReadMask[_StencilReadMask] + WriteMask[_StencilWriteMask] + } + + Cull[_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest[unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask[_ColorMask] + + Pass { + CGPROGRAM + #pragma target 3.0 + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ BEVEL_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + #pragma shader_feature __ GLOW_ON + #pragma shader_feature __ FORCE_LINEAR + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 position : POSITION; + float3 normal : NORMAL; + float4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 position : SV_POSITION; + float4 color : COLOR; + float2 atlas : TEXCOORD0; + float weight : TEXCOORD1; + float2 mask : TEXCOORD2; // Position in object space(xy) + float3 viewDir : TEXCOORD3; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float2 texcoord2 : TEXCOORD4; + float4 underlayColor : COLOR1; + #endif + float4 textures : TEXCOORD5; + }; + + // Used by Unity internally to handle Texture Tiling and Offset. + float4 _FaceTex_ST; + float4 _OutlineTex_ST; + + float4 SRGBToLinear(float4 rgba) { + return float4(lerp(rgba.rgb / 12.92f, pow((rgba.rgb + 0.055f) / 1.055f, 2.4f), step(0.04045f, rgba.rgb)), rgba.a); + } + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input,output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + float4 vPosition = UnityObjectToClipPos(vert); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 bOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + + // Support for texture tiling and offset + float2 textureUV = UnpackUV(input.texcoord1.x); + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + float4 color = input.color; + #if (FORCE_LINEAR && !UNITY_COLORSPACE_GAMMA) + color = SRGBToLinear(input.color); + #endif + + output.position = vPosition; + output.color = color; + output.atlas = input.texcoord0; + output.weight = weight; + output.mask = half2(vert.xy * 2 - clampedRect.xy - clampedRect.zw); + output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord2 = input.texcoord0 + bOffset; + output.underlayColor = underlayColor; + #endif + output.textures = float4(faceUV, outlineUV); + + return output; + } + + + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + float c = tex2D(_MainTex, input.atlas).a; + + float2 pixelSize = float2(ddx(input.atlas.y), ddy(input.atlas.y)); + pixelSize *= _TextureWidth * .75; + float scale = rsqrt(dot(pixelSize, pixelSize)) * _GradientScale * (_Sharpness + 1); + + float weight = input.weight; + float bias = (.5 - weight) + (.5 / scale); + float sd = (bias - c) * scale; + + float outline = (_OutlineWidth * _ScaleRatioA) * scale; + float softness = (_OutlineSoftness * _ScaleRatioA) * scale; + + half4 faceColor = _FaceColor; + half4 outlineColor = _OutlineColor; + + faceColor.rgb *= input.color.rgb; + + faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y); + outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y); + + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + + #if BEVEL_ON + float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); + float3 n = GetSurfaceNormal(input.atlas, weight, dxy); + + float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + n = normalize(n - bump); + + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0)); + + float3 col = GetSpecular(n, light); + faceColor.rgb += col * faceColor.a; + faceColor.rgb *= 1 - (dot(n, light) * _Diffuse); + faceColor.rgb *= lerp(_Ambient, 1, n.z * n.z); + + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + #endif + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float bScale = scale; + bScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * bScale); + float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); + #endif + + #if UNDERLAY_ON + float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale; + faceColor += input.underlayColor * saturate(d - bBias) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float d = tex2D(_MainTex, input.texcoord2.xy).a * bScale; + faceColor += input.underlayColor * (1 - saturate(d - bBias)) * saturate(1 - sd) * (1 - faceColor.a); + #endif + + #if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + faceColor.rgb += glowColor.rgb * glowColor.a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + float2 maskZW = 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + (1 / scale)); + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * maskZW); + faceColor *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor * input.color.a; + } + + ENDCG + } +} + +Fallback "TextMeshPro/Mobile/Distance Field" +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF SSD.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF SSD.shader.meta new file mode 100644 index 0000000..97facd0 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF SSD.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f9ef7b3e3b869a348bce0a7852d93e79 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Masking.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Masking.shader new file mode 100644 index 0000000..7019aaf --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Masking.shader @@ -0,0 +1,247 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field - Masking" { + +Properties { + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + _MaskTex ("Mask Texture", 2D) = "white" {} + _MaskInverse ("Inverse", float) = 0 + _MaskEdgeColor ("Edge Color", Color) = (1,1,1,1) + _MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01 + _MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + float _MaskWipeControl; + float _MaskEdgeSoftness; + fixed4 _MaskEdgeColor; + bool _MaskInverse; + + pixel_t VertShader(vertex_t input) + { + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Structure for pixel shader + pixel_t output = { + vPosition, + faceColor, + outlineColor, + float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y), + half4(scale, bias - outline, bias + outline, bias), + half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)), + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4(input.texcoord0 + layerOffset, input.color.a, 0), + half2(layerScale, layerBias), + #endif + }; + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + //#if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + //#endif + + float a = abs(_MaskInverse - tex2D(_MaskTex, input.texcoord0.zw).a); + float t = a + (1 - _MaskWipeControl) * _MaskEdgeSoftness - _MaskWipeControl; + a = saturate(t / _MaskEdgeSoftness); + c.rgb = lerp(_MaskEdgeColor.rgb*c.a, c.rgb, a); + c *= a; + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Masking.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Masking.shader.meta new file mode 100644 index 0000000..c47e690 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Masking.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 25229adaac96caa42a737b60465f3229 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Overlay.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Overlay.shader new file mode 100644 index 0000000..ce82bed --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Overlay.shader @@ -0,0 +1,240 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field Overlay" { + +Properties { + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Overlay" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest Always + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Populate structure for pixel shader + output.vertex = vPosition; + output.faceColor = faceColor; + output.outlineColor = outlineColor; + output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); + output.param = half4(scale, bias - outline, bias + outline, bias); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0); + output.underlayParam = half2(layerScale, layerBias); + #endif + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Overlay.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Overlay.shader.meta new file mode 100644 index 0000000..0f0213f --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile Overlay.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7f1361f834115be4ea4ec2387c67334e +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile SSD.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile SSD.shader new file mode 100644 index 0000000..df4d5b0 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile SSD.shader @@ -0,0 +1,106 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field SSD" { + +Properties { + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + _MaskTex ("Mask Texture", 2D) = "white" {} + _MaskInverse ("Inverse", float) = 0 + _MaskEdgeColor ("Edge Color", Color) = (1,1,1,1) + _MaskEdgeSoftness ("Edge Softness", Range(0, 1)) = 0.01 + _MaskWipeControl ("Wipe Position", Range(0, 1)) = 0.5 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + #include "TMPro_Mobile.cginc" + + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile SSD.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile SSD.shader.meta new file mode 100644 index 0000000..b2b0403 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile SSD.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1aeec1235e121cb46ba8ea88d1025009 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile.shader new file mode 100644 index 0000000..d3f5866 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile.shader @@ -0,0 +1,240 @@ +// Simplified SDF shader: +// - No Shading Option (bevel / bump / env map) +// - No Glow Option +// - Softness is applied on both side of the outline + +Shader "TextMeshPro/Mobile/Distance Field" { + +Properties { + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineWidth ("Outline Thickness", Range(0,1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0,.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = .5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5 + _ScaleX ("Scale X", float) = 1 + _ScaleY ("Scale Y", float) = 1 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ OUTLINE_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 vertex : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 vertex : SV_POSITION; + fixed4 faceColor : COLOR; + fixed4 outlineColor : COLOR1; + float4 texcoord0 : TEXCOORD0; // Texture UV, Mask UV + half4 param : TEXCOORD1; // Scale(x), BiasIn(y), BiasOut(z), Bias(w) + half4 mask : TEXCOORD2; // Position in clip space(xy), Softness(zw) + #if (UNDERLAY_ON | UNDERLAY_INNER) + float4 texcoord1 : TEXCOORD3; // Texture UV, alpha, reserved + half2 underlayParam : TEXCOORD4; // Scale(x), Bias(y) + #endif + }; + + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input, output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.vertex; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + if(UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float layerScale = scale; + + scale /= 1 + (_OutlineSoftness * _ScaleRatioA * scale); + float bias = (0.5 - weight) * scale - 0.5; + float outline = _OutlineWidth * _ScaleRatioA * 0.5 * scale; + + float opacity = input.color.a; + #if (UNDERLAY_ON | UNDERLAY_INNER) + opacity = 1.0; + #endif + + fixed4 faceColor = fixed4(input.color.rgb, opacity) * _FaceColor; + faceColor.rgb *= faceColor.a; + + fixed4 outlineColor = _OutlineColor; + outlineColor.a *= opacity; + outlineColor.rgb *= outlineColor.a; + outlineColor = lerp(faceColor, outlineColor, sqrt(min(1.0, (outline * 2)))); + + #if (UNDERLAY_ON | UNDERLAY_INNER) + layerScale /= 1 + ((_UnderlaySoftness * _ScaleRatioC) * layerScale); + float layerBias = (.5 - weight) * layerScale - .5 - ((_UnderlayDilate * _ScaleRatioC) * .5 * layerScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 layerOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Populate structure for pixel shader + output.vertex = vPosition; + output.faceColor = faceColor; + output.outlineColor = outlineColor; + output.texcoord0 = float4(input.texcoord0.x, input.texcoord0.y, maskUV.x, maskUV.y); + output.param = half4(scale, bias - outline, bias + outline, bias); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord1 = float4(input.texcoord0 + layerOffset, input.color.a, 0); + output.underlayParam = half2(layerScale, layerBias); + #endif + + return output; + } + + + // PIXEL SHADER + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + half d = tex2D(_MainTex, input.texcoord0.xy).a * input.param.x; + half4 c = input.faceColor * saturate(d - input.param.w); + + #ifdef OUTLINE_ON + c = lerp(input.outlineColor, input.faceColor, saturate(d - input.param.z)); + c *= saturate(d - input.param.y); + #endif + + #if UNDERLAY_ON + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * saturate(d - input.underlayParam.y) * (1 - c.a); + #endif + + #if UNDERLAY_INNER + half sd = saturate(d - input.param.z); + d = tex2D(_MainTex, input.texcoord1.xy).a * input.underlayParam.x; + c += float4(_UnderlayColor.rgb * _UnderlayColor.a, _UnderlayColor.a) * (1 - saturate(d - input.underlayParam.y)) * sd * (1 - c.a); + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + c *= m.x * m.y; + #endif + + #if (UNDERLAY_ON | UNDERLAY_INNER) + c *= input.texcoord1.z; + #endif + + #if UNITY_UI_ALPHACLIP + clip(c.a - 0.001); + #endif + + return c; + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile.shader.meta new file mode 100644 index 0000000..335e0fd --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Mobile.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fb171366644152948b39e5c17f4b1f39 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface-Mobile.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface-Mobile.shader new file mode 100644 index 0000000..be764ae --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface-Mobile.shader @@ -0,0 +1,138 @@ +// Simplified version of the SDF Surface shader : +// - No support for Bevel, Bump or envmap +// - Diffuse only lighting +// - Fully supports only 1 directional light. Other lights can affect it, but it will be per-vertex/SH. + +Shader "TextMeshPro/Mobile/Distance Field (Surface)" { + +Properties { + _FaceTex ("Fill Texture", 2D) = "white" {} + [HDR]_FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + // Should not be directly exposed to the user + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _CullMode ("Cull Mode", Float) = 0 + //_MaskCoord ("Mask Coords", vector) = (0,0,0,0) + //_MaskSoftness ("Mask Softness", float) = 0 +} + +SubShader { + + Tags { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + LOD 300 + Cull [_CullMode] + + CGPROGRAM + #pragma surface PixShader Lambert alpha:blend vertex:VertShader noforwardadd nolightmap nodirlightmap + #pragma target 3.0 + #pragma shader_feature __ GLOW_ON + + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + half _FaceShininess; + half _OutlineShininess; + + struct Input + { + fixed4 color : COLOR; + float2 uv_MainTex; + float2 uv2_FaceTex; + float2 uv2_OutlineTex; + float2 param; // Weight, Scale + float3 viewDirEnv; + }; + + #include "TMPro_Surface.cginc" + + ENDCG + + // Pass to render object as a shadow caster + Pass + { + Name "Caster" + Tags { "LightMode" = "ShadowCaster" } + Offset 1, 1 + + Fog {Mode Off} + ZWrite On ZTest LEqual Cull Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #include "UnityCG.cginc" + + struct v2f { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + float2 uv2 : TEXCOORD3; + float alphaClip : TEXCOORD2; + }; + + uniform float4 _MainTex_ST; + uniform float4 _OutlineTex_ST; + float _OutlineWidth; + float _FaceDilate; + float _ScaleRatioA; + + v2f vert( appdata_base v ) + { + v2f o; + TRANSFER_SHADOW_CASTER(o) + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + o.uv2 = TRANSFORM_TEX(v.texcoord, _OutlineTex); + o.alphaClip = o.alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _FaceDilate * _ScaleRatioA) / 2; + return o; + } + + uniform sampler2D _MainTex; + + float4 frag(v2f i) : COLOR + { + fixed4 texcol = tex2D(_MainTex, i.uv).a; + clip(texcol.a - i.alphaClip); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface-Mobile.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface-Mobile.shader.meta new file mode 100644 index 0000000..a663819 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface-Mobile.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4ca22ae3bc068c84eb7858d5b9bdf3e2 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface.shader new file mode 100644 index 0000000..bcb2bb2 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface.shader @@ -0,0 +1,158 @@ +Shader "TextMeshPro/Distance Field (Surface)" { + +Properties { + _FaceTex ("Fill Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + [HDR]_FaceColor ("Fill Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _BumpMap ("Normalmap", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0.5 + _BumpFace ("Bump Face", Range(0,1)) = 0.5 + + _ReflectFaceColor ("Face Color", Color) = (0,0,0,1) + _ReflectOutlineColor ("Outline Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + [HDR]_SpecColor ("Specular Color", Color) = (0,0,0,1) + + _FaceShininess ("Face Shininess", Range(0,1)) = 0 + _OutlineShininess ("Outline Shininess", Range(0,1)) = 0 + + [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + // Should not be directly exposed to the user + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _CullMode ("Cull Mode", Float) = 0 + //_MaskCoord ("Mask Coords", vector) = (0,0,0,0) + //_MaskSoftness ("Mask Softness", float) = 0 +} + +SubShader { + + Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" } + + LOD 300 + Cull [_CullMode] + + CGPROGRAM + #pragma surface PixShader BlinnPhong alpha:blend vertex:VertShader nolightmap nodirlightmap + #pragma target 3.0 + #pragma shader_feature __ GLOW_ON + #pragma glsl + + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + half _FaceShininess; + half _OutlineShininess; + + struct Input + { + fixed4 color : COLOR; + float2 uv_MainTex; + float2 uv2_FaceTex; + float2 uv2_OutlineTex; + float2 param; // Weight, Scale + float3 viewDirEnv; + }; + + + #define BEVEL_ON 1 + #include "TMPro_Surface.cginc" + + ENDCG + + // Pass to render object as a shadow caster + Pass + { + Name "Caster" + Tags { "LightMode" = "ShadowCaster" } + Offset 1, 1 + + Fog {Mode Off} + ZWrite On + ZTest LEqual + Cull Off + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma multi_compile_shadowcaster + #include "UnityCG.cginc" + + struct v2f { + V2F_SHADOW_CASTER; + float2 uv : TEXCOORD1; + float2 uv2 : TEXCOORD3; + float alphaClip : TEXCOORD2; + }; + + uniform float4 _MainTex_ST; + uniform float4 _OutlineTex_ST; + float _OutlineWidth; + float _FaceDilate; + float _ScaleRatioA; + + v2f vert( appdata_base v ) + { + v2f o; + TRANSFER_SHADOW_CASTER(o) + o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); + o.uv2 = TRANSFORM_TEX(v.texcoord, _OutlineTex); + o.alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _FaceDilate * _ScaleRatioA) / 2; + return o; + } + + uniform sampler2D _MainTex; + + float4 frag(v2f i) : COLOR + { + fixed4 texcol = tex2D(_MainTex, i.uv).a; + clip(texcol.a - i.alphaClip); + SHADOW_CASTER_FRAGMENT(i) + } + ENDCG + } +} + +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} + diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface.shader.meta new file mode 100644 index 0000000..261e4a6 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF-Surface.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f5b2cc6c7ce8cc5408ad507a4f40af49 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF.shader b/Assets/GameMain/Fonts/Shaders/TMP_SDF.shader new file mode 100644 index 0000000..011ee19 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF.shader @@ -0,0 +1,317 @@ +Shader "TextMeshPro/Distance Field" { + +Properties { + _FaceTex ("Face Texture", 2D) = "white" {} + _FaceUVSpeedX ("Face UV Speed X", Range(-5, 5)) = 0.0 + _FaceUVSpeedY ("Face UV Speed Y", Range(-5, 5)) = 0.0 + [HDR]_FaceColor ("Face Color", Color) = (1,1,1,1) + _FaceDilate ("Face Dilate", Range(-1,1)) = 0 + + [HDR]_OutlineColor ("Outline Color", Color) = (0,0,0,1) + _OutlineTex ("Outline Texture", 2D) = "white" {} + _OutlineUVSpeedX ("Outline UV Speed X", Range(-5, 5)) = 0.0 + _OutlineUVSpeedY ("Outline UV Speed Y", Range(-5, 5)) = 0.0 + _OutlineWidth ("Outline Thickness", Range(0, 1)) = 0 + _OutlineSoftness ("Outline Softness", Range(0,1)) = 0 + + _Bevel ("Bevel", Range(0,1)) = 0.5 + _BevelOffset ("Bevel Offset", Range(-0.5,0.5)) = 0 + _BevelWidth ("Bevel Width", Range(-.5,0.5)) = 0 + _BevelClamp ("Bevel Clamp", Range(0,1)) = 0 + _BevelRoundness ("Bevel Roundness", Range(0,1)) = 0 + + _LightAngle ("Light Angle", Range(0.0, 6.2831853)) = 3.1416 + [HDR]_SpecularColor ("Specular", Color) = (1,1,1,1) + _SpecularPower ("Specular", Range(0,4)) = 2.0 + _Reflectivity ("Reflectivity", Range(5.0,15.0)) = 10 + _Diffuse ("Diffuse", Range(0,1)) = 0.5 + _Ambient ("Ambient", Range(1,0)) = 0.5 + + _BumpMap ("Normal map", 2D) = "bump" {} + _BumpOutline ("Bump Outline", Range(0,1)) = 0 + _BumpFace ("Bump Face", Range(0,1)) = 0 + + _ReflectFaceColor ("Reflection Color", Color) = (0,0,0,1) + _ReflectOutlineColor("Reflection Color", Color) = (0,0,0,1) + _Cube ("Reflection Cubemap", Cube) = "black" { /* TexGen CubeReflect */ } + _EnvMatrixRotation ("Texture Rotation", vector) = (0, 0, 0, 0) + + + [HDR]_UnderlayColor ("Border Color", Color) = (0,0,0, 0.5) + _UnderlayOffsetX ("Border OffsetX", Range(-1,1)) = 0 + _UnderlayOffsetY ("Border OffsetY", Range(-1,1)) = 0 + _UnderlayDilate ("Border Dilate", Range(-1,1)) = 0 + _UnderlaySoftness ("Border Softness", Range(0,1)) = 0 + + [HDR]_GlowColor ("Color", Color) = (0, 1, 0, 0.5) + _GlowOffset ("Offset", Range(-1,1)) = 0 + _GlowInner ("Inner", Range(0,1)) = 0.05 + _GlowOuter ("Outer", Range(0,1)) = 0.05 + _GlowPower ("Falloff", Range(1, 0)) = 0.75 + + _WeightNormal ("Weight Normal", float) = 0 + _WeightBold ("Weight Bold", float) = 0.5 + + _ShaderFlags ("Flags", float) = 0 + _ScaleRatioA ("Scale RatioA", float) = 1 + _ScaleRatioB ("Scale RatioB", float) = 1 + _ScaleRatioC ("Scale RatioC", float) = 1 + + _MainTex ("Font Atlas", 2D) = "white" {} + _TextureWidth ("Texture Width", float) = 512 + _TextureHeight ("Texture Height", float) = 512 + _GradientScale ("Gradient Scale", float) = 5.0 + _ScaleX ("Scale X", float) = 1.0 + _ScaleY ("Scale Y", float) = 1.0 + _PerspectiveFilter ("Perspective Correction", Range(0, 1)) = 0.875 + _Sharpness ("Sharpness", Range(-1,1)) = 0 + + _VertexOffsetX ("Vertex OffsetX", float) = 0 + _VertexOffsetY ("Vertex OffsetY", float) = 0 + + _MaskCoord ("Mask Coordinates", vector) = (0, 0, 32767, 32767) + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + _MaskSoftnessX ("Mask SoftnessX", float) = 0 + _MaskSoftnessY ("Mask SoftnessY", float) = 0 + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 +} + +SubShader { + + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + ZWrite Off + Lighting Off + Fog { Mode Off } + ZTest [unity_GUIZTestMode] + Blend One OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass { + CGPROGRAM + #pragma target 3.0 + #pragma vertex VertShader + #pragma fragment PixShader + #pragma shader_feature __ BEVEL_ON + #pragma shader_feature __ UNDERLAY_ON UNDERLAY_INNER + #pragma shader_feature __ GLOW_ON + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + #include "TMPro_Properties.cginc" + #include "TMPro.cginc" + + struct vertex_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + float4 position : POSITION; + float3 normal : NORMAL; + fixed4 color : COLOR; + float2 texcoord0 : TEXCOORD0; + float2 texcoord1 : TEXCOORD1; + }; + + + struct pixel_t { + UNITY_VERTEX_INPUT_INSTANCE_ID + UNITY_VERTEX_OUTPUT_STEREO + float4 position : SV_POSITION; + fixed4 color : COLOR; + float2 atlas : TEXCOORD0; // Atlas + float4 param : TEXCOORD1; // alphaClip, scale, bias, weight + float4 mask : TEXCOORD2; // Position in object space(xy), pixel Size(zw) + float3 viewDir : TEXCOORD3; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 texcoord2 : TEXCOORD4; // u,v, scale, bias + fixed4 underlayColor : COLOR1; + #endif + float4 textures : TEXCOORD5; + }; + + // Used by Unity internally to handle Texture Tiling and Offset. + float4 _FaceTex_ST; + float4 _OutlineTex_ST; + + pixel_t VertShader(vertex_t input) + { + pixel_t output; + + UNITY_INITIALIZE_OUTPUT(pixel_t, output); + UNITY_SETUP_INSTANCE_ID(input); + UNITY_TRANSFER_INSTANCE_ID(input,output); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); + + float bold = step(input.texcoord1.y, 0); + + float4 vert = input.position; + vert.x += _VertexOffsetX; + vert.y += _VertexOffsetY; + + float4 vPosition = UnityObjectToClipPos(vert); + + float2 pixelSize = vPosition.w; + pixelSize /= float2(_ScaleX, _ScaleY) * abs(mul((float2x2)UNITY_MATRIX_P, _ScreenParams.xy)); + float scale = rsqrt(dot(pixelSize, pixelSize)); + scale *= abs(input.texcoord1.y) * _GradientScale * (_Sharpness + 1); + if (UNITY_MATRIX_P[3][3] == 0) scale = lerp(abs(scale) * (1 - _PerspectiveFilter), scale, abs(dot(UnityObjectToWorldNormal(input.normal.xyz), normalize(WorldSpaceViewDir(vert))))); + + float weight = lerp(_WeightNormal, _WeightBold, bold) / 4.0; + weight = (weight + _FaceDilate) * _ScaleRatioA * 0.5; + + float bias =(.5 - weight) + (.5 / scale); + + float alphaClip = (1.0 - _OutlineWidth * _ScaleRatioA - _OutlineSoftness * _ScaleRatioA); + + #if GLOW_ON + alphaClip = min(alphaClip, 1.0 - _GlowOffset * _ScaleRatioB - _GlowOuter * _ScaleRatioB); + #endif + + alphaClip = alphaClip / 2.0 - ( .5 / scale) - weight; + + #if (UNDERLAY_ON || UNDERLAY_INNER) + float4 underlayColor = _UnderlayColor; + underlayColor.rgb *= underlayColor.a; + + float bScale = scale; + bScale /= 1 + ((_UnderlaySoftness*_ScaleRatioC) * bScale); + float bBias = (0.5 - weight) * bScale - 0.5 - ((_UnderlayDilate * _ScaleRatioC) * 0.5 * bScale); + + float x = -(_UnderlayOffsetX * _ScaleRatioC) * _GradientScale / _TextureWidth; + float y = -(_UnderlayOffsetY * _ScaleRatioC) * _GradientScale / _TextureHeight; + float2 bOffset = float2(x, y); + #endif + + // Generate UV for the Masking Texture + float4 clampedRect = clamp(_ClipRect, -2e10, 2e10); + float2 maskUV = (vert.xy - clampedRect.xy) / (clampedRect.zw - clampedRect.xy); + + // Support for texture tiling and offset + float2 textureUV = UnpackUV(input.texcoord1.x); + float2 faceUV = TRANSFORM_TEX(textureUV, _FaceTex); + float2 outlineUV = TRANSFORM_TEX(textureUV, _OutlineTex); + + + output.position = vPosition; + output.color = input.color; + output.atlas = input.texcoord0; + output.param = float4(alphaClip, scale, bias, weight); + output.mask = half4(vert.xy * 2 - clampedRect.xy - clampedRect.zw, 0.25 / (0.25 * half2(_MaskSoftnessX, _MaskSoftnessY) + pixelSize.xy)); + output.viewDir = mul((float3x3)_EnvMatrix, _WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld, vert).xyz); + #if (UNDERLAY_ON || UNDERLAY_INNER) + output.texcoord2 = float4(input.texcoord0 + bOffset, bScale, bBias); + output.underlayColor = underlayColor; + #endif + output.textures = float4(faceUV, outlineUV); + + return output; + } + + + fixed4 PixShader(pixel_t input) : SV_Target + { + UNITY_SETUP_INSTANCE_ID(input); + + float c = tex2D(_MainTex, input.atlas).a; + + #ifndef UNDERLAY_ON + clip(c - input.param.x); + #endif + + float scale = input.param.y; + float bias = input.param.z; + float weight = input.param.w; + float sd = (bias - c) * scale; + + float outline = (_OutlineWidth * _ScaleRatioA) * scale; + float softness = (_OutlineSoftness * _ScaleRatioA) * scale; + + half4 faceColor = _FaceColor; + half4 outlineColor = _OutlineColor; + + faceColor.rgb *= input.color.rgb; + + faceColor *= tex2D(_FaceTex, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y); + outlineColor *= tex2D(_OutlineTex, input.textures.zw + float2(_OutlineUVSpeedX, _OutlineUVSpeedY) * _Time.y); + + faceColor = GetColor(sd, faceColor, outlineColor, outline, softness); + + #if BEVEL_ON + float3 dxy = float3(0.5 / _TextureWidth, 0.5 / _TextureHeight, 0); + float3 n = GetSurfaceNormal(input.atlas, weight, dxy); + + float3 bump = UnpackNormal(tex2D(_BumpMap, input.textures.xy + float2(_FaceUVSpeedX, _FaceUVSpeedY) * _Time.y)).xyz; + bump *= lerp(_BumpFace, _BumpOutline, saturate(sd + outline * 0.5)); + n = normalize(n- bump); + + float3 light = normalize(float3(sin(_LightAngle), cos(_LightAngle), -1.0)); + + float3 col = GetSpecular(n, light); + faceColor.rgb += col*faceColor.a; + faceColor.rgb *= 1-(dot(n, light)*_Diffuse); + faceColor.rgb *= lerp(_Ambient, 1, n.z*n.z); + + fixed4 reflcol = texCUBE(_Cube, reflect(input.viewDir, -n)); + faceColor.rgb += reflcol.rgb * lerp(_ReflectFaceColor.rgb, _ReflectOutlineColor.rgb, saturate(sd + outline * 0.5)) * faceColor.a; + #endif + + #if UNDERLAY_ON + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * saturate(d - input.texcoord2.w) * (1 - faceColor.a); + #endif + + #if UNDERLAY_INNER + float d = tex2D(_MainTex, input.texcoord2.xy).a * input.texcoord2.z; + faceColor += input.underlayColor * (1 - saturate(d - input.texcoord2.w)) * saturate(1 - sd) * (1 - faceColor.a); + #endif + + #if GLOW_ON + float4 glowColor = GetGlowColor(sd, scale); + faceColor.rgb += glowColor.rgb * glowColor.a; + #endif + + // Alternative implementation to UnityGet2DClipping with support for softness. + #if UNITY_UI_CLIP_RECT + half2 m = saturate((_ClipRect.zw - _ClipRect.xy - abs(input.mask.xy)) * input.mask.zw); + faceColor *= m.x * m.y; + #endif + + #if UNITY_UI_ALPHACLIP + clip(faceColor.a - 0.001); + #endif + + return faceColor * input.color.a; + } + + ENDCG + } +} + +Fallback "TextMeshPro/Mobile/Distance Field" +CustomEditor "TMPro.EditorUtilities.TMP_SDFShaderGUI" +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_SDF.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_SDF.shader.meta new file mode 100644 index 0000000..693dc09 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_SDF.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5b5a6a737c460eb4abc105d6583d405e +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Fonts/Shaders/TMP_Sprite.shader b/Assets/GameMain/Fonts/Shaders/TMP_Sprite.shader new file mode 100644 index 0000000..e8283a7 --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_Sprite.shader @@ -0,0 +1,116 @@ +Shader "TextMeshPro/Sprite" +{ + Properties + { + [PerRendererData] _MainTex ("Sprite Texture", 2D) = "white" {} + _Color ("Tint", Color) = (1,1,1,1) + + _StencilComp ("Stencil Comparison", Float) = 8 + _Stencil ("Stencil ID", Float) = 0 + _StencilOp ("Stencil Operation", Float) = 0 + _StencilWriteMask ("Stencil Write Mask", Float) = 255 + _StencilReadMask ("Stencil Read Mask", Float) = 255 + + _CullMode ("Cull Mode", Float) = 0 + _ColorMask ("Color Mask", Float) = 15 + _ClipRect ("Clip Rect", vector) = (-32767, -32767, 32767, 32767) + + [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0 + } + + SubShader + { + Tags + { + "Queue"="Transparent" + "IgnoreProjector"="True" + "RenderType"="Transparent" + "PreviewType"="Plane" + "CanUseSpriteAtlas"="True" + } + + Stencil + { + Ref [_Stencil] + Comp [_StencilComp] + Pass [_StencilOp] + ReadMask [_StencilReadMask] + WriteMask [_StencilWriteMask] + } + + Cull [_CullMode] + Lighting Off + ZWrite Off + ZTest [unity_GUIZTestMode] + Blend SrcAlpha OneMinusSrcAlpha + ColorMask [_ColorMask] + + Pass + { + Name "Default" + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 2.0 + + #include "UnityCG.cginc" + #include "UnityUI.cginc" + + #pragma multi_compile __ UNITY_UI_CLIP_RECT + #pragma multi_compile __ UNITY_UI_ALPHACLIP + + struct appdata_t + { + float4 vertex : POSITION; + float4 color : COLOR; + float2 texcoord : TEXCOORD0; + UNITY_VERTEX_INPUT_INSTANCE_ID + }; + + struct v2f + { + float4 vertex : SV_POSITION; + fixed4 color : COLOR; + float2 texcoord : TEXCOORD0; + float4 worldPosition : TEXCOORD1; + UNITY_VERTEX_OUTPUT_STEREO + }; + + sampler2D _MainTex; + fixed4 _Color; + fixed4 _TextureSampleAdd; + float4 _ClipRect; + float4 _MainTex_ST; + + v2f vert(appdata_t v) + { + v2f OUT; + UNITY_SETUP_INSTANCE_ID(v); + UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); + OUT.worldPosition = v.vertex; + OUT.vertex = UnityObjectToClipPos(OUT.worldPosition); + + OUT.texcoord = TRANSFORM_TEX(v.texcoord, _MainTex); + + OUT.color = v.color * _Color; + return OUT; + } + + fixed4 frag(v2f IN) : SV_Target + { + half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color; + + #ifdef UNITY_UI_CLIP_RECT + color.a *= UnityGet2DClipping(IN.worldPosition.xy, _ClipRect); + #endif + + #ifdef UNITY_UI_ALPHACLIP + clip (color.a - 0.001); + #endif + + return color; + } + ENDCG + } + } +} diff --git a/Assets/GameMain/Fonts/Shaders/TMP_Sprite.shader.meta b/Assets/GameMain/Fonts/Shaders/TMP_Sprite.shader.meta new file mode 100644 index 0000000..1c5a1fc --- /dev/null +++ b/Assets/GameMain/Fonts/Shaders/TMP_Sprite.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ab1c66f8a301fe043930c9f0c23716cf +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/TextMesh Pro/Resources/Sprite Assets/coin.asset b/Assets/GameMain/Fonts/coin.asset similarity index 100% rename from Assets/TextMesh Pro/Resources/Sprite Assets/coin.asset rename to Assets/GameMain/Fonts/coin.asset diff --git a/Assets/TextMesh Pro/Resources/Sprite Assets/coin.asset.meta b/Assets/GameMain/Fonts/coin.asset.meta similarity index 100% rename from Assets/TextMesh Pro/Resources/Sprite Assets/coin.asset.meta rename to Assets/GameMain/Fonts/coin.asset.meta diff --git a/Assets/GameMain/Materials/Blue.mat b/Assets/GameMain/Materials/Blue.mat new file mode 100644 index 0000000..4dea6ad --- /dev/null +++ b/Assets/GameMain/Materials/Blue.mat @@ -0,0 +1,137 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: Blue + m_Shader: {fileID: 4800000, guid: 933532a4fcc9baf4fa0491de14d08ed7, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 1 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: + RenderType: Opaque + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BlendOp: 0 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _FlashAmount: 0 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _SampleGI: 0 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 0.1, g: 1, b: 0.9, a: 1} + - _Color: {r: 0.09999997, g: 1, b: 0.9, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _FlashColor: {r: 1, g: 1, b: 1, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} + m_BuildTextureStacks: [] +--- !u!114 &4582237545370899445 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 7 diff --git a/Assets/GameMain/Scenes/StressTest/GlobalVolumeProfile.asset.meta b/Assets/GameMain/Materials/Blue.mat.meta similarity index 64% rename from Assets/GameMain/Scenes/StressTest/GlobalVolumeProfile.asset.meta rename to Assets/GameMain/Materials/Blue.mat.meta index 06bddd4..9b5ed68 100644 --- a/Assets/GameMain/Scenes/StressTest/GlobalVolumeProfile.asset.meta +++ b/Assets/GameMain/Materials/Blue.mat.meta @@ -1,8 +1,8 @@ fileFormatVersion: 2 -guid: 94ca859a535c2074392c01285b2754e0 +guid: c4f37184fcb9306428d7d002f7dca96d NativeFormatImporter: externalObjects: {} - mainObjectFileID: 11400000 + mainObjectFileID: 2100000 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/GameMain/Materials/Green.mat b/Assets/GameMain/Materials/InstancingGreen.mat similarity index 99% rename from Assets/GameMain/Materials/Green.mat rename to Assets/GameMain/Materials/InstancingGreen.mat index 1b10d11..ea4f2b0 100644 --- a/Assets/GameMain/Materials/Green.mat +++ b/Assets/GameMain/Materials/InstancingGreen.mat @@ -7,7 +7,7 @@ Material: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Green + m_Name: InstancingGreen m_Shader: {fileID: 4800000, guid: f17bc7e2694233349a8b22e96c5c43de, type: 3} m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 diff --git a/Assets/GameMain/Materials/Green.mat.meta b/Assets/GameMain/Materials/InstancingGreen.mat.meta similarity index 100% rename from Assets/GameMain/Materials/Green.mat.meta rename to Assets/GameMain/Materials/InstancingGreen.mat.meta diff --git a/Assets/GameMain/Materials/InstancingGrey.mat b/Assets/GameMain/Materials/InstancingGrey.mat new file mode 100644 index 0000000..87cc500 --- /dev/null +++ b/Assets/GameMain/Materials/InstancingGrey.mat @@ -0,0 +1,136 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 8 + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_Name: InstancingGrey + m_Shader: {fileID: 4800000, guid: f17bc7e2694233349a8b22e96c5c43de, type: 3} + m_Parent: {fileID: 0} + m_ModifiedSerializedProperties: 0 + m_ValidKeywords: [] + m_InvalidKeywords: [] + m_LightmapFlags: 4 + m_EnableInstancingVariants: 1 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_LockedProperties: + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BaseMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_Lightmaps: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_LightmapsInd: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - unity_ShadowMasks: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Ints: [] + m_Floats: + - _AlphaClip: 0 + - _AlphaToMask: 0 + - _Blend: 0 + - _BlendModePreserveSpecular: 1 + - _BlendOp: 0 + - _BumpScale: 1 + - _ClearCoatMask: 0 + - _ClearCoatSmoothness: 0 + - _Cull: 2 + - _Cutoff: 0.5 + - _DetailAlbedoMapScale: 1 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _DstBlendAlpha: 0 + - _EnvironmentReflections: 1 + - _FlashAmount: 0 + - _GlossMapScale: 0 + - _Glossiness: 0 + - _GlossyReflections: 0 + - _Metallic: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.005 + - _QueueOffset: 0 + - _ReceiveShadows: 1 + - _SampleGI: 0 + - _Smoothness: 0.5 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _SrcBlendAlpha: 1 + - _Surface: 0 + - _WorkflowMode: 1 + - _ZWrite: 1 + m_Colors: + - _BaseColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} + - _Color: {r: 1, g: 0.29245266, b: 0.29245266, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _FlashColor: {r: 1, g: 1, b: 1, a: 1} + - _SpecColor: {r: 0.19999996, g: 0.19999996, b: 0.19999996, a: 1} + m_BuildTextureStacks: [] +--- !u!114 &4582237545370899445 +MonoBehaviour: + m_ObjectHideFlags: 11 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: d0353a89b1f911e48b9e16bdc9f2e058, type: 3} + m_Name: + m_EditorClassIdentifier: + version: 7 diff --git a/Assets/GameMain/Scenes/MainSettings.lighting.meta b/Assets/GameMain/Materials/InstancingGrey.mat.meta similarity index 60% rename from Assets/GameMain/Scenes/MainSettings.lighting.meta rename to Assets/GameMain/Materials/InstancingGrey.mat.meta index 6d5e4b0..ab4237d 100644 --- a/Assets/GameMain/Scenes/MainSettings.lighting.meta +++ b/Assets/GameMain/Materials/InstancingGrey.mat.meta @@ -1,8 +1,8 @@ fileFormatVersion: 2 -guid: bd0dcd203508e774b84313644b9fad2c +guid: 83e5fce2d1e5b3e4ab6551de03cc9c22 NativeFormatImporter: externalObjects: {} - mainObjectFileID: 4890085278179872738 + mainObjectFileID: 2100000 userData: assetBundleName: assetBundleVariant: diff --git a/Assets/GameMain/Materials/Red.mat b/Assets/GameMain/Materials/InstancingRed.mat similarity index 99% rename from Assets/GameMain/Materials/Red.mat rename to Assets/GameMain/Materials/InstancingRed.mat index 390f724..e590da2 100644 --- a/Assets/GameMain/Materials/Red.mat +++ b/Assets/GameMain/Materials/InstancingRed.mat @@ -7,7 +7,7 @@ Material: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Red + m_Name: InstancingRed m_Shader: {fileID: 4800000, guid: f17bc7e2694233349a8b22e96c5c43de, type: 3} m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 diff --git a/Assets/GameMain/Materials/Red.mat.meta b/Assets/GameMain/Materials/InstancingRed.mat.meta similarity index 100% rename from Assets/GameMain/Materials/Red.mat.meta rename to Assets/GameMain/Materials/InstancingRed.mat.meta diff --git a/Assets/GameMain/Materials/Yellow.mat b/Assets/GameMain/Materials/InstancingYellow.mat similarity index 99% rename from Assets/GameMain/Materials/Yellow.mat rename to Assets/GameMain/Materials/InstancingYellow.mat index 0c94059..ff98550 100644 --- a/Assets/GameMain/Materials/Yellow.mat +++ b/Assets/GameMain/Materials/InstancingYellow.mat @@ -7,7 +7,7 @@ Material: m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} - m_Name: Yellow + m_Name: InstancingYellow m_Shader: {fileID: 4800000, guid: f17bc7e2694233349a8b22e96c5c43de, type: 3} m_Parent: {fileID: 0} m_ModifiedSerializedProperties: 0 diff --git a/Assets/GameMain/Materials/Yellow.mat.meta b/Assets/GameMain/Materials/InstancingYellow.mat.meta similarity index 100% rename from Assets/GameMain/Materials/Yellow.mat.meta rename to Assets/GameMain/Materials/InstancingYellow.mat.meta diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator.meta b/Assets/GameMain/Scenes/Game.meta similarity index 77% rename from Assets/GameMain/Scripts/Editor/DataTableGenerator.meta rename to Assets/GameMain/Scenes/Game.meta index 4c9a657..4daa879 100644 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator.meta +++ b/Assets/GameMain/Scenes/Game.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 051868bff0e1df3498c100dc5a9f027d +guid: 1e2a290aa42884640815cb6fd552deac folderAsset: yes DefaultImporter: externalObjects: {} diff --git a/Assets/GameMain/Scenes/Game.unity b/Assets/GameMain/Scenes/Game.unity index b4db875..42b3eee 100644 --- a/Assets/GameMain/Scenes/Game.unity +++ b/Assets/GameMain/Scenes/Game.unity @@ -96,7 +96,8 @@ LightmapSettings: m_ExportTrainingData: 0 m_TrainingDataDestination: TrainingData m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} + m_LightingDataAsset: {fileID: 112000000, guid: fb9bd70ff25fcde4e954a6f3ec6ca2cd, + type: 2} m_LightingSettings: {fileID: 0} --- !u!196 &4 NavMeshSettings: diff --git a/Assets/GameMain/Scenes/Game/LightingData.asset b/Assets/GameMain/Scenes/Game/LightingData.asset new file mode 100644 index 0000000000000000000000000000000000000000..f058418abeea8f486c3248f487238879acc0400a GIT binary patch literal 18192 zcmdU%eVkO)dB@M}8!uwOR}>Wo1q4)NW&sh_b$FHKb!8WXfPvZFyX?U3>@qVeyQnZ2 zMG0ymF=>1a*d}Tcqf)IcZqSy*rbd!lHBD_|V$)cfsHv%KjWKSX-#O=*xo6HkoAlE^ z+MdtOx#ynmJG#!Q@7lF)%(|fF!F)OoQP77S1ARGaH $=h{@;cU0L`Bq> z%T@kRMCEZU71KYy0{mn;Sy-X+Bj|`KaSewE<-AU^Cs78t1C81iS+F=^#j>bwFb>dL1s4Jv<#$0KS_naXFZe6(S(_7C&QyX_zD@rYVX{rf6) z8smEccpkNwK<$rE-_d`~F@}*un3wDEJBwssY)%B%BgN&*)m2n>3;odUk9jT{Ifi6g6Ao+p>%$tlt0+~ zj03l2alrgx{4qah|9LtO#01Pw*#6I_Y`6Ut&iG@FU2fX{B;}+1aDRife=Y<}Rs23>jhxEhvUF31s zzg?_(o?;VVzhV8IO4+63hw=Y8<->nmqB%u2z`uS#>5()j?R1<*KX-h})IlnLA!VXG z`KbYU-14}Z@2skf!}3$Lg4pWK3CumT0T$Uk61om;E!9r zK;TbXzEI#tEMFw>Z&`k&z+bd{vA|!pyiVY+S-wQzZ&<$6~rAQ?`Y4a1)*5UcluQY9#S7^n?GY_qe-$k}sq3d5TRaT|ZY* zw#zHjJLF%-k$l`+G-w{B*aVb6NNt-=9R8(|ei0QlP^S%_Y58h_&$4`tz-L>2wZ~2S zYKWtKYd!9^Z=JxoeIFM%w{N|`xqTZvUZM8U_%%}d=ucgvIYl;LeFbl_{1cR4I=>kI z?Y4g#HILfTxYq68CV_MRk^<-cH3^*i*X(gK{x{n8wRqfZUm$R9U#q~meVYZ&?ZbVn ztA7=0FFhOFW!sn1oFW@Aeg|lLA0du$Cp#+{f5Q)1zE$AQSdKN=oj+6lo0fM7{Fvow zfq&ofPJ#c}@-BfNw|twx-?cm=@DD7{3cS4B^c(m31NHwz%ew_W+VX1!KF;#(0>9Am z9)ZuWyw~H#e_ufy{(A>_o+2Ac{r7d0A4xDpUtRxwJ$MmozJX-Jf5SiB;Bj;RoS|!m z65A>8U6$|ictqVs>_PgW{dsUiHsJmR&v%C{-%a^0FL&;bZv;=+!bp>U!u==TAAeHk zx%_#Ojs7Jl`zDW9s$P1&_$gh3_337hS2@oYdo<5eY(hj;Irqo6P`0~1RqFNWEs~G% zy;bul#U`NqL24VXPkSlb^$&)#|M`@_+5hYlIQyU5JZ{$CDq0+|KHjc5MK-|yz(0*7 zi1yz>KUaUM9RKubfwO=5jKJAH-6?SPPx}SV{^_#w-rpY9Vl`=|Q_&i?5Ej~o3s+v>*`HP2IQ0`xn)ejT7} z*FFqq{UBQykh6X~C~($~KNdLa$DatC_2WwdXZ`rHz*#>Y5;*I}!vbghctqf=A72qT z>&I6G&ie5+fwO)*Dsa}1uM3>@<1vpL|2~=Y1OESU@H|B}(E8-~_a`Vnl3)s5aQ*us z@FLc{nq490?%3gw7_>;{^tX5_}4p# z!@vH8$6fn5EO54;X9Ujn(8~^%%)sGiE?&`;P1kU>LqQF@{jtQLg z&L4CXZ`rTz*#^3Uf`@BKM*+U z$3F<1_2V^<8~=KU^aK9&AHnk!*-+|Ve@OX*`PUzTb77q}&!_OO@K59mOSt=d`eT8! z{{2MYtbcC^ob~UY1kU>RQ-QPo{jnDu9kKfNOYl5JHk9h$zft~R`u8q47uM+t^<9z;{X2us zf8}xW{PGT6Lx1Yu2jEy=-zNzDeb3{r|NIYuv;O|4z*&F)OW>@(?+cvu_tyev{ry1T ztiQhzIP33+0%!gGt-x7-KN2|WZ@<7U(C-mcY?#O0_6-;KJlp;g z1isSp5gs@DOB;xzelLI0PLUP`H}Z0CwcNKo$qTVd))MImF?dYuYR|Gc#rPZ z@AmH^Pky<2JoJ6V#U3~MF^Rea{g|qGzR*GFNBH}IOFVAczs^MYh9IX9aPa;m;Qm#JCUlFD^v7WU+VbT-wQ zu2mfy7p2;Rx&@S|Pv+Vvp|7jY1g*)Yx^y;|Og9I$CbOYANC#RN%IPyY>Y6%|U0KB` z)ENSlT#(8zM9H>fOXv3G$?R4-nY*$v=*e|wf^4Wrc7C$CEkMh%rfOZfKGWG0WKnnM zl+VzD<((~oYUpYUGO6Zd`{HD#qcfdq&Mu47Me~wdgO<4+O{pNA(}L>K%TnnenNiuc z_0eh9=tImL;^t6o4%5wHhB?eMhfB?2mN{Ie4>2PpW~9W7l$encGg4wkO3X-!87VO% zC1#|=jg+{N5;s!fMoQdBi5n?#l2RQ1uApUAkZuVwK}Ju2bD}48d5~?ZRo&O(sB%Fj zlT4)-^rn*?spi#d8X8rP>Qy_`c1H8ty3U}dXzI-c+4a#bK>mkX2gqS2k@4nsaq6q)w^URFF}*WM*@aGuigUSdm(o z)?*Q*b;0Gyt}Zf6szS==nadVSa#mfswKLO^%#rP?jGb-OV&-s}ot}oqx^zQtHWzfL ztUlDWsFby2J>;8%&W<3L>D4D>j{2fdWhP^ws?5xD#SN()flB7ulUb9mlPglwhVsY(Y5NXx@B{|Tg>do##gWo&)!E_p>6(kp(RH+@ zGFe+E4M4}nMx*drt3wi8VBnr z!&#~eU0>PU+};hhtY^}UX(#8wUCwVyrqe-t!O_B}X`jcoHeg0$Z&#o?QawS7mP_r> zWl~vOjgisERY7YzDKyotr(u3~Q$VI3^238(hmH;;2Kj}_v+II$z9z_^$9h@AGaTKl zZ9cZ<j+EY@B3sNk5a$ylkxND z8Z4<)B}vRvYyw_Mjw5u5o!p;Z;MDwiQqh-PsZ^29(E=&GKpGE-CNIAL8*p z?2~bpKg=ud${+6W|NT$K>!?j@>4*6pNypIe(^!?Mjg+;+a%|hUyjoFP2hMH1%A4~k61oh;CK~)^4RtY z2fR{+eqk#c{LC<@So_}K$+Y-8Y2dm6EGJU&E!(tt-*lpiZ_ zJW7I}D{wsOfky?7M=|hm0>`5gIP4@GBFeN6k22urhashz^C!pS1&&7nl%F7Q+^U05 z6nL%W7YKZw<#_Z82X5aY%O{5+r7{0_WL`p?{?ruB^EyU^M!n^<#W4(Il#4M9eo@4joe} zs$)dVla|LciRu^;{0I7nPpZ+sI5P8yOrZWd{i{ZH!Z5_V<-w2a@b%#U-bu32KiKAs zFr+m4k1gjL=o*(*>Gu-w1R@hk^?NCU5D(ig`4S3I z9V3E%AEX-DewS+!)iEOGY`-fsiRu^;bGF}=nnZPs2=@Cf$)9QaS6?6|QEIyOpUpstFn6~M+lol1uzq)vY^*=+l#}v! zg|^R|=o++-u5$wPANIS?@~sXv_5r@%a?}wHT>fs$JHn9C%nw*@9{P$GF@MPN&LYw& z=3lqGOW;pgzD?kLmS+Th)bgyrU$8tU@Ruy_7WfY=zgFOQWsCXQF7P)k?-BUhmiG$$ zJq%GFw1Wc_$bSF3LLL|A%B;^$6B5j_yo&$3;ZI> zZxnd7<)0MzY|C%*xUuiK#IgR~44yAuRBGRQfD&Qu+V?F*q*Ji(t4TKO8}e`Uc!ion zzGthgf3L?Y9slwvkDKR5zQ5fkaMX|axy|FI{ynz-+db~qe}~82`tcke4)E{rKV1K3 z!jRI?PxODkt^ZDsyY=t)xLf~c2jKL%fUZA6?5+~7ch}4w=Kt(vOHq*BG1CVvnRd+^ zY3nxG7PMrN?WrARCm5TXgJ!A%r>(YBx+T?Y_S`v1JL8te>h#+Py7d3@+XS-_P94&l)YJ{^ ze$&1u_D5HArVG=9ISpEzuF?Afx=3%X&hHFbTj>o7y>pdssGOMzWN8>p7Y}Khv&Te?6|&{ub5nO`fsQ71*4DE z+%s--?ZmZ{FaN?z2m6k^GP|aE$!RseSh~CKy}P&8G`IKmy)xp&%Rd@_f9;liWwraS zJK-DeR~@WbI%-eNj+*0rGop9ajDPFNzKPFHD1E~B8y3nz+c0(qjujWSC3L4&YMGp6=T?NRRkC}Tz7(&6;O&dO2bVF|=>EIEFD6vQpzFl7D#VF+C_X?}ZWI+#4@ G)xQHij~E;P literal 0 HcmV?d00001 diff --git a/Assets/GameMain/Scenes/Game/LightingData.asset.meta b/Assets/GameMain/Scenes/Game/LightingData.asset.meta new file mode 100644 index 0000000..86c47b1 --- /dev/null +++ b/Assets/GameMain/Scenes/Game/LightingData.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fb9bd70ff25fcde4e954a6f3ec6ca2cd +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 112000000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scenes/Game/ReflectionProbe-0.exr b/Assets/GameMain/Scenes/Game/ReflectionProbe-0.exr new file mode 100644 index 0000000000000000000000000000000000000000..f38e702271bdeaeada94347ac0ba7616f66eff97 GIT binary patch literal 163864 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
d7$kXh%(BRID-a!dmJy z8Iwf1M(>T};s_#V6{u%4#N?n2OxjDr3Jl)*A3S+gLKT&?$7J^Jh|YeE0(h?J?DpBv zd#X%rQT(uMcICX~LSK!ZT%p%XzaXlDPV;BNWjT=yNT;gbf136; zxe@OxtS*(CZj?}ss$P#CSdT`=<6fx&EQVCYcTUR7$X&jDN=e4-<0#AhSYa`@`>~@V zKn4++>qL*9%O8=JFwF4W9@ySb+J%*U+tZ;-giB{U-X2)~00 zJ|MUQj%z+T+4?suVh}NC^08z@?tKAQH8#}Z1E^pQjH4OvOTH*|?ilf&ytFU+GrG6L z^yEdDd{4(OZ-Ah305DFN?id@_M1Nul$Ub`m*iWaG?js_N0D#zOE0O_D5bVniFdh(A z#4<(@KJ1#~;}yOXzYtJ?y4N=8L?P&88YII~3#V1H?oiEnUy_tiT_%pXl#+bu=hL&Q z`%qPel%wQVosyA{6IC0AQ8t^ zwLoLomri!hGs$`W#PCGeS&jOCN6(`bF?EU&ErvjWkrxYtwX=c*+(2NFSLL_tbjCogOcWT84OM*PIc7kDbYf^T=-_ZFWuu@JAfpx=A?qE*GRx5pQw0)QLVYot@n>ZI&nTeb8Zi{gat3$SwVOA7 ziQ&NW_pft$K_*KWQ;cM1iGS$HoeZvv1IG8|=r?$eoMyv&e0or4l@B>txWZVw_eHz* zsh&%B0q4T1L%=Hk^ngK4gi|Jx^oyONrg^M;%j_=$9d==`_avO zZ4JeI`+D8j)1VzBUwYzYKhfQ+wdVp%H!gq~26!Mx`pTJiKaSo3GvyT+j^4e+djt8= z94<^ndLrIV_Zd7XU_H`KU(qT% hn>reclYwo=$2a6HXVTA|~PZJqSK6a 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�SNDAKT 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­)Xg8$I{8Yh)SWmxemd%QJEBIKT~sYD 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 literal 0 HcmV?d00001 diff --git a/Assets/GameMain/Scenes/Game/ReflectionProbe-0.exr.meta b/Assets/GameMain/Scenes/Game/ReflectionProbe-0.exr.meta new file mode 100644 index 0000000..821a177 --- /dev/null +++ b/Assets/GameMain/Scenes/Game/ReflectionProbe-0.exr.meta @@ -0,0 +1,127 @@ +fileFormatVersion: 2 +guid: 0e45b8557b1831845a6e03fce7b5aa2b +TextureImporter: + internalIDToNameTable: [] + externalObjects: {} + serializedVersion: 13 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + flipGreenChannel: 0 + isReadable: 0 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + vTOnly: 0 + ignoreMipmapLimit: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 1 + seamlessCubemap: 1 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: 2 + aniso: 0 + mipBias: 0 + wrapU: 1 + wrapV: 1 + wrapW: 1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 2 + singleChannelComponent: 0 + flipbookRows: 1 + flipbookColumns: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + ignorePngGamma: 0 + applyGammaDecoding: 0 + swizzle: 50462976 + cookieLightType: 0 + platformSettings: + - serializedVersion: 3 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 100 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + - serializedVersion: 3 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + ignorePlatformSupport: 0 + androidETC2FallbackOverride: 0 + forceMaximumCompressionQuality_BC6H_BC7: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + internalID: 0 + vertices: [] + indices: + edges: [] + weights: [] + secondaryTextures: [] + nameFileIdTable: {} + mipmapLimitGroupName: + pSDRemoveMatte: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scenes/MainSettings.lighting b/Assets/GameMain/Scenes/MainSettings.lighting deleted file mode 100644 index fdc42a1..0000000 --- a/Assets/GameMain/Scenes/MainSettings.lighting +++ /dev/null @@ -1,66 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!850595691 &4890085278179872738 -LightingSettings: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_Name: MainSettings - serializedVersion: 6 - m_GIWorkflowMode: 1 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_RealtimeEnvironmentLighting: 1 - m_BounceScale: 1 - m_AlbedoBoost: 1 - m_IndirectOutputScale: 1 - m_UsingShadowmask: 0 - m_BakeBackend: 0 - m_LightmapMaxSize: 1024 - m_BakeResolution: 50 - m_Padding: 2 - m_LightmapCompression: 0 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 0 - m_CompAOExponentDirect: 0 - m_ExtractAO: 0 - m_MixedBakeMode: 1 - m_LightmapsBakeMode: 1 - m_FilterMode: 1 - m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0} - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_RealtimeResolution: 1 - m_ForceWhiteAlbedo: 0 - m_ForceUpdates: 0 - m_FinalGather: 0 - m_FinalGatherRayCount: 1024 - m_FinalGatherFiltering: 1 - m_PVRCulling: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVREnvironmentSampleCount: 512 - m_PVREnvironmentReferencePointCount: 2048 - m_LightProbeSampleCountMultiplier: 4 - m_PVRBounces: 2 - m_PVRMinBounces: 2 - m_PVREnvironmentImportanceSampling: 0 - m_PVRFilteringMode: 0 - m_PVRDenoiserTypeDirect: 0 - m_PVRDenoiserTypeIndirect: 0 - m_PVRDenoiserTypeAO: 0 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_PVRTiledBaking: 0 - m_NumRaysToShootPerTexel: -1 - m_RespectSceneVisibilityWhenBakingGI: 0 diff --git a/Assets/GameMain/Scenes/Menu.meta b/Assets/GameMain/Scenes/Menu.meta new file mode 100644 index 0000000..256b42b --- /dev/null +++ b/Assets/GameMain/Scenes/Menu.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 29930de0f940628418fed89e3808746f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scenes/Menu/LightingData.asset b/Assets/GameMain/Scenes/Menu/LightingData.asset new file mode 100644 index 0000000000000000000000000000000000000000..7f850159669310e355aafe38e8e4a803a484824d GIT binary patch literal 18256 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 literal 0 HcmV?d00001 diff --git a/Assets/GameMain/Scenes/Menu/LightingData.asset.meta b/Assets/GameMain/Scenes/Menu/LightingData.asset.meta new file mode 100644 index 0000000..48b1d34 --- /dev/null +++ b/Assets/GameMain/Scenes/Menu/LightingData.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6756a079a4ef9c6428b0209b454e1241 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 112000000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scenes/StressTest/GlobalVolumeProfile.asset b/Assets/GameMain/Scenes/StressTest/GlobalVolumeProfile.asset deleted file mode 100644 index c76f07b..0000000 --- a/Assets/GameMain/Scenes/StressTest/GlobalVolumeProfile.asset +++ /dev/null @@ -1,104 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!114 &-32820517437979890 -MonoBehaviour: - m_ObjectHideFlags: 3 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 0b2db86121404754db890f4c8dfe81b2, type: 3} - m_Name: Bloom - m_EditorClassIdentifier: - active: 1 - skipIterations: - m_OverrideState: 0 - m_Value: 1 - threshold: - m_OverrideState: 0 - m_Value: 0.9 - intensity: - m_OverrideState: 1 - m_Value: 1 - scatter: - m_OverrideState: 0 - m_Value: 0.7 - clamp: - m_OverrideState: 0 - m_Value: 65472 - tint: - m_OverrideState: 0 - m_Value: {r: 1, g: 1, b: 1, a: 1} - highQualityFiltering: - m_OverrideState: 0 - m_Value: 0 - downscale: - m_OverrideState: 0 - m_Value: 0 - maxIterations: - m_OverrideState: 0 - m_Value: 6 - dirtTexture: - m_OverrideState: 0 - m_Value: {fileID: 0} - dimension: 1 - dirtIntensity: - m_OverrideState: 0 - m_Value: 0 ---- !u!114 &11400000 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: d7fd9488000d3734a9e00ee676215985, type: 3} - m_Name: GlobalVolumeProfile - m_EditorClassIdentifier: - components: - - {fileID: 1881579288749618558} - - {fileID: -32820517437979890} ---- !u!114 &1881579288749618558 -MonoBehaviour: - m_ObjectHideFlags: 3 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 0} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: 97c23e3b12dc18c42a140437e53d3951, type: 3} - m_Name: Tonemapping - m_EditorClassIdentifier: - active: 1 - mode: - m_OverrideState: 1 - m_Value: 1 - neutralHDRRangeReductionMode: - m_OverrideState: 0 - m_Value: 2 - acesPreset: - m_OverrideState: 0 - m_Value: 3 - hueShiftAmount: - m_OverrideState: 0 - m_Value: 0 - detectPaperWhite: - m_OverrideState: 0 - m_Value: 0 - paperWhite: - m_OverrideState: 0 - m_Value: 300 - detectBrightnessLimits: - m_OverrideState: 0 - m_Value: 1 - minNits: - m_OverrideState: 0 - m_Value: 0.005 - maxNits: - m_OverrideState: 0 - m_Value: 1000 diff --git a/Assets/GameMain/Scripts/Base/GameEntry.Custom.cs b/Assets/GameMain/Scripts/Base/GameEntry.Custom.cs index d70f028..456e71c 100644 --- a/Assets/GameMain/Scripts/Base/GameEntry.Custom.cs +++ b/Assets/GameMain/Scripts/Base/GameEntry.Custom.cs @@ -18,6 +18,11 @@ public partial class GameEntry : MonoBehaviour public static BuiltinDataComponent BuiltinData { get; private set; } public static HPBarComponent HPBar { get; private set; } + + public static DamageTextComponent DamageText { get; private set; } +#if UNITY_EDITOR || DEVELOPMENT_BUILD + public static RuntimeDebugPanelComponent RuntimeDebugPanel { get; private set; } +#endif public static EnemyManagerComponent EnemyManager { get; private set; } @@ -29,6 +34,18 @@ public partial class GameEntry : MonoBehaviour { BuiltinData = UnityGameFramework.Runtime.GameEntry.GetComponent(); HPBar = UnityGameFramework.Runtime.GameEntry.GetComponent(); + DamageText = UnityGameFramework.Runtime.GameEntry.GetComponent(); + if (DamageText == null && Base != null) + { + DamageText = Base.gameObject.AddComponent(); + } +#if UNITY_EDITOR || DEVELOPMENT_BUILD + RuntimeDebugPanel = UnityGameFramework.Runtime.GameEntry.GetComponent(); + if (RuntimeDebugPanel == null && Base != null) + { + RuntimeDebugPanel = Base.gameObject.AddComponent(); + } +#endif EnemyManager = UnityGameFramework.Runtime.GameEntry.GetComponent(); SpriteCache = UnityGameFramework.Runtime.GameEntry.GetComponent(); UIRouter = UnityGameFramework.Runtime.GameEntry.GetComponent(); diff --git a/Assets/GameMain/Scripts/Components/AbsorbComponent.cs b/Assets/GameMain/Scripts/Components/AbsorbComponent.cs new file mode 100644 index 0000000..6c6bc7b --- /dev/null +++ b/Assets/GameMain/Scripts/Components/AbsorbComponent.cs @@ -0,0 +1,101 @@ +using System; +using Definition.DataStruct; +using Definition.Enum; +using Entity; +using UnityEngine; + +namespace Components +{ + public class AbsorbComponent : MonoBehaviour + { + [SerializeField] private float _absorbRangeBase = 3f; + [SerializeField] private float _absorbSpeed = 15f; + [SerializeField] private float _collectDistance = 0.35f; + [SerializeField] private int _maxDetectCount = 64; + [SerializeField] private LayerMask _detectLayerMask = ~0; + + private Player _player; + private Transform _target; + private StatComponent _statComponent; + private Collider[] _buffer; + + private StatProperty _absorbRangeStat; + private Action _absorbRangeStatCallback; + + private float AbsorbRange => Mathf.Max(0f, (_absorbRangeBase + _absorbRangeStat.Value) * _absorbRangeStat.Percent); + + public void OnInit(Player player, StatComponent statComponent = null) + { + _player = player; + _target = player != null ? player.CachedTransform : null; + _statComponent = statComponent; + _buffer = new Collider[Mathf.Max(1, _maxDetectCount)]; + + if (_statComponent != null) + { + _absorbRangeStat = _statComponent.GetStat(StatType.AbsorbRange); + _absorbRangeStatCallback = (modifier, isApply) => + _statComponent.UpdateStat(_absorbRangeStat, modifier, isApply); + _statComponent.Subscribe(StatType.AbsorbRange, _absorbRangeStatCallback); + } + else + { + _absorbRangeStat = new StatProperty(); + } + } + + public void OnUpdate(float elapseSeconds, float realElapseSeconds) + { + if (_player == null || !_player.Available || _target == null || _buffer == null) return; + + int hitCount = Physics.OverlapSphereNonAlloc( + _target.position, + AbsorbRange, + _buffer, + _detectLayerMask, + QueryTriggerInteraction.Collide + ); + + for (int i = 0; i < hitCount; i++) + { + Collider hit = _buffer[i]; + if (hit == null) continue; + + CoinEntity coin = hit.GetComponent(); + if (coin != null && coin.Available) + { + AbsorbDrop(coin.CachedTransform, elapseSeconds); + coin.TryCollect(_player, _collectDistance); + continue; + } + + ExpEntity exp = hit.GetComponent(); + if (exp != null && exp.Available) + { + AbsorbDrop(exp.CachedTransform, elapseSeconds); + exp.TryCollect(_player, _collectDistance); + } + } + } + + public void OnReset() + { + if (_statComponent != null) + { + _statComponent.Unsubscribe(StatType.AbsorbRange, _absorbRangeStatCallback); + _absorbRangeStatCallback = null; + } + + _statComponent = null; + _target = null; + _player = null; + _buffer = null; + } + + private void AbsorbDrop(Transform drop, float deltaTime) + { + if (drop == null || _target == null) return; + drop.position = Vector3.MoveTowards(drop.position, _target.position, _absorbSpeed * deltaTime); + } + } +} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableCodeGenerator.cs.meta b/Assets/GameMain/Scripts/Components/AbsorbComponent.cs.meta similarity index 83% rename from Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableCodeGenerator.cs.meta rename to Assets/GameMain/Scripts/Components/AbsorbComponent.cs.meta index 9c867cf..0d15fec 100644 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableCodeGenerator.cs.meta +++ b/Assets/GameMain/Scripts/Components/AbsorbComponent.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 40941eb45ca7d284f8a806370b88fa78 +guid: 46f46350fed64d8389ebb4ae72b65796 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/GameMain/Scripts/Components/HealthComponent.cs b/Assets/GameMain/Scripts/Components/HealthComponent.cs index 26aca1e..5aad635 100644 --- a/Assets/GameMain/Scripts/Components/HealthComponent.cs +++ b/Assets/GameMain/Scripts/Components/HealthComponent.cs @@ -1,4 +1,4 @@ -using System; +using System; using CustomEvent; using Definition.DataStruct; using Definition.Enum; @@ -119,7 +119,9 @@ namespace Components private void CauseDamage(int damage) { - //TODO:受击效果:跳字、粒子 + if (damage <= 0 || GameEntry.DamageText == null) return; + GameEntry.DamageText.ShowDamage(transform.position + Vector3.up * 1.1f, damage); } } -} \ No newline at end of file +} + diff --git a/Assets/GameMain/Scripts/CustomComponent/DamageText.meta b/Assets/GameMain/Scripts/CustomComponent/DamageText.meta new file mode 100644 index 0000000..814975c --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/DamageText.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6befdfdd5f3e430a864a90bf445000e8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextComponent.cs b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextComponent.cs new file mode 100644 index 0000000..86efb80 --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextComponent.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using GameFramework.ObjectPool; +using TMPro; +using UnityEngine; +using UnityEngine.UI; +using UnityGameFramework.Runtime; + +namespace CustomComponent +{ + public class DamageTextComponent : GameFrameworkComponent + { + [SerializeField] private int _instancePoolCapacity = 32; + + [SerializeField] private string _poolName = "DamageTextItem"; + + [SerializeField] private RectTransform _instanceRoot; + + [SerializeField] private Canvas _canvas; + + [SerializeField] private GameObject _damageTextItemPrefab; + + private IObjectPool _damageTextItemPool; + + private readonly List _activeDamageTextItems = new(); + + private void Start() + { + _damageTextItemPool = + GameEntry.ObjectPool.CreateSingleSpawnObjectPool(_poolName, + _instancePoolCapacity); + } + + public void ShowDamage(Vector3 worldPosition, int damage) + { + if (damage <= 0 || _damageTextItemPool == null || _canvas == null) return; + + DamageTextItem item = CreateDamageTextItem(); + if (item == null) return; + + item.Show(worldPosition, damage, _canvas, OnItemComplete); + _activeDamageTextItems.Add(item); + } + + private DamageTextItem CreateDamageTextItem() + { + DamageTextItemObject itemObject = _damageTextItemPool.Spawn(); + if (itemObject != null) + { + return (DamageTextItem)itemObject.Target; + } + + GameObject itemGo = Instantiate(_damageTextItemPrefab, _instanceRoot, false); + + DamageTextItem item = itemGo.GetComponent(); + _damageTextItemPool.Register(DamageTextItemObject.Create(item), true); + return item; + } + + private void OnItemComplete(DamageTextItem item) + { + if (item == null) return; + item.ResetItem(); + _activeDamageTextItems.Remove(item); + _damageTextItemPool.Unspawn(item); + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGenerator.cs.meta b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextComponent.cs.meta similarity index 83% rename from Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGenerator.cs.meta rename to Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextComponent.cs.meta index 37a8f2f..ff14999 100644 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGenerator.cs.meta +++ b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextComponent.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: f91ec109eb6c73a408325960701b4c94 +guid: 366eb88b821a4048891b7fb01a1b8d42 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItem.cs b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItem.cs new file mode 100644 index 0000000..21ea3c4 --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItem.cs @@ -0,0 +1,80 @@ +using System; +using DG.Tweening; +using TMPro; +using UnityEngine; + +namespace CustomComponent +{ + public class DamageTextItem : MonoBehaviour + { + private const float RiseDistance = 80f; + private const float RiseDuration = 0.55f; + private const float FadeDelay = 0.2f; + private const float FadeDuration = 0.35f; + private static readonly Color NormalColor = new Color(1f, 0.32f, 0.23f, 1f); + + [SerializeField] private RectTransform _cachedTransform; + + [SerializeField] private CanvasGroup _canvasGroup; + + [SerializeField] private TMP_Text _text; + + private Sequence _sequence; + private Action _onComplete; + + private void Awake() + { + if (_cachedTransform == null) _cachedTransform = GetComponent(); + if (_canvasGroup == null) _canvasGroup = GetComponent(); + if (_text == null) _text = GetComponent(); + } + + public void Show(Vector3 worldPosition, int damage, Canvas canvas, Action onComplete) + { + if (canvas == null || GameEntry.Scene.MainCamera == null) return; + + _onComplete = onComplete; + gameObject.SetActive(true); + KillSequence(); + + _canvasGroup.alpha = 1f; + _cachedTransform.localScale = Vector3.one; + _text.color = NormalColor; + _text.text = damage.ToString(); + + Vector3 screenPos = GameEntry.Scene.MainCamera.WorldToScreenPoint(worldPosition); + RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)canvas.transform, screenPos, + canvas.worldCamera, out Vector2 localPos); + localPos.x += UnityEngine.Random.Range(-24f, 24f); + _cachedTransform.anchoredPosition = localPos; + + _sequence = DOTween.Sequence(); + _sequence.Append(_cachedTransform.DOAnchorPosY(localPos.y + RiseDistance, RiseDuration) + .SetEase(Ease.OutQuad)); + _sequence.Join(_cachedTransform.DOPunchScale(new Vector3(0.15f, 0.15f, 0f), 0.18f, 6, 0.75f)); + _sequence.Join(_canvasGroup.DOFade(0f, FadeDuration).SetDelay(FadeDelay)); + _sequence.OnComplete(() => _onComplete?.Invoke(this)); + } + + public void ResetItem() + { + KillSequence(); + _onComplete = null; + _canvasGroup.alpha = 1f; + _text.text = string.Empty; + gameObject.SetActive(false); + } + + private void OnDestroy() + { + KillSequence(); + } + + private void KillSequence() + { + if (_sequence == null) return; + _sequence.Kill(); + _sequence = null; + } + } +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGeneratorMenu.cs.meta b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItem.cs.meta similarity index 83% rename from Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGeneratorMenu.cs.meta rename to Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItem.cs.meta index 9c5322f..552af7c 100644 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGeneratorMenu.cs.meta +++ b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItem.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 7ddc8f13b2516c643a67d92a319dbf72 +guid: 501e678f9cb14af6ac45e8d2050388d3 MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItemObject.cs b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItemObject.cs new file mode 100644 index 0000000..3ff5800 --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItemObject.cs @@ -0,0 +1,23 @@ +using GameFramework; +using GameFramework.ObjectPool; +using UnityEngine; + +namespace CustomComponent +{ + public class DamageTextItemObject : ObjectBase + { + public static DamageTextItemObject Create(object target) + { + DamageTextItemObject itemObject = ReferencePool.Acquire(); + itemObject.Initialize(target); + return itemObject; + } + + protected override void Release(bool isShutdown) + { + DamageTextItem item = (DamageTextItem)Target; + if (item == null) return; + Object.Destroy(item.gameObject); + } + } +} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.BooleanProcessor.cs.meta b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItemObject.cs.meta similarity index 83% rename from Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.BooleanProcessor.cs.meta rename to Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItemObject.cs.meta index 1c86b4f..8fb6ccb 100644 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.BooleanProcessor.cs.meta +++ b/Assets/GameMain/Scripts/CustomComponent/DamageText/DamageTextItemObject.cs.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: 00bc8bc968fa2134095a36a43f326d56 +guid: 4aba1230dece448eba1fa7579ca7a13d MonoImporter: externalObjects: {} serializedVersion: 2 diff --git a/Assets/GameMain/Scripts/CustomComponent/DebugPanel.meta b/Assets/GameMain/Scripts/CustomComponent/DebugPanel.meta new file mode 100644 index 0000000..38c84e7 --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/DebugPanel.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a11ef2e359b24bfdb6c9120cc2ec81b8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/CustomComponent/DebugPanel/RuntimeDebugPanelComponent.cs b/Assets/GameMain/Scripts/CustomComponent/DebugPanel/RuntimeDebugPanelComponent.cs new file mode 100644 index 0000000..06228ed --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/DebugPanel/RuntimeDebugPanelComponent.cs @@ -0,0 +1,349 @@ +#if UNITY_EDITOR || DEVELOPMENT_BUILD +using System; +using System.Linq; +using DataTable; +using Definition.DataStruct; +using Entity; +using Game.Utility; +using UnityEngine; +using UnityGameFramework.Runtime; +#if ENABLE_INPUT_SYSTEM +using UnityEngine.InputSystem; +#endif + +namespace CustomComponent +{ + public class RuntimeDebugPanelComponent : GameFrameworkComponent + { + private const float MinSpawnRate = 0.1f; + private const float CornerTapWindow = 0.6f; + private const int RequiredCornerTapCount = 3; + + private Rect _windowRect = new Rect(20f, 60f, 460f, 620f); + private bool _isPanelVisible; + private int _windowId; + + private string _searchText = string.Empty; + private int _selectedIndex; + private int _addCount = 1; + private Vector2 _buffScroll; + + private float _spawnRateScaleInput = 1f; + private float _extendDurationSeconds = 30f; + + private DRProp[] _allProps = Array.Empty(); + private DRProp[] _filteredProps = Array.Empty(); + private string[] _displayNames = Array.Empty(); + + private int _cornerTapCount; + private float _lastCornerTapTime = -10f; + + protected override void Awake() + { + base.Awake(); + + _windowId = GetInstanceID(); + } + + private void Update() + { + if (IsTogglePressed()) + { + _isPanelVisible = !_isPanelVisible; + } + + HandleCornerTapGesture(); + } + + private void OnGUI() + { + DrawToggleButton(); + if (!_isPanelVisible) return; + + _windowRect = GUI.Window(_windowId, _windowRect, DrawWindow, "Runtime Debug Panel"); + } + + private void DrawToggleButton() + { + const float width = 64f; + const float height = 30f; + Rect buttonRect = new Rect(Screen.width - width - 12f, 10f, width, height); + if (GUI.Button(buttonRect, "DEBUG")) + { + _isPanelVisible = !_isPanelVisible; + } + } + + private void DrawWindow(int windowId) + { + EnsurePropList(); + + GUILayout.BeginVertical(); + + DrawBuffSection(); + + GUILayout.Space(8f); + GUILayout.Label(string.Empty, GUI.skin.horizontalSlider); + GUILayout.Space(8f); + + DrawBattleSection(); + + GUILayout.Space(8f); + GUILayout.Label("Tips: press `F8` or tap top-left corner 3 times to toggle.", GUILayout.Height(20f)); + + GUILayout.EndVertical(); + GUI.DragWindow(new Rect(0, 0, 10000, 22)); + } + + private void DrawBuffSection() + { + GUILayout.Label("Buff Debug"); + GUILayout.BeginHorizontal(); + GUILayout.Label("Search", GUILayout.Width(52f)); + _searchText = GUILayout.TextField(_searchText); + if (GUILayout.Button("Refresh", GUILayout.Width(80f))) + { + EnsurePropList(true); + } + GUILayout.EndHorizontal(); + + ApplyFilter(_searchText); + if (_displayNames.Length == 0) + { + GUILayout.Label("No Buff data. Enter battle and try again."); + return; + } + + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1); + _buffScroll = GUILayout.BeginScrollView(_buffScroll, GUILayout.Height(120f)); + _selectedIndex = GUILayout.SelectionGrid(_selectedIndex, _displayNames, 1); + GUILayout.EndScrollView(); + + DRProp selectedProp = GetSelectedProp(); + if (selectedProp == null) return; + + GUILayout.Label($"Selected: {selectedProp.Title} ({selectedProp.Rarity})"); + GUILayout.Label(ItemDescUtility.CreatePropDescription(selectedProp.Modifiers), GUILayout.Height(40f)); + + GUILayout.BeginHorizontal(); + GUILayout.Label("Count", GUILayout.Width(52f)); + string addCountText = GUILayout.TextField(_addCount.ToString(), GUILayout.Width(60f)); + if (!int.TryParse(addCountText, out _addCount)) _addCount = 1; + _addCount = Mathf.Clamp(_addCount, 1, 99); + + if (GUILayout.Button("Add Buff To Player", GUILayout.Height(24f))) + { + AddSelectedBuffToPlayer(selectedProp, _addCount); + } + GUILayout.EndHorizontal(); + } + + private void DrawBattleSection() + { + GUILayout.Label("Battle Debug"); + EnemyManagerComponent enemyManager = GameEntry.EnemyManager; + Player player = FindPlayer(); + + if (enemyManager == null) + { + GUILayout.Label("EnemyManager unavailable."); + return; + } + + GUILayout.Label($"Spawn Rate: {enemyManager.SpawnRateScale:F2}"); + GUILayout.Label($"Battle Time: {enemyManager.ElapsedBattleTime:F1}s / {enemyManager.BattleDuration:F1}s"); + + GUILayout.BeginHorizontal(); + GUILayout.Label("Rate", GUILayout.Width(52f)); + string rateText = GUILayout.TextField(_spawnRateScaleInput.ToString("F2"), GUILayout.Width(60f)); + if (float.TryParse(rateText, out float parsedRate)) + { + _spawnRateScaleInput = Mathf.Clamp(parsedRate, MinSpawnRate, 50f); + } + + if (GUILayout.Button("Apply", GUILayout.Width(70f))) + { + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + } + if (GUILayout.Button("x0.5", GUILayout.Width(60f))) + { + _spawnRateScaleInput = Mathf.Max(MinSpawnRate, enemyManager.SpawnRateScale * 0.5f); + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + } + if (GUILayout.Button("x2", GUILayout.Width(60f))) + { + _spawnRateScaleInput = enemyManager.SpawnRateScale * 2f; + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + } + GUILayout.EndHorizontal(); + + GUILayout.BeginHorizontal(); + GUILayout.Label("Add Sec", GUILayout.Width(52f)); + string durationText = GUILayout.TextField(_extendDurationSeconds.ToString("F0"), GUILayout.Width(60f)); + if (float.TryParse(durationText, out float parsedDuration)) + { + _extendDurationSeconds = Mathf.Clamp(parsedDuration, 1f, 3600f); + } + + if (GUILayout.Button("Extend Battle", GUILayout.Height(24f))) + { + enemyManager.AddBattleDuration(_extendDurationSeconds); + } + GUILayout.EndHorizontal(); + + GUILayout.Label($"Player Weapon: {(player == null ? "Player not found" : (player.WeaponEnabled ? "Enabled" : "Disabled"))}"); + GUILayout.BeginHorizontal(); + GUI.enabled = player != null; + if (GUILayout.Button("Disable Weapons", GUILayout.Height(24f))) + { + player.SetWeaponEnabled(false); + } + if (GUILayout.Button("Enable Weapons", GUILayout.Height(24f))) + { + player.SetWeaponEnabled(true); + } + GUI.enabled = true; + GUILayout.EndHorizontal(); + } + + private void EnsurePropList(bool force = false) + { + if (!force && _allProps != null && _allProps.Length > 0) return; + + if (GameEntry.DataTable == null) + { + _allProps = Array.Empty(); + _filteredProps = Array.Empty(); + _displayNames = Array.Empty(); + return; + } + + var table = GameEntry.DataTable.GetDataTable(); + _allProps = table != null ? table.ToArray() : Array.Empty(); + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, Mathf.Max(0, _allProps.Length - 1)); + ApplyFilter(_searchText); + } + + private void ApplyFilter(string keyword) + { + if (_allProps == null || _allProps.Length == 0) + { + _filteredProps = Array.Empty(); + _displayNames = Array.Empty(); + return; + } + + if (string.IsNullOrWhiteSpace(keyword)) + { + _filteredProps = _allProps; + } + else + { + string search = keyword.Trim(); + _filteredProps = _allProps.Where(p => + p != null && + (p.Title?.IndexOf(search, StringComparison.OrdinalIgnoreCase) >= 0 || + p.Id.ToString().Contains(search))).ToArray(); + } + + _displayNames = _filteredProps.Select(p => $"[{p.Id}] {p.Title} ({p.Rarity})").ToArray(); + if (_displayNames.Length == 0) _selectedIndex = 0; + else _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1); + } + + private DRProp GetSelectedProp() + { + if (_filteredProps == null || _filteredProps.Length == 0) return null; + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _filteredProps.Length - 1); + return _filteredProps[_selectedIndex]; + } + + private static Player FindPlayer() + { + return UnityEngine.Object.FindObjectOfType(); + } + + private static void AddSelectedBuffToPlayer(DRProp prop, int count) + { + Player player = FindPlayer(); + if (player == null || prop == null || prop.Modifiers == null) return; + + int applyCount = Mathf.Clamp(count, 1, 99); + for (int i = 0; i < applyCount; i++) + { + player.AddProp(new PropItem(prop.Modifiers, prop.Rarity, prop.Title, prop.IconAssetName)); + } + } + + private void HandleCornerTapGesture() + { + if (!TryGetTouchReleased(out Vector2 touchPosition)) return; + if (touchPosition.x > 80f || touchPosition.y < Screen.height - 80f) return; + + float now = Time.unscaledTime; + if (now - _lastCornerTapTime > CornerTapWindow) + { + _cornerTapCount = 0; + } + + _lastCornerTapTime = now; + _cornerTapCount++; + + if (_cornerTapCount >= RequiredCornerTapCount) + { + _cornerTapCount = 0; + _isPanelVisible = !_isPanelVisible; + } + } + + private static bool IsTogglePressed() + { +#if ENABLE_INPUT_SYSTEM + Keyboard keyboard = Keyboard.current; + if (keyboard == null) return false; + return keyboard.backquoteKey.wasPressedThisFrame || keyboard.f8Key.wasPressedThisFrame; +#else + return Input.GetKeyDown(KeyCode.BackQuote) || Input.GetKeyDown(KeyCode.F8); +#endif + } + + private static bool TryGetTouchReleased(out Vector2 touchPosition) + { +#if ENABLE_INPUT_SYSTEM + Touchscreen touchscreen = Touchscreen.current; + if (touchscreen == null) + { + touchPosition = default; + return false; + } + + var touch = touchscreen.primaryTouch; + if (!touch.press.wasReleasedThisFrame) + { + touchPosition = default; + return false; + } + + touchPosition = touch.position.ReadValue(); + return true; +#else + if (Input.touchCount <= 0) + { + touchPosition = default; + return false; + } + + Touch touch = Input.GetTouch(0); + if (touch.phase != TouchPhase.Ended) + { + touchPosition = default; + return false; + } + + touchPosition = touch.position; + return true; +#endif + } + } +} +#endif diff --git a/Assets/GameMain/Scripts/CustomComponent/DebugPanel/RuntimeDebugPanelComponent.cs.meta b/Assets/GameMain/Scripts/CustomComponent/DebugPanel/RuntimeDebugPanelComponent.cs.meta new file mode 100644 index 0000000..c9a928c --- /dev/null +++ b/Assets/GameMain/Scripts/CustomComponent/DebugPanel/RuntimeDebugPanelComponent.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1d8ada5157a04921a6e543a040e57960 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/CustomComponent/EnemyManager/EnemyManagerComponent.cs b/Assets/GameMain/Scripts/CustomComponent/EnemyManager/EnemyManagerComponent.cs index 0110d03..b6e81a4 100644 --- a/Assets/GameMain/Scripts/CustomComponent/EnemyManager/EnemyManagerComponent.cs +++ b/Assets/GameMain/Scripts/CustomComponent/EnemyManager/EnemyManagerComponent.cs @@ -13,6 +13,8 @@ namespace CustomComponent { public class EnemyManagerComponent : GameFrameworkComponent { + private const float MinSpawnRateScale = 0.1f; + private EntityComponent _entity; private List _enemies; @@ -20,23 +22,35 @@ namespace CustomComponent public List Enemies => _enemies; private float _spawnEnemyTimer; + private int _spawnEnemyMaxCount = 5000; + private int _currentEnemyCount; + private int _spawnDistanceFromPlayer = 20; + private int _currentSpawnEnemyId; + private int _currentLevel; + private float[] _baseSpawnEnemyIntervals; private float[] _spawnEnemyIntervals; private int[] _spawnEnemyIds; private int[] _spawnEnemyCounts; private float _duration; + private float _baseDuration; private float[] _nextSpawnTimes; + private float _spawnRateScale = 1f; private Transform _player; private GameStateBattle _battle; + public float SpawnRateScale => _spawnRateScale; + public float BattleDuration => _duration; + public float ElapsedBattleTime => _spawnEnemyTimer; + #region FSM private void Start() @@ -64,12 +78,14 @@ namespace CustomComponent _currentLevel = level; DRLevel levelData = GameEntry.DataTable.GetDataTableRow(_currentLevel); - _spawnEnemyIntervals = levelData.Intervals; + _baseSpawnEnemyIntervals = (float[])levelData.Intervals.Clone(); + _spawnEnemyIntervals = (float[])_baseSpawnEnemyIntervals.Clone(); _spawnEnemyIds = levelData.EntityIds; _spawnEnemyCounts = levelData.EntityCounts; - _duration = levelData.Duration; + _baseDuration = levelData.Duration; + _duration = _baseDuration; - _nextSpawnTimes = (float[])_spawnEnemyIntervals.Clone(); + SetSpawnRateScale(_spawnRateScale); _currentSpawnEnemyId = 0; } @@ -77,10 +93,7 @@ namespace CustomComponent public void OnUpdate(float elapseSeconds, float realElapseSeconds) { _spawnEnemyTimer += elapseSeconds; - // if (_spawnEnemyTimer < _spawnEnemyInterval) return; - // SpawnEnemy(); - // _spawnEnemyTimer = 0; - // _spawnEnemyInterval = Mathf.Max(0.1f, _spawnEnemyInterval - _spawnEnemyAccelerate); + if (_spawnEnemyTimer > _duration) { _battle.LevelOver(); @@ -108,9 +121,11 @@ namespace CustomComponent _currentSpawnEnemyId = 0; _currentLevel = 0; + _baseSpawnEnemyIntervals = null; _spawnEnemyIntervals = null; _spawnEnemyIds = null; _spawnEnemyCounts = null; + _baseDuration = 0; _duration = 0; _nextSpawnTimes = null; @@ -120,6 +135,57 @@ namespace CustomComponent ClearEnemies(); } + public void SetSpawnRateScale(float scale) + { + float newScale = Mathf.Max(MinSpawnRateScale, scale); + if (_baseSpawnEnemyIntervals == null || _baseSpawnEnemyIntervals.Length == 0) + { + _spawnRateScale = newScale; + return; + } + + bool hasRuntimeState = _nextSpawnTimes != null && _spawnEnemyIntervals != null && + _nextSpawnTimes.Length == _baseSpawnEnemyIntervals.Length && + _spawnEnemyIntervals.Length == _baseSpawnEnemyIntervals.Length; + float oldScale = _spawnRateScale; + _spawnRateScale = newScale; + + if (!hasRuntimeState) + { + for (int i = 0; i < _baseSpawnEnemyIntervals.Length; i++) + { + _spawnEnemyIntervals[i] = GetScaledInterval(_baseSpawnEnemyIntervals[i], _spawnRateScale); + } + + _nextSpawnTimes = (float[])_spawnEnemyIntervals.Clone(); + return; + } + + for (int i = 0; i < _baseSpawnEnemyIntervals.Length; i++) + { + float oldInterval = GetScaledInterval(_baseSpawnEnemyIntervals[i], oldScale); + float newInterval = GetScaledInterval(_baseSpawnEnemyIntervals[i], _spawnRateScale); + + float remainTime = Mathf.Max(0f, _nextSpawnTimes[i] - _spawnEnemyTimer); + float remainRatio = oldInterval > Mathf.Epsilon ? Mathf.Clamp01(remainTime / oldInterval) : 0f; + + _spawnEnemyIntervals[i] = newInterval; + _nextSpawnTimes[i] = _spawnEnemyTimer + newInterval * remainRatio; + } + } + + public void AddBattleDuration(float seconds) + { + if (seconds <= 0f) return; + _duration += seconds; + } + + private static float GetScaledInterval(float baseInterval, float scale) + { + float safeScale = Mathf.Max(MinSpawnRateScale, scale); + return baseInterval / safeScale; + } + #endregion private void SpawnEnemy(int entityId) @@ -128,7 +194,7 @@ namespace CustomComponent if (_currentEnemyCount >= _spawnEnemyMaxCount) return; int entityPoolId = _currentSpawnEnemyId % _spawnEnemyMaxCount; - var enemyData = new EnemyData(entityPoolId, entityId) + var enemyData = new EnemyData(entityPoolId, entityId, _currentLevel) { Position = GetRandomPosition() }; @@ -187,4 +253,4 @@ namespace CustomComponent #endregion } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/CustomComponent/HPBar/HPBarComponent.cs b/Assets/GameMain/Scripts/CustomComponent/HPBar/HPBarComponent.cs index ebc7833..dbcbc64 100644 --- a/Assets/GameMain/Scripts/CustomComponent/HPBar/HPBarComponent.cs +++ b/Assets/GameMain/Scripts/CustomComponent/HPBar/HPBarComponent.cs @@ -17,14 +17,11 @@ namespace CustomComponent { public class HPBarComponent : GameFrameworkComponent { - [FormerlySerializedAs("m_HPBarItemTemplate")] [SerializeField] - private HPBarItem _hpBarItemTemplate = null; + [SerializeField] private HPBarItem _hpBarItemTemplate = null; - [FormerlySerializedAs("m_HPBarInstanceRoot")] [SerializeField] - private Transform _hpBarInstanceRoot = null; + [SerializeField] private Transform _hpBarInstanceRoot = null; - [FormerlySerializedAs("m_InstancePoolCapacity")] [SerializeField] - private int _instancePoolCapacity = 16; + [SerializeField] private int _instancePoolCapacity = 16; private IObjectPool _hpBarItemObjectPool = null; private List _activeHPBarItems = null; @@ -39,7 +36,8 @@ namespace CustomComponent } _cachedCanvas = _hpBarInstanceRoot.GetComponent(); - _hpBarItemObjectPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool("HPBarItem", _instancePoolCapacity); + _hpBarItemObjectPool = + GameEntry.ObjectPool.CreateSingleSpawnObjectPool("HPBarItem", _instancePoolCapacity); _activeHPBarItems = new List(); } @@ -124,4 +122,4 @@ namespace CustomComponent return hpBarItem; } } -} +} \ No newline at end of file diff --git a/Assets/GameMain/Scripts/DataTable/DREnemy.cs b/Assets/GameMain/Scripts/DataTable/DREnemy.cs index 546c1be..f56e9ad 100644 --- a/Assets/GameMain/Scripts/DataTable/DREnemy.cs +++ b/Assets/GameMain/Scripts/DataTable/DREnemy.cs @@ -7,6 +7,7 @@ namespace DataTable private int m_id; public override int Id => m_id; public int MaxHealth { get; private set; } + public int HpAddPerLevel { get; private set; } public float Speed { get; private set; } public int DropCoin { get; private set; } public int DropExp { get; private set; } @@ -21,6 +22,7 @@ namespace DataTable m_id = int.Parse(columnStrings[index++]); index++; MaxHealth = int.Parse(columnStrings[index++]); + HpAddPerLevel = int.Parse(columnStrings[index++]); Speed = float.Parse(columnStrings[index++]); DropCoin = int.Parse(columnStrings[index++]); DropExp = int.Parse(columnStrings[index++]); @@ -29,4 +31,4 @@ namespace DataTable return true; } } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/DataTable/DRLevelRarity.cs b/Assets/GameMain/Scripts/DataTable/DRLevelRarity.cs new file mode 100644 index 0000000..90e7e97 --- /dev/null +++ b/Assets/GameMain/Scripts/DataTable/DRLevelRarity.cs @@ -0,0 +1,39 @@ +using UnityGameFramework.Runtime; + +namespace DataTable +{ + public class DRLevelRarity : DataRowBase + { + private int m_Id; + + public override int Id => m_Id; + + public int LevelMin { get; private set; } + public int LevelMax { get; private set; } + + public int WhiteWeight { get; private set; } + public int GreenWeight { get; private set; } + public int BlueWeight { get; private set; } + public int PurpleWeight { get; private set; } + public int RedWeight { get; private set; } + + public override bool ParseDataRow(string dataRowString, object userData) + { + string[] fields = dataRowString.Split(DataTableExtension.DataSplitSeparators); + + int index = 0; + index++; + m_Id = int.Parse(fields[index++]); + index++; + LevelMin = int.Parse(fields[index++]); + LevelMax = int.Parse(fields[index++]); + WhiteWeight = int.Parse(fields[index++]); + GreenWeight = int.Parse(fields[index++]); + BlueWeight = int.Parse(fields[index++]); + PurpleWeight = int.Parse(fields[index++]); + RedWeight = int.Parse(fields[index++]); + + return true; + } + } +} diff --git a/Assets/GameMain/Scripts/DataTable/DRLevelRarity.cs.meta b/Assets/GameMain/Scripts/DataTable/DRLevelRarity.cs.meta new file mode 100644 index 0000000..13b53a9 --- /dev/null +++ b/Assets/GameMain/Scripts/DataTable/DRLevelRarity.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2be3a3c9896a441496abfb07467e9e19 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/DataTable/DRLevelUpReward.cs b/Assets/GameMain/Scripts/DataTable/DRLevelUpReward.cs index e37c5ed..57c8f24 100644 --- a/Assets/GameMain/Scripts/DataTable/DRLevelUpReward.cs +++ b/Assets/GameMain/Scripts/DataTable/DRLevelUpReward.cs @@ -1,5 +1,7 @@ using Definition.DataStruct; +using Definition.Enum; using Newtonsoft.Json; +using StarForce; using UnityGameFramework.Runtime; namespace DataTable @@ -13,6 +15,8 @@ namespace DataTable public string Title { get; private set; } public string IconAssetName { get; private set; } + + public ItemRarity Rarity { get; private set; } public StatModifier[] Modifiers { get; private set; } @@ -26,6 +30,7 @@ namespace DataTable index++; Title = fields[index++]; IconAssetName = fields[index++]; + Rarity = EnumUtility.Get(fields[index++]); Modifiers = JsonConvert.DeserializeObject(fields[index++]); return true; diff --git a/Assets/GameMain/Scripts/Definition/DataStruct/StatModifier.cs b/Assets/GameMain/Scripts/Definition/DataStruct/StatModifier.cs index 6d79cb1..97b59b6 100644 --- a/Assets/GameMain/Scripts/Definition/DataStruct/StatModifier.cs +++ b/Assets/GameMain/Scripts/Definition/DataStruct/StatModifier.cs @@ -16,6 +16,7 @@ namespace Definition.DataStruct // Critical = 6, // CriticalDamage = 7, // Dodge = 8, + // AbsorbRange = 9 private readonly string[] _statTypeNames = { @@ -27,7 +28,8 @@ namespace Definition.DataStruct "冷却", "暴击率", "暴击伤害", - "闪避" + "闪避", + "金币/经验吸收范围" }; public StatType StatType; diff --git a/Assets/GameMain/Scripts/Definition/Enum/StatType.cs b/Assets/GameMain/Scripts/Definition/Enum/StatType.cs index 388e680..b1e5961 100644 --- a/Assets/GameMain/Scripts/Definition/Enum/StatType.cs +++ b/Assets/GameMain/Scripts/Definition/Enum/StatType.cs @@ -3,7 +3,7 @@ namespace Definition.Enum public enum StatType { None = 0, - + MaxHealth = 1, MovementSpeed = 2, Attack = 3, @@ -12,5 +12,6 @@ namespace Definition.Enum Critical = 6, CriticalDamage = 7, Dodge = 8, + AbsorbRange = 9, } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableCodeGenerator.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableCodeGenerator.cs deleted file mode 100644 index af3c559..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableCodeGenerator.cs +++ /dev/null @@ -1,13 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.Text; - -namespace StarForce.Editor.DataTableTools -{ - public delegate void DataTableCodeGenerator(DataTableProcessor dataTableProcessor, StringBuilder codeContent, object userData); -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGenerator.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGenerator.cs deleted file mode 100644 index fd76f3e..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGenerator.cs +++ /dev/null @@ -1,412 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using GameFramework; -using System; -using System.Collections.Generic; -using System.IO; -using System.Text; -using System.Text.RegularExpressions; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed class DataTableGenerator - { - private const string DataTablePath = "Assets/GameMain/DataTables"; - private const string CSharpCodePath = "Assets/GameMain/Scripts/DataTable"; - private const string CSharpCodeTemplateFileName = "Assets/GameMain/Configs/DataTableCodeTemplate.txt"; - private static readonly Regex EndWithNumberRegex = new Regex(@"\d+$"); - private static readonly Regex NameRegex = new Regex(@"^[A-Z][A-Za-z0-9_]*$"); - - public static DataTableProcessor CreateDataTableProcessor(string dataTableName) - { - return new DataTableProcessor(Utility.Path.GetRegularPath(Path.Combine(DataTablePath, dataTableName + ".txt")), Encoding.GetEncoding("GB2312"), 1, 2, null, 3, 4, 1); - } - - public static bool CheckRawData(DataTableProcessor dataTableProcessor, string dataTableName) - { - for (int i = 0; i < dataTableProcessor.RawColumnCount; i++) - { - string name = dataTableProcessor.GetName(i); - if (string.IsNullOrEmpty(name) || name == "#") - { - continue; - } - - if (!NameRegex.IsMatch(name)) - { - Debug.LogWarning(Utility.Text.Format("Check raw data failure. DataTableName='{0}' Name='{1}'", dataTableName, name)); - return false; - } - } - - return true; - } - - public static void GenerateDataFile(DataTableProcessor dataTableProcessor, string dataTableName) - { - string binaryDataFileName = Utility.Path.GetRegularPath(Path.Combine(DataTablePath, dataTableName + ".bytes")); - if (!dataTableProcessor.GenerateDataFile(binaryDataFileName) && File.Exists(binaryDataFileName)) - { - File.Delete(binaryDataFileName); - } - } - - public static void GenerateCodeFile(DataTableProcessor dataTableProcessor, string dataTableName) - { - dataTableProcessor.SetCodeTemplate(CSharpCodeTemplateFileName, Encoding.UTF8); - dataTableProcessor.SetCodeGenerator(DataTableCodeGenerator); - - string csharpCodeFileName = Utility.Path.GetRegularPath(Path.Combine(CSharpCodePath, "DR" + dataTableName + ".cs")); - if (!dataTableProcessor.GenerateCodeFile(csharpCodeFileName, Encoding.UTF8, dataTableName) && File.Exists(csharpCodeFileName)) - { - File.Delete(csharpCodeFileName); - } - } - - private static void DataTableCodeGenerator(DataTableProcessor dataTableProcessor, StringBuilder codeContent, object userData) - { - string dataTableName = (string)userData; - - codeContent.Replace("__DATA_TABLE_CREATE_TIME__", DateTime.UtcNow.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss.fff")); - codeContent.Replace("__DATA_TABLE_NAME_SPACE__", "StarForce"); - codeContent.Replace("__DATA_TABLE_CLASS_NAME__", "DR" + dataTableName); - codeContent.Replace("__DATA_TABLE_COMMENT__", dataTableProcessor.GetValue(0, 1) + "。"); - codeContent.Replace("__DATA_TABLE_ID_COMMENT__", "获取" + dataTableProcessor.GetComment(dataTableProcessor.IdColumn) + "。"); - codeContent.Replace("__DATA_TABLE_PROPERTIES__", GenerateDataTableProperties(dataTableProcessor)); - codeContent.Replace("__DATA_TABLE_PARSER__", GenerateDataTableParser(dataTableProcessor)); - codeContent.Replace("__DATA_TABLE_PROPERTY_ARRAY__", GenerateDataTablePropertyArray(dataTableProcessor)); - } - - private static string GenerateDataTableProperties(DataTableProcessor dataTableProcessor) - { - StringBuilder stringBuilder = new StringBuilder(); - bool firstProperty = true; - for (int i = 0; i < dataTableProcessor.RawColumnCount; i++) - { - if (dataTableProcessor.IsCommentColumn(i)) - { - // 注释列 - continue; - } - - if (dataTableProcessor.IsIdColumn(i)) - { - // 编号列 - continue; - } - - if (firstProperty) - { - firstProperty = false; - } - else - { - stringBuilder.AppendLine().AppendLine(); - } - - stringBuilder - .AppendLine(" /// ") - .AppendFormat(" /// 获取{0}。", dataTableProcessor.GetComment(i)).AppendLine() - .AppendLine(" /// ") - .AppendFormat(" public {0} {1}", dataTableProcessor.GetLanguageKeyword(i), dataTableProcessor.GetName(i)).AppendLine() - .AppendLine(" {") - .AppendLine(" get;") - .AppendLine(" private set;") - .Append(" }"); - } - - return stringBuilder.ToString(); - } - - private static string GenerateDataTableParser(DataTableProcessor dataTableProcessor) - { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder - .AppendLine(" public override bool ParseDataRow(string dataRowString, object userData)") - .AppendLine(" {") - .AppendLine(" string[] columnStrings = dataRowString.Split(DataTableExtension.DataSplitSeparators);") - .AppendLine(" for (int i = 0; i < columnStrings.Length; i++)") - .AppendLine(" {") - .AppendLine(" columnStrings[i] = columnStrings[i].Trim(DataTableExtension.DataTrimSeparators);") - .AppendLine(" }") - .AppendLine() - .AppendLine(" int index = 0;"); - - for (int i = 0; i < dataTableProcessor.RawColumnCount; i++) - { - if (dataTableProcessor.IsCommentColumn(i)) - { - // 注释列 - stringBuilder.AppendLine(" index++;"); - continue; - } - - if (dataTableProcessor.IsIdColumn(i)) - { - // 编号列 - stringBuilder.AppendLine(" m_Id = int.Parse(columnStrings[index++]);"); - continue; - } - - if (dataTableProcessor.IsSystem(i)) - { - string languageKeyword = dataTableProcessor.GetLanguageKeyword(i); - if (languageKeyword == "string") - { - stringBuilder.AppendFormat(" {0} = columnStrings[index++];", dataTableProcessor.GetName(i)).AppendLine(); - } - else - { - stringBuilder.AppendFormat(" {0} = {1}.Parse(columnStrings[index++]);", dataTableProcessor.GetName(i), languageKeyword).AppendLine(); - } - } - else - { - stringBuilder.AppendFormat(" {0} = DataTableExtension.Parse{1}(columnStrings[index++]);", dataTableProcessor.GetName(i), dataTableProcessor.GetType(i).Name).AppendLine(); - } - } - - stringBuilder.AppendLine() - .AppendLine(" GeneratePropertyArray();") - .AppendLine(" return true;") - .AppendLine(" }") - .AppendLine() - .AppendLine(" public override bool ParseDataRow(byte[] dataRowBytes, int startIndex, int length, object userData)") - .AppendLine(" {") - .AppendLine(" using (MemoryStream memoryStream = new MemoryStream(dataRowBytes, startIndex, length, false))") - .AppendLine(" {") - .AppendLine(" using (BinaryReader binaryReader = new BinaryReader(memoryStream, Encoding.UTF8))") - .AppendLine(" {"); - - for (int i = 0; i < dataTableProcessor.RawColumnCount; i++) - { - if (dataTableProcessor.IsCommentColumn(i)) - { - // 注释列 - continue; - } - - if (dataTableProcessor.IsIdColumn(i)) - { - // 编号列 - stringBuilder.AppendLine(" m_Id = binaryReader.Read7BitEncodedInt32();"); - continue; - } - - string languageKeyword = dataTableProcessor.GetLanguageKeyword(i); - if (languageKeyword == "int" || languageKeyword == "uint" || languageKeyword == "long" || languageKeyword == "ulong") - { - stringBuilder.AppendFormat(" {0} = binaryReader.Read7BitEncoded{1}();", dataTableProcessor.GetName(i), dataTableProcessor.GetType(i).Name).AppendLine(); - } - else - { - stringBuilder.AppendFormat(" {0} = binaryReader.Read{1}();", dataTableProcessor.GetName(i), dataTableProcessor.GetType(i).Name).AppendLine(); - } - } - - stringBuilder - .AppendLine(" }") - .AppendLine(" }") - .AppendLine() - .AppendLine(" GeneratePropertyArray();") - .AppendLine(" return true;") - .Append(" }"); - - return stringBuilder.ToString(); - } - - private static string GenerateDataTablePropertyArray(DataTableProcessor dataTableProcessor) - { - List propertyCollections = new List(); - for (int i = 0; i < dataTableProcessor.RawColumnCount; i++) - { - if (dataTableProcessor.IsCommentColumn(i)) - { - // 注释列 - continue; - } - - if (dataTableProcessor.IsIdColumn(i)) - { - // 编号列 - continue; - } - - string name = dataTableProcessor.GetName(i); - if (!EndWithNumberRegex.IsMatch(name)) - { - continue; - } - - string propertyCollectionName = EndWithNumberRegex.Replace(name, string.Empty); - int id = int.Parse(EndWithNumberRegex.Match(name).Value); - - PropertyCollection propertyCollection = null; - foreach (PropertyCollection pc in propertyCollections) - { - if (pc.Name == propertyCollectionName) - { - propertyCollection = pc; - break; - } - } - - if (propertyCollection == null) - { - propertyCollection = new PropertyCollection(propertyCollectionName, dataTableProcessor.GetLanguageKeyword(i)); - propertyCollections.Add(propertyCollection); - } - - propertyCollection.AddItem(id, name); - } - - StringBuilder stringBuilder = new StringBuilder(); - bool firstProperty = true; - foreach (PropertyCollection propertyCollection in propertyCollections) - { - if (firstProperty) - { - firstProperty = false; - } - else - { - stringBuilder.AppendLine().AppendLine(); - } - - stringBuilder - .AppendFormat(" private KeyValuePair[] m_{0} = null;", propertyCollection.Name, propertyCollection.LanguageKeyword).AppendLine() - .AppendLine() - .AppendFormat(" public int {0}Count", propertyCollection.Name).AppendLine() - .AppendLine(" {") - .AppendLine(" get") - .AppendLine(" {") - .AppendFormat(" return m_{0}.Length;", propertyCollection.Name).AppendLine() - .AppendLine(" }") - .AppendLine(" }") - .AppendLine() - .AppendFormat(" public {1} Get{0}(int id)", propertyCollection.Name, propertyCollection.LanguageKeyword).AppendLine() - .AppendLine(" {") - .AppendFormat(" foreach (KeyValuePair i in m_{0})", propertyCollection.Name, propertyCollection.LanguageKeyword).AppendLine() - .AppendLine(" {") - .AppendLine(" if (i.Key == id)") - .AppendLine(" {") - .AppendLine(" return i.Value;") - .AppendLine(" }") - .AppendLine(" }") - .AppendLine() - .AppendFormat(" throw new GameFrameworkException(Utility.Text.Format(\"Get{0} with invalid id '{{0}}'.\", id));", propertyCollection.Name).AppendLine() - .AppendLine(" }") - .AppendLine() - .AppendFormat(" public {1} Get{0}At(int index)", propertyCollection.Name, propertyCollection.LanguageKeyword).AppendLine() - .AppendLine(" {") - .AppendFormat(" if (index < 0 || index >= m_{0}.Length)", propertyCollection.Name).AppendLine() - .AppendLine(" {") - .AppendFormat(" throw new GameFrameworkException(Utility.Text.Format(\"Get{0}At with invalid index '{{0}}'.\", index));", propertyCollection.Name).AppendLine() - .AppendLine(" }") - .AppendLine() - .AppendFormat(" return m_{0}[index].Value;", propertyCollection.Name).AppendLine() - .Append(" }"); - } - - if (propertyCollections.Count > 0) - { - stringBuilder.AppendLine().AppendLine(); - } - - stringBuilder - .AppendLine(" private void GeneratePropertyArray()") - .AppendLine(" {"); - - firstProperty = true; - foreach (PropertyCollection propertyCollection in propertyCollections) - { - if (firstProperty) - { - firstProperty = false; - } - else - { - stringBuilder.AppendLine().AppendLine(); - } - - stringBuilder - .AppendFormat(" m_{0} = new KeyValuePair[]", propertyCollection.Name, propertyCollection.LanguageKeyword).AppendLine() - .AppendLine(" {"); - - int itemCount = propertyCollection.ItemCount; - for (int i = 0; i < itemCount; i++) - { - KeyValuePair item = propertyCollection.GetItem(i); - stringBuilder.AppendFormat(" new KeyValuePair({1}, {2}),", propertyCollection.LanguageKeyword, item.Key.ToString(), item.Value).AppendLine(); - } - - stringBuilder.Append(" };"); - } - - stringBuilder - .AppendLine() - .Append(" }"); - - return stringBuilder.ToString(); - } - - private sealed class PropertyCollection - { - private readonly string m_Name; - private readonly string m_LanguageKeyword; - private readonly List> m_Items; - - public PropertyCollection(string name, string languageKeyword) - { - m_Name = name; - m_LanguageKeyword = languageKeyword; - m_Items = new List>(); - } - - public string Name - { - get - { - return m_Name; - } - } - - public string LanguageKeyword - { - get - { - return m_LanguageKeyword; - } - } - - public int ItemCount - { - get - { - return m_Items.Count; - } - } - - public KeyValuePair GetItem(int index) - { - if (index < 0 || index >= m_Items.Count) - { - throw new GameFrameworkException(Utility.Text.Format("GetItem with invalid index '{0}'.", index)); - } - - return m_Items[index]; - } - - public void AddItem(int id, string propertyName) - { - m_Items.Add(new KeyValuePair(id, propertyName)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGeneratorMenu.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGeneratorMenu.cs deleted file mode 100644 index 1daace5..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableGeneratorMenu.cs +++ /dev/null @@ -1,36 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using GameFramework; -using Procedure; -using UnityEditor; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed class DataTableGeneratorMenu - { - [MenuItem("Star Force/Generate DataTables")] - private static void GenerateDataTables() - { - foreach (string dataTableName in ProcedurePreload.DataTableNames) - { - DataTableProcessor dataTableProcessor = DataTableGenerator.CreateDataTableProcessor(dataTableName); - if (!DataTableGenerator.CheckRawData(dataTableProcessor, dataTableName)) - { - Debug.LogError(Utility.Text.Format("Check raw data failure. DataTableName='{0}'", dataTableName)); - break; - } - - DataTableGenerator.GenerateDataFile(dataTableProcessor, dataTableName); - DataTableGenerator.GenerateCodeFile(dataTableProcessor, dataTableName); - } - - AssetDatabase.Refresh(); - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.BooleanProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.BooleanProcessor.cs deleted file mode 100644 index 7eeafc1..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.BooleanProcessor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class BooleanProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "bool"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "bool", - "boolean", - "system.boolean" - }; - } - - public override bool Parse(string value) - { - return bool.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ByteProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ByteProcessor.cs deleted file mode 100644 index 231f681..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ByteProcessor.cs +++ /dev/null @@ -1,52 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class ByteProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "byte"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "byte", - "system.byte" - }; - } - - public override byte Parse(string value) - { - return byte.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ByteProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ByteProcessor.cs.meta deleted file mode 100644 index 53f2fef..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ByteProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 11199a40fe5a3ef49a3c3d1ae670ac97 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CharProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CharProcessor.cs deleted file mode 100644 index b1b3d99..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CharProcessor.cs +++ /dev/null @@ -1,52 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class CharProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "char"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "char", - "system.char" - }; - } - - public override char Parse(string value) - { - return char.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CharProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CharProcessor.cs.meta deleted file mode 100644 index 2e7685d..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CharProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 37f1181bc8fb29742b06ec3f42f652b4 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Color32Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Color32Processor.cs deleted file mode 100644 index 5651d6a..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Color32Processor.cs +++ /dev/null @@ -1,58 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class Color32Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return "Color32"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "color32", - "unityengine.color32" - }; - } - - public override Color32 Parse(string value) - { - string[] splitedValue = value.Split(','); - return new Color32(byte.Parse(splitedValue[0]), byte.Parse(splitedValue[1]), byte.Parse(splitedValue[2]), byte.Parse(splitedValue[3])); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - Color32 color32 = Parse(value); - binaryWriter.Write(color32.r); - binaryWriter.Write(color32.g); - binaryWriter.Write(color32.b); - binaryWriter.Write(color32.a); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Color32Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Color32Processor.cs.meta deleted file mode 100644 index 06aacf1..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Color32Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2a9b916d7c8e446439b74c27340be473 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ColorProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ColorProcessor.cs deleted file mode 100644 index 44ab1b1..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ColorProcessor.cs +++ /dev/null @@ -1,58 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class ColorProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return "Color"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "color", - "unityengine.color" - }; - } - - public override Color Parse(string value) - { - string[] splitedValue = value.Split(','); - return new Color(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]), float.Parse(splitedValue[3])); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - Color color = Parse(value); - binaryWriter.Write(color.r); - binaryWriter.Write(color.g); - binaryWriter.Write(color.b); - binaryWriter.Write(color.a); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ColorProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ColorProcessor.cs.meta deleted file mode 100644 index 55de18f..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.ColorProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f4583af9902c99a4fad14d732796117e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CommentProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CommentProcessor.cs deleted file mode 100644 index 79127fd..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CommentProcessor.cs +++ /dev/null @@ -1,71 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class CommentProcessor : DataProcessor - { - public override System.Type Type - { - get - { - return null; - } - } - - public override bool IsId - { - get - { - return false; - } - } - - public override bool IsComment - { - get - { - return true; - } - } - - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return null; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - string.Empty, - "#", - "comment" - }; - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CommentProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CommentProcessor.cs.meta deleted file mode 100644 index a55709c..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.CommentProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 2ece238877c1e9344a50ce47697a93ef -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessor.cs deleted file mode 100644 index a6bf5a1..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessor.cs +++ /dev/null @@ -1,46 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - public abstract class DataProcessor - { - public abstract System.Type Type - { - get; - } - - public abstract bool IsId - { - get; - } - - public abstract bool IsComment - { - get; - } - - public abstract bool IsSystem - { - get; - } - - public abstract string LanguageKeyword - { - get; - } - - public abstract string[] GetTypeStrings(); - - public abstract void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value); - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessor.cs.meta deleted file mode 100644 index 5273a49..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ccc7c992b5573ae4fafd0d5706bdad48 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessorUtility.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessorUtility.cs deleted file mode 100644 index 07fac3d..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessorUtility.cs +++ /dev/null @@ -1,61 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using GameFramework; -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private static class DataProcessorUtility - { - private static readonly IDictionary s_DataProcessors = new SortedDictionary(StringComparer.Ordinal); - - static DataProcessorUtility() - { - System.Type dataProcessorBaseType = typeof(DataProcessor); - Assembly assembly = Assembly.GetExecutingAssembly(); - System.Type[] types = assembly.GetTypes(); - for (int i = 0; i < types.Length; i++) - { - if (!types[i].IsClass || types[i].IsAbstract) - { - continue; - } - - if (dataProcessorBaseType.IsAssignableFrom(types[i])) - { - DataProcessor dataProcessor = (DataProcessor)Activator.CreateInstance(types[i]); - foreach (string typeString in dataProcessor.GetTypeStrings()) - { - s_DataProcessors.Add(typeString.ToLowerInvariant(), dataProcessor); - } - } - } - } - - public static DataProcessor GetDataProcessor(string type) - { - if (type == null) - { - type = string.Empty; - } - - DataProcessor dataProcessor = null; - if (s_DataProcessors.TryGetValue(type.ToLowerInvariant(), out dataProcessor)) - { - return dataProcessor; - } - - throw new GameFrameworkException(Utility.Text.Format("Not supported data processor type '{0}'.", type)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessorUtility.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessorUtility.cs.meta deleted file mode 100644 index 4b62e43..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DataProcessorUtility.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 83d25f17cbb262649959b7952811f8c8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DateTimeProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DateTimeProcessor.cs deleted file mode 100644 index cb098a7..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DateTimeProcessor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System; -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class DateTimeProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "DateTime"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "datetime", - "system.datetime" - }; - } - - public override DateTime Parse(string value) - { - return DateTime.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value).Ticks); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DateTimeProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DateTimeProcessor.cs.meta deleted file mode 100644 index cfd722d..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DateTimeProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4223bbe977dd5244a8611c6aad7f693e -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DecimalProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DecimalProcessor.cs deleted file mode 100644 index 1187dbf..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DecimalProcessor.cs +++ /dev/null @@ -1,52 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class DecimalProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "decimal"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "decimal", - "system.decimal" - }; - } - - public override decimal Parse(string value) - { - return decimal.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DecimalProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DecimalProcessor.cs.meta deleted file mode 100644 index 36756eb..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DecimalProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: ad6d6ba18487f7643830e156d300ee75 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DoubleProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DoubleProcessor.cs deleted file mode 100644 index 92f34e5..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DoubleProcessor.cs +++ /dev/null @@ -1,52 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class DoubleProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "double"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "double", - "system.double" - }; - } - - public override double Parse(string value) - { - return double.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DoubleProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DoubleProcessor.cs.meta deleted file mode 100644 index fbe633b..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.DoubleProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 44293fe0c3e108248bc98e8674238aed -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.GenericDataProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.GenericDataProcessor.cs deleted file mode 100644 index d94476b..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.GenericDataProcessor.cs +++ /dev/null @@ -1,41 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - public abstract class GenericDataProcessor : DataProcessor - { - public override System.Type Type - { - get - { - return typeof(T); - } - } - - public override bool IsId - { - get - { - return false; - } - } - - public override bool IsComment - { - get - { - return false; - } - } - - public abstract T Parse(string value); - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.GenericDataProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.GenericDataProcessor.cs.meta deleted file mode 100644 index d2a3178..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.GenericDataProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 65dd2cb98d350654fb3df2ddfc4fa4b8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.IdProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.IdProcessor.cs deleted file mode 100644 index 004a614..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.IdProcessor.cs +++ /dev/null @@ -1,70 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class IdProcessor : DataProcessor - { - public override System.Type Type - { - get - { - return typeof(int); - } - } - - public override bool IsId - { - get - { - return true; - } - } - - public override bool IsComment - { - get - { - return false; - } - } - - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return "int"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "id" - }; - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write7BitEncodedInt32(int.Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.IdProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.IdProcessor.cs.meta deleted file mode 100644 index c2575a3..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.IdProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: f4171c2dabb4ee9468f7297ab334ddf1 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int16Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int16Processor.cs deleted file mode 100644 index 2eb7e14..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int16Processor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class Int16Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "short"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "short", - "int16", - "system.int16" - }; - } - - public override short Parse(string value) - { - return short.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int16Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int16Processor.cs.meta deleted file mode 100644 index ea450fe..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int16Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c1e3b1767ca81c343a31324956e5f032 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int32Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int32Processor.cs deleted file mode 100644 index e55d63e..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int32Processor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class Int32Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "int"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "int", - "int32", - "system.int32" - }; - } - - public override int Parse(string value) - { - return int.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write7BitEncodedInt32(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int32Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int32Processor.cs.meta deleted file mode 100644 index a960179..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int32Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 239560231c239b54f95c183913ec9cbf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int64Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int64Processor.cs deleted file mode 100644 index 9d070d6..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int64Processor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class Int64Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "long"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "long", - "int64", - "system.int64" - }; - } - - public override long Parse(string value) - { - return long.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write7BitEncodedInt64(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int64Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int64Processor.cs.meta deleted file mode 100644 index d7e5893..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Int64Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d6dadc699adc6744e898979b1e85d6cf -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.QuaternionProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.QuaternionProcessor.cs deleted file mode 100644 index 8b91194..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.QuaternionProcessor.cs +++ /dev/null @@ -1,58 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class QuaternionProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return "Quaternion"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "quaternion", - "unityengine.quaternion" - }; - } - - public override Quaternion Parse(string value) - { - string[] splitedValue = value.Split(','); - return new Quaternion(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]), float.Parse(splitedValue[3])); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - Quaternion quaternion = Parse(value); - binaryWriter.Write(quaternion.x); - binaryWriter.Write(quaternion.y); - binaryWriter.Write(quaternion.z); - binaryWriter.Write(quaternion.w); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.QuaternionProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.QuaternionProcessor.cs.meta deleted file mode 100644 index 563017f..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.QuaternionProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: c288505f764c21149b9986dd3ebff1ac -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.RectProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.RectProcessor.cs deleted file mode 100644 index bb2e313..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.RectProcessor.cs +++ /dev/null @@ -1,58 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class RectProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return "Rect"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "rect", - "unityengine.rect" - }; - } - - public override Rect Parse(string value) - { - string[] splitedValue = value.Split(','); - return new Rect(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]), float.Parse(splitedValue[3])); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - Rect rect = Parse(value); - binaryWriter.Write(rect.x); - binaryWriter.Write(rect.y); - binaryWriter.Write(rect.width); - binaryWriter.Write(rect.height); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.RectProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.RectProcessor.cs.meta deleted file mode 100644 index 147707a..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.RectProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 235589b35d4744a4d8ef100da517e0ce -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SByteProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SByteProcessor.cs deleted file mode 100644 index bb16e65..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SByteProcessor.cs +++ /dev/null @@ -1,52 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class SByteProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "sbyte"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "sbyte", - "system.sbyte" - }; - } - - public override sbyte Parse(string value) - { - return sbyte.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SByteProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SByteProcessor.cs.meta deleted file mode 100644 index 5c07fd5..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SByteProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 49f8d16f80f1ec046bfcae38be8c96a7 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SingleProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SingleProcessor.cs deleted file mode 100644 index 60565aa..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SingleProcessor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class SingleProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "float"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "float", - "single", - "system.single" - }; - } - - public override float Parse(string value) - { - return float.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SingleProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SingleProcessor.cs.meta deleted file mode 100644 index 7210146..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.SingleProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 4c1502c70e1294543b14df45c7841a73 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.StringProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.StringProcessor.cs deleted file mode 100644 index a8036ca..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.StringProcessor.cs +++ /dev/null @@ -1,52 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class StringProcessor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "string"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "string", - "system.string" - }; - } - - public override string Parse(string value) - { - return value; - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.StringProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.StringProcessor.cs.meta deleted file mode 100644 index 9f1c1f4..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.StringProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d502b9a1939b46246bd8e4c107b77744 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt16Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt16Processor.cs deleted file mode 100644 index b5ad678..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt16Processor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class UInt16Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "ushort"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "ushort", - "uint16", - "system.uint16" - }; - } - - public override ushort Parse(string value) - { - return ushort.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt16Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt16Processor.cs.meta deleted file mode 100644 index f334209..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt16Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 20f758534f1981b4593f97deb2a5ae25 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt32Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt32Processor.cs deleted file mode 100644 index b089aca..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt32Processor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class UInt32Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "uint"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "uint", - "uint32", - "system.uint32" - }; - } - - public override uint Parse(string value) - { - return uint.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write7BitEncodedUInt32(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt32Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt32Processor.cs.meta deleted file mode 100644 index aabf465..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt32Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: fd3c289549d93924ea928ea558436a57 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt64Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt64Processor.cs deleted file mode 100644 index 03b93fc..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt64Processor.cs +++ /dev/null @@ -1,53 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class UInt64Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return true; - } - } - - public override string LanguageKeyword - { - get - { - return "ulong"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "ulong", - "uint64", - "system.uint64" - }; - } - - public override ulong Parse(string value) - { - return ulong.Parse(value); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - binaryWriter.Write7BitEncodedUInt64(Parse(value)); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt64Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt64Processor.cs.meta deleted file mode 100644 index 6d64997..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.UInt64Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 23d841306167268488c7c5a8bb8cf685 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector2Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector2Processor.cs deleted file mode 100644 index 4812ea4..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector2Processor.cs +++ /dev/null @@ -1,56 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class Vector2Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return "Vector2"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "vector2", - "unityengine.vector2" - }; - } - - public override Vector2 Parse(string value) - { - string[] splitedValue = value.Split(','); - return new Vector2(float.Parse(splitedValue[0]), float.Parse(splitedValue[1])); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - Vector2 vector2 = Parse(value); - binaryWriter.Write(vector2.x); - binaryWriter.Write(vector2.y); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector2Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector2Processor.cs.meta deleted file mode 100644 index 37771b0..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector2Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 165df2a7d4a52984282f1c3bc87d5aaa -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector3Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector3Processor.cs deleted file mode 100644 index ef5ceda..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector3Processor.cs +++ /dev/null @@ -1,57 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class Vector3Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return "Vector3"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "vector3", - "unityengine.vector3" - }; - } - - public override Vector3 Parse(string value) - { - string[] splitedValue = value.Split(','); - return new Vector3(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2])); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - Vector3 vector3 = Parse(value); - binaryWriter.Write(vector3.x); - binaryWriter.Write(vector3.y); - binaryWriter.Write(vector3.z); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector3Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector3Processor.cs.meta deleted file mode 100644 index a2dd42c..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector3Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: d45ef71d28b25f047ab0f4d4acac8b42 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector4Processor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector4Processor.cs deleted file mode 100644 index 8147fe6..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector4Processor.cs +++ /dev/null @@ -1,58 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using System.IO; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private sealed class Vector4Processor : GenericDataProcessor - { - public override bool IsSystem - { - get - { - return false; - } - } - - public override string LanguageKeyword - { - get - { - return "Vector4"; - } - } - - public override string[] GetTypeStrings() - { - return new string[] - { - "vector4", - "unityengine.vector4" - }; - } - - public override Vector4 Parse(string value) - { - string[] splitedValue = value.Split(','); - return new Vector4(float.Parse(splitedValue[0]), float.Parse(splitedValue[1]), float.Parse(splitedValue[2]), float.Parse(splitedValue[3])); - } - - public override void WriteToStream(DataTableProcessor dataTableProcessor, BinaryWriter binaryWriter, string value) - { - Vector4 vector4 = Parse(value); - binaryWriter.Write(vector4.x); - binaryWriter.Write(vector4.y); - binaryWriter.Write(vector4.z); - binaryWriter.Write(vector4.w); - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector4Processor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector4Processor.cs.meta deleted file mode 100644 index 25caf31..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.Vector4Processor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 40409bde40a898b48af91126d343c4ae -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.cs b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.cs deleted file mode 100644 index 0c34f3d..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.cs +++ /dev/null @@ -1,498 +0,0 @@ -//------------------------------------------------------------ -// Game Framework -// Copyright © 2013-2021 Jiang Yin. All rights reserved. -// Homepage: https://gameframework.cn/ -// Feedback: mailto:ellan@gameframework.cn -//------------------------------------------------------------ - -using GameFramework; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using UnityEngine; - -namespace StarForce.Editor.DataTableTools -{ - public sealed partial class DataTableProcessor - { - private const string CommentLineSeparator = "#"; - private static readonly char[] DataSplitSeparators = new char[] { '\t' }; - private static readonly char[] DataTrimSeparators = new char[] { '\"' }; - - private readonly string[] m_NameRow; - private readonly string[] m_TypeRow; - private readonly string[] m_DefaultValueRow; - private readonly string[] m_CommentRow; - private readonly int m_ContentStartRow; - private readonly int m_IdColumn; - - private readonly DataProcessor[] m_DataProcessor; - private readonly string[][] m_RawValues; - private readonly string[] m_Strings; - - private string m_CodeTemplate; - private DataTableCodeGenerator m_CodeGenerator; - - public DataTableProcessor(string dataTableFileName, Encoding encoding, int nameRow, int typeRow, int? defaultValueRow, int? commentRow, int contentStartRow, int idColumn) - { - if (string.IsNullOrEmpty(dataTableFileName)) - { - throw new GameFrameworkException("Data table file name is invalid."); - } - - if (!dataTableFileName.EndsWith(".txt", StringComparison.Ordinal)) - { - throw new GameFrameworkException(Utility.Text.Format("Data table file '{0}' is not a txt.", dataTableFileName)); - } - - if (!File.Exists(dataTableFileName)) - { - throw new GameFrameworkException(Utility.Text.Format("Data table file '{0}' is not exist.", dataTableFileName)); - } - - string[] lines = File.ReadAllLines(dataTableFileName, encoding); - int rawRowCount = lines.Length; - - int rawColumnCount = 0; - List rawValues = new List(); - for (int i = 0; i < lines.Length; i++) - { - string[] rawValue = lines[i].Split(DataSplitSeparators); - for (int j = 0; j < rawValue.Length; j++) - { - rawValue[j] = rawValue[j].Trim(DataTrimSeparators); - } - - if (i == 0) - { - rawColumnCount = rawValue.Length; - } - else if (rawValue.Length != rawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Data table file '{0}', raw Column is '{2}', but line '{1}' column is '{3}'.", dataTableFileName, i, rawColumnCount, rawValue.Length)); - } - - rawValues.Add(rawValue); - } - - m_RawValues = rawValues.ToArray(); - - if (nameRow < 0) - { - throw new GameFrameworkException(Utility.Text.Format("Name row '{0}' is invalid.", nameRow)); - } - - if (typeRow < 0) - { - throw new GameFrameworkException(Utility.Text.Format("Type row '{0}' is invalid.", typeRow)); - } - - if (contentStartRow < 0) - { - throw new GameFrameworkException(Utility.Text.Format("Content start row '{0}' is invalid.", contentStartRow)); - } - - if (idColumn < 0) - { - throw new GameFrameworkException(Utility.Text.Format("Id column '{0}' is invalid.", idColumn)); - } - - if (nameRow >= rawRowCount) - { - throw new GameFrameworkException(Utility.Text.Format("Name row '{0}' >= raw row count '{1}' is not allow.", nameRow, rawRowCount)); - } - - if (typeRow >= rawRowCount) - { - throw new GameFrameworkException(Utility.Text.Format("Type row '{0}' >= raw row count '{1}' is not allow.", typeRow, rawRowCount)); - } - - if (defaultValueRow.HasValue && defaultValueRow.Value >= rawRowCount) - { - throw new GameFrameworkException(Utility.Text.Format("Default value row '{0}' >= raw row count '{1}' is not allow.", defaultValueRow.Value, rawRowCount)); - } - - if (commentRow.HasValue && commentRow.Value >= rawRowCount) - { - throw new GameFrameworkException(Utility.Text.Format("Comment row '{0}' >= raw row count '{1}' is not allow.", commentRow.Value, rawRowCount)); - } - - if (contentStartRow > rawRowCount) - { - throw new GameFrameworkException(Utility.Text.Format("Content start row '{0}' > raw row count '{1}' is not allow.", contentStartRow, rawRowCount)); - } - - if (idColumn >= rawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Id column '{0}' >= raw column count '{1}' is not allow.", idColumn, rawColumnCount)); - } - - m_NameRow = m_RawValues[nameRow]; - m_TypeRow = m_RawValues[typeRow]; - m_DefaultValueRow = defaultValueRow.HasValue ? m_RawValues[defaultValueRow.Value] : null; - m_CommentRow = commentRow.HasValue ? m_RawValues[commentRow.Value] : null; - m_ContentStartRow = contentStartRow; - m_IdColumn = idColumn; - - m_DataProcessor = new DataProcessor[rawColumnCount]; - for (int i = 0; i < rawColumnCount; i++) - { - if (i == IdColumn) - { - m_DataProcessor[i] = DataProcessorUtility.GetDataProcessor("id"); - } - else - { - m_DataProcessor[i] = DataProcessorUtility.GetDataProcessor(m_TypeRow[i]); - } - } - - Dictionary strings = new Dictionary(StringComparer.Ordinal); - for (int i = contentStartRow; i < rawRowCount; i++) - { - if (IsCommentRow(i)) - { - continue; - } - - for (int j = 0; j < rawColumnCount; j++) - { - if (m_DataProcessor[j].LanguageKeyword != "string") - { - continue; - } - - string str = m_RawValues[i][j]; - if (strings.ContainsKey(str)) - { - strings[str]++; - } - else - { - strings[str] = 1; - } - } - } - - m_Strings = strings.OrderBy(value => value.Key).OrderByDescending(value => value.Value).Select(value => value.Key).ToArray(); - - m_CodeTemplate = null; - m_CodeGenerator = null; - } - - public int RawRowCount - { - get - { - return m_RawValues.Length; - } - } - - public int RawColumnCount - { - get - { - return m_RawValues.Length > 0 ? m_RawValues[0].Length : 0; - } - } - - public int StringCount - { - get - { - return m_Strings.Length; - } - } - - public int ContentStartRow - { - get - { - return m_ContentStartRow; - } - } - - public int IdColumn - { - get - { - return m_IdColumn; - } - } - - public bool IsIdColumn(int rawColumn) - { - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - return m_DataProcessor[rawColumn].IsId; - } - - public bool IsCommentRow(int rawRow) - { - if (rawRow < 0 || rawRow >= RawRowCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw row '{0}' is out of range.", rawRow)); - } - - return GetValue(rawRow, 0).StartsWith(CommentLineSeparator, StringComparison.Ordinal); - } - - public bool IsCommentColumn(int rawColumn) - { - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - return string.IsNullOrEmpty(GetName(rawColumn)) || m_DataProcessor[rawColumn].IsComment; - } - - public string GetName(int rawColumn) - { - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - if (IsIdColumn(rawColumn)) - { - return "Id"; - } - - return m_NameRow[rawColumn]; - } - - public bool IsSystem(int rawColumn) - { - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - return m_DataProcessor[rawColumn].IsSystem; - } - - public System.Type GetType(int rawColumn) - { - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - return m_DataProcessor[rawColumn].Type; - } - - public string GetLanguageKeyword(int rawColumn) - { - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - return m_DataProcessor[rawColumn].LanguageKeyword; - } - - public string GetDefaultValue(int rawColumn) - { - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - return m_DefaultValueRow != null ? m_DefaultValueRow[rawColumn] : null; - } - - public string GetComment(int rawColumn) - { - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - return m_CommentRow != null ? m_CommentRow[rawColumn] : null; - } - - public string GetValue(int rawRow, int rawColumn) - { - if (rawRow < 0 || rawRow >= RawRowCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw row '{0}' is out of range.", rawRow)); - } - - if (rawColumn < 0 || rawColumn >= RawColumnCount) - { - throw new GameFrameworkException(Utility.Text.Format("Raw column '{0}' is out of range.", rawColumn)); - } - - return m_RawValues[rawRow][rawColumn]; - } - - public string GetString(int index) - { - if (index < 0 || index >= StringCount) - { - throw new GameFrameworkException(Utility.Text.Format("String index '{0}' is out of range.", index)); - } - - return m_Strings[index]; - } - - public int GetStringIndex(string str) - { - for (int i = 0; i < StringCount; i++) - { - if (m_Strings[i] == str) - { - return i; - } - } - - return -1; - } - - public bool GenerateDataFile(string outputFileName) - { - if (string.IsNullOrEmpty(outputFileName)) - { - throw new GameFrameworkException("Output file name is invalid."); - } - - try - { - using (FileStream fileStream = new FileStream(outputFileName, FileMode.Create, FileAccess.Write)) - { - using (BinaryWriter binaryWriter = new BinaryWriter(fileStream, Encoding.UTF8)) - { - for (int rawRow = ContentStartRow; rawRow < RawRowCount; rawRow++) - { - if (IsCommentRow(rawRow)) - { - continue; - } - - byte[] bytes = GetRowBytes(outputFileName, rawRow); - binaryWriter.Write7BitEncodedInt32(bytes.Length); - binaryWriter.Write(bytes); - } - } - } - - Debug.Log(Utility.Text.Format("Parse data table '{0}' success.", outputFileName)); - return true; - } - catch (Exception exception) - { - Debug.LogError(Utility.Text.Format("Parse data table '{0}' failure, exception is '{1}'.", outputFileName, exception)); - return false; - } - } - - public bool SetCodeTemplate(string codeTemplateFileName, Encoding encoding) - { - try - { - m_CodeTemplate = File.ReadAllText(codeTemplateFileName, encoding); - Debug.Log(Utility.Text.Format("Set code template '{0}' success.", codeTemplateFileName)); - return true; - } - catch (Exception exception) - { - Debug.LogError(Utility.Text.Format("Set code template '{0}' failure, exception is '{1}'.", codeTemplateFileName, exception)); - return false; - } - } - - public void SetCodeGenerator(DataTableCodeGenerator codeGenerator) - { - m_CodeGenerator = codeGenerator; - } - - public bool GenerateCodeFile(string outputFileName, Encoding encoding, object userData = null) - { - if (string.IsNullOrEmpty(m_CodeTemplate)) - { - throw new GameFrameworkException("You must set code template first."); - } - - if (string.IsNullOrEmpty(outputFileName)) - { - throw new GameFrameworkException("Output file name is invalid."); - } - - try - { - StringBuilder stringBuilder = new StringBuilder(m_CodeTemplate); - if (m_CodeGenerator != null) - { - m_CodeGenerator(this, stringBuilder, userData); - } - - using (FileStream fileStream = new FileStream(outputFileName, FileMode.Create, FileAccess.Write)) - { - using (StreamWriter stream = new StreamWriter(fileStream, encoding)) - { - stream.Write(stringBuilder.ToString()); - } - } - - Debug.Log(Utility.Text.Format("Generate code file '{0}' success.", outputFileName)); - return true; - } - catch (Exception exception) - { - Debug.LogError(Utility.Text.Format("Generate code file '{0}' failure, exception is '{1}'.", outputFileName, exception)); - return false; - } - } - - private byte[] GetRowBytes(string outputFileName, int rawRow) - { - using (MemoryStream memoryStream = new MemoryStream()) - { - using (BinaryWriter binaryWriter = new BinaryWriter(memoryStream, Encoding.UTF8)) - { - for (int rawColumn = 0; rawColumn < RawColumnCount; rawColumn++) - { - if (IsCommentColumn(rawColumn)) - { - continue; - } - - try - { - m_DataProcessor[rawColumn].WriteToStream(this, binaryWriter, GetValue(rawRow, rawColumn)); - } - catch - { - if (m_DataProcessor[rawColumn].IsId || string.IsNullOrEmpty(GetDefaultValue(rawColumn))) - { - Debug.LogError(Utility.Text.Format("Parse raw value failure. OutputFileName='{0}' RawRow='{1}' RowColumn='{2}' Name='{3}' Type='{4}' RawValue='{5}'", outputFileName, rawRow, rawColumn, GetName(rawColumn), GetLanguageKeyword(rawColumn), GetValue(rawRow, rawColumn))); - return null; - } - else - { - Debug.LogWarning(Utility.Text.Format("Parse raw value failure, will try default value. OutputFileName='{0}' RawRow='{1}' RowColumn='{2}' Name='{3}' Type='{4}' RawValue='{5}'", outputFileName, rawRow, rawColumn, GetName(rawColumn), GetLanguageKeyword(rawColumn), GetValue(rawRow, rawColumn))); - try - { - m_DataProcessor[rawColumn].WriteToStream(this, binaryWriter, GetDefaultValue(rawColumn)); - } - catch - { - Debug.LogError(Utility.Text.Format("Parse default value failure. OutputFileName='{0}' RawRow='{1}' RowColumn='{2}' Name='{3}' Type='{4}' RawValue='{5}'", outputFileName, rawRow, rawColumn, GetName(rawColumn), GetLanguageKeyword(rawColumn), GetComment(rawColumn))); - return null; - } - } - } - } - - return memoryStream.ToArray(); - } - } - } - } -} diff --git a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.cs.meta b/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.cs.meta deleted file mode 100644 index 8b7a023..0000000 --- a/Assets/GameMain/Scripts/Editor/DataTableGenerator/DataTableProcessor.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 81b27209918096743b988ea62b39d109 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Editor/PlayerBuffConsoleWindow.cs b/Assets/GameMain/Scripts/Editor/PlayerBuffConsoleWindow.cs new file mode 100644 index 0000000..7bdc7dc --- /dev/null +++ b/Assets/GameMain/Scripts/Editor/PlayerBuffConsoleWindow.cs @@ -0,0 +1,278 @@ +#if UNITY_EDITOR +using System; +using System.Linq; +using CustomComponent; +using DataTable; +using Definition.DataStruct; +using Entity; +using Game.Utility; +using UnityEditor; +using UnityEngine; + +namespace StarForce.Editor +{ + public class PlayerBuffConsoleWindow : EditorWindow + { + private const string WindowTitle = "Player Buff Console"; + + private string _searchText = string.Empty; + private int _selectedIndex; + private int _addCount = 1; + private Vector2 _scroll; + private DRProp[] _allProps = Array.Empty(); + private DRProp[] _filteredProps = Array.Empty(); + private string[] _displayNames = Array.Empty(); + + private float _spawnRateScaleInput = 1f; + private float _extendDurationSeconds = 30f; + + [MenuItem("StarForce/Debug/Player Buff Console")] + private static void Open() + { + GetWindow(WindowTitle); + } + + private void OnEnable() + { + RefreshPropList(); + EditorApplication.playModeStateChanged += OnPlayModeStateChanged; + } + + private void OnDisable() + { + EditorApplication.playModeStateChanged -= OnPlayModeStateChanged; + } + + private void OnGUI() + { + EditorGUILayout.LabelField("Player Buff Console (Editor Only)", EditorStyles.boldLabel); + EditorGUILayout.Space(4f); + + using (new EditorGUI.DisabledScope(!EditorApplication.isPlaying)) + { + DrawBuffSection(); + + EditorGUILayout.Space(8f); + EditorGUILayout.LabelField(string.Empty, GUI.skin.horizontalSlider); + EditorGUILayout.Space(8f); + + DrawBattleControlSection(); + } + + if (!EditorApplication.isPlaying) + { + EditorGUILayout.HelpBox("Enter Play mode to use debug controls.", MessageType.Info); + } + } + + private void DrawBuffSection() + { + EditorGUILayout.LabelField("Buff Debug", EditorStyles.boldLabel); + DrawToolbar(); + DrawBuffSelector(); + DrawSelectedBuffPreview(); + DrawBuffActions(); + } + + private void DrawBattleControlSection() + { + EditorGUILayout.LabelField("Battle Debug", EditorStyles.boldLabel); + + EnemyManagerComponent enemyManager = GameEntry.EnemyManager; + Player player = FindPlayer(); + if (enemyManager == null) + { + EditorGUILayout.HelpBox("EnemyManager is unavailable.", MessageType.Warning); + return; + } + + EditorGUILayout.LabelField("Current Spawn Rate Scale", enemyManager.SpawnRateScale.ToString("F2")); + EditorGUILayout.LabelField("Battle Time", + $"{enemyManager.ElapsedBattleTime:F1}s / {enemyManager.BattleDuration:F1}s"); + + _spawnRateScaleInput = Mathf.Clamp(EditorGUILayout.FloatField("Spawn Rate Scale", _spawnRateScaleInput), 0.1f, + 50f); + _extendDurationSeconds = Mathf.Clamp(EditorGUILayout.FloatField("Add Duration (Seconds)", _extendDurationSeconds), + 1f, 3600f); + + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Apply Spawn Rate")) + { + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + ShowNotification(new GUIContent($"Spawn rate scale = {enemyManager.SpawnRateScale:F2}")); + } + + if (GUILayout.Button("x0.5")) + { + _spawnRateScaleInput = Mathf.Max(0.1f, enemyManager.SpawnRateScale * 0.5f); + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + } + + if (GUILayout.Button("x2")) + { + _spawnRateScaleInput = enemyManager.SpawnRateScale * 2f; + enemyManager.SetSpawnRateScale(_spawnRateScaleInput); + } + EditorGUILayout.EndHorizontal(); + + if (GUILayout.Button("Add Battle Duration")) + { + enemyManager.AddBattleDuration(_extendDurationSeconds); + ShowNotification(new GUIContent($"+{_extendDurationSeconds:F0}s Battle Duration")); + } + + EditorGUILayout.Space(6f); + EditorGUILayout.LabelField("Player Weapon", player == null ? "Player not found" : (player.WeaponEnabled ? "Enabled" : "Disabled")); + using (new EditorGUI.DisabledScope(player == null)) + { + EditorGUILayout.BeginHorizontal(); + if (GUILayout.Button("Disable Weapons")) + { + player.SetWeaponEnabled(false); + ShowNotification(new GUIContent("Player weapons disabled")); + } + + if (GUILayout.Button("Enable Weapons")) + { + player.SetWeaponEnabled(true); + ShowNotification(new GUIContent("Player weapons enabled")); + } + + EditorGUILayout.EndHorizontal(); + } + } + + private void DrawToolbar() + { + EditorGUILayout.BeginHorizontal(); + _searchText = EditorGUILayout.TextField("Search", _searchText); + if (GUILayout.Button("Refresh", GUILayout.Width(80f))) + { + RefreshPropList(); + } + + EditorGUILayout.EndHorizontal(); + } + + private void DrawBuffSelector() + { + ApplyFilter(_searchText); + + if (_displayNames.Length == 0) + { + EditorGUILayout.HelpBox("No Buff data found. Ensure data tables are loaded.", MessageType.Warning); + return; + } + + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1); + _selectedIndex = EditorGUILayout.Popup("Buff", _selectedIndex, _displayNames); + } + + private void DrawSelectedBuffPreview() + { + DRProp selectedProp = GetSelectedProp(); + if (selectedProp == null) return; + + _scroll = EditorGUILayout.BeginScrollView(_scroll, GUILayout.Height(120f)); + EditorGUILayout.LabelField("Title", selectedProp.Title); + EditorGUILayout.LabelField("Rarity", selectedProp.Rarity.ToString()); + EditorGUILayout.LabelField("Description"); + EditorGUILayout.HelpBox(ItemDescUtility.CreatePropDescription(selectedProp.Modifiers), MessageType.None); + EditorGUILayout.EndScrollView(); + } + + private void DrawBuffActions() + { + DRProp selectedProp = GetSelectedProp(); + if (selectedProp == null) return; + + _addCount = Mathf.Clamp(EditorGUILayout.IntField("Add Count", _addCount), 1, 99); + if (!GUILayout.Button("Add Buff To Player", GUILayout.Height(28f))) return; + + Player player = FindPlayer(); + if (player == null) + { + ShowNotification(new GUIContent("Player not found")); + return; + } + + for (int i = 0; i < _addCount; i++) + { + player.AddProp(new PropItem(selectedProp.Modifiers, selectedProp.Rarity, selectedProp.Title, + selectedProp.IconAssetName)); + } + + ShowNotification(new GUIContent($"Added Buff: {selectedProp.Title} x{_addCount}")); + } + + private void RefreshPropList() + { + if (!EditorApplication.isPlaying || GameEntry.DataTable == null) + { + _allProps = Array.Empty(); + _filteredProps = Array.Empty(); + _displayNames = Array.Empty(); + return; + } + + var table = GameEntry.DataTable.GetDataTable(); + _allProps = table != null ? table.ToArray() : Array.Empty(); + _selectedIndex = 0; + ApplyFilter(_searchText); + } + + private void ApplyFilter(string searchText) + { + if (_allProps == null || _allProps.Length == 0) + { + _filteredProps = Array.Empty(); + _displayNames = Array.Empty(); + return; + } + + if (string.IsNullOrWhiteSpace(searchText)) + { + _filteredProps = _allProps; + } + else + { + string keyword = searchText.Trim(); + _filteredProps = _allProps.Where(p => + p != null && + (p.Title?.IndexOf(keyword, StringComparison.OrdinalIgnoreCase) >= 0 || + p.Id.ToString().Contains(keyword))).ToArray(); + } + + _displayNames = _filteredProps.Select(p => $"[{p.Id}] {p.Title} ({p.Rarity})").ToArray(); + if (_displayNames.Length == 0) + { + _selectedIndex = 0; + return; + } + + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _displayNames.Length - 1); + } + + private DRProp GetSelectedProp() + { + if (_filteredProps == null || _filteredProps.Length == 0) return null; + _selectedIndex = Mathf.Clamp(_selectedIndex, 0, _filteredProps.Length - 1); + return _filteredProps[_selectedIndex]; + } + + private static Player FindPlayer() + { + return UnityEngine.Object.FindObjectOfType(); + } + + private void OnPlayModeStateChanged(PlayModeStateChange state) + { + if (state == PlayModeStateChange.EnteredPlayMode || state == PlayModeStateChange.EnteredEditMode) + { + RefreshPropList(); + Repaint(); + } + } + } +} +#endif diff --git a/Assets/GameMain/Scripts/Editor/PlayerBuffConsoleWindow.cs.meta b/Assets/GameMain/Scripts/Editor/PlayerBuffConsoleWindow.cs.meta new file mode 100644 index 0000000..be3f6ae --- /dev/null +++ b/Assets/GameMain/Scripts/Editor/PlayerBuffConsoleWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e43be978219545f294fbc211e32e8196 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/GameMain/Scripts/Entity/EntityData/Enemy/EnemyData.cs b/Assets/GameMain/Scripts/Entity/EntityData/Enemy/EnemyData.cs index 7c4e079..67041a7 100644 --- a/Assets/GameMain/Scripts/Entity/EntityData/Enemy/EnemyData.cs +++ b/Assets/GameMain/Scripts/Entity/EntityData/Enemy/EnemyData.cs @@ -16,11 +16,12 @@ namespace Entity.EntityData [SerializeField] private float _dropPercent = 0; - public EnemyData(int entityId, int typeId) : base( + public EnemyData(int entityId, int typeId, int level) : base( entityId, typeId, CampType.Enemy) { DREnemy enemyRow = GameEntry.DataTable.GetDataTableRow(typeId); - MaxHealthBase = enemyRow.MaxHealth; + int effectiveLevel = Mathf.Max(1, level); + MaxHealthBase = enemyRow.MaxHealth + enemyRow.HpAddPerLevel * (effectiveLevel - 1); SpeedBase = enemyRow.Speed; DropCoin = enemyRow.DropCoin; DropExp = enemyRow.DropExp; @@ -53,4 +54,4 @@ namespace Entity.EntityData set => _dropPercent = value; } } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/CoinEntity.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/CoinEntity.cs index bb63722..272a98a 100644 --- a/Assets/GameMain/Scripts/Entity/EntityLogic/CoinEntity.cs +++ b/Assets/GameMain/Scripts/Entity/EntityLogic/CoinEntity.cs @@ -7,10 +7,12 @@ namespace Entity public class CoinEntity : EntityBase { private CoinData _coinData; + private bool _isCollected; protected override void OnShow(object userData) { base.OnShow(userData); + _isCollected = false; if (userData is CoinData coinData) { @@ -24,14 +26,25 @@ namespace Entity this.CachedTransform.localScale = new Vector3(0.3f, 0.3f, 0.3f); } + public bool TryCollect(Player player, float collectDistance = 0f) + { + if (_isCollected || player == null || !player.Available || _coinData == null) return false; + + if (collectDistance > 0f) + { + float distance = Vector3.Distance(player.CachedTransform.position, CachedTransform.position); + if (distance > collectDistance) return false; + } + + _isCollected = true; + player.Coin += _coinData.Value; + GameEntry.Entity.HideEntity(this); + return true; + } + private void OnTriggerEnter(Collider other) { - var player = other.GetComponent(); - if (player != null && player.Available) - { - player.Coin += _coinData.Value; - GameEntry.Entity.HideEntity(this); - } + TryCollect(other.GetComponent()); } } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/ExpEntity.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/ExpEntity.cs index 2845522..1c87e98 100644 --- a/Assets/GameMain/Scripts/Entity/EntityLogic/ExpEntity.cs +++ b/Assets/GameMain/Scripts/Entity/EntityLogic/ExpEntity.cs @@ -7,10 +7,12 @@ namespace Entity public class ExpEntity:EntityBase { private ExpData _expData; + private bool _isCollected; protected override void OnShow(object userData) { base.OnShow(userData); + _isCollected = false; if (userData is ExpData expData) { @@ -23,14 +25,25 @@ namespace Entity this.CachedTransform.localScale = new Vector3(0.3f, 0.3f, 0.3f); } + public bool TryCollect(Player player, float collectDistance = 0f) + { + if (_isCollected || player == null || !player.Available || _expData == null) return false; + + if (collectDistance > 0f) + { + float distance = Vector3.Distance(player.CachedTransform.position, CachedTransform.position); + if (distance > collectDistance) return false; + } + + _isCollected = true; + player.Exp += _expData.Value; + GameEntry.Entity.HideEntity(this); + return true; + } + private void OnTriggerEnter(Collider other) { - var player = other.GetComponent(); - if (player != null && player.Available) - { - player.Exp += _expData.Value; - GameEntry.Entity.HideEntity(this); - } + TryCollect(other.GetComponent()); } } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Player.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Player.cs index d3cfb61..d7c161e 100644 --- a/Assets/GameMain/Scripts/Entity/EntityLogic/Player.cs +++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Player.cs @@ -15,6 +15,7 @@ namespace Entity private InputComponent _inputComponent; private MovementComponent _movementComponent; + private AbsorbComponent _absorbComponent; private StatComponent _statComponent; private BackpackComponent _backpackComponent; private PlayerData _playerData; @@ -44,6 +45,7 @@ namespace Entity /// 玩家是否启用。 /// private bool _enable; + private bool _weaponEnabled = true; public int Coin { @@ -95,11 +97,19 @@ namespace Entity if (value == _enable) return; _enable = value; _movementComponent.SetMove(value); - _backpackComponent.SetWeaponState(value); + _backpackComponent.SetWeaponState(value && _weaponEnabled); _inputComponent.SetListening(value); } } + public bool WeaponEnabled => _weaponEnabled; + + public void SetWeaponEnabled(bool enabled) + { + _weaponEnabled = enabled; + _backpackComponent?.SetWeaponState(_enable && _weaponEnabled); + } + public void InitRole(DRRole role) { // MovementComponent @@ -146,9 +156,15 @@ namespace Entity _inputComponent = GetComponent(); _movementComponent = GetComponent(); + _absorbComponent = GetComponent(); _statComponent = GetComponent(); _healthComponent = GetComponent(); _backpackComponent = GetComponent(); + + if (_absorbComponent == null) + { + _absorbComponent = gameObject.AddComponent(); + } } protected override void OnShow(object userData) @@ -166,6 +182,8 @@ namespace Entity _inputComponent.OnInit(); _inputComponent.SetListening(true); + _absorbComponent.OnInit(this, _statComponent); + _weaponEnabled = true; _currentLevel = 0; } @@ -178,6 +196,7 @@ namespace Entity _movementComponent.SetDirection(_inputComponent.Direction); _movementComponent.OnUpdate(elapseSeconds, realElapseSeconds); + _absorbComponent.OnUpdate(elapseSeconds, realElapseSeconds); } protected override void OnHide(bool isShutdown, object userData) @@ -187,6 +206,7 @@ namespace Entity _healthComponent.OnReset(); _statComponent.OnReset(); _backpackComponent.OnReset(); + _absorbComponent.OnReset(); base.OnHide(isShutdown, userData); } @@ -206,4 +226,4 @@ namespace Entity #endregion } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs index 4610baf..c594bef 100644 --- a/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs +++ b/Assets/GameMain/Scripts/Entity/EntityLogic/Weapon/WeaponBase.cs @@ -24,15 +24,15 @@ namespace Entity public abstract class WeaponBase : EntityBase { protected const string AttachPoint = "Weapon Point"; - + protected bool _isAttacking = false; - - protected bool _isEnabled = false; - + + [SerializeField] protected bool _isEnabled = false; + public WeaponData WeaponData; - + public bool IsAttacking => _isAttacking; - + protected WeaponStateBase _currentState; #region FSM diff --git a/Assets/GameMain/Scripts/Procedure/Base/ProcedurePreload.cs b/Assets/GameMain/Scripts/Procedure/Base/ProcedurePreload.cs index f675b69..fbeb920 100644 --- a/Assets/GameMain/Scripts/Procedure/Base/ProcedurePreload.cs +++ b/Assets/GameMain/Scripts/Procedure/Base/ProcedurePreload.cs @@ -37,7 +37,8 @@ namespace Procedure "Prop", "Role", "Level", - "LevelUpReward" + "LevelUpReward", + "LevelRarity" }; private Dictionary _loadedFlag = new Dictionary(); diff --git a/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs b/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs index 557cf92..927c079 100644 --- a/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs +++ b/Assets/GameMain/Scripts/Procedure/Game/GameStateBattle.cs @@ -50,7 +50,6 @@ namespace Procedure if (_levelOver) { - procedureOwner.SetData("CurrentLevel", (byte)(_currentLevel + 1)); _procedureGame.BattleToShopOrLevelUp(); } } diff --git a/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs b/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs index 83c47ba..10f58fe 100644 --- a/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs +++ b/Assets/GameMain/Scripts/Procedure/Game/ProcedureGame.cs @@ -53,6 +53,7 @@ namespace Procedure public void BattleToShopOrLevelUp() { + CurrentLevel++; if (_currentGameState == GameStateType.Shop || _currentGameState == GameStateType.LevelUp) return; _gameStates[_currentGameState].OnLeave(_procedureOwner); diff --git a/Assets/GameMain/Scripts/SpriteCache/SpriteCacheComponent.cs b/Assets/GameMain/Scripts/SpriteCache/SpriteCacheComponent.cs index 15bb660..44cd430 100644 --- a/Assets/GameMain/Scripts/SpriteCache/SpriteCacheComponent.cs +++ b/Assets/GameMain/Scripts/SpriteCache/SpriteCacheComponent.cs @@ -45,7 +45,7 @@ public class SpriteCacheComponent : GameFrameworkComponent new Rect(0, 0, texture.width, texture.height), _defaultPivot, _pixelsPerUnit); - _spriteCache.Add(assetName, newSprite); + _spriteCache.TryAdd(assetName, newSprite); callback?.Invoke(newSprite); } }, diff --git a/Assets/GameMain/Scripts/UI/GameScene/UseCase/LevelUpFormUseCase.cs b/Assets/GameMain/Scripts/UI/GameScene/UseCase/LevelUpFormUseCase.cs index 823353e..4901588 100644 --- a/Assets/GameMain/Scripts/UI/GameScene/UseCase/LevelUpFormUseCase.cs +++ b/Assets/GameMain/Scripts/UI/GameScene/UseCase/LevelUpFormUseCase.cs @@ -7,6 +7,8 @@ using Entity; using Procedure; using UnityEngine; using UnityGameFramework.Runtime; +using Game.Utility; +using GameFramework.DataTable; namespace UI { @@ -15,6 +17,9 @@ namespace UI private const int BaseRefreshPrice = 2; private readonly GameStateLevelUp _gameStateLevelUp; private readonly DRLevelUpReward[] _allRewards; + private readonly IDataTable _levelRarityTable; + private readonly Dictionary> _rewardsByRarity = new(); + private readonly List _validRewards = new(); private int _refreshCount; private LevelUpFormRawData _currentModel; @@ -26,6 +31,9 @@ namespace UI _player = player; _gameStateLevelUp = gameStateLevelUp; _allRewards = GameEntry.DataTable.GetDataTable().ToArray(); + _levelRarityTable = GameEntry.DataTable.GetDataTable(); + + BuildRewardRarityPools(); } public LevelUpFormRawData CreateInitialModel(int count = 4) @@ -99,10 +107,18 @@ namespace UI int finalCount = count > 0 ? System.Math.Min(count, _allRewards.Length) : _allRewards.Length; List selections = new List(finalCount); + int currentLevel = _player != null ? _player.CurrentLevel : 1; for (int i = 0; i < finalCount; i++) { - int index = Random.Range(0, _allRewards.Length); - selections.Add(_allRewards[index]); + ItemRarity rarity = RarityUtility.SelectRarityForLevel(_levelRarityTable, currentLevel); + DRLevelUpReward reward = PickRewardByRarity(rarity); + if (reward == null) + { + Log.Warning("LevelUpFormUseCase::BuildModel(): No available reward for selection."); + break; + } + + selections.Add(reward); } return new LevelUpFormRawData @@ -131,7 +147,49 @@ namespace UI return; } - _player.AddProp(new PropItem(reward.Modifiers, ItemRarity.White, reward.Title, reward.IconAssetName)); + _player.AddProp(new PropItem(reward.Modifiers, reward.Rarity, reward.Title, reward.IconAssetName)); + } + + private void BuildRewardRarityPools() + { + _rewardsByRarity.Clear(); + _validRewards.Clear(); + + if (_allRewards == null) return; + + foreach (DRLevelUpReward reward in _allRewards) + { + if (reward == null) + { + continue; + } + + ItemRarity rarity = reward.Rarity; + _validRewards.Add(reward); + + if (!_rewardsByRarity.TryGetValue(rarity, out List list)) + { + list = new List(); + _rewardsByRarity.Add(rarity, list); + } + + list.Add(reward); + } + } + + private DRLevelUpReward PickRewardByRarity(ItemRarity rarity) + { + if (_rewardsByRarity.TryGetValue(rarity, out List list) && list.Count > 0) + { + return list[Random.Range(0, list.Count)]; + } + + if (_validRewards.Count > 0) + { + return _validRewards[Random.Range(0, _validRewards.Count)]; + } + + return null; } } -} \ No newline at end of file +} diff --git a/Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs b/Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs index 2563aca..43732d5 100644 --- a/Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs +++ b/Assets/GameMain/Scripts/UI/GameScene/UseCase/ShopFormUseCase.cs @@ -33,6 +33,10 @@ namespace UI private readonly DRGoods[] _allGoods; private readonly IDataTable _propDataTable; private readonly IDataTable _weaponDataTable; + private readonly IDataTable _levelRarityTable; + + private readonly List _validGoods = new(); + private readonly Dictionary> _goodsByRarity = new(); private readonly List _selections = new(); private int _refreshTime; @@ -53,6 +57,9 @@ namespace UI _allGoods = GameEntry.DataTable.GetDataTable().ToArray(); _propDataTable = GameEntry.DataTable.GetDataTable(); _weaponDataTable = GameEntry.DataTable.GetDataTable(); + _levelRarityTable = GameEntry.DataTable.GetDataTable(); + + BuildGoodsRarityPools(); } public ShopFormRawData CreateInitialModel() @@ -148,10 +155,18 @@ namespace UI List goodsItems = new List(finalCount); _selections.Clear(); + int currentLevel = _procedureGame != null ? _procedureGame.CurrentLevel : 1; + for (int i = 0; i < finalCount; i++) { - int index = Random.Range(0, _allGoods.Length); - DRGoods drGoods = _allGoods[index]; + ItemRarity rarity = RarityUtility.SelectRarityForLevel(_levelRarityTable, currentLevel); + DRGoods drGoods = PickGoodsByRarity(rarity); + if (drGoods == null) + { + Log.Warning("ShopFormUseCase::BuildRandomGoodsItems: No available goods for selection."); + break; + } + GoodsItemContext goodsItem = new GoodsItemContext(); int price; @@ -208,6 +223,87 @@ namespace UI return goodsItems; } + private void BuildGoodsRarityPools() + { + _goodsByRarity.Clear(); + _validGoods.Clear(); + + if (_allGoods == null) return; + + foreach (DRGoods goods in _allGoods) + { + if (goods == null) continue; + + if (!TryGetGoodsRarity(goods, out ItemRarity rarity)) + { + continue; + } + + _validGoods.Add(goods); + + if (!_goodsByRarity.TryGetValue(rarity, out List list)) + { + list = new List(); + _goodsByRarity.Add(rarity, list); + } + + list.Add(goods); + } + } + + private DRGoods PickGoodsByRarity(ItemRarity rarity) + { + if (_goodsByRarity.TryGetValue(rarity, out List list) && list.Count > 0) + { + return list[Random.Range(0, list.Count)]; + } + + if (_validGoods.Count > 0) + { + return _validGoods[Random.Range(0, _validGoods.Count)]; + } + + return null; + } + + private bool TryGetGoodsRarity(DRGoods goods, out ItemRarity rarity) + { + rarity = ItemRarity.None; + if (goods == null) + { + return false; + } + + if (goods.GoodsType == GoodsType.Prop) + { + DRProp drProp = _propDataTable != null ? _propDataTable.GetDataRow(goods.GoodsTypeId) : null; + if (drProp == null) + { + Log.Warning($"ShopFormUseCase::TryGetGoodsRarity: Missing DRProp, id = {goods.GoodsTypeId}"); + return false; + } + + rarity = drProp.Rarity; + return true; + } + + if (goods.GoodsType == GoodsType.Weapon) + { + DRWeapon drWeapon = _weaponDataTable != null ? _weaponDataTable.GetDataRow(goods.GoodsTypeId) : null; + if (drWeapon == null) + { + Log.Warning($"ShopFormUseCase::TryGetGoodsRarity: Missing DRWeapon, id = {goods.GoodsTypeId}"); + return false; + } + + rarity = drWeapon.Rarity; + return true; + } + + Log.Warning($"ShopFormUseCase::TryGetGoodsRarity: Unsupported goods type = {goods.GoodsType}"); + return false; + } + private static int CalculateRandomizedPrice(int basePrice, float priceRandomPercent) { float normalizedPercent = priceRandomPercent > 1f ? priceRandomPercent / 100f : priceRandomPercent; diff --git a/Assets/GameMain/Scripts/Utility/RarityUtility.cs b/Assets/GameMain/Scripts/Utility/RarityUtility.cs new file mode 100644 index 0000000..1941625 --- /dev/null +++ b/Assets/GameMain/Scripts/Utility/RarityUtility.cs @@ -0,0 +1,89 @@ +using DataTable; +using Definition.Enum; +using GameFramework.DataTable; +using UnityEngine; + +namespace Game.Utility +{ + public static class RarityUtility + { + public static ItemRarity SelectRarityForLevel(IDataTable table, int level) + { + DRLevelRarity row = GetLevelRarityRow(table, level); + if (row == null) + { + return ItemRarity.White; + } + + int white = Mathf.Max(0, row.WhiteWeight); + int green = Mathf.Max(0, row.GreenWeight); + int blue = Mathf.Max(0, row.BlueWeight); + int purple = Mathf.Max(0, row.PurpleWeight); + int red = Mathf.Max(0, row.RedWeight); + + int total = white + green + blue + purple + red; + if (total <= 0) + { + return ItemRarity.White; + } + + int roll = Random.Range(1, total + 1); + if (roll <= white) return ItemRarity.White; + roll -= white; + if (roll <= green) return ItemRarity.Green; + roll -= green; + if (roll <= blue) return ItemRarity.Blue; + roll -= blue; + if (roll <= purple) return ItemRarity.Purple; + return ItemRarity.Red; + } + + private static DRLevelRarity GetLevelRarityRow(IDataTable table, int level) + { + if (table == null) + { + return null; + } + + DRLevelRarity[] rows = table.GetAllDataRows(); + if (rows == null || rows.Length == 0) + { + return null; + } + + int safeLevel = Mathf.Max(1, level); + DRLevelRarity below = null; + DRLevelRarity above = null; + + foreach (DRLevelRarity row in rows) + { + if (row == null) + { + continue; + } + + if (safeLevel >= row.LevelMin && safeLevel <= row.LevelMax) + { + return row; + } + + if (safeLevel < row.LevelMin) + { + if (above == null || row.LevelMin < above.LevelMin) + { + above = row; + } + } + else if (safeLevel > row.LevelMax) + { + if (below == null || row.LevelMax > below.LevelMax) + { + below = row; + } + } + } + + return above ?? below; + } + } +} diff --git a/Assets/GameMain/Scripts/Utility/RarityUtility.cs.meta b/Assets/GameMain/Scripts/Utility/RarityUtility.cs.meta new file mode 100644 index 0000000..c7bf09b --- /dev/null +++ b/Assets/GameMain/Scripts/Utility/RarityUtility.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d9186261c82d4f0b8270048f08158b0f +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Settings.meta b/Assets/GameMain/Settings.meta similarity index 100% rename from Assets/Settings.meta rename to Assets/GameMain/Settings.meta diff --git a/Assets/Settings/SampleSceneProfile.asset b/Assets/GameMain/Settings/SampleSceneProfile.asset similarity index 100% rename from Assets/Settings/SampleSceneProfile.asset rename to Assets/GameMain/Settings/SampleSceneProfile.asset diff --git a/Assets/Settings/SampleSceneProfile.asset.meta b/Assets/GameMain/Settings/SampleSceneProfile.asset.meta similarity index 100% rename from Assets/Settings/SampleSceneProfile.asset.meta rename to Assets/GameMain/Settings/SampleSceneProfile.asset.meta diff --git a/Assets/Settings/URP-Balanced-Renderer.asset b/Assets/GameMain/Settings/URP-Balanced-Renderer.asset similarity index 100% rename from Assets/Settings/URP-Balanced-Renderer.asset rename to Assets/GameMain/Settings/URP-Balanced-Renderer.asset diff --git a/Assets/Settings/URP-Balanced-Renderer.asset.meta b/Assets/GameMain/Settings/URP-Balanced-Renderer.asset.meta similarity index 100% rename from Assets/Settings/URP-Balanced-Renderer.asset.meta rename to Assets/GameMain/Settings/URP-Balanced-Renderer.asset.meta diff --git a/Assets/Settings/URP-Balanced.asset b/Assets/GameMain/Settings/URP-Balanced.asset similarity index 76% rename from Assets/Settings/URP-Balanced.asset rename to Assets/GameMain/Settings/URP-Balanced.asset index 65bbfc8..aef05b8 100644 --- a/Assets/Settings/URP-Balanced.asset +++ b/Assets/GameMain/Settings/URP-Balanced.asset @@ -82,33 +82,33 @@ MonoBehaviour: m_Textures: blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} - m_PrefilteringModeMainLightShadows: 1 - m_PrefilteringModeAdditionalLight: 4 - m_PrefilteringModeAdditionalLightShadows: 1 - m_PrefilterXRKeywords: 0 - m_PrefilteringModeForwardPlus: 1 - m_PrefilteringModeDeferredRendering: 1 - m_PrefilteringModeScreenSpaceOcclusion: 1 - m_PrefilterDebugKeywords: 0 - m_PrefilterWriteRenderingLayers: 0 - m_PrefilterHDROutput: 0 - m_PrefilterSSAODepthNormals: 0 + m_PrefilteringModeMainLightShadows: 3 + m_PrefilteringModeAdditionalLight: 3 + m_PrefilteringModeAdditionalLightShadows: 0 + m_PrefilterXRKeywords: 1 + m_PrefilteringModeForwardPlus: 0 + m_PrefilteringModeDeferredRendering: 0 + m_PrefilteringModeScreenSpaceOcclusion: 2 + m_PrefilterDebugKeywords: 1 + m_PrefilterWriteRenderingLayers: 1 + m_PrefilterHDROutput: 1 + m_PrefilterSSAODepthNormals: 1 m_PrefilterSSAOSourceDepthLow: 0 - m_PrefilterSSAOSourceDepthMedium: 0 - m_PrefilterSSAOSourceDepthHigh: 0 + m_PrefilterSSAOSourceDepthMedium: 1 + m_PrefilterSSAOSourceDepthHigh: 1 m_PrefilterSSAOInterleaved: 0 - m_PrefilterSSAOBlueNoise: 0 + m_PrefilterSSAOBlueNoise: 1 m_PrefilterSSAOSampleCountLow: 0 - m_PrefilterSSAOSampleCountMedium: 0 - m_PrefilterSSAOSampleCountHigh: 0 - m_PrefilterDBufferMRT1: 0 - m_PrefilterDBufferMRT2: 0 - m_PrefilterDBufferMRT3: 0 - m_PrefilterSoftShadowsQualityLow: 0 - m_PrefilterSoftShadowsQualityMedium: 0 - m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterSSAOSampleCountMedium: 1 + m_PrefilterSSAOSampleCountHigh: 1 + m_PrefilterDBufferMRT1: 1 + m_PrefilterDBufferMRT2: 1 + m_PrefilterDBufferMRT3: 1 + m_PrefilterSoftShadowsQualityLow: 1 + m_PrefilterSoftShadowsQualityMedium: 1 + m_PrefilterSoftShadowsQualityHigh: 1 m_PrefilterSoftShadows: 0 - m_PrefilterScreenCoord: 0 - m_PrefilterNativeRenderPass: 0 + m_PrefilterScreenCoord: 1 + m_PrefilterNativeRenderPass: 1 m_ShaderVariantLogLevel: 0 m_ShadowCascades: 0 diff --git a/Assets/Settings/URP-Balanced.asset.meta b/Assets/GameMain/Settings/URP-Balanced.asset.meta similarity index 100% rename from Assets/Settings/URP-Balanced.asset.meta rename to Assets/GameMain/Settings/URP-Balanced.asset.meta diff --git a/Assets/Settings/URP-HighFidelity-Renderer.asset b/Assets/GameMain/Settings/URP-HighFidelity-Renderer.asset similarity index 100% rename from Assets/Settings/URP-HighFidelity-Renderer.asset rename to Assets/GameMain/Settings/URP-HighFidelity-Renderer.asset diff --git a/Assets/Settings/URP-HighFidelity-Renderer.asset.meta b/Assets/GameMain/Settings/URP-HighFidelity-Renderer.asset.meta similarity index 100% rename from Assets/Settings/URP-HighFidelity-Renderer.asset.meta rename to Assets/GameMain/Settings/URP-HighFidelity-Renderer.asset.meta diff --git a/Assets/Settings/URP-HighFidelity.asset b/Assets/GameMain/Settings/URP-HighFidelity.asset similarity index 76% rename from Assets/Settings/URP-HighFidelity.asset rename to Assets/GameMain/Settings/URP-HighFidelity.asset index d526597..627e0eb 100644 --- a/Assets/Settings/URP-HighFidelity.asset +++ b/Assets/GameMain/Settings/URP-HighFidelity.asset @@ -82,33 +82,33 @@ MonoBehaviour: m_Textures: blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} - m_PrefilteringModeMainLightShadows: 1 - m_PrefilteringModeAdditionalLight: 4 - m_PrefilteringModeAdditionalLightShadows: 1 - m_PrefilterXRKeywords: 0 - m_PrefilteringModeForwardPlus: 1 - m_PrefilteringModeDeferredRendering: 1 - m_PrefilteringModeScreenSpaceOcclusion: 1 - m_PrefilterDebugKeywords: 0 - m_PrefilterWriteRenderingLayers: 0 - m_PrefilterHDROutput: 0 + m_PrefilteringModeMainLightShadows: 3 + m_PrefilteringModeAdditionalLight: 3 + m_PrefilteringModeAdditionalLightShadows: 2 + m_PrefilterXRKeywords: 1 + m_PrefilteringModeForwardPlus: 0 + m_PrefilteringModeDeferredRendering: 0 + m_PrefilteringModeScreenSpaceOcclusion: 2 + m_PrefilterDebugKeywords: 1 + m_PrefilterWriteRenderingLayers: 1 + m_PrefilterHDROutput: 1 m_PrefilterSSAODepthNormals: 0 - m_PrefilterSSAOSourceDepthLow: 0 - m_PrefilterSSAOSourceDepthMedium: 0 - m_PrefilterSSAOSourceDepthHigh: 0 + m_PrefilterSSAOSourceDepthLow: 1 + m_PrefilterSSAOSourceDepthMedium: 1 + m_PrefilterSSAOSourceDepthHigh: 1 m_PrefilterSSAOInterleaved: 0 - m_PrefilterSSAOBlueNoise: 0 - m_PrefilterSSAOSampleCountLow: 0 - m_PrefilterSSAOSampleCountMedium: 0 + m_PrefilterSSAOBlueNoise: 1 + m_PrefilterSSAOSampleCountLow: 1 + m_PrefilterSSAOSampleCountMedium: 1 m_PrefilterSSAOSampleCountHigh: 0 - m_PrefilterDBufferMRT1: 0 - m_PrefilterDBufferMRT2: 0 - m_PrefilterDBufferMRT3: 0 - m_PrefilterSoftShadowsQualityLow: 0 - m_PrefilterSoftShadowsQualityMedium: 0 - m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilterDBufferMRT1: 1 + m_PrefilterDBufferMRT2: 1 + m_PrefilterDBufferMRT3: 1 + m_PrefilterSoftShadowsQualityLow: 1 + m_PrefilterSoftShadowsQualityMedium: 1 + m_PrefilterSoftShadowsQualityHigh: 1 m_PrefilterSoftShadows: 0 - m_PrefilterScreenCoord: 0 - m_PrefilterNativeRenderPass: 0 + m_PrefilterScreenCoord: 1 + m_PrefilterNativeRenderPass: 1 m_ShaderVariantLogLevel: 0 m_ShadowCascades: 1 diff --git a/Assets/Settings/URP-HighFidelity.asset.meta b/Assets/GameMain/Settings/URP-HighFidelity.asset.meta similarity index 100% rename from Assets/Settings/URP-HighFidelity.asset.meta rename to Assets/GameMain/Settings/URP-HighFidelity.asset.meta diff --git a/Assets/Settings/URP-Performant-Renderer.asset b/Assets/GameMain/Settings/URP-Performant-Renderer.asset similarity index 100% rename from Assets/Settings/URP-Performant-Renderer.asset rename to Assets/GameMain/Settings/URP-Performant-Renderer.asset diff --git a/Assets/Settings/URP-Performant-Renderer.asset.meta b/Assets/GameMain/Settings/URP-Performant-Renderer.asset.meta similarity index 100% rename from Assets/Settings/URP-Performant-Renderer.asset.meta rename to Assets/GameMain/Settings/URP-Performant-Renderer.asset.meta diff --git a/Assets/Settings/URP-Performant.asset b/Assets/GameMain/Settings/URP-Performant.asset similarity index 74% rename from Assets/Settings/URP-Performant.asset rename to Assets/GameMain/Settings/URP-Performant.asset index 8650b69..05bb741 100644 --- a/Assets/Settings/URP-Performant.asset +++ b/Assets/GameMain/Settings/URP-Performant.asset @@ -82,33 +82,33 @@ MonoBehaviour: m_Textures: blueNoise64LTex: {fileID: 2800000, guid: e3d24661c1e055f45a7560c033dbb837, type: 3} bayerMatrixTex: {fileID: 2800000, guid: f9ee4ed84c1d10c49aabb9b210b0fc44, type: 3} - m_PrefilteringModeMainLightShadows: 1 - m_PrefilteringModeAdditionalLight: 4 - m_PrefilteringModeAdditionalLightShadows: 1 - m_PrefilterXRKeywords: 0 - m_PrefilteringModeForwardPlus: 1 - m_PrefilteringModeDeferredRendering: 1 - m_PrefilteringModeScreenSpaceOcclusion: 1 - m_PrefilterDebugKeywords: 0 - m_PrefilterWriteRenderingLayers: 0 - m_PrefilterHDROutput: 0 - m_PrefilterSSAODepthNormals: 0 - m_PrefilterSSAOSourceDepthLow: 0 - m_PrefilterSSAOSourceDepthMedium: 0 - m_PrefilterSSAOSourceDepthHigh: 0 - m_PrefilterSSAOInterleaved: 0 - m_PrefilterSSAOBlueNoise: 0 - m_PrefilterSSAOSampleCountLow: 0 - m_PrefilterSSAOSampleCountMedium: 0 - m_PrefilterSSAOSampleCountHigh: 0 - m_PrefilterDBufferMRT1: 0 - m_PrefilterDBufferMRT2: 0 - m_PrefilterDBufferMRT3: 0 - m_PrefilterSoftShadowsQualityLow: 0 - m_PrefilterSoftShadowsQualityMedium: 0 - m_PrefilterSoftShadowsQualityHigh: 0 + m_PrefilteringModeMainLightShadows: 0 + m_PrefilteringModeAdditionalLight: 0 + m_PrefilteringModeAdditionalLightShadows: 0 + m_PrefilterXRKeywords: 1 + m_PrefilteringModeForwardPlus: 0 + m_PrefilteringModeDeferredRendering: 0 + m_PrefilteringModeScreenSpaceOcclusion: 0 + m_PrefilterDebugKeywords: 1 + m_PrefilterWriteRenderingLayers: 1 + m_PrefilterHDROutput: 1 + m_PrefilterSSAODepthNormals: 1 + m_PrefilterSSAOSourceDepthLow: 1 + m_PrefilterSSAOSourceDepthMedium: 1 + m_PrefilterSSAOSourceDepthHigh: 1 + m_PrefilterSSAOInterleaved: 1 + m_PrefilterSSAOBlueNoise: 1 + m_PrefilterSSAOSampleCountLow: 1 + m_PrefilterSSAOSampleCountMedium: 1 + m_PrefilterSSAOSampleCountHigh: 1 + m_PrefilterDBufferMRT1: 1 + m_PrefilterDBufferMRT2: 1 + m_PrefilterDBufferMRT3: 1 + m_PrefilterSoftShadowsQualityLow: 1 + m_PrefilterSoftShadowsQualityMedium: 1 + m_PrefilterSoftShadowsQualityHigh: 1 m_PrefilterSoftShadows: 0 - m_PrefilterScreenCoord: 0 - m_PrefilterNativeRenderPass: 0 + m_PrefilterScreenCoord: 1 + m_PrefilterNativeRenderPass: 1 m_ShaderVariantLogLevel: 0 m_ShadowCascades: 0 diff --git a/Assets/Settings/URP-Performant.asset.meta b/Assets/GameMain/Settings/URP-Performant.asset.meta similarity index 100% rename from Assets/Settings/URP-Performant.asset.meta rename to Assets/GameMain/Settings/URP-Performant.asset.meta diff --git a/Assets/GameMain/UI/UIItems/DamageTextItem.prefab b/Assets/GameMain/UI/UIItems/DamageTextItem.prefab new file mode 100644 index 0000000..a3dc0c5 --- /dev/null +++ b/Assets/GameMain/UI/UIItems/DamageTextItem.prefab @@ -0,0 +1,166 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &8729657611800212236 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 6585707618525138319} + - component: {fileID: 3880047934229121052} + - component: {fileID: 7710035529272699062} + - component: {fileID: 3312007461897115449} + - component: {fileID: 8516728773988177298} + m_Layer: 5 + m_Name: DamageTextItem + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &6585707618525138319 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8729657611800212236} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 0} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 200, y: 50} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!114 &3880047934229121052 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8729657611800212236} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 501e678f9cb14af6ac45e8d2050388d3, type: 3} + m_Name: + m_EditorClassIdentifier: + _cachedTransform: {fileID: 6585707618525138319} + _canvasGroup: {fileID: 8516728773988177298} + _text: {fileID: 3312007461897115449} +--- !u!222 &7710035529272699062 +CanvasRenderer: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8729657611800212236} + m_CullTransparentMesh: 1 +--- !u!114 &3312007461897115449 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8729657611800212236} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f4688fdb7df04437aeb418b961361dc5, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 0 + m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0} + m_Maskable: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_text: 100 + m_isRightToLeft: 0 + m_fontAsset: {fileID: 11400000, guid: 99d811b0183246646a2ce8df996f4bca, type: 2} + m_sharedMaterial: {fileID: -1106088975554028259, guid: 99d811b0183246646a2ce8df996f4bca, + type: 2} + m_fontSharedMaterials: [] + m_fontMaterial: {fileID: 0} + m_fontMaterials: [] + m_fontColor32: + serializedVersion: 2 + rgba: 4282077951 + m_fontColor: {r: 1, g: 0.32, b: 0.23, a: 1} + m_enableVertexGradient: 0 + m_colorMode: 3 + m_fontColorGradient: + topLeft: {r: 1, g: 1, b: 1, a: 1} + topRight: {r: 1, g: 1, b: 1, a: 1} + bottomLeft: {r: 1, g: 1, b: 1, a: 1} + bottomRight: {r: 1, g: 1, b: 1, a: 1} + m_fontColorGradientPreset: {fileID: 0} + m_spriteAsset: {fileID: 0} + m_tintAllSprites: 0 + m_StyleSheet: {fileID: 0} + m_TextStyleHashCode: -1183493901 + m_overrideHtmlColors: 0 + m_faceColor: + serializedVersion: 2 + rgba: 4294967295 + m_fontSize: 45 + m_fontSizeBase: 45 + m_fontWeight: 400 + m_enableAutoSizing: 0 + m_fontSizeMin: 18 + m_fontSizeMax: 72 + m_fontStyle: 1 + m_HorizontalAlignment: 2 + m_VerticalAlignment: 512 + m_textAlignment: 65535 + m_characterSpacing: 0 + m_wordSpacing: 0 + m_lineSpacing: 0 + m_lineSpacingMax: 0 + m_paragraphSpacing: 0 + m_charWidthMaxAdj: 0 + m_enableWordWrapping: 1 + m_wordWrappingRatios: 0.4 + m_overflowMode: 0 + m_linkedTextComponent: {fileID: 0} + parentLinkedComponent: {fileID: 0} + m_enableKerning: 1 + m_enableExtraPadding: 0 + checkPaddingRequired: 0 + m_isRichText: 1 + m_parseCtrlCharacters: 1 + m_isOrthographic: 1 + m_isCullingEnabled: 0 + m_horizontalMapping: 0 + m_verticalMapping: 0 + m_uvLineOffset: 0 + m_geometrySortingOrder: 0 + m_IsTextObjectScaleStatic: 0 + m_VertexBufferAutoSizeReduction: 0 + m_useMaxVisibleDescender: 1 + m_pageToDisplay: 1 + m_margin: {x: 0, y: 0, z: 0, w: 0} + m_isUsingLegacyAnimationComponent: 0 + m_isVolumetricText: 0 + m_hasFontAssetChanged: 0 + m_baseMaterial: {fileID: 0} + m_maskOffset: {x: 0, y: 0, z: 0, w: 0} +--- !u!225 &8516728773988177298 +CanvasGroup: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 8729657611800212236} + m_Enabled: 1 + m_Alpha: 1 + m_Interactable: 1 + m_BlocksRaycasts: 1 + m_IgnoreParentGroups: 0 diff --git a/Assets/GameMain/UI/UIItems/DamageTextItem.prefab.meta b/Assets/GameMain/UI/UIItems/DamageTextItem.prefab.meta new file mode 100644 index 0000000..795fef8 --- /dev/null +++ b/Assets/GameMain/UI/UIItems/DamageTextItem.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 308577c72eb4cd14ca676aeee62b0ea5 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/UniversalRenderPipelineGlobalSettings.asset b/Assets/GameMain/UniversalRenderPipelineGlobalSettings.asset similarity index 100% rename from Assets/UniversalRenderPipelineGlobalSettings.asset rename to Assets/GameMain/UniversalRenderPipelineGlobalSettings.asset diff --git a/Assets/UniversalRenderPipelineGlobalSettings.asset.meta b/Assets/GameMain/UniversalRenderPipelineGlobalSettings.asset.meta similarity index 100% rename from Assets/UniversalRenderPipelineGlobalSettings.asset.meta rename to Assets/GameMain/UniversalRenderPipelineGlobalSettings.asset.meta diff --git a/Assets/Launcher.unity b/Assets/Launcher.unity index 4112299..fae577e 100644 --- a/Assets/Launcher.unity +++ b/Assets/Launcher.unity @@ -122,6 +122,89 @@ NavMeshSettings: debug: m_Flags: 0 m_NavMeshData: {fileID: 0} +--- !u!1 &31248796 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 31248797} + - component: {fileID: 31248799} + - component: {fileID: 31248798} + m_Layer: 5 + m_Name: DamageText Instances + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!224 &31248797 +RectTransform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 31248796} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0, y: 0, z: 0} + m_ConstrainProportionsScale: 0 + m_Children: [] + m_Father: {fileID: 534968532} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 0, y: 0} + m_Pivot: {x: 0, y: 0} +--- !u!114 &31248798 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 31248796} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 0cd44c1031e13a943bb63640046fad76, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 1 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 2560, y: 1600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 + m_PresetInfoIsWorld: 0 +--- !u!223 &31248799 +Canvas: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 31248796} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 0 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_VertexColorAlwaysGammaSpace: 0 + m_AdditionalShaderChannelsFlag: 25 + m_UpdateRectTransformForStandalone: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 --- !u!1 &119167775 GameObject: m_ObjectHideFlags: 0 @@ -156,6 +239,7 @@ Transform: - {fileID: 1968988098} - {fileID: 472081678} - {fileID: 2050832067} + - {fileID: 534968532} m_Father: {fileID: 1852670053} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &120093239 @@ -248,143 +332,6 @@ MonoBehaviour: m_PointerBehavior: 0 m_CursorLockBehavior: 0 m_ScrollDeltaPerTick: 6 ---- !u!1 &278770807 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 278770808} - - component: {fileID: 278770811} - - component: {fileID: 278770810} - - component: {fileID: 278770809} - m_Layer: 0 - m_Name: Camera - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!4 &278770808 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 278770807} - serializedVersion: 2 - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 0, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_ConstrainProportionsScale: 0 - m_Children: [] - m_Father: {fileID: 1852670053} - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!114 &278770809 -MonoBehaviour: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 278770807} - m_Enabled: 1 - m_EditorHideFlags: 0 - m_Script: {fileID: 11500000, guid: a79441f348de89743a2939f4d699eac1, type: 3} - m_Name: - m_EditorClassIdentifier: - m_RenderShadows: 1 - m_RequiresDepthTextureOption: 2 - m_RequiresOpaqueTextureOption: 2 - m_CameraType: 0 - m_Cameras: [] - m_RendererIndex: -1 - m_VolumeLayerMask: - serializedVersion: 2 - m_Bits: 1 - m_VolumeTrigger: {fileID: 0} - m_VolumeFrameworkUpdateModeOption: 2 - m_RenderPostProcessing: 0 - m_Antialiasing: 0 - m_AntialiasingQuality: 2 - m_StopNaN: 0 - m_Dithering: 0 - m_ClearDepth: 1 - m_AllowXRRendering: 1 - m_AllowHDROutput: 1 - m_UseScreenCoordOverride: 0 - m_ScreenSizeOverride: {x: 0, y: 0, z: 0, w: 0} - m_ScreenCoordScaleBias: {x: 0, y: 0, z: 0, w: 0} - m_RequiresDepthTexture: 0 - m_RequiresColorTexture: 0 - m_Version: 2 - m_TaaSettings: - m_Quality: 3 - m_FrameInfluence: 0.1 - m_JitterScale: 1 - m_MipBias: 0 - m_VarianceClampScale: 0.9 - m_ContrastAdaptiveSharpening: 0 ---- !u!81 &278770810 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 278770807} - m_Enabled: 1 ---- !u!20 &278770811 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 278770807} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_Iso: 200 - m_ShutterSpeed: 0.005 - m_Aperture: 16 - m_FocusDistance: 10 - m_FocalLength: 50 - m_BladeCount: 5 - m_Curvature: {x: 2, y: 11} - m_BarrelClipping: 0.25 - m_Anamorphism: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 --- !u!1001 &343730742 PrefabInstance: m_ObjectHideFlags: 0 @@ -765,7 +712,7 @@ PrefabInstance: objectReference: {fileID: 0} - target: {fileID: 11497722, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3} propertyPath: m_ResourceMode - value: 2 + value: 1 objectReference: {fileID: 0} - target: {fileID: 11499388, guid: adb3eb1c35fcff14f89fba7b05c9d71c, type: 3} propertyPath: m_FrameRate @@ -904,6 +851,57 @@ MonoBehaviour: type: 3} m_UpdateResourceFormTemplate: {fileID: 11487720, guid: a6c731de80e9d824d8f657301a357269, type: 3} +--- !u!1 &534968531 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + serializedVersion: 6 + m_Component: + - component: {fileID: 534968532} + - component: {fileID: 534968533} + m_Layer: 0 + m_Name: DamageText + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &534968532 +Transform: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 534968531} + serializedVersion: 2 + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 + m_Children: + - {fileID: 31248797} + m_Father: {fileID: 119167776} + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &534968533 +MonoBehaviour: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInstance: {fileID: 0} + m_PrefabAsset: {fileID: 0} + m_GameObject: {fileID: 534968531} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 366eb88b821a4048891b7fb01a1b8d42, type: 3} + m_Name: + m_EditorClassIdentifier: + _instancePoolCapacity: 32 + _poolName: DamageTextItem + _instanceRoot: {fileID: 31248797} + _canvas: {fileID: 31248799} + _damageTextItemPrefab: {fileID: 8729657611800212236, guid: 308577c72eb4cd14ca676aeee62b0ea5, + type: 3} --- !u!1 &553656361 GameObject: m_ObjectHideFlags: 0 @@ -976,7 +974,7 @@ MonoBehaviour: m_ScaleFactor: 1 m_ReferenceResolution: {x: 2560, y: 1600} m_ScreenMatchMode: 0 - m_MatchWidthOrHeight: 0 + m_MatchWidthOrHeight: 0.6 m_PhysicalUnit: 3 m_FallbackScreenDPI: 96 m_DefaultSpriteDPI: 96 @@ -1232,7 +1230,6 @@ Transform: m_Children: - {fileID: 343730743} - {fileID: 119167776} - - {fileID: 278770808} m_Father: {fileID: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!114 &1852670054 diff --git a/Assets/StreamingAssets/.gitkeep b/Assets/StreamingAssets/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/ProjectSettings/BurstAotSettings_StandaloneWindows.json b/ProjectSettings/BurstAotSettings_StandaloneWindows.json index 2144f6d..34712b4 100644 --- a/ProjectSettings/BurstAotSettings_StandaloneWindows.json +++ b/ProjectSettings/BurstAotSettings_StandaloneWindows.json @@ -1,16 +1,18 @@ { "MonoBehaviour": { - "Version": 3, + "Version": 5, "EnableBurstCompilation": true, "EnableOptimisations": true, "EnableSafetyChecks": false, "EnableDebugInAllBuilds": false, - "UsePlatformSDKLinker": false, + "DebugDataKind": 0, + "EnableArmv9SecurityFeatures": false, "CpuMinTargetX32": 0, "CpuMaxTargetX32": 0, "CpuMinTargetX64": 0, "CpuMaxTargetX64": 0, "CpuTargetsX32": 6, - "CpuTargetsX64": 72 + "CpuTargetsX64": 72, + "OptimizeFor": 0 } } diff --git a/ProjectSettings/CommonBurstAotSettings.json b/ProjectSettings/CommonBurstAotSettings.json index 3dffdba..a6a6297 100644 --- a/ProjectSettings/CommonBurstAotSettings.json +++ b/ProjectSettings/CommonBurstAotSettings.json @@ -1,6 +1,6 @@ { "MonoBehaviour": { - "Version": 3, + "Version": 5, "DisabledWarnings": "" } } diff --git a/ProjectSettings/GraphicsSettings.asset b/ProjectSettings/GraphicsSettings.asset index 56859a2..d0b1054 100644 --- a/ProjectSettings/GraphicsSettings.asset +++ b/ProjectSettings/GraphicsSettings.asset @@ -3,7 +3,7 @@ --- !u!30 &1 GraphicsSettings: m_ObjectHideFlags: 0 - serializedVersion: 14 + serializedVersion: 15 m_Deferred: m_Mode: 1 m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} @@ -13,9 +13,6 @@ GraphicsSettings: m_ScreenSpaceShadows: m_Mode: 1 m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} - m_LegacyDeferred: - m_Mode: 1 - m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} m_DepthNormals: m_Mode: 1 m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} @@ -37,11 +34,15 @@ GraphicsSettings: - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} - {fileID: 10783, guid: 0000000000000000f000000000000000, type: 0} + - {fileID: 4800000, guid: 68e6db2ebdc24f95958faec2be5558d6, type: 3} + - {fileID: 4800000, guid: 128e987d567d4e2c824d754223b3f3b0, type: 3} + - {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3} + - {fileID: 4800000, guid: 1e3b057af24249748ff873be7fafee47, type: 3} m_PreloadedShaders: [] m_PreloadShadersBatchTimeLimit: -1 m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, type: 0} - m_CustomRenderPipeline: {fileID: 11400000, guid: 7b7fd9122c28c4d15b667c7040e3b3fd, + m_CustomRenderPipeline: {fileID: 11400000, guid: e1260c1148f6143b28bae5ace5e9c5d1, type: 2} m_TransparencySortMode: 0 m_TransparencySortAxis: {x: 0, y: 0, z: 1} @@ -51,6 +52,7 @@ GraphicsSettings: m_LightmapStripping: 0 m_FogStripping: 0 m_InstancingStripping: 0 + m_BrgStripping: 0 m_LightmapKeepPlain: 1 m_LightmapKeepDirCombined: 1 m_LightmapKeepDynamicPlain: 1 @@ -68,3 +70,6 @@ GraphicsSettings: m_SRPDefaultSettings: UnityEngine.Rendering.Universal.UniversalRenderPipeline: {fileID: 11400000, guid: 18dc0cd2c080841dea60987a38ce93fa, type: 2} + m_LightProbeOutsideHullStrategy: 0 + m_CameraRelativeLightCulling: 0 + m_CameraRelativeShadowCulling: 0 diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 403c004..30ac6af 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -13,7 +13,7 @@ PlayerSettings: useOnDemandResources: 0 accelerometerFrequency: 60 companyName: DefaultCompany - productName: StarForce1 + productName: VampileLike defaultCursor: {fileID: 0} cursorHotspot: {x: 0, y: 0} m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} @@ -526,7 +526,7 @@ PlayerSettings: m_APIs: 10000000 m_Automatic: 1 - m_BuildTarget: AndroidPlayer - m_APIs: 150000000b000000 + m_APIs: 0b000000 m_Automatic: 0 m_BuildTargetVRSettings: [] m_DefaultShaderChunkSizeInMB: 16 @@ -935,7 +935,7 @@ PlayerSettings: hmiLogStartupTiming: 0 hmiCpuConfiguration: apiCompatibilityLevel: 6 - activeInputHandler: 2 + activeInputHandler: 1 windowsGamepadBackendHint: 0 cloudProjectId: framebufferDepthMemorylessMode: 0 diff --git a/TodoList.md b/TodoList.md index 59dbc7f..0c8ae14 100644 --- a/TodoList.md +++ b/TodoList.md @@ -114,6 +114,6 @@ ## 8. 交付物清单(每阶段都要有) - [ ] 设计文档(接口、数据结构、生命周期)。 -- [ ] Profiling 对比(改造前后同场景同参数)。 - [ ] 回归用例(至少战斗、关卡切换、商店、升级)。 +- [ ] Profiling 对比(改造前后同场景同参数)。 - [ ] 风险与回滚说明(特别是热更新与渲染链路)。 diff --git a/数据表/Enemy.txt b/数据表/Enemy.txt deleted file mode 100644 index 7ca14d2..0000000 --- a/数据表/Enemy.txt +++ /dev/null @@ -1,5 +0,0 @@ -# 敌人基础属性表 -# Id MaxHealth Speed CoinDrop ExpDrop DropPercent -# int int float int int float -# 实体编号 策划备注 最大生命 移动速度 金币掉落 经验掉落 掉落概率 - 101 近战敌人 20 3 2 1 0.3 diff --git a/数据表/Enemy.xlsx b/数据表/Enemy.xlsx index 0ed36d574e7cb3d4d81996c0e319c03513fbd3fc..4c34885546218bcd2d7c94aa38dd753d24fd63c8 100644 GIT binary patch delta 2243 zcmV;!2t4=iQKM3@wE+cW3icIKlez&Oe@#xqFc5|JNZcXvKDC|x2&^=f0Chzrq!xkL z8GG7B#ExYf((YMtB^F$U4Y$Ba+mH&x((~SY^Je69vQb6!0@mfF9wXW#C;}}?nd{XU z-7co_8H$|eTJoaQFh*N&Xp)_tq{1*!TDY;L0qb*cQ6Oo@gc+l?_l9BY#2OTLf4$() zL0pzraUY&`g$)-^d<8fmWP}xXF1hEp2F9i(qCHZI7HOVs(Ey~tP=EsM9i}~sf4m;7 za(^~7O2?^kzcpc}ecUcvik;ZHH!g3DRaNz>eiI|)r}%z$J#SWxb6wv`0LoG+n6SWo zX|p*P59$$YiaXW%f(3Ve7LL8lW@6aWAK2mpsp;y{rINOnS#IRhYnTTg>97>4gn{12q}(2uezEWk1jO^g>Box3%p zl#K*hLd$e9{&zd)Jltx$Yx6cwpT7O##dF^|J2C23$prZxAV)~9>Q-(N^sr)Xh#YMy zSy!EsB0+nh(IP!Ri*H9Yh|#n{I~E~zg0{vCbBs0LioVjGjipT*HTIRU+i`<`RnxRw z6pBy1kOmWg3(O~NRPPR-ICSLAcjmXqTJeLOUa$6p)lK6M_}*!H)7A-kDQI346sSwe zD0hAEGdBvNOBX@_l98N6%kmXD!{IPNj;wn7^y~W@i>)VavZ?LrwHPgWXXf4Tq|KNT zpv3iwXFK!=C4|KID~$2U;g2>#!O7+-U;nrsii?m05u;&V&RCFTbP1FJFcy%UmhkBR zkI?KSlvf>}y2{u=x|=$2lxt@xy!T)i-#fsE4?2!d`Ua31le7du3d@&g2yFuZ05%Jg z{{$?5=FtL$icob>3eqN3>mHv?V!&z=XSN~je*LZ;@^sd+$r4Vk59eN=oH%!S`;x@y zNQGoP4Y2Qc7|}H35leRg{{C%wF~&$Ll13!vDGl%|mH2k{@xwId;#uw~RR|bT8Q{HA z*^TSUa8DB=9iGt?R<>LuM8U1txiS-!MCMO_N$g&F-pEY|OL4()BhKOA+bs*}f`^BM zrm7$jG$sn_mwT4UlIk=h4%g3H)f zp06m|?G=pdL1I>Ga|8#H);1&hxb$x(@VbOLc&DRg4a_VddYpMv_XuxB zctU)#5q^bmfxAkerLq&~=-UZw#ATJh6uGbwS8c?-jTp2MOB*q4BOYwTsEt_Ji0d|D zZ6n4Nq9v9#s4bR`zAcuGm{bXW3bEcr+`o%h+6cd6iw7IhDP;97Vr?TDXfpjg{1L=CO2hufR59BW{)Cafa!cRJ?W!0yF z?{)PmS5b9h_?;)eC?T3)*fGxiTZ_x)Vn^bK=2}O%RdcOVFtio*c08wLW-Sa>v;)OS znUNj+Ld1@x62){28}uCbGKk_^Z>|;3OcY2rTtQ<~-tD2kq;R4_28_0xtMUeV0nPhF z)geO}$*6c@zu~J72Rs)HI!V(&1~}tF3Br_a1`4vJVbLv1)$z{$0Fz(}F|(uy2MT|k z0)k6)0RRB30ssIM0001ZY%g zh}hi-D+~&P>H-G$D;IWWww*ET%!07OH2b52&=bD3BOD?UMGTDE?*(6|_ zr{y5&E}7;gcNk#qVqSI*zRUjU{pgARGd28e#t*Y76i5&O z){}80Kmsrzld~i;0aTObB$EYX3icIKlYS*S8<7Y|c0vIF0E7Yn022TJ000000096X z0000flhY+Y4V(l30C;RKP)h*<6abS^3>uRX9#Tr001@%000;O0000000031AOHXW=>(IH2o;k^C@%tx2$PQp8k3VK RDgk+uz9=gOdL#e<002cL`j`L! delta 2135 zcmV-d2&ng?Qtwf)wE+cYidP;`lez&Of3Z%(Fc5}!B;FzNp4d)lg`y;t0Cl1gQj0)r z#=f=@v18eWv^x{8#K6n2@D?~p8&ZK7egA*o{daOY-O4g}0b`3wWr#)u1)z8(3boGA z?Q#~Lqrf_*1S=~A8QOtG)BN-#~2N5)u!H2SDEDKK>K=H&9Ch z1QY-O00;nwPU1i)5p(22lRN_;e_c<5FcgOGP5cj}_s~P38!W&wz7pewM(1t~DP<#p zme4X?jQ`!vIX`YS-nDs~=RD{1M9b&Cv-W&ctrRhG9Y7WrOxCT~#^_;P+5xhZu0&mR zQt%iZxI)Y1@*=t&<-kYXa%CBWP%+wRJuEO*Y{&abIVKh+Y2?^f+FZvif0j+tGM-B| z^;~F70A`p?O3U6JK5^*8TkQ33k+oz;JGEIK2BVuqAMk_K^t!EM^pevo&nZxw6k%q& z;HGxyg>xGM0Fsid3|GY~vWDYhf-F(>ruFOl8-uMUrqikI>J1+adaoDV@TByZ5TL|% ziDPEy5PwGJ5&jAze0KPwLydQ~xym*_%0oU2h!>VL$O^yo(v+@%mH=hxk&G7b=#qaC z^3Ot9)v>9ov{|IPspBWP)=%KQtT}w20X}}vX?>D6kQ$S=1VIW}xC78u0{{Sf3X=f^ zEPo~h+VT*g>S!sGHmO?o_-qmbR+Bih4Qco5cWviw)UqiOPOeYRz4vfzXMXdNCg@0o zWIPLT;0-XMS;S+O?Lz$H`|4tXkyIp$Ny0N4;#Vs1&En&SdBMfA+*7I$Fk~{sd!_Q3 z@5^XUQzAW{(+p;|T%<(7quBW}7nH>2rGGT>hl9bjpAwc~%PZ@ zk_eg*1@+54%Vov(5}(Bv3sOL@RXwc|@9a#?7hF2^r7RL$@~!eBp8B>lx67$N?ev*O z4$%p*QX-xY`2`T?(AZ-xEe}%h^o}Tk7k_i} z4?GHgF^?IjsQ-E-=r+W+!EAknA#M;q87*Y%9x1YUq6v)@jln7yX$x#Pf7Zay5E^K1 z1JH~lQtU{VG)Y1XtVsSgIcx&I&ajv__f@u)G0meuG2N0wqLw`Q#bUJ&@f26FZ@gGj zw%aQxr5i((bNuOMKtv;ubNBCeojSz zGej^}L|0zBGbr^eqU(|f#)>HLf=P3McxMrfOClH>qW`G~_Ak>Kj1|%7Uw<_6tzV2^ z_4--N1uqcnEnpm(6TR~Vvk5pq(!pCDHFMxg3DM(XF!zsO@~A|7auGp|@PWHdprvvX z=;+%CT*R8RFBFVbMp>vUPoqIw|*jXA9t6+{yZdt%ppN)&Zvy2Eh3JF;S=Jr_u003%}%@Q4dPfG$p7>Dmc-(i`~xhfPA zyX(P z!tjoguQ;}Jfjnvvtb$A`4J3qhVpzDOg0s{8%^Z*@gV=yJ!AJ#{h=RPfzNS#hq_~Tz z3QWe_9a*M-x``Y}Q^Z9$Hbvq&kj0}{lBw$PygvRgnZ zW9z((3QLg50ZpNnrZ8<>eIwv{-O_OyeHUV^#tS3ML zD3k3cJOR6tDkvcvS-1nxRs#S4dkO#m7ytkO000000RSKX008HcW++7gbCawnMFC)w N@+d0?MkD|L004xN-;w|T diff --git a/数据表/Entity.txt b/数据表/Entity.txt deleted file mode 100644 index 499034d..0000000 --- a/数据表/Entity.txt +++ /dev/null @@ -1,11 +0,0 @@ -# 实体表 -# Id AssetName -# int string -# 实体编号 策划备注 资源名称 - 1001 测试玩家 Player - 101 近战敌人 MeleeEnemy - 102 远程敌人 RemoteEnemy - 11 跟随相机 FollowCamera - 201 武器小刀 WeaponKnife - 10001 金币实体 CoinEntity - 10002 经验实体 ExpEntity diff --git a/数据表/Goods.txt b/数据表/Goods.txt deleted file mode 100644 index 3d5237b..0000000 --- a/数据表/Goods.txt +++ /dev/null @@ -1,9 +0,0 @@ -# 商品表 -# Id GoodsType GoodsTypeId -# int GoodsType int -# 商品编号 策划备注 商品类型 商品对应物品Id - 101 道具:药 Prop 101 - 102 小刀 Weapon 201 - 103 Prop 102 - 104 Prop 103 - 105 Prop 104 diff --git a/数据表/Level.txt b/数据表/Level.txt deleted file mode 100644 index 914673d..0000000 --- a/数据表/Level.txt +++ /dev/null @@ -1,14 +0,0 @@ -# 关卡配置表 -# Id EntityIds EntityCounts Interval Duration -# int int[] int[] float[] int -# 关卡号 策划备注 实体编号 每次出怪数量 每次出怪间隔 关卡时间 - 1 第一关 [101] [5] [2] 60 - 2 第二关 [101] [10] [3] 60 - 3 第三关 [101] [10] [3] 60 - 4 第四关 [101] [10] [3] 60 - 5 第五关 [101] [10] [3] 60 - 6 第六关 [101] [10] [3] 60 - 7 第七关 [101] [10] [3] 60 - 8 第八关 [101] [10] [3] 60 - 9 第九关 [101] [10] [3] 60 - 10 第十关 [101] [10] [3] 60 diff --git a/数据表/LevelRarity.xlsx b/数据表/LevelRarity.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..85eaea7538d26b69c535fd27f2e88f82f5ff4c5d GIT binary patch literal 10771 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 literal 0 HcmV?d00001 diff --git a/数据表/LevelUpReward.txt b/数据表/LevelUpReward.txt deleted file mode 100644 index b2eb50e..0000000 --- a/数据表/LevelUpReward.txt +++ /dev/null @@ -1,8 +0,0 @@ -# 道具表 -# Id Title IconAssetName Modifiers -# int string string StatModifier[] -# 奖励编号 策划备注 奖励名 图标资源名 道具属性 - 101 测试道具 肌肉 Almighty_Icon [{"StatType":"Attack","Value":0.05,"IsPercent":true}] - 102 牙齿 Almighty_Icon [{"StatType":"Attack","Value":0.05,"IsPercent":true}] - 103 脑 Almighty_Icon [{"StatType":"Attack","Value":0.05,"IsPercent":true}] - 104 鼻子 Almighty_Icon [{"StatType":"Attack","Value":0.05,"IsPercent":true}] diff --git a/数据表/LevelUpReward.xlsx b/数据表/LevelUpReward.xlsx index ffa763dbc0ca470d646bdf1daf90bc50a1a5d366..4875cd7ec223234c393b6a95a67e17b271e77b36 100644 GIT binary patch delta 5376 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 GCH)s&S1s27 delta 4622 zcmZ8lXHXMN*G)nXO{8~1uOUe99YQZs1*Aw30!l{^h;)z^5{XhpIwHMy1SB9RO%MU4 zcSM>rDIY%1JM(_??vFFGd(J(3XYS0-y?bnRY+Bs_#INUnhsLx3*^vf@y|7y`C-6DQ zfl^IQJ%P23AaLusE?fjuBYs?;9M3u=RsX$iNmsa;jQLRn=4uq&H-7jd^w4!BwAnP^ z2sCA$483JQ{9Gkb%Od1{-s~p7l6Kmmt=@fUCU8ArTW4eQ80Wd34mz6A4acx*Suq4kj9d zueTtYB0(=TYZH36^VKq_{+<#&jkIgw$MsaX3sWW^-s$_TRC#UZe{{>5v1jLo_Ol)N1{sc(jIMcDuz- zu!*mF1m8}{XYb%0t&H>%;rk??8t6cvyQ~R8qTG-)ZZRtY*^eOk{`<6hLeYeRO@yUM zGUy}yDQ+DQ&G~}Rz9qfMiE&T4hwYEqkT;E=#Dkn_aU~j+)(3I@2Ml?PwKeSTPSrLR z`6GsjWsy7F)R}3ISM+Z)fJf^YqiBFk<>OR(c@!7&0t6G3X_zJHFp;-RYMp!zL0x^! zD`5%Ih=e1e-OIu&U^2YQU#C%)RVx6}9B%y3mUGdA)L?F``RaXlx*En;&UR>%dY;vA zo1J*W@MO4kqm#cxm_D19Vu$l#!$8f<@>M8E5t(APr=$5h|NS{>eD2Grn4nl!Egq*y z%~ONE8BVjiX5$9()m}tBiO+~G1ks}(*wBI@InMNAo@w>*&kM8gKMBlIQaRG^8?Qdxh%^{2(9^8i-r{sM z2OaTxz|tpl%s))$;q+pINscZXG+S!1i}s+H9EbMwk8-3CYfT4T2e?W%JYJi99* z%m|rS9W^Nt7^z(wZ<`7P08T&vz~86jiKnRFLq}g1=ez#C?vLF3pijI!z0h`gy)c^C zUj*0c2@C0!Ir;I8=@8;JWBd|n&fBfc1hf89B}=zdi^d(@ICLu2PqbL=Y|1f;P5k8ZbcWA2Ool8#w9GQGdR$zYu zbAkI^pdw;ICg7xuc4UL`_=@h%S=lqZ)2zi5jb+lzBuv|UPKP|5t#@NQ@AJrlp(c(~ z`_{2YKhW|tf(nP8Tz5yuZRL}h^+DiHrkmUjryVY?7Umxe40e>J<`GMKnv+{6k~Lw% zl}-62*zbi#W|U?and>BI)6#nKM#FikaPRF@`mvb`kL28wrMSDYZ#;Zllq+{iC6+_# zjiV22#nsKTtv7AS!WcXVQ9>`{cL-eu0S;1bs<~~>8U2q=<(&(YI@z;Vskyz0qu7=4 zA=X}lHJyG_r>CZ`Z#`xyE8V~1-7QC&87Wm>lGlaM%Yu+Zp>@S106?<}06_kq()kB_ zy8KhK54MQZSu4h?ls;s&?R%m={UyCeb%QSqU4<*^;c$`LxAQ(?WEe?t6e)LI0~<`= z*bvgulF;(MvvB%mF2KG4AayEtnY|P@$UN(_Ur@xoJj`8@*_Q|$hg0K@|Fk!)D=JAN zn}RR>7vMp{Nav@I^eh60YMonHs}OCM*o*Hr{f2f}t%%J)1Dsz4HqLD=qGjDB?Gj8J8r$ytXeoo}WW0lhNw$0;*7ZHrzMqTzy}^you|vC(RT4gzDnR>QpZr#b+(eYc2dM)wFk4qPnc z)O$1GRYmGLhwX&e{aI^3tj>-zubdLepML#{R5*^54(t&P!8JY7^A)g&@tF)p&KYkY z?Ug7ft21NtthReT>}l|F)dzENRr?v z#wDoh+o3Jixq-}@*X=l~ps7f{7|$giMHZldJ1hcBQ&<`v;M5<$VxLMV0It; z@(KO<%aS0ROm;xzFptqtq26Go0y9G0ECFpPKEQ|hm^8RNS5EVjtt2_Na=^iN#u!%6 zIwTvQXH~|SX;O|}SThH?S86Iizzs`JBAploBp!XC7;2$A15=Wpi;f^s(82k&_O@{@ z$b$q?AF@^x-A;F#{C8uqe5#e^)n?WWrtNMft-d^+17)G^s%@lP8yV9n7=O5A@{#$% za5%LbE@HKf@B)>;Y~!ZBQPw<~%Ew~~{$=A6G%r0uldg2PmLy35w|iUY+-pYp`79m( z@4&1L#T4lDqpxxedA&&6qOknicVxXD4oxG)TM%R(1b5E`FCbVlIQpo*>F+G5esWJ1Pjn?^BeQ{Rjp6cW2 z!?tQc9!((;=Y1Z9hI#*Y_W{fB`Q6v3U){`TlOlTj>ZH2)of+48KLa8Py&8=R18$_F zBq?3xJzsASsnNcIw**|#crZ=@pt~{!*VZEOpp@h*05Gu4=9qB$`!=L5JmZ(E!A49r z;G+7@3Yl4Bllp34v^p6Z&V~73k9-ZPN+)4!*54B^Zxx{oD%}hq=mD%6H%cr9&PmDs ztA3Oa^PDuoc~%#6F;}|#o*TVb2QDi7@1X2 z!Qs*9iw;9Ouux3-$)u8Blc+eC$D=pT<1Z61+k!_2)2wtJ(o6@<<;n0FZ% z^;e}y6uoP57d7(|tZlz2gz2%yBFfeB&cH@Ib)c*#aOsUcBh) zt&p0S_ij|xuxY9uv}T6nD-@yLanU=V-b_wBNw;LbO>LPwxfQ`A9x8d!VyaKG0uf@pc8*uj+n`^=tee3`b-Emck)679r@+y;w0UR^O#~=hbZZ3#mwO0&82gB8V9|a zzqLFH865c07tc(%X?DjNp*%3y*W-7jNe_l4ZwG_?D*9TxWoTNktc0H%cD<8Sb;A97 zyS=m7VPFE!HDO|zuOHRl82eQykYyuQ7a7*?1vA_n^}ZQsKpw!nE7RlDfw&Je#8$6w z0%EX;RmTNeA<7R{PjfyBEw-e3^Wqyts<8ju^5YnH7tLf8i&J0U(Nch@1?E&uT58+< zZrO1*4_-Puo`oeu@w(hGoVfK}$PKwR40C8#%f@1Hj&)i^#atN1aidVbCqr^EKjjxS z*fU1*xj{3?ybOtOHW5gM#xZBp%3z&a9pA6_vrsXU6kH>okSWB=Vb@1>;eE%;5qACX z{lg*3aOT7`IVY#Z{@o{>qT}L!PB4RYulqrTO0NLly(FsEC)w?vp*QELc~;)^I&Vy6 z1ZR-c{`|Ab-aj*NH%4dtJHsLRO)xxG0rrZ_ZpI#kJR7+jiW4pF3TN4djDUElJB4BN zv4d`}KSMj)L;d%+qE1{74+;m}4*Y?>_t%f?ksS(1Wea$wFE8K$o@%G7(e<6PPk$!n zUmGc3*a&Oi^Wdi6UC*uaKOZ|=#UbN)Hk$Dgh& zoor2$xT`{b8xG&A;QSc3XhHoiJ4+)~P&OV;1-?8={?R*^E4xQVseF{-(k;lx=VSB< z!Xu>SuS!t|q_y==hYyOth>-J*B>2-Lbr%5=o+!2-09C4coJ4 z8^MO+NIdso$W_inDNjzq6iV`fxT>`l3{77O8VOG$pa6KXE=XNIGU>shp828XOD0+* zVeg?K^#N2;kc=?JSP|hQ2leG~f5Jh=@(lI5%)}9<;3f%iyIauX@MO(HZLL@<=KbFA zWXv$FH;=ouWNzJ_;f{Ip4f(le1_R)|afx+FfBlLt1x)K4RGA%j|Z=ChyFlW zMp1q9zwv7ME8kN4{Erv%ubDwII4a`Qp(J{kR)c__PLm)H_6$|`@9jeW5e`=nXJj$a z684HWsbvfi#*H>m4%lq@rz>pE;&ruJjIhYRuUK)?bH&XUGY4_}8MB+O`Sk=C^KfwI zRHRl6d@j)K!(iDi85yR(Cz2f2#?$5JZ;W7JGiTf~>_L!w}V}lnGuP}K@4taKUAve#CMHD zmQfd(9N1IrT(hH?>Tj{2S$!x{01NKqyPO$!55Gx_;=9P5U>E|V6p_n zfDp_l0jV3r7Zhgs-+un4F9ZMq95;x&jnNn6WB#9}@xOd69VSIk78FE=85EQR<&vR= zltJ+{7*!#8U?(O_2*UE;F&+S5_#1b#{ KOhv%`SNDJY9g?#E diff --git a/数据表/Music.txt b/数据表/Music.txt deleted file mode 100644 index c94009f..0000000 --- a/数据表/Music.txt +++ /dev/null @@ -1,7 +0,0 @@ -# 音乐配置表 -# Id AssetName -# int string -# 音乐编号 策划备注 资源名称 - 1 菜单音乐 music_menu - 2 战斗音乐 music_background - 3 关于音乐 music_about diff --git a/数据表/Prop.txt b/数据表/Prop.txt deleted file mode 100644 index 028dce3..0000000 --- a/数据表/Prop.txt +++ /dev/null @@ -1,24 +0,0 @@ -# 道具表 -# Id Title IconAssetName Rarity Price PriceRandomPercent Modifiers -# int string string RarityType int float StatModifier[] -# 道具编号 策划备注 道具名 图标资源名 道具品质 道具价格 价格浮动 道具属性 - 101 道具_1 Almighty_Icon White 119 0.0500000007450581 [{"StatType":"Attack","Value":10,"IsPercent":false},{"StatType":"Defense","Value":12,"IsPercent":false}] - 102 道具_2 Almighty_Icon Green 225 0.0799999982118607 [{"StatType":"MaxHealth","Value":53,"IsPercent":false},{"StatType":"AttackSpeed","Value":0.09,"IsPercent":true},{"StatType":"Attack","Value":11,"IsPercent":false}] - 103 道具_3 Almighty_Icon Blue 329 0.100000001490116 [{"StatType":"Critical","Value":15,"IsPercent":false},{"StatType":"CriticalDamage","Value":21,"IsPercent":false},{"StatType":"Defense","Value":23,"IsPercent":false}] - 104 道具_4 Almighty_Icon Red 423 0.119999997317791 [{"StatType":"Defense","Value":79,"IsPercent":false}] - 105 道具_5 Almighty_Icon White 120 0.0500000007450581 [{"StatType":"MovementSpeed","Value":0.8,"IsPercent":false},{"StatType":"Attack","Value":10,"IsPercent":false}] - 106 道具_6 Almighty_Icon Green 195 0.0799999982118607 [{"StatType":"Dodge","Value":10,"IsPercent":false},{"StatType":"Attack","Value":12,"IsPercent":false},{"StatType":"MaxHealth","Value":44,"IsPercent":false}] - 107 道具_7 Almighty_Icon Blue 335 0.100000001490116 [{"StatType":"Defense","Value":62,"IsPercent":false}] - 108 道具_8 Almighty_Icon Red 433 0.119999997317791 [{"StatType":"Attack","Value":44,"IsPercent":false},{"StatType":"Dodge","Value":27,"IsPercent":false}] - 109 道具_9 Almighty_Icon White 121 0.0500000007450581 [{"StatType":"MaxHealth","Value":32,"IsPercent":false},{"StatType":"Attack","Value":7,"IsPercent":false},{"StatType":"Defense","Value":8,"IsPercent":false}] - 110 道具_10 Almighty_Icon Green 198 0.0799999982118607 [{"StatType":"AttackSpeed","Value":0.19,"IsPercent":true}] - 111 道具_11 Almighty_Icon Blue 341 0.100000001490116 [{"StatType":"Attack","Value":57,"IsPercent":false}] - 112 道具_12 Almighty_Icon Red 443 0.119999997317791 [{"StatType":"MaxHealth","Value":139,"IsPercent":false},{"StatType":"Critical","Value":27,"IsPercent":false}] - 113 道具_13 Almighty_Icon White 122 0.0500000007450581 [{"StatType":"Critical","Value":5,"IsPercent":false},{"StatType":"Dodge","Value":7,"IsPercent":false},{"StatType":"MovementSpeed","Value":0.6,"IsPercent":false}] - 114 道具_14 Almighty_Icon Green 201 0.0799999982118607 [{"StatType":"Defense","Value":38,"IsPercent":false}] - 115 道具_15 Almighty_Icon Blue 346 0.100000001490116 [{"StatType":"MovementSpeed","Value":1.6,"IsPercent":false},{"StatType":"Defense","Value":32,"IsPercent":false}] - 116 道具_16 Almighty_Icon Red 454 0.119999997317791 [{"StatType":"Dodge","Value":28,"IsPercent":false},{"StatType":"Defense","Value":24,"IsPercent":false},{"StatType":"Attack","Value":24,"IsPercent":false}] - 117 道具_17 Almighty_Icon White 124 0.0500000007450581 [{"StatType":"Defense","Value":23,"IsPercent":false}] - 118 道具_18 Almighty_Icon Green 204 0.0799999982118607 [{"StatType":"Attack","Value":17,"IsPercent":false},{"StatType":"MaxHealth","Value":69,"IsPercent":false}] - 119 道具_19 Almighty_Icon Blue 352 0.100000001490116 [{"StatType":"MaxHealth","Value":74,"IsPercent":false},{"StatType":"Attack","Value":19,"IsPercent":false},{"StatType":"Dodge","Value":20,"IsPercent":false}] - 120 道具_20 Almighty_Icon Red 464 0.119999997317791 [{"StatType":"AttackSpeed","Value":0.15,"IsPercent":true},{"StatType":"Attack","Value":29,"IsPercent":false},{"StatType":"Defense","Value":27,"IsPercent":false}] diff --git a/数据表/Role.txt b/数据表/Role.txt deleted file mode 100644 index beceb9a..0000000 --- a/数据表/Role.txt +++ /dev/null @@ -1,6 +0,0 @@ -# 角色表 ROUND(100*(1.1^L3),0) -# Id RoleName IconAssetName MaxHp Speed Coin WeaponCapacity InitialProperty InitialItem Lv0 Lv1 Lv2 Lv3 Lv4 Lv5 Lv6 Lv7 Lv8 Lv9 Lv10 Lv11 Lv12 Lv13 Lv14 Lv15 Lv16 Lv17 Lv18 Lv19 Lv20 Lv21 Lv22 Lv23 Lv24 Lv25 Lv26 Lv27 Lv28 Lv29 Lv30 Lv31 Lv32 Lv33 Lv34 Lv35 Lv36 Lv37 Lv38 Lv39 Lv40 Lv41 Lv42 Lv43 Lv44 Lv45 Lv46 Lv47 Lv48 Lv49 Lv50 Lv51 Lv52 Lv53 Lv54 Lv55 Lv56 Lv57 Lv58 Lv59 Lv60 -# int string string int float int int Modifier[] Item[] 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 -# 角色编号 策划备注 角色名称 图标资源名 初始最大生命 初始速度 初始金币 最大持有武器数 初始额外属性 初始额外物品 每级升级所需经验 - 101 全能者 全能者 Almighty_Icon 100 6 10 6 [{"StatType":"MovementSpeed","Value":0.5,"IsPercent":false},{"StatType":"MaxHealth","Value":0.2,"IsPercent":true}] [] 100 110 121 133 146 161 177 195 214 236 259 285 314 345 380 418 459 505 556 612 673 740 814 895 985 1083 1192 1311 1442 1586 1745 1919 2111 2323 2555 2810 3091 3400 3740 4114 4526 4979 5476 6024 6626 7289 8018 8820 9702 10672 11739 12913 14204 15625 17187 18906 20797 22876 25164 27680 30448 - 102 老人 老人 Old_Man_Icon 200 4 5 6 [] [] 100 112 125 140 157 176 197 221 248 277 311 348 390 436 489 547 613 687 769 861 965 1080 1210 1355 1518 1700 1904 2132 2388 2675 2996 3356 3758 4209 4714 5280 5914 6623 7418 8308 9305 10422 11672 13073 14642 16399 18367 20571 23039 25804 28900 32368 36252 40603 45475 50932 57044 63889 71556 80143 89760 diff --git a/数据表/Scene.txt b/数据表/Scene.txt deleted file mode 100644 index aac4294..0000000 --- a/数据表/Scene.txt +++ /dev/null @@ -1,8 +0,0 @@ -# 场景配置表 -# Id AssetName BackgroundMusicId -# int string int -# 场景编号 备注 资源名称 背景音乐编号 - 1 菜单场景 Menu 1 - 2 战斗场景 Main 2 - 3 压力测试场景 StressTest 0 - 4 游戏主场景 Game 0 diff --git a/数据表/Sound.txt b/数据表/Sound.txt deleted file mode 100644 index 0d22e6d..0000000 --- a/数据表/Sound.txt +++ /dev/null @@ -1,9 +0,0 @@ -# 声音配置表 -# Id AssetName Priority Loop Volume SpatialBlend MaxDistance -# int string int bool float float float -# 声音编号 策划备注 资源名称 优先级(默认0,128最高,-128最低) 是否循环 音量(0~1) 声音空间混合量(0为2D,1为3D,中间值混合效果) 声音最大距离 - 10000 玩家子弹 weapon_player 0 False 1 0 100 - 10001 敌人子弹 weapon_enemy 0 False 1 0 100 - 20000 玩家爆炸 explosion_player 0 False 1 0 100 - 20001 敌人爆炸 explosion_enemy 0 False 1 0 100 - 20002 小行星爆炸 explosion_asteroid 0 False 1 0 100 diff --git a/数据表/UIForm.txt b/数据表/UIForm.txt deleted file mode 100644 index fb145ef..0000000 --- a/数据表/UIForm.txt +++ /dev/null @@ -1,14 +0,0 @@ -# 界面配置表 -# Id AssetName UIGroupName AllowMultiInstance PauseCoveredUIForm -# int string string bool bool -# 界面编号 策划备注 资源名称 界面组名称 是否允许多个界面实例 是否暂停被其覆盖的界面 - 1 弹出框 DialogForm Default True True - 100 主菜单 MenuForm Default False True - 101 设置 SettingForm Default False True - 102 关于 AboutForm Default False True - 200 开始菜单 StartMenuForm Default False True - 201 角色选择页 SelectRoleForm Default False True - 202 游戏商店页 ShopForm Default False True - 203 游戏HUD HudForm HUD False True - 204 角色升级奖励页 LevelUpForm Default False True - 205 物品信息展示 DisplayItemInfoForm Default False False diff --git a/数据表/UISound.txt b/数据表/UISound.txt deleted file mode 100644 index 87e1cd2..0000000 --- a/数据表/UISound.txt +++ /dev/null @@ -1,6 +0,0 @@ -# 声音配置表 -# Id AssetName Priority Volume -# int string int float -# 声音编号 策划备注 资源名称 优先级(默认0,128最高,-128最低) 音量(0~1) - 10000 选择音效 select 0 1 - 10001 点击音效 click 0 1 diff --git a/数据表/Weapon.txt b/数据表/Weapon.txt deleted file mode 100644 index 8e6d608..0000000 --- a/数据表/Weapon.txt +++ /dev/null @@ -1,6 +0,0 @@ -# 武器表 -# Id Title IconAssetName Rarity Price PriceRandomPercent Attack Cooldown AttackRange AttackSoundId Pramas Modifiers -# int string string RarityType int float int float float int string[] StatModifier[] -# 武器编号 策划备注 武器名 图标资源名 道具品质 武器价格 价格浮动 伤害 冷却 范围 攻击音效编号 额外参数 额外属性 - 201 玩家武器 小刀 Almighty_Icon White 120 0.05 100 1.5 3 10000 [] [] - 202 手枪 Almighty_Icon White 130 0.05 120 1 10 10000 [] [] diff --git a/数据表/Weapon.xlsx b/数据表/Weapon.xlsx index d49019c13e44a3909507769b4221a1346d8eb32c..ad34dd462e3fec25626addbfae7180f49d7980e9 100644 GIT binary patch delta 2076 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 G0000~ywqm^ diff --git a/数据表/convert.py b/数据表/convert.py index 36ef9a8..bc22421 100644 --- a/数据表/convert.py +++ b/数据表/convert.py @@ -1,6 +1,5 @@ import pandas as pd import os -import shutil import csv def convert_excel_to_txt(folder_path='.'): @@ -21,8 +20,8 @@ def convert_excel_to_txt(folder_path='.'): continue if file_name.endswith(('.xlsx', '.xls')): file_path = os.path.join(scan_dir, file_name) - base_name = os.path.splitext(file_path)[0] - output_file = base_name.replace(os.path.basename(base_name), os.path.basename(base_name)) + '.txt' + base_name = os.path.splitext(file_name)[0] + output_file = os.path.join(target_dir, f"{base_name}.txt") print(f"正在处理: {file_name}...") @@ -47,12 +46,7 @@ def convert_excel_to_txt(folder_path='.'): escapechar='\\' ) - # 复制文件到目标目录 - target_file = os.path.join(target_dir, os.path.basename(output_file)) - shutil.copy2(output_file, target_file) - print(f"成功转换 -> {output_file}") - print(f"已复制到 -> {target_file}") count += 1 except Exception as e: