补充参战防御塔进入战斗逻辑

- 将 Inventory 中参战的防御塔数据传递到 CombatSelectForm 中
- 为防御塔的图标展示添加 TowerRepoItem 与 TowerIconArea 适配防御塔的三层 Image
This commit is contained in:
SepComet 2026-03-05 13:44:49 +08:00
parent 9db9aeabcd
commit 8a478982f8
56 changed files with 2507 additions and 467 deletions

View File

@ -76,7 +76,7 @@ SpriteRenderer:
m_SortingOrder: 2 m_SortingOrder: 2
m_Sprite: {fileID: 7482667652216324306, guid: 5ba74e3a185274149b15c24b321bead2, m_Sprite: {fileID: 7482667652216324306, guid: 5ba74e3a185274149b15c24b321bead2,
type: 3} type: 3}
m_Color: {r: 1, g: 0.40566027, b: 0.40566027, a: 1} m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0 m_FlipX: 0
m_FlipY: 0 m_FlipY: 0
m_DrawMode: 0 m_DrawMode: 0
@ -103,6 +103,7 @@ MonoBehaviour:
_bulletTypeId: 501 _bulletTypeId: 501
_muzzlePoint: {fileID: 7637292285124107611} _muzzlePoint: {fileID: 7637292285124107611}
_bulletSpeed: 12 _bulletSpeed: 12
_renderer: {fileID: 7170949026143225663}
--- !u!1 &1221576993898367501 --- !u!1 &1221576993898367501
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -113,7 +114,6 @@ GameObject:
m_Component: m_Component:
- component: {fileID: 6791423131335728073} - component: {fileID: 6791423131335728073}
- component: {fileID: 8183383920109690380} - component: {fileID: 8183383920109690380}
- component: {fileID: 3255949411223456789}
- component: {fileID: 4014432302095443276} - component: {fileID: 4014432302095443276}
m_Layer: 0 m_Layer: 0
m_Name: TowerEntity m_Name: TowerEntity
@ -160,18 +160,6 @@ MonoBehaviour:
_attackRangeLineWidth: 0.08 _attackRangeLineWidth: 0.08
_attackRangeColor: {r: 0.1, g: 1, b: 0.4, a: 0.8} _attackRangeColor: {r: 0.1, g: 1, b: 0.4, a: 0.8}
_attackRangeZOffset: -0.01 _attackRangeZOffset: -0.01
--- !u!114 &3255949411223456789
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1221576993898367501}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d87f56efd9024709a3baf8ef8a6f4fd3, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!120 &4014432302095443276 --- !u!120 &4014432302095443276
LineRenderer: LineRenderer:
serializedVersion: 2 serializedVersion: 2
@ -379,6 +367,7 @@ MonoBehaviour:
_attackRange: 5 _attackRange: 5
_aimToleranceAngle: 2 _aimToleranceAngle: 2
_rotateRoot: {fileID: 5517541809701307552} _rotateRoot: {fileID: 5517541809701307552}
_renderer: {fileID: 7775658596736532582}
--- !u!1 &4867507345079921359 --- !u!1 &4867507345079921359
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -456,7 +445,7 @@ SpriteRenderer:
m_SortingOrder: 0 m_SortingOrder: 0
m_Sprite: {fileID: 7482667652216324306, guid: 80a3790c48fc91d4ebcb4d7e2efbb8c8, m_Sprite: {fileID: 7482667652216324306, guid: 80a3790c48fc91d4ebcb4d7e2efbb8c8,
type: 3} type: 3}
m_Color: {r: 0.3584906, g: 0.3584906, b: 0.3584906, a: 1} m_Color: {r: 1, g: 1, b: 1, a: 1}
m_FlipX: 0 m_FlipX: 0
m_FlipY: 0 m_FlipY: 0
m_DrawMode: 0 m_DrawMode: 0
@ -480,3 +469,4 @@ MonoBehaviour:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_attackSpeed: 1 _attackSpeed: 1
_attackPropertyType: 1 _attackPropertyType: 1
_renderer: {fileID: 6516390239457838709}

View File

@ -7,8 +7,11 @@ namespace Components
public class BasicBaseComp : MonoBehaviour public class BasicBaseComp : MonoBehaviour
{ {
[SerializeField] [Min(0.01f)] private float _attackSpeed = 1f; [SerializeField] [Min(0.01f)] private float _attackSpeed = 1f;
[SerializeField] private AttackPropertyType _attackPropertyType = AttackPropertyType.Physics; [SerializeField] private AttackPropertyType _attackPropertyType = AttackPropertyType.Physics;
[SerializeField] private SpriteRenderer _renderer;
private float _cooldownRemaining; private float _cooldownRemaining;
public float AttackSpeed => _attackSpeed; public float AttackSpeed => _attackSpeed;
@ -29,6 +32,14 @@ namespace Components
_cooldownRemaining = 0f; _cooldownRemaining = 0f;
} }
public void SetColor(Color color)
{
if (_renderer != null)
{
_renderer.color = color;
}
}
public void Tick(float deltaTime) public void Tick(float deltaTime)
{ {
if (_cooldownRemaining <= 0f) if (_cooldownRemaining <= 0f)

View File

@ -6,10 +6,15 @@ namespace Components
public class BasicBearingComp : MonoBehaviour public class BasicBearingComp : MonoBehaviour
{ {
[SerializeField] [Min(1f)] private float _rotateSpeed = 180f; [SerializeField] [Min(1f)] private float _rotateSpeed = 180f;
[SerializeField] [Min(0.1f)] private float _attackRange = 5f; [SerializeField] [Min(0.1f)] private float _attackRange = 5f;
[SerializeField] [Min(0.1f)] private float _aimToleranceAngle = 2f; [SerializeField] [Min(0.1f)] private float _aimToleranceAngle = 2f;
[SerializeField] private Transform _rotateRoot; [SerializeField] private Transform _rotateRoot;
[SerializeField] private SpriteRenderer _renderer;
public float RotateSpeed => _rotateSpeed; public float RotateSpeed => _rotateSpeed;
public float AttackRange => _attackRange; public float AttackRange => _attackRange;
public float AimToleranceAngle => _aimToleranceAngle; public float AimToleranceAngle => _aimToleranceAngle;
@ -26,6 +31,14 @@ namespace Components
_attackRange = 5f; _attackRange = 5f;
} }
public void SetColor(Color color)
{
if (_renderer != null)
{
_renderer.color = color;
}
}
public bool IsTargetInRange(Transform target, Transform origin = null) public bool IsTargetInRange(Transform target, Transform origin = null)
{ {
if (target == null) if (target == null)

View File

@ -9,11 +9,17 @@ namespace Components
public class ShooterMuzzleComp : MonoBehaviour public class ShooterMuzzleComp : MonoBehaviour
{ {
[SerializeField] [Min(1f)] private int _attackDamage = 100; [SerializeField] [Min(1f)] private int _attackDamage = 100;
[SerializeField] private AttackMethodType _attackMethodType = AttackMethodType.NormalBullet; [SerializeField] private AttackMethodType _attackMethodType = AttackMethodType.NormalBullet;
[SerializeField] [Min(1)] private int _bulletTypeId = 501; [SerializeField] [Min(1)] private int _bulletTypeId = 501;
[SerializeField] private Transform _muzzlePoint; [SerializeField] private Transform _muzzlePoint;
[SerializeField] [Min(0.1f)] private float _bulletSpeed = 12f; [SerializeField] [Min(0.1f)] private float _bulletSpeed = 12f;
[SerializeField] private SpriteRenderer _renderer;
public int AttackDamage => _attackDamage; public int AttackDamage => _attackDamage;
public AttackMethodType AttackMethodType => _attackMethodType; public AttackMethodType AttackMethodType => _attackMethodType;
@ -31,6 +37,14 @@ namespace Components
_bulletTypeId = 501; _bulletTypeId = 501;
} }
public void SetColor(Color color)
{
if (_renderer != null)
{
_renderer.color = color;
}
}
public bool Attack(Transform target) public bool Attack(Transform target)
{ {
return Attack(target, AttackPropertyType.None); return Attack(target, AttackPropertyType.None);

View File

@ -10,7 +10,8 @@ namespace Components
private const string AttackRangeIndicatorObjectName = "AttackRangeIndicator"; private const string AttackRangeIndicatorObjectName = "AttackRangeIndicator";
private const int MinTowerLevel = 0; private const int MinTowerLevel = 0;
private const int MaxTowerLevel = 4; private const int MaxTowerLevel = 4;
private static Material s_AttackRangeSharedMaterial;
private static Material _attackRangeSharedMaterial;
[SerializeField] private ShooterMuzzleComp _muzzleComp; [SerializeField] private ShooterMuzzleComp _muzzleComp;
[SerializeField] private BasicBearingComp _bearingComp; [SerializeField] private BasicBearingComp _bearingComp;
@ -27,6 +28,9 @@ namespace Components
private float _retargetTimer; private float _retargetTimer;
private float _attackRange; private float _attackRange;
private int _towerLevel; private int _towerLevel;
private Color _muzzleColor = Color.white;
private Color _bearingColor = Color.white;
private Color _baseColor = Color.white;
public Transform CurrentTarget => _currentTarget; public Transform CurrentTarget => _currentTarget;
@ -40,6 +44,12 @@ namespace Components
OnInit(stats, MinTowerLevel); OnInit(stats, MinTowerLevel);
} }
public void OnInit(TowerStatsData stats, int towerLevel, Color muzzleColor, Color bearingColor, Color baseColor)
{
SetComponentColors(muzzleColor, bearingColor, baseColor);
OnInit(stats, towerLevel);
}
public void OnInit(TowerStatsData stats, int towerLevel) public void OnInit(TowerStatsData stats, int towerLevel)
{ {
ResolveComponents(); ResolveComponents();
@ -57,6 +67,7 @@ namespace Components
_muzzleComp?.OnInit(attackDamage, stats.AttackMethodType); _muzzleComp?.OnInit(attackDamage, stats.AttackMethodType);
_bearingComp?.OnInit(rotateSpeed, attackRange); _bearingComp?.OnInit(rotateSpeed, attackRange);
_baseComp?.OnInit(attackSpeed, stats.AttackPropertyType); _baseComp?.OnInit(attackSpeed, stats.AttackPropertyType);
ApplyComponentColors();
SetAttackRange(attackRange); SetAttackRange(attackRange);
SetAttackRangeVisible(false); SetAttackRangeVisible(false);
_currentTarget = null; _currentTarget = null;
@ -90,6 +101,14 @@ namespace Components
RebuildAttackRangeGeometry(); RebuildAttackRangeGeometry();
} }
public void SetComponentColors(Color muzzleColor, Color bearingColor, Color baseColor)
{
_muzzleColor = muzzleColor;
_bearingColor = bearingColor;
_baseColor = baseColor;
ApplyComponentColors();
}
public void SetTarget(Transform target) public void SetTarget(Transform target)
{ {
_currentTarget = target; _currentTarget = target;
@ -141,9 +160,9 @@ namespace Components
EnemyEntity bestEnemy = null; EnemyEntity bestEnemy = null;
float bestDistanceSquared = float.MaxValue; float bestDistanceSquared = float.MaxValue;
for (int i = 0; i < EnemyEntity.ActiveEnemies.Count; i++)
foreach (var enemy in EnemyEntity.ActiveEnemies)
{ {
EnemyEntity enemy = EnemyEntity.ActiveEnemies[i];
if (enemy == null || !enemy.isActiveAndEnabled) if (enemy == null || !enemy.isActiveAndEnabled)
{ {
continue; continue;
@ -164,6 +183,13 @@ namespace Components
return bestEnemy != null ? bestEnemy.transform : null; return bestEnemy != null ? bestEnemy.transform : null;
} }
private void ApplyComponentColors()
{
_muzzleComp?.SetColor(_muzzleColor);
_bearingComp?.SetColor(_bearingColor);
_baseComp?.SetColor(_baseColor);
}
private void ResolveComponents() private void ResolveComponents()
{ {
if (_muzzleComp == null) if (_muzzleComp == null)
@ -181,6 +207,7 @@ namespace Components
_baseComp = GetComponent<BasicBaseComp>(); _baseComp = GetComponent<BasicBaseComp>();
} }
ApplyComponentColors();
EnsureAttackRangeRenderer(); EnsureAttackRangeRenderer();
} }
@ -250,18 +277,18 @@ namespace Components
_attackRangeRenderer.allowOcclusionWhenDynamic = false; _attackRangeRenderer.allowOcclusionWhenDynamic = false;
_attackRangeRenderer.enabled = false; _attackRangeRenderer.enabled = false;
if (s_AttackRangeSharedMaterial == null) if (_attackRangeSharedMaterial == null)
{ {
Shader lineShader = Shader.Find("Sprites/Default"); Shader lineShader = Shader.Find("Sprites/Default");
if (lineShader != null) if (lineShader != null)
{ {
s_AttackRangeSharedMaterial = new Material(lineShader); _attackRangeSharedMaterial = new Material(lineShader);
} }
} }
if (s_AttackRangeSharedMaterial != null) if (_attackRangeSharedMaterial != null)
{ {
_attackRangeRenderer.sharedMaterial = s_AttackRangeSharedMaterial; _attackRangeRenderer.sharedMaterial = _attackRangeSharedMaterial;
} }
} }

View File

@ -23,6 +23,7 @@ namespace GeometryTD.CustomComponent
private readonly Dictionary<int, List<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new(); private readonly Dictionary<int, List<DRLevelSpawnEntry>> _spawnEntriesByPhaseId = new();
private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _selectedSpawnEntriesByPhaseId = new(); private readonly Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> _selectedSpawnEntriesByPhaseId = new();
private readonly List<int> _levelIdBuffer = new(); private readonly List<int> _levelIdBuffer = new();
private readonly List<TowerStatsData> _currentBuildTowerStats = new();
private readonly CombatScheduler _combatScheduler = new CombatScheduler(); private readonly CombatScheduler _combatScheduler = new CombatScheduler();
private bool _runtimeInitialized; private bool _runtimeInitialized;
@ -39,6 +40,7 @@ namespace GeometryTD.CustomComponent
public int CurrentBaseHp => _currentBaseHp; public int CurrentBaseHp => _currentBaseHp;
public bool LastCombatSucceeded => _lastCombatSucceeded; public bool LastCombatSucceeded => _lastCombatSucceeded;
public bool CanEndCombat => _combatScheduler.CanEndCombat; public bool CanEndCombat => _combatScheduler.CanEndCombat;
public int CurrentBuildTowerCount => _currentBuildTowerStats.Count;
public int LastDefeatedEnemyCount { get; private set; } public int LastDefeatedEnemyCount { get; private set; }
public int LastGainedCoin { get; private set; } public int LastGainedCoin { get; private set; }
public int LastGainedGold { get; private set; } public int LastGainedGold { get; private set; }
@ -88,6 +90,7 @@ namespace GeometryTD.CustomComponent
_spawnEntriesByPhaseId.Clear(); _spawnEntriesByPhaseId.Clear();
_selectedSpawnEntriesByPhaseId.Clear(); _selectedSpawnEntriesByPhaseId.Clear();
_levelIdBuffer.Clear(); _levelIdBuffer.Clear();
_currentBuildTowerStats.Clear();
IDataTable<DRLevel> dtLevel = GameEntry.DataTable.GetDataTable<DRLevel>(); IDataTable<DRLevel> dtLevel = GameEntry.DataTable.GetDataTable<DRLevel>();
IDataTable<DRLevelPhase> dtLevelPhase = GameEntry.DataTable.GetDataTable<DRLevelPhase>(); IDataTable<DRLevelPhase> dtLevelPhase = GameEntry.DataTable.GetDataTable<DRLevelPhase>();
@ -181,6 +184,7 @@ namespace GeometryTD.CustomComponent
public void StartCombat() public void StartCombat()
{ {
_currentBuildTowerStats.Clear();
if (!EnsureCombatRuntimeInitialized()) if (!EnsureCombatRuntimeInitialized())
{ {
Log.Warning("CombatNodeComponent start failed. Missing scheduler runtime."); Log.Warning("CombatNodeComponent start failed. Missing scheduler runtime.");
@ -216,6 +220,7 @@ namespace GeometryTD.CustomComponent
} }
CurrentLevel = selectedLevel; CurrentLevel = selectedLevel;
CacheBuildTowerStatsSnapshot();
_isCombatActive = false; _isCombatActive = false;
_currentCoin = Mathf.Max(0, selectedLevel.StartCoin); _currentCoin = Mathf.Max(0, selectedLevel.StartCoin);
_currentGold = 0; _currentGold = 0;
@ -230,6 +235,7 @@ namespace GeometryTD.CustomComponent
_currentCoin = 0; _currentCoin = 0;
_currentGold = 0; _currentGold = 0;
_currentBaseHp = 0; _currentBaseHp = 0;
_currentBuildTowerStats.Clear();
return; return;
} }
@ -252,6 +258,7 @@ namespace GeometryTD.CustomComponent
_currentGold = 0; _currentGold = 0;
_currentBaseHp = 0; _currentBaseHp = 0;
CurrentLevel = null; CurrentLevel = null;
_currentBuildTowerStats.Clear();
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create()); GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
} }
@ -281,6 +288,7 @@ namespace GeometryTD.CustomComponent
LastDefeatedEnemyCount = 0; LastDefeatedEnemyCount = 0;
LastGainedCoin = 0; LastGainedCoin = 0;
LastGainedGold = 0; LastGainedGold = 0;
_currentBuildTowerStats.Clear();
ShutdownCombatRuntime(); ShutdownCombatRuntime();
} }
@ -341,6 +349,18 @@ namespace GeometryTD.CustomComponent
return true; return true;
} }
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
{
stats = null;
if (buildIndex < 0 || buildIndex >= _currentBuildTowerStats.Count)
{
return false;
}
stats = CloneTowerStats(_currentBuildTowerStats[buildIndex]);
return stats != null;
}
public void AddCoin(int coin) public void AddCoin(int coin)
{ {
int gainCoin = Mathf.Max(0, coin); int gainCoin = Mathf.Max(0, coin);
@ -353,6 +373,54 @@ namespace GeometryTD.CustomComponent
FireCoinChangedEventIfNeeded(); FireCoinChangedEventIfNeeded();
} }
private void CacheBuildTowerStatsSnapshot()
{
_currentBuildTowerStats.Clear();
if (GameEntry.PlayerInventory == null)
{
return;
}
IReadOnlyList<TowerItemData> towers = GameEntry.PlayerInventory.GetParticipantTowerSnapshot();
if (towers == null || towers.Count <= 0)
{
return;
}
for (int i = 0; i < towers.Count; i++)
{
TowerItemData tower = towers[i];
TowerStatsData clonedStats = CloneTowerStats(tower?.Stats);
if (clonedStats == null)
{
continue;
}
_currentBuildTowerStats.Add(clonedStats);
}
}
private static TowerStatsData CloneTowerStats(TowerStatsData source)
{
if (source == null)
{
return null;
}
return new TowerStatsData
{
AttackDamage = source.AttackDamage != null ? (int[])source.AttackDamage.Clone() : null,
DamageRandomRate = source.DamageRandomRate,
RotateSpeed = source.RotateSpeed != null ? (float[])source.RotateSpeed.Clone() : null,
AttackRange = source.AttackRange != null ? (float[])source.AttackRange.Clone() : null,
AttackSpeed = source.AttackSpeed != null ? (float[])source.AttackSpeed.Clone() : null,
AttackMethodType = source.AttackMethodType,
AttackPropertyType = source.AttackPropertyType,
Tags = source.Tags != null ? (TagType[])source.Tags.Clone() : null
};
}
private void OnDestroy() private void OnDestroy()
{ {
OnShutdown(); OnShutdown();
@ -437,3 +505,5 @@ namespace GeometryTD.CustomComponent
} }
} }
} }

View File

@ -1,4 +1,5 @@
using GeometryTD.CustomUtility; using System.Collections.Generic;
using GeometryTD.CustomUtility;
using GeometryTD.Definition; using GeometryTD.Definition;
using UnityGameFramework.Runtime; using UnityGameFramework.Runtime;
@ -44,6 +45,31 @@ namespace GeometryTD.CustomComponent
return _queryModel.GetSnapshot(); return _queryModel.GetSnapshot();
} }
public IReadOnlyList<TowerItemData> GetParticipantTowerSnapshot()
{
EnsureInitialized();
BackpackInventoryData inventory = _queryModel.Inventory;
if (inventory?.ParticipantTowerInstanceIds == null || inventory.ParticipantTowerInstanceIds.Count <= 0)
{
return new List<TowerItemData>();
}
List<TowerItemData> result = new List<TowerItemData>(inventory.ParticipantTowerInstanceIds.Count);
for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count && result.Count < MaxParticipantTowerCount; i++)
{
long towerId = inventory.ParticipantTowerInstanceIds[i];
if (!_queryModel.TryGetTowerById(towerId, out TowerItemData tower) || tower == null)
{
continue;
}
result.Add(InventoryCloneUtility.CloneTower(tower));
}
return result;
}
public void MergeInventory(BackpackInventoryData gainedInventory) public void MergeInventory(BackpackInventoryData gainedInventory)
{ {
EnsureInitialized(); EnsureInitialized();
@ -126,3 +152,4 @@ namespace GeometryTD.CustomComponent
} }
} }
} }

View File

@ -34,6 +34,9 @@ namespace GeometryTD.Definition
/// </summary> /// </summary>
public List<TowerItemData> Towers { get; set; } = new List<TowerItemData>(); public List<TowerItemData> Towers { get; set; } = new List<TowerItemData>();
/// <summary>
/// 参与战斗的防御塔 Id。
/// </summary>
public List<long> ParticipantTowerInstanceIds { get; set; } = new List<long>(); public List<long> ParticipantTowerInstanceIds { get; set; } = new List<long>();
} }
} }

View File

@ -1,4 +1,6 @@
using System; using System;
using Newtonsoft.Json;
using UnityEngine;
namespace GeometryTD.Definition namespace GeometryTD.Definition
{ {
@ -41,7 +43,7 @@ namespace GeometryTD.Definition
public RarityType Rarity { get; set; } public RarityType Rarity { get; set; }
public bool IsParticipatingInCombat { get; set; } public bool IsParticipatingInCombat { get; set; }
/// <summary> /// <summary>
/// 构成该防御塔的枪口组件实例 Id。 /// 构成该防御塔的枪口组件实例 Id。
/// </summary> /// </summary>
@ -61,5 +63,9 @@ namespace GeometryTD.Definition
/// 防御塔独立属性,不依赖组件对象引用。 /// 防御塔独立属性,不依赖组件对象引用。
/// </summary> /// </summary>
public TowerStatsData Stats { get; set; } = new TowerStatsData(); public TowerStatsData Stats { get; set; } = new TowerStatsData();
[JsonIgnore] public Sprite ComposedIconSprite { get; set; }
[JsonIgnore] public string ComposedIconKey { get; set; }
} }
} }

View File

@ -9,15 +9,22 @@ namespace GeometryTD.Entity.EntityData
{ {
[SerializeField] private TowerStatsData _stats = new TowerStatsData(); [SerializeField] private TowerStatsData _stats = new TowerStatsData();
[SerializeField] private int _towerLevel = 0; [SerializeField] private int _towerLevel = 0;
[SerializeField] private Color _muzzleColor = Color.white;
[SerializeField] private Color _bearingColor = Color.white;
[SerializeField] private Color _baseColor = Color.white;
public TowerData(int entityId, int typeId, Vector3 position, Quaternion rotation, public TowerData(int entityId, int typeId, Vector3 position, Quaternion rotation,
TowerStatsData stats, int towerLevel = 0) TowerStatsData stats, int towerLevel = 0, Color? muzzleColor = null, Color? bearingColor = null,
Color? baseColor = null)
: base(entityId, typeId) : base(entityId, typeId)
{ {
Position = position; Position = position;
Rotation = rotation; Rotation = rotation;
_stats = stats ?? new TowerStatsData(); _stats = stats ?? new TowerStatsData();
_towerLevel = Mathf.Max(0, towerLevel); _towerLevel = Mathf.Max(0, towerLevel);
_muzzleColor = muzzleColor ?? Color.white;
_bearingColor = bearingColor ?? Color.white;
_baseColor = baseColor ?? Color.white;
} }
public TowerStatsData Stats public TowerStatsData Stats
@ -31,5 +38,23 @@ namespace GeometryTD.Entity.EntityData
get => _towerLevel; get => _towerLevel;
set => _towerLevel = Mathf.Max(0, value); set => _towerLevel = Mathf.Max(0, value);
} }
public Color MuzzleColor
{
get => _muzzleColor;
set => _muzzleColor = value;
}
public Color BearingColor
{
get => _bearingColor;
set => _bearingColor = value;
}
public Color BaseColor
{
get => _baseColor;
set => _baseColor = value;
}
} }
} }

View File

@ -1,5 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using GeometryTD.CustomComponent;
using GeometryTD.CustomUtility;
using GeometryTD.Map; using GeometryTD.Map;
using GeometryTD.Definition; using GeometryTD.Definition;
using GeometryTD.Entity.EntityData; using GeometryTD.Entity.EntityData;
@ -14,12 +16,17 @@ namespace GeometryTD.Entity
public class MapEntity : EntityBase public class MapEntity : EntityBase
{ {
private const int DefaultTowerTypeId = 401; private const int DefaultTowerTypeId = 401;
private static readonly Spawner[] EmptySpawners = Array.Empty<Spawner>(); private static readonly Spawner[] EmptySpawners = Array.Empty<Spawner>();
[SerializeField] private bool _enableCombatSelectInput = true; [SerializeField] private bool _enableCombatSelectInput = true;
[SerializeField] private int _towerTypeId = DefaultTowerTypeId; [SerializeField] private int _towerTypeId = DefaultTowerTypeId;
[SerializeField] private int[] _buildTowerCosts = { 40, 60, 60, 80 }; [SerializeField] private int[] _buildTowerCosts = { 40, 60, 60, 80 };
[SerializeField] private int _upgradeCost = 50; [SerializeField] private int _upgradeCost = 50;
[SerializeField] private int _destroyGain = 40; [SerializeField] private int _destroyGain = 40;
private MapDataRefs _mapDataRefs; private MapDataRefs _mapDataRefs;
@ -29,6 +36,8 @@ namespace GeometryTD.Entity
private CombatSelectInputService _combatSelectInputService; private CombatSelectInputService _combatSelectInputService;
private TowerPlacementService _towerPlacementService; private TowerPlacementService _towerPlacementService;
private TowerSelectionPresenter _towerSelectionPresenter; private TowerSelectionPresenter _towerSelectionPresenter;
private readonly BuildTowerVisualInfo[] _buildTowerVisualInfos = new BuildTowerVisualInfo[4];
public IReadOnlyList<Vector3Int> PathCells => _mapTopologyService != null public IReadOnlyList<Vector3Int> PathCells => _mapTopologyService != null
? _mapTopologyService.PathCells ? _mapTopologyService.PathCells
@ -209,22 +218,38 @@ namespace GeometryTD.Entity
} }
_combatSelectFormUseCase.SetCoinProvider(GetCurrentCoin); _combatSelectFormUseCase.SetCoinProvider(GetCurrentCoin);
BackpackInventoryData inventorySnapshot = GameEntry.PlayerInventory != null
? GameEntry.PlayerInventory.GetInventorySnapshot()
: null;
IReadOnlyList<TowerItemData> participantTowers = GameEntry.PlayerInventory != null
? GameEntry.PlayerInventory.GetParticipantTowerSnapshot()
: null;
Dictionary<long, MuzzleCompItemData> muzzleMap = BuildComponentMap(inventorySnapshot?.MuzzleComponents);
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(inventorySnapshot?.BearingComponents);
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(inventorySnapshot?.BaseComponents);
int currentBuildTowerCount = GetCurrentBuildTowerCount();
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
int buildIndex = i; int buildIndex = i;
int buildCost = GetBuildTowerCost(buildIndex);
bool isBuildAvailable = buildIndex < currentBuildTowerCount;
BuildTowerVisualInfo buildVisual = ResolveBuildTowerVisual(participantTowers, buildIndex, muzzleMap, bearingMap, baseMap);
_buildTowerVisualInfos[buildIndex] = buildVisual;
_combatSelectFormUseCase.SetBuildAction( _combatSelectFormUseCase.SetBuildAction(
buildIndex, buildIndex,
() => TryBuildTower(buildIndex), isBuildAvailable ? () => TryBuildTower(buildIndex) : (Func<bool>)null,
GetBuildTowerCost(buildIndex)); buildCost,
null,
isBuildAvailable,
buildVisual.BaseColor,
buildVisual.BearingColor,
buildVisual.MuzzleColor);
_combatSelectFormUseCase.SetBuildVisible(buildIndex, isBuildAvailable);
} }
_combatSelectFormUseCase.SetUpgradeAction( _combatSelectFormUseCase.SetUpgradeAction(TryUpgradeTower, Mathf.Max(0, _upgradeCost));
TryUpgradeTower, _combatSelectFormUseCase.SetDestroyAction(TryDestroyTower, Mathf.Max(0, _destroyGain));
Mathf.Max(0, _upgradeCost));
_combatSelectFormUseCase.SetDestroyAction(
TryDestroyTower,
Mathf.Max(0, _destroyGain));
} }
private void HandleCombatSelectInput() private void HandleCombatSelectInput()
@ -275,8 +300,18 @@ namespace GeometryTD.Entity
return false; return false;
} }
CombatNodeComponent combatNode = GameEntry.CombatNode;
if (combatNode == null || !combatNode.TryGetBuildTowerStats(buildIndex, out TowerStatsData buildTowerStats))
{
return false;
}
BuildTowerVisualInfo buildVisual = buildIndex >= 0 && buildIndex < _buildTowerVisualInfos.Length
? _buildTowerVisualInfos[buildIndex]
: BuildTowerVisualInfo.Default;
if (!_towerPlacementService.TryBuildTower(selectedFoundationCell, IsFoundationCell, buildIndex, _buildTowerCosts, if (!_towerPlacementService.TryBuildTower(selectedFoundationCell, IsFoundationCell, buildIndex, _buildTowerCosts,
_towerTypeId, Tilemap, TryConsumeCoin, AddCoin, out int towerEntityId)) buildTowerStats, buildVisual.MuzzleColor, buildVisual.BearingColor, buildVisual.BaseColor, _towerTypeId, Tilemap, TryConsumeCoin, AddCoin, out int towerEntityId))
{ {
return false; return false;
} }
@ -350,6 +385,77 @@ namespace GeometryTD.Entity
return Mathf.Max(0, _buildTowerCosts[buildIndex]); return Mathf.Max(0, _buildTowerCosts[buildIndex]);
} }
private static int GetCurrentBuildTowerCount()
{
if (GameEntry.CombatNode == null)
{
return 0;
}
return Mathf.Clamp(GameEntry.CombatNode.CurrentBuildTowerCount, 0, 4);
}
private static BuildTowerVisualInfo ResolveBuildTowerVisual(
IReadOnlyList<TowerItemData> participantTowers,
int buildIndex,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
if (participantTowers == null || buildIndex < 0 || buildIndex >= participantTowers.Count)
{
return BuildTowerVisualInfo.Default;
}
TowerItemData tower = participantTowers[buildIndex];
if (tower == null)
{
return BuildTowerVisualInfo.Default;
}
Color muzzleColor = ResolveComponentColor(muzzleMap, tower.MuzzleComponentInstanceId);
Color bearingColor = ResolveComponentColor(bearingMap, tower.BearingComponentInstanceId);
Color baseColor = ResolveComponentColor(baseMap, tower.BaseComponentInstanceId);
return new BuildTowerVisualInfo(muzzleColor, bearingColor, baseColor);
}
private static Color ResolveComponentColor<TComp>(IReadOnlyDictionary<long, TComp> componentMap, long componentId)
where TComp : TowerCompItemData
{
if (componentMap == null || componentId <= 0)
{
return Color.white;
}
return componentMap.TryGetValue(componentId, out TComp component) && component != null
? IconColorGenerator.GenerateForComponent(component)
: Color.white;
}
private static Dictionary<long, TComp> BuildComponentMap<TComp>(IReadOnlyList<TComp> items)
where TComp : TowerCompItemData
{
Dictionary<long, TComp> map = new Dictionary<long, TComp>();
if (items == null)
{
return map;
}
for (int i = 0; i < items.Count; i++)
{
TComp item = items[i];
if (item == null || item.InstanceId <= 0)
{
continue;
}
map[item.InstanceId] = item;
}
return map;
}
private static bool TryConsumeCoin(int cost) private static bool TryConsumeCoin(int cost)
{ {
int requiredCoin = Mathf.Max(0, cost); int requiredCoin = Mathf.Max(0, cost);
@ -371,6 +477,22 @@ namespace GeometryTD.Entity
return GameEntry.CombatNode != null ? Mathf.Max(0, GameEntry.CombatNode.CurrentCoin) : 0; return GameEntry.CombatNode != null ? Mathf.Max(0, GameEntry.CombatNode.CurrentCoin) : 0;
} }
private readonly struct BuildTowerVisualInfo
{
public static BuildTowerVisualInfo Default => new BuildTowerVisualInfo(Color.white, Color.white, Color.white);
public BuildTowerVisualInfo(Color muzzleColor, Color bearingColor, Color baseColor)
{
MuzzleColor = muzzleColor;
BearingColor = bearingColor;
BaseColor = baseColor;
}
public Color MuzzleColor { get; }
public Color BearingColor { get; }
public Color BaseColor { get; }
}
private static void AddCoin(int coin) private static void AddCoin(int coin)
{ {
int amount = Mathf.Max(0, coin); int amount = Mathf.Max(0, coin);
@ -382,3 +504,4 @@ namespace GeometryTD.Entity
} }
} }
} }

View File

@ -53,7 +53,12 @@ namespace GeometryTD.Entity
return; return;
} }
_towerController.OnInit(towerData.Stats, towerData.TowerLevel); _towerController.OnInit(
towerData.Stats,
towerData.TowerLevel,
towerData.MuzzleColor,
towerData.BearingColor,
towerData.BaseColor);
} }
protected override void OnUpdate(float elapseSeconds, float realElapseSeconds) protected override void OnUpdate(float elapseSeconds, float realElapseSeconds)

View File

@ -0,0 +1,28 @@
using GameFramework;
using GameFramework.ObjectPool;
using GeometryTD.UI;
using UnityEngine;
namespace GeometryTD.PoolObjectBase
{
public class TowerRepoItemObject : ObjectBase
{
public static TowerRepoItemObject Create(object target)
{
TowerRepoItemObject itemObject = ReferencePool.Acquire<TowerRepoItemObject>();
itemObject.Initialize(target);
return itemObject;
}
protected override void Release(bool isShutdown)
{
TowerRepoItem item = (TowerRepoItem)Target;
if (item == null)
{
return;
}
Object.Destroy(item.gameObject);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6f6f2603e451c5f4f9b0d0cb8ee247d6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -40,7 +40,7 @@ namespace GeometryTD.Map
} }
public bool TryBuildTower(Vector3Int foundationCell, Func<Vector3Int, bool> isFoundationCell, int buildIndex, public bool TryBuildTower(Vector3Int foundationCell, Func<Vector3Int, bool> isFoundationCell, int buildIndex,
int[] buildTowerCosts, int towerTypeId, Tilemap tilemap, Func<int, bool> tryConsumeCoin, int[] buildTowerCosts, TowerStatsData buildTowerStats, Color muzzleColor, Color bearingColor, Color baseColor, int towerTypeId, Tilemap tilemap, Func<int, bool> tryConsumeCoin,
Action<int> addCoin, Action<int> addCoin,
out int towerEntityId) out int towerEntityId)
{ {
@ -55,14 +55,19 @@ namespace GeometryTD.Map
return false; return false;
} }
TowerStatsData towerStats = CloneTowerStats(buildTowerStats);
if (towerStats == null)
{
return false;
}
int buildCost = GetBuildTowerCost(buildTowerCosts, buildIndex); int buildCost = GetBuildTowerCost(buildTowerCosts, buildIndex);
if (tryConsumeCoin != null && !tryConsumeCoin(buildCost)) if (tryConsumeCoin != null && !tryConsumeCoin(buildCost))
{ {
return false; return false;
} }
TowerStatsData towerStats = BuildTowerStats(buildIndex); if (!TryShowTowerEntity(foundationCell, towerStats, muzzleColor, bearingColor, baseColor, towerTypeId, tilemap, out int newTowerEntityId))
if (!TryShowTowerEntity(foundationCell, towerStats, towerTypeId, tilemap, out int newTowerEntityId))
{ {
addCoin?.Invoke(buildCost); addCoin?.Invoke(buildCost);
return false; return false;
@ -177,7 +182,7 @@ namespace GeometryTD.Map
return Mathf.Max(0, buildTowerCosts[buildIndex]); return Mathf.Max(0, buildTowerCosts[buildIndex]);
} }
private static bool TryShowTowerEntity(Vector3Int foundationCell, TowerStatsData towerStats, private static bool TryShowTowerEntity(Vector3Int foundationCell, TowerStatsData towerStats, Color muzzleColor, Color bearingColor, Color baseColor,
int towerTypeId, int towerTypeId,
Tilemap tilemap, out int towerEntityId) Tilemap tilemap, out int towerEntityId)
{ {
@ -192,7 +197,7 @@ namespace GeometryTD.Map
Vector3 towerPosition = tilemap != null ? tilemap.GetCellCenterWorld(foundationCell) : foundationCell; Vector3 towerPosition = tilemap != null ? tilemap.GetCellCenterWorld(foundationCell) : foundationCell;
towerPosition.z = 0f; towerPosition.z = 0f;
var towerData = new TowerData(entityId, typeId, towerPosition, Quaternion.identity, towerStats, var towerData = new TowerData(entityId, typeId, towerPosition, Quaternion.identity, towerStats,
MinTowerLevel); MinTowerLevel, muzzleColor, bearingColor, baseColor);
GameEntry.Entity.ShowDefenseTower(towerData); GameEntry.Entity.ShowDefenseTower(towerData);
towerEntityId = entityId; towerEntityId = entityId;
@ -346,4 +351,4 @@ namespace GeometryTD.Map
return values != null ? values.Length : 0; return values != null ? values.Length : 0;
} }
} }
} }

View File

@ -10,5 +10,6 @@ namespace GeometryTD.UI
public bool IsInteractable; public bool IsInteractable;
public CombatSelectActionType ActionType; public CombatSelectActionType ActionType;
public int ActionIndex; public int ActionIndex;
public TowerIconAreaContext TowerIconAreaContext;
} }
} }

View File

@ -116,9 +116,8 @@ namespace GeometryTD.UI
if (inventory.Towers != null) if (inventory.Towers != null)
{ {
for (int i = 0; i < inventory.Towers.Count; i++) foreach (TowerItemData tower in inventory.Towers)
{ {
var tower = inventory.Towers[i];
if (tower == null) if (tower == null)
{ {
continue; continue;
@ -131,7 +130,7 @@ namespace GeometryTD.UI
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap), EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = RepoItemClickActionType.OpenDetail, ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.None, ComponentSlotType = TowerCompSlotType.None,
IconAreaContext = BuildIconAreaContext(tower) IconAreaContext = BuildTowerIconContext(tower, muzzleMap, bearingMap, baseMap)
}); });
AddItemDescSeed( AddItemDescSeed(
@ -145,9 +144,8 @@ namespace GeometryTD.UI
if (inventory.MuzzleComponents != null) if (inventory.MuzzleComponents != null)
{ {
for (int i = 0; i < inventory.MuzzleComponents.Count; i++) foreach (MuzzleCompItemData item in inventory.MuzzleComponents)
{ {
var item = inventory.MuzzleComponents[i];
if (item == null) if (item == null)
{ {
continue; continue;
@ -174,7 +172,7 @@ namespace GeometryTD.UI
if (inventory.BearingComponents != null) if (inventory.BearingComponents != null)
{ {
foreach (var item in inventory.BearingComponents) foreach (BearingCompItemData item in inventory.BearingComponents)
{ {
if (item == null) if (item == null)
{ {
@ -202,9 +200,8 @@ namespace GeometryTD.UI
if (inventory.BaseComponents != null) if (inventory.BaseComponents != null)
{ {
for (int i = 0; i < inventory.BaseComponents.Count; i++) foreach (BaseCompItemData item in inventory.BaseComponents)
{ {
var item = inventory.BaseComponents[i];
if (item == null) if (item == null)
{ {
continue; continue;
@ -232,6 +229,38 @@ namespace GeometryTD.UI
return itemContexts.ToArray(); return itemContexts.ToArray();
} }
private static TowerIconAreaContext BuildTowerIconContext(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
if (tower == null)
{
return null;
}
return new TowerIconAreaContext
{
Rarity = tower.Rarity,
MuzzleColor = ResolveComponentColor(tower.MuzzleComponentInstanceId, muzzleMap),
BearingColor = ResolveComponentColor(tower.BearingComponentInstanceId, bearingMap),
BaseColor = ResolveComponentColor(tower.BaseComponentInstanceId, baseMap)
};
}
private static Color ResolveComponentColor<TComp>(long instanceId, IReadOnlyDictionary<long, TComp> componentMap)
where TComp : TowerCompItemData
{
if (instanceId > 0 && componentMap != null && componentMap.TryGetValue(instanceId, out TComp comp) &&
comp != null)
{
return IconColorGenerator.GenerateForComponent(comp);
}
return Color.white;
}
private void AddItemDescSeed(long itemId, string title, string typeText, string description, TagType[] tags) private void AddItemDescSeed(long itemId, string title, string typeText, string description, TagType[] tags)
{ {
if (itemId <= 0) if (itemId <= 0)
@ -274,9 +303,8 @@ namespace GeometryTD.UI
return map; return map;
} }
for (int i = 0; i < items.Count; i++) foreach (TComp item in items)
{ {
TComp item = items[i];
if (item == null || item.InstanceId <= 0) if (item == null || item.InstanceId <= 0)
{ {
continue; continue;
@ -288,35 +316,13 @@ namespace GeometryTD.UI
return map; return map;
} }
private static IconAreaContext BuildIconAreaContext(TowerItemData tower)
{
if (tower == null)
{
return new IconAreaContext
{
ComponentSlotType = TowerCompSlotType.None,
Rarity = RarityType.None,
Color = Color.white,
Icon = null
};
}
return new IconAreaContext
{
ComponentSlotType = TowerCompSlotType.None,
Rarity = tower.Rarity,
Color = IconColorGenerator.GenerateForTower(tower),
Icon = null
};
}
private static IconAreaContext BuildIconAreaContext(TowerCompItemData item) private static IconAreaContext BuildIconAreaContext(TowerCompItemData item)
{ {
if (item == null) if (item == null)
{ {
return new IconAreaContext return new IconAreaContext
{ {
ComponentSlotType = TowerCompSlotType.None, ComponentSlotType = TowerCompSlotType.None,
Rarity = RarityType.None, Rarity = RarityType.None,
Color = Color.white, Color = Color.white,
Icon = null Icon = null
@ -332,6 +338,8 @@ namespace GeometryTD.UI
}; };
} }
#region Event Handlers
private void OnCombatFinishReturnButtonClicked(object sender, GameEventArgs e) private void OnCombatFinishReturnButtonClicked(object sender, GameEventArgs e)
{ {
if (!IsEventFromCurrentForm(sender) || !(e is CombatFinishReturnEventArgs)) if (!IsEventFromCurrentForm(sender) || !(e is CombatFinishReturnEventArgs))
@ -370,6 +378,8 @@ namespace GeometryTD.UI
}); });
} }
#endregion
private bool IsEventFromCurrentForm(object sender) private bool IsEventFromCurrentForm(object sender)
{ {
if (Form == null) if (Form == null)
@ -392,3 +402,7 @@ namespace GeometryTD.UI
} }
} }
} }

View File

@ -229,7 +229,13 @@ namespace GeometryTD.UI
IsVisible = rawData.IsVisible, IsVisible = rawData.IsVisible,
IsInteractable = rawData.IsInteractable, IsInteractable = rawData.IsInteractable,
ActionType = rawData.ActionType, ActionType = rawData.ActionType,
ActionIndex = rawData.ActionIndex ActionIndex = rawData.ActionIndex,
TowerIconAreaContext = new TowerIconAreaContext()
{
BaseColor = rawData.BaseColor,
BearingColor = rawData.BearingColor,
MuzzleColor = rawData.MuzzleColor
}
}; };
} }
@ -284,4 +290,4 @@ namespace GeometryTD.UI
RefreshFromUseCase(); RefreshFromUseCase();
} }
} }
} }

View File

@ -11,5 +11,9 @@ namespace GeometryTD.UI
public bool IsInteractable; public bool IsInteractable;
public CombatSelectActionType ActionType; public CombatSelectActionType ActionType;
public int ActionIndex; public int ActionIndex;
public bool UseTowerLayers;
public Color BaseColor = Color.white;
public Color BearingColor = Color.white;
public Color MuzzleColor = Color.white;
} }
} }

View File

@ -42,6 +42,19 @@ namespace GeometryTD.UI
} }
public void SetBuildAction(int buildIndex, Func<bool> buildAction, int cost, Sprite icon = null) public void SetBuildAction(int buildIndex, Func<bool> buildAction, int cost, Sprite icon = null)
{
SetBuildAction(buildIndex, buildAction, cost, icon, false, Color.white, Color.white, Color.white);
}
public void SetBuildAction(
int buildIndex,
Func<bool> buildAction,
int cost,
Sprite icon,
bool useTowerLayers,
Color baseColor,
Color bearingColor,
Color muzzleColor)
{ {
if (buildIndex < 0 || buildIndex >= _buildOptions.Length) if (buildIndex < 0 || buildIndex >= _buildOptions.Length)
{ {
@ -54,6 +67,10 @@ namespace GeometryTD.UI
option.Icon = icon; option.Icon = icon;
option.IsGain = false; option.IsGain = false;
option.IsVisible = true; option.IsVisible = true;
option.UseTowerLayers = useTowerLayers;
option.BaseColor = baseColor;
option.BearingColor = bearingColor;
option.MuzzleColor = muzzleColor;
} }
public void SetBuildAction(int buildIndex, Action buildAction, int cost, Sprite icon = null) public void SetBuildAction(int buildIndex, Action buildAction, int cost, Sprite icon = null)
@ -75,6 +92,16 @@ namespace GeometryTD.UI
icon); icon);
} }
public void SetBuildVisible(int buildIndex, bool visible)
{
if (buildIndex < 0 || buildIndex >= _buildOptions.Length)
{
return;
}
_buildOptions[buildIndex].IsVisible = visible;
}
public void SetUpgradeAction(Func<bool> upgradeAction, int cost, Sprite icon = null) public void SetUpgradeAction(Func<bool> upgradeAction, int cost, Sprite icon = null)
{ {
_upgradeOption.Action = upgradeAction; _upgradeOption.Action = upgradeAction;
@ -82,6 +109,7 @@ namespace GeometryTD.UI
_upgradeOption.Icon = icon; _upgradeOption.Icon = icon;
_upgradeOption.IsGain = false; _upgradeOption.IsGain = false;
_upgradeOption.IsVisible = true; _upgradeOption.IsVisible = true;
_upgradeOption.UseTowerLayers = false;
} }
public void SetUpgradeAction(Action upgradeAction, int cost, Sprite icon = null) public void SetUpgradeAction(Action upgradeAction, int cost, Sprite icon = null)
@ -109,6 +137,7 @@ namespace GeometryTD.UI
_destroyOption.Icon = icon; _destroyOption.Icon = icon;
_destroyOption.IsGain = true; _destroyOption.IsGain = true;
_destroyOption.IsVisible = true; _destroyOption.IsVisible = true;
_destroyOption.UseTowerLayers = false;
} }
public void SetDestroyAction(Action destroyAction, int gain, Sprite icon = null) public void SetDestroyAction(Action destroyAction, int gain, Sprite icon = null)
@ -278,7 +307,11 @@ namespace GeometryTD.UI
IsVisible = option.IsVisible, IsVisible = option.IsVisible,
IsInteractable = option.Action != null && CanExecute(option, currentCoin), IsInteractable = option.Action != null && CanExecute(option, currentCoin),
ActionType = option.ActionType, ActionType = option.ActionType,
ActionIndex = option.ActionIndex ActionIndex = option.ActionIndex,
UseTowerLayers = option.UseTowerLayers,
BaseColor = option.BaseColor,
BearingColor = option.BearingColor,
MuzzleColor = option.MuzzleColor
}; };
} }
@ -293,6 +326,10 @@ namespace GeometryTD.UI
public bool IsVisible = true; public bool IsVisible = true;
public Sprite Icon; public Sprite Icon;
public Func<bool> Action; public Func<bool> Action;
public bool UseTowerLayers;
public Color BaseColor = Color.white;
public Color BearingColor = Color.white;
public Color MuzzleColor = Color.white;
public Option(CombatSelectActionType actionType, int actionIndex, bool requiresAffordable) public Option(CombatSelectActionType actionType, int actionIndex, bool requiresAffordable)
{ {

View File

@ -2,20 +2,23 @@ using TMPro;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
using GeometryTD.CustomEvent; using GeometryTD.CustomEvent;
using UnityGameFramework.Runtime;
namespace GeometryTD.UI namespace GeometryTD.UI
{ {
public class TowerSelectItem : MonoBehaviour public class TowerSelectItem : MonoBehaviour
{ {
[SerializeField] private Image _icon; [SerializeField] private Image _icon;
[SerializeField] private TMP_Text _price; [SerializeField] private TMP_Text _price;
[SerializeField] private CommonButton _button; [SerializeField] private CommonButton _button;
[SerializeField] private TowerIconArea _towerIconArea;
private TowerSelectItemContext _context; private TowerSelectItemContext _context;
private Sprite _defaultIcon; private Sprite _defaultIcon;
private bool _hasCachedDefaultIcon; private bool _hasCachedDefaultIcon;
public void OnInit(TowerSelectItemContext context) public void OnInit(TowerSelectItemContext context)
@ -23,28 +26,45 @@ namespace GeometryTD.UI
CacheDefaultIcon(); CacheDefaultIcon();
_context = context; _context = context;
if (_icon != null) if (context.ActionType == CombatSelectActionType.BuildTower)
{ {
if (context != null && context.Icon != null) _icon?.gameObject.SetActive(false);
_towerIconArea?.OnInit(_context.TowerIconAreaContext);
if (_price != null)
{ {
_icon.sprite = context.Icon; _price.text = context.PriceText ?? string.Empty;
}
else if (_defaultIcon != null)
{
_icon.sprite = _defaultIcon;
} }
_icon.enabled = _icon.sprite != null; if (_button != null)
{
_button.Interactive = context.IsInteractable;
}
} }
else if (context.ActionType is CombatSelectActionType.UpgradeTower or CombatSelectActionType.DestroyTower)
if (_price != null)
{ {
_price.text = context?.PriceText ?? string.Empty; if (_icon != null)
{
_icon.sprite = _context.Icon ?? _defaultIcon;
_icon.gameObject.SetActive(true);
}
_towerIconArea?.OnReset();
if (_price != null)
{
_price.text = context.PriceText ?? string.Empty;
}
if (_button != null)
{
_button.Interactive = context.IsInteractable;
}
} }
else
if (_button != null)
{ {
_button.Interactive = context != null && context.IsInteractable; _icon?.gameObject.SetActive(false);
_towerIconArea?.OnReset();
} }
} }
@ -59,6 +79,8 @@ namespace GeometryTD.UI
_icon.enabled = _icon.sprite != null; _icon.enabled = _icon.sprite != null;
} }
_towerIconArea.OnReset();
if (_price != null) if (_price != null)
{ {
_price.text = string.Empty; _price.text = string.Empty;
@ -93,4 +115,4 @@ namespace GeometryTD.UI
_hasCachedDefaultIcon = true; _hasCachedDefaultIcon = true;
} }
} }
} }

View File

@ -2,6 +2,7 @@ namespace GeometryTD.UI
{ {
public class CompAreaContext public class CompAreaContext
{ {
public RepoItemContext[] Items; public RepoItemContext[] ComponentItems;
public TowerRepoItemContext[] TowerItems;
} }
} }

View File

@ -2,7 +2,7 @@ namespace GeometryTD.UI
{ {
public class ParticipantAreaContext : UIContext public class ParticipantAreaContext : UIContext
{ {
public RepoItemContext[] Items; public TowerRepoItemContext[] TowerItems;
public int MaxCount; public int MaxCount;
} }
} }

View File

@ -0,0 +1,9 @@
using System;
namespace GeometryTD.UI
{
[Serializable]
public class TowerRepoItemContext : RepoItemContext
{
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 813496ec671788a4b975fa980ce16555
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -10,8 +10,9 @@ namespace GeometryTD.UI
{ {
private RepoFormContext BuildContext(RepoFormRawData rawData) private RepoFormContext BuildContext(RepoFormRawData rawData)
{ {
_itemContextMap.Clear(); _itemClickActionMap.Clear();
_itemDescSeedMap.Clear(); _itemDescSeedMap.Clear();
_compAreaTowerIds.Clear();
if (rawData?.Inventory == null) if (rawData?.Inventory == null)
{ {
_participantTowerIds.Clear(); _participantTowerIds.Clear();
@ -22,7 +23,8 @@ namespace GeometryTD.UI
Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(rawData.Inventory.BearingComponents); Dictionary<long, BearingCompItemData> bearingMap = BuildComponentMap(rawData.Inventory.BearingComponents);
Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(rawData.Inventory.BaseComponents); Dictionary<long, BaseCompItemData> baseMap = BuildComponentMap(rawData.Inventory.BaseComponents);
Dictionary<long, TowerItemData> towerMap = BuildTowerMap(rawData.Inventory.Towers); Dictionary<long, TowerItemData> towerMap = BuildTowerMap(rawData.Inventory.Towers);
List<RepoItemContext> items = new List<RepoItemContext>(); List<RepoItemContext> componentItems = new List<RepoItemContext>();
List<TowerRepoItemContext> towerItems = new List<TowerRepoItemContext>();
if (rawData.Inventory.Towers != null) if (rawData.Inventory.Towers != null)
{ {
@ -33,15 +35,9 @@ namespace GeometryTD.UI
continue; continue;
} }
AddItemContext(items, new RepoItemContext TowerRepoItemContext towerContext = BuildTowerRepoItemContext(tower, muzzleMap, bearingMap, baseMap,
{ RepoItemClickActionType.OpenDetail, true);
InstanceId = tower.InstanceId, AddTowerItemContext(towerItems, towerContext);
CanDrag = true,
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.None,
IconAreaContext = BuildIconAreaContext(tower)
});
AddItemDescSeed( AddItemDescSeed(
tower.InstanceId, tower.InstanceId,
tower.Name, tower.Name,
@ -60,7 +56,7 @@ namespace GeometryTD.UI
continue; continue;
} }
AddItemContext(items, new RepoItemContext RepoItemContext componentContext = new RepoItemContext
{ {
InstanceId = item.InstanceId, InstanceId = item.InstanceId,
CanDrag = true, CanDrag = true,
@ -68,7 +64,8 @@ namespace GeometryTD.UI
ClickActionType = RepoItemClickActionType.OpenDetail, ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Muzzle, ComponentSlotType = TowerCompSlotType.Muzzle,
IconAreaContext = BuildIconAreaContext(item) IconAreaContext = BuildIconAreaContext(item)
}); };
AddComponentItemContext(componentItems, componentContext);
AddItemDescSeed( AddItemDescSeed(
item.InstanceId, item.InstanceId,
item.Name, item.Name,
@ -87,7 +84,7 @@ namespace GeometryTD.UI
continue; continue;
} }
AddItemContext(items, new RepoItemContext RepoItemContext componentContext = new RepoItemContext
{ {
InstanceId = item.InstanceId, InstanceId = item.InstanceId,
CanDrag = true, CanDrag = true,
@ -95,7 +92,8 @@ namespace GeometryTD.UI
ClickActionType = RepoItemClickActionType.OpenDetail, ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Bearing, ComponentSlotType = TowerCompSlotType.Bearing,
IconAreaContext = BuildIconAreaContext(item) IconAreaContext = BuildIconAreaContext(item)
}); };
AddComponentItemContext(componentItems, componentContext);
AddItemDescSeed( AddItemDescSeed(
item.InstanceId, item.InstanceId,
item.Name, item.Name,
@ -114,7 +112,7 @@ namespace GeometryTD.UI
continue; continue;
} }
AddItemContext(items, new RepoItemContext RepoItemContext componentContext = new RepoItemContext
{ {
InstanceId = item.InstanceId, InstanceId = item.InstanceId,
CanDrag = true, CanDrag = true,
@ -122,7 +120,8 @@ namespace GeometryTD.UI
ClickActionType = RepoItemClickActionType.OpenDetail, ClickActionType = RepoItemClickActionType.OpenDetail,
ComponentSlotType = TowerCompSlotType.Base, ComponentSlotType = TowerCompSlotType.Base,
IconAreaContext = BuildIconAreaContext(item) IconAreaContext = BuildIconAreaContext(item)
}); };
AddComponentItemContext(componentItems, componentContext);
AddItemDescSeed( AddItemDescSeed(
item.InstanceId, item.InstanceId,
item.Name, item.Name,
@ -140,13 +139,14 @@ namespace GeometryTD.UI
CombineAreaContext = new CombineAreaContext(), CombineAreaContext = new CombineAreaContext(),
CompAreaContext = new CompAreaContext CompAreaContext = new CompAreaContext
{ {
Items = items.ToArray() ComponentItems = componentItems.ToArray(),
TowerItems = towerItems.ToArray()
}, },
ParticipantAreaContext = participantAreaContext ParticipantAreaContext = participantAreaContext
}; };
} }
private void AddItemContext(List<RepoItemContext> items, RepoItemContext itemContext) private void AddComponentItemContext(List<RepoItemContext> items, RepoItemContext itemContext)
{ {
if (itemContext == null) if (itemContext == null)
{ {
@ -154,7 +154,19 @@ namespace GeometryTD.UI
} }
items.Add(itemContext); items.Add(itemContext);
_itemContextMap[itemContext.InstanceId] = itemContext; _itemClickActionMap[itemContext.InstanceId] = itemContext.ClickActionType;
}
private void AddTowerItemContext(List<TowerRepoItemContext> items, TowerRepoItemContext itemContext)
{
if (itemContext == null)
{
return;
}
items.Add(itemContext);
_itemClickActionMap[itemContext.InstanceId] = itemContext.ClickActionType;
_compAreaTowerIds.Add(itemContext.InstanceId);
} }
private void AddItemDescSeed(long itemId, string title, string typeText, string description, TagType[] tags) private void AddItemDescSeed(long itemId, string title, string typeText, string description, TagType[] tags)
@ -243,7 +255,7 @@ namespace GeometryTD.UI
IReadOnlyDictionary<long, BaseCompItemData> baseMap) IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{ {
_participantTowerIds.Clear(); _participantTowerIds.Clear();
List<RepoItemContext> participantItems = new List<RepoItemContext>(); List<TowerRepoItemContext> participantItems = new List<TowerRepoItemContext>();
if (inventory?.ParticipantTowerInstanceIds != null && towerMap != null) if (inventory?.ParticipantTowerInstanceIds != null && towerMap != null)
{ {
for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count; i++) for (int i = 0; i < inventory.ParticipantTowerInstanceIds.Count; i++)
@ -264,41 +276,33 @@ namespace GeometryTD.UI
continue; continue;
} }
participantItems.Add(new RepoItemContext TowerRepoItemContext towerContext = BuildTowerRepoItemContext(tower, muzzleMap, bearingMap, baseMap,
RepoItemClickActionType.RemoveParticipant, false);
if (towerContext != null)
{ {
InstanceId = tower.InstanceId, participantItems.Add(towerContext);
CanDrag = false, _itemClickActionMap[towerContext.InstanceId] = towerContext.ClickActionType;
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap), }
ClickActionType = RepoItemClickActionType.RemoveParticipant,
ComponentSlotType = TowerCompSlotType.None,
IconAreaContext = BuildIconAreaContext(tower)
});
} }
} }
return new ParticipantAreaContext return new ParticipantAreaContext
{ {
Items = participantItems.ToArray(), TowerItems = participantItems.ToArray(),
MaxCount = MaxParticipantCount MaxCount = MaxParticipantCount
}; };
} }
private void ApplyParticipantSelection() private void ApplyParticipantSelection()
{ {
if (Form == null || _itemContextMap.Count <= 0) if (Form == null || _compAreaTowerIds.Count <= 0)
{ {
return; return;
} }
foreach (KeyValuePair<long, RepoItemContext> pair in _itemContextMap) foreach (long towerId in _compAreaTowerIds)
{ {
RepoItemContext itemContext = pair.Value; Form.SetRepoItemSelected(towerId, _participantTowerIds.Contains(towerId));
if (itemContext == null || itemContext.ComponentSlotType != TowerCompSlotType.None)
{
continue;
}
Form.SetRepoItemSelected(pair.Key, _participantTowerIds.Contains(pair.Key));
} }
} }
@ -319,25 +323,33 @@ namespace GeometryTD.UI
ApplyParticipantSelection(); ApplyParticipantSelection();
} }
private static IconAreaContext BuildIconAreaContext(TowerItemData tower) private static TowerRepoItemContext BuildTowerRepoItemContext(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap,
RepoItemClickActionType clickActionType,
bool canDrag)
{ {
if (tower == null) if (tower == null)
{ {
return new IconAreaContext return null;
{
ComponentSlotType = TowerCompSlotType.None,
Rarity = RarityType.None,
Color = Color.white,
Icon = null
};
} }
return new IconAreaContext return new TowerRepoItemContext
{ {
InstanceId = tower.InstanceId,
CanDrag = canDrag,
EnduranceRate01 = ItemDescUtility.ResolveTowerEnduranceRate(tower, muzzleMap, bearingMap, baseMap),
ClickActionType = clickActionType,
ComponentSlotType = TowerCompSlotType.None, ComponentSlotType = TowerCompSlotType.None,
Rarity = tower.Rarity, IconAreaContext = new TowerIconAreaContext
Color = IconColorGenerator.GenerateForTower(tower), {
Icon = null Rarity = tower.Rarity,
MuzzleColor = ResolveComponentColor(tower.MuzzleComponentInstanceId, muzzleMap),
BearingColor = ResolveComponentColor(tower.BearingComponentInstanceId, bearingMap),
BaseColor = ResolveComponentColor(tower.BaseComponentInstanceId, baseMap)
}
}; };
} }
@ -362,5 +374,21 @@ namespace GeometryTD.UI
Icon = null Icon = null
}; };
} }
private static Color ResolveComponentColor<TComp>(long instanceId,
IReadOnlyDictionary<long, TComp> componentMap)
where TComp : TowerCompItemData
{
if (instanceId > 0 &&
componentMap != null &&
componentMap.TryGetValue(instanceId, out TComp component) &&
component != null)
{
return IconColorGenerator.GenerateForComponent(component);
}
return Color.white;
}
} }
} }

View File

@ -11,9 +11,11 @@ namespace GeometryTD.UI
{ {
private const int MaxParticipantCount = 4; private const int MaxParticipantCount = 4;
private RepoFormUseCase _useCase; private RepoFormUseCase _useCase;
private readonly Dictionary<long, RepoItemContext> _itemContextMap = new Dictionary<long, RepoItemContext>(); private readonly Dictionary<long, RepoItemClickActionType> _itemClickActionMap =
new Dictionary<long, RepoItemClickActionType>();
private readonly Dictionary<long, ItemDescSeed> _itemDescSeedMap = new Dictionary<long, ItemDescSeed>(); private readonly Dictionary<long, ItemDescSeed> _itemDescSeedMap = new Dictionary<long, ItemDescSeed>();
private readonly HashSet<long> _participantTowerIds = new HashSet<long>(); private readonly HashSet<long> _participantTowerIds = new HashSet<long>();
private readonly HashSet<long> _compAreaTowerIds = new HashSet<long>();
private sealed class ItemDescSeed private sealed class ItemDescSeed
{ {
@ -111,14 +113,9 @@ namespace GeometryTD.UI
} }
RepoItemClickActionType clickActionType = RepoItemClickActionType.OpenDetail; RepoItemClickActionType clickActionType = RepoItemClickActionType.OpenDetail;
if (sender is RepoItem clickedItem && clickedItem.Context != null) if (_itemClickActionMap.TryGetValue(args.ItemId, out RepoItemClickActionType mappedAction))
{ {
clickActionType = clickedItem.Context.ClickActionType; clickActionType = mappedAction;
}
else if (_itemContextMap.TryGetValue(args.ItemId, out RepoItemContext itemContextFromMap) &&
itemContextFromMap != null)
{
clickActionType = itemContextFromMap.ClickActionType;
} }
if (args.ItemId <= 0) if (args.ItemId <= 0)
@ -170,7 +167,7 @@ namespace GeometryTD.UI
return; return;
} }
if (Form == null || !_itemContextMap.ContainsKey(args.ItemId)) if (Form == null || !_itemClickActionMap.ContainsKey(args.ItemId))
{ {
return; return;
} }
@ -212,8 +209,8 @@ namespace GeometryTD.UI
{ {
return; return;
} }
this.CloseUI(); CloseUI();
} }
private void OnRepoCombineRequested(object sender, GameEventArgs e) private void OnRepoCombineRequested(object sender, GameEventArgs e)
@ -258,12 +255,12 @@ namespace GeometryTD.UI
{ {
return; return;
} }
if (_useCase == null || Form == null || args.TowerItemId <= 0) if (_useCase == null || Form == null || args.TowerItemId <= 0)
{ {
return; return;
} }
if (!_useCase.TryAddParticipantTower(args.TowerItemId)) if (!_useCase.TryAddParticipantTower(args.TowerItemId))
{ {
return; return;

View File

@ -67,11 +67,6 @@ namespace GeometryTD.UI
InventoryParticipantUtility.NormalizeParticipantState(_fallbackInventory, MaxParticipantCount); InventoryParticipantUtility.NormalizeParticipantState(_fallbackInventory, MaxParticipantCount);
return _fallbackInventory; return _fallbackInventory;
} }
public static BackpackInventoryData SampleInventory()
{
return InventorySeedUtility.CreateSampleInventory();
}
} }
} }

View File

@ -1,5 +1,5 @@
using GeometryTD.Definition;
using GeometryTD.CustomEvent; using GeometryTD.CustomEvent;
using GeometryTD.Definition;
using UnityEngine; using UnityEngine;
using UnityEngine.EventSystems; using UnityEngine.EventSystems;
@ -102,19 +102,15 @@ namespace GeometryTD.UI
return; return;
} }
RepoItem repoItem = pointerDrag.GetComponent<RepoItem>(); IRepoDragItemView dragItem = pointerDrag.GetComponent<IRepoDragItemView>() ??
if (repoItem == null) pointerDrag.GetComponentInParent<IRepoDragItemView>();
{ if (dragItem == null)
repoItem = pointerDrag.GetComponentInParent<RepoItem>();
}
if (repoItem == null)
{ {
return; return;
} }
bool assigned = TryAssignItem(repoItem.Context); bool assigned = TryAssignItem(dragItem.ComponentContext);
repoItem.SetDropResult(assigned); dragItem.SetDropResult(assigned);
} }
private CombineSlotItem FindSlot(TowerCompSlotType slotType) private CombineSlotItem FindSlot(TowerCompSlotType slotType)

View File

@ -11,12 +11,17 @@ namespace GeometryTD.UI
{ {
[FormerlySerializedAs("m_Content")] [SerializeField] private Transform _content; [FormerlySerializedAs("m_Content")] [SerializeField] private Transform _content;
[FormerlySerializedAs("m_ItemTemplate")] [SerializeField] private RepoItem _itemTemplate; [FormerlySerializedAs("m_ItemTemplate")] [SerializeField] private RepoItem _itemTemplate;
[SerializeField] private TowerRepoItem _towerItemTemplate;
[FormerlySerializedAs("m_InstancePoolCapacity")] [SerializeField] private int _instancePoolCapacity = 64; [FormerlySerializedAs("m_InstancePoolCapacity")] [SerializeField] private int _instancePoolCapacity = 64;
private readonly List<RepoItem> _activeItems = new List<RepoItem>(); private readonly List<RepoItem> _activeComponentItems = new List<RepoItem>();
private readonly Dictionary<long, RepoItem> _itemMap = new Dictionary<long, RepoItem>(); private readonly List<TowerRepoItem> _activeTowerItems = new List<TowerRepoItem>();
private IObjectPool<RepoItemObject> _itemPool; private readonly Dictionary<long, RepoItem> _componentItemMap = new Dictionary<long, RepoItem>();
private string _poolName; private readonly Dictionary<long, TowerRepoItem> _towerItemMap = new Dictionary<long, TowerRepoItem>();
private IObjectPool<RepoItemObject> _componentItemPool;
private IObjectPool<TowerRepoItemObject> _towerItemPool;
private string _componentPoolName;
private string _towerPoolName;
public void OnInit(CompAreaContext context) public void OnInit(CompAreaContext context)
{ {
@ -29,31 +34,46 @@ namespace GeometryTD.UI
EnsurePool(); EnsurePool();
OnReset(); OnReset();
if (context.Items == null || context.Items.Length == 0) if (context.ComponentItems != null)
{ {
return; foreach (RepoItemContext itemContext in context.ComponentItems)
{
RepoItem item = CreateOrSpawnComponentItem();
if (item == null)
{
continue;
}
item.gameObject.SetActive(true);
item.OnInit(itemContext);
_activeComponentItems.Add(item);
_componentItemMap[itemContext.InstanceId] = item;
}
} }
foreach (var itemContext in context.Items) if (context.TowerItems != null)
{ {
RepoItem item = CreateOrSpawnItem(); foreach (TowerRepoItemContext itemContext in context.TowerItems)
if (item == null)
{ {
continue; TowerRepoItem item = CreateOrSpawnTowerItem();
} if (item == null)
{
continue;
}
item.gameObject.SetActive(true); item.gameObject.SetActive(true);
item.OnInit(itemContext); item.OnInit(itemContext);
_activeItems.Add(item); _activeTowerItems.Add(item);
_itemMap[itemContext.InstanceId] = item; _towerItemMap[itemContext.InstanceId] = item;
}
} }
} }
public void OnReset() public void OnReset()
{ {
for (int i = _activeItems.Count - 1; i >= 0; i--) for (int i = _activeComponentItems.Count - 1; i >= 0; i--)
{ {
RepoItem item = _activeItems[i]; RepoItem item = _activeComponentItems[i];
if (item == null) if (item == null)
{ {
continue; continue;
@ -61,49 +81,102 @@ namespace GeometryTD.UI
item.OnReset(); item.OnReset();
item.gameObject.SetActive(false); item.gameObject.SetActive(false);
_itemPool?.Unspawn(item); _componentItemPool?.Unspawn(item);
} }
_activeItems.Clear(); for (int i = _activeTowerItems.Count - 1; i >= 0; i--)
_itemMap.Clear(); {
TowerRepoItem item = _activeTowerItems[i];
if (item == null)
{
continue;
}
item.OnReset();
item.gameObject.SetActive(false);
_towerItemPool?.Unspawn(item);
}
_activeComponentItems.Clear();
_activeTowerItems.Clear();
_componentItemMap.Clear();
_towerItemMap.Clear();
} }
private void OnDestroy() private void OnDestroy()
{ {
OnReset(); OnReset();
_itemPool?.ReleaseAllUnused(); _componentItemPool?.ReleaseAllUnused();
_towerItemPool?.ReleaseAllUnused();
} }
private void EnsurePool() private void EnsurePool()
{ {
if (_itemPool != null) if (_componentItemPool == null)
{ {
return; _componentPoolName = $"RepoItemPool_{GetInstanceID()}";
_componentItemPool =
GameEntry.ObjectPool.CreateSingleSpawnObjectPool<RepoItemObject>(_componentPoolName,
_instancePoolCapacity);
} }
_poolName = $"RepoItemPool_{GetInstanceID()}"; if (_towerItemPool == null)
_itemPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool<RepoItemObject>(_poolName, _instancePoolCapacity); {
_towerPoolName = $"TowerRepoItemPool_{GetInstanceID()}";
_towerItemPool =
GameEntry.ObjectPool.CreateSingleSpawnObjectPool<TowerRepoItemObject>(_towerPoolName,
_instancePoolCapacity);
}
} }
private RepoItem CreateOrSpawnItem() private RepoItem CreateOrSpawnComponentItem()
{ {
if (_itemPool == null) if (_componentItemPool == null)
{ {
return null; return null;
} }
RepoItemObject itemObject = _itemPool.Spawn(); RepoItemObject itemObject = _componentItemPool.Spawn();
RepoItem item = itemObject != null ? (RepoItem)itemObject.Target : null; RepoItem item = itemObject != null ? (RepoItem)itemObject.Target : null;
if (item == null) if (item == null)
{ {
if (_itemTemplate == null) if (_itemTemplate == null)
{ {
Log.Warning("CompArea requires an item template."); Log.Warning("CompArea requires a component item template.");
return null; return null;
} }
item = Instantiate(_itemTemplate); item = Instantiate(_itemTemplate);
_itemPool.Register(RepoItemObject.Create(item), true); _componentItemPool.Register(RepoItemObject.Create(item), true);
}
if (_content != null)
{
item.transform.SetParent(_content, false);
}
return item;
}
private TowerRepoItem CreateOrSpawnTowerItem()
{
if (_towerItemPool == null)
{
return null;
}
TowerRepoItemObject itemObject = _towerItemPool.Spawn();
TowerRepoItem item = itemObject != null ? (TowerRepoItem)itemObject.Target : null;
if (item == null)
{
if (_towerItemTemplate == null)
{
Log.Warning("CompArea requires a tower item template.");
return null;
}
item = Instantiate(_towerItemTemplate);
_towerItemPool.Register(TowerRepoItemObject.Create(item), true);
} }
if (_content != null) if (_content != null)
@ -116,12 +189,15 @@ namespace GeometryTD.UI
public void SetItemSelected(long itemId, bool isSelected) public void SetItemSelected(long itemId, bool isSelected)
{ {
if (!_itemMap.TryGetValue(itemId, out RepoItem item)) if (_componentItemMap.TryGetValue(itemId, out RepoItem componentItem))
{ {
return; componentItem.SetSelected(isSelected);
} }
item.SetSelected(isSelected); if (_towerItemMap.TryGetValue(itemId, out TowerRepoItem towerItem))
{
towerItem.SetSelected(isSelected);
}
} }
} }
} }

View File

@ -0,0 +1,19 @@
using GeometryTD.Definition;
namespace GeometryTD.UI
{
public interface IRepoDragItemView
{
long InstanceId { get; }
bool CanDrag { get; }
TowerCompSlotType ComponentSlotType { get; }
RepoItemClickActionType ClickActionType { get; }
RepoItemContext ComponentContext { get; }
void SetDropResult(bool assigned);
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5cb3c8e275a9ba646a58a2656af31faa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -12,12 +12,12 @@ namespace GeometryTD.UI
public class ParticipantArea : MonoBehaviour, IDropHandler public class ParticipantArea : MonoBehaviour, IDropHandler
{ {
[SerializeField] private Transform _content; [SerializeField] private Transform _content;
[SerializeField] private RepoItem _itemTemplate; [SerializeField] private TowerRepoItem _towerItemTemplate;
[SerializeField] private int _instancePoolCapacity = 8; [SerializeField] private int _instancePoolCapacity = 8;
private readonly List<RepoItem> _activeItems = new List<RepoItem>(); private readonly List<TowerRepoItem> _activeItems = new List<TowerRepoItem>();
private readonly HashSet<long> _boundItemIds = new HashSet<long>(); private readonly HashSet<long> _boundItemIds = new HashSet<long>();
private IObjectPool<RepoItemObject> _itemPool; private IObjectPool<TowerRepoItemObject> _itemPool;
private string _poolName; private string _poolName;
private int _maxCount = 4; private int _maxCount = 4;
@ -27,20 +27,20 @@ namespace GeometryTD.UI
EnsurePool(); EnsurePool();
_maxCount = Mathf.Max(1, context != null ? context.MaxCount : 4); _maxCount = Mathf.Max(1, context != null ? context.MaxCount : 4);
if (context?.Items == null || context.Items.Length <= 0) if (context?.TowerItems == null || context.TowerItems.Length <= 0)
{ {
return; return;
} }
for (int i = 0; i < context.Items.Length; i++) for (int i = 0; i < context.TowerItems.Length; i++)
{ {
RepoItemContext itemContext = context.Items[i]; TowerRepoItemContext itemContext = context.TowerItems[i];
if (itemContext == null || itemContext.InstanceId <= 0) if (itemContext == null || itemContext.InstanceId <= 0)
{ {
continue; continue;
} }
RepoItem item = CreateOrSpawnItem(); TowerRepoItem item = CreateOrSpawnItem();
if (item == null) if (item == null)
{ {
continue; continue;
@ -57,7 +57,7 @@ namespace GeometryTD.UI
{ {
for (int i = _activeItems.Count - 1; i >= 0; i--) for (int i = _activeItems.Count - 1; i >= 0; i--)
{ {
RepoItem item = _activeItems[i]; TowerRepoItem item = _activeItems[i];
if (item == null) if (item == null)
{ {
continue; continue;
@ -79,19 +79,19 @@ namespace GeometryTD.UI
_itemPool?.ReleaseAllUnused(); _itemPool?.ReleaseAllUnused();
} }
public bool CanAssign(RepoItemContext itemContext) public bool CanAssign(IRepoDragItemView dragItem)
{ {
if (itemContext == null || itemContext.InstanceId <= 0) if (dragItem == null || dragItem.InstanceId <= 0)
{ {
return false; return false;
} }
if (itemContext.ComponentSlotType != TowerCompSlotType.None) if (dragItem.ComponentSlotType != TowerCompSlotType.None)
{ {
return false; return false;
} }
if (_boundItemIds.Contains(itemContext.InstanceId)) if (_boundItemIds.Contains(dragItem.InstanceId))
{ {
return false; return false;
} }
@ -117,21 +117,21 @@ namespace GeometryTD.UI
return; return;
} }
RepoItem repoItem = pointerDrag.GetComponent<RepoItem>() ?? pointerDrag.GetComponentInParent<RepoItem>(); IRepoDragItemView dragItem = pointerDrag.GetComponent<IRepoDragItemView>() ??
if (repoItem == null) pointerDrag.GetComponentInParent<IRepoDragItemView>();
if (dragItem == null)
{ {
return; return;
} }
RepoItemContext itemContext = repoItem.Context; bool assigned = CanAssign(dragItem);
bool assigned = CanAssign(itemContext); dragItem.SetDropResult(assigned);
repoItem.SetDropResult(assigned);
if (!assigned) if (!assigned)
{ {
return; return;
} }
GameEntry.Event.Fire(this, RepoParticipantAssignRequestedEventArgs.Create(itemContext.InstanceId)); GameEntry.Event.Fire(this, RepoParticipantAssignRequestedEventArgs.Create(dragItem.InstanceId));
} }
private void EnsurePool() private void EnsurePool()
@ -141,29 +141,30 @@ namespace GeometryTD.UI
return; return;
} }
_poolName = $"ParticipantRepoItemPool_{GetInstanceID()}"; _poolName = $"ParticipantTowerRepoItemPool_{GetInstanceID()}";
_itemPool = GameEntry.ObjectPool.CreateSingleSpawnObjectPool<RepoItemObject>(_poolName, _instancePoolCapacity); _itemPool =
GameEntry.ObjectPool.CreateSingleSpawnObjectPool<TowerRepoItemObject>(_poolName, _instancePoolCapacity);
} }
private RepoItem CreateOrSpawnItem() private TowerRepoItem CreateOrSpawnItem()
{ {
if (_itemPool == null) if (_itemPool == null)
{ {
return null; return null;
} }
RepoItemObject itemObject = _itemPool.Spawn(); TowerRepoItemObject itemObject = _itemPool.Spawn();
RepoItem item = itemObject != null ? (RepoItem)itemObject.Target : null; TowerRepoItem item = itemObject != null ? (TowerRepoItem)itemObject.Target : null;
if (item == null) if (item == null)
{ {
if (_itemTemplate == null) if (_towerItemTemplate == null)
{ {
Log.Warning("ParticipantArea requires an item template."); Log.Warning("ParticipantArea requires a tower item template.");
return null; return null;
} }
item = Instantiate(_itemTemplate); item = Instantiate(_towerItemTemplate);
_itemPool.Register(RepoItemObject.Create(item), true); _itemPool.Register(TowerRepoItemObject.Create(item), true);
} }
if (_content != null) if (_content != null)

View File

@ -6,10 +6,10 @@ using UnityEngine.UI;
namespace GeometryTD.UI namespace GeometryTD.UI
{ {
public class RepoItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler public class RepoItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IRepoDragItemView
{ {
[SerializeField] private Image _bgImage; [SerializeField] private Image _bgImage;
[SerializeField] private IconArea _iconArea; [SerializeField] private IconArea _iconArea;
private static readonly Color SelectedColor = new Color32(255, 216, 102, 255); private static readonly Color SelectedColor = new Color32(255, 216, 102, 255);
@ -20,8 +20,8 @@ namespace GeometryTD.UI
[SerializeField] private RepoItemContext _context; [SerializeField] private RepoItemContext _context;
private CanvasGroup _canvasGroup; private CanvasGroup _canvasGroup;
private RectTransform _dragRoot; private RectTransform _dragRoot;
private GameObject _dragGhostObject; protected GameObject _dragGhostObject;
private RectTransform _dragGhostRect; protected RectTransform _dragGhostRect;
private bool _isSelected; private bool _isSelected;
private bool _isDragging; private bool _isDragging;
private bool _dropHandled; private bool _dropHandled;
@ -29,6 +29,24 @@ namespace GeometryTD.UI
public RepoItemContext Context => _context; public RepoItemContext Context => _context;
public long InstanceId => _context != null ? _context.InstanceId : 0;
bool IRepoDragItemView.CanDrag => _context != null && _context.CanDrag;
public TowerCompSlotType ComponentSlotType =>
_context != null ? _context.ComponentSlotType : TowerCompSlotType.None;
public RepoItemClickActionType ClickActionType =>
_context != null ? _context.ClickActionType : RepoItemClickActionType.OpenDetail;
public RepoItemContext ComponentContext => _context;
protected IconArea IconArea => _iconArea;
protected Image BackgroundImage => _bgImage;
protected RectTransform DragRoot => _dragRoot;
private void Awake() private void Awake()
{ {
_canvasGroup = GetComponent<CanvasGroup>(); _canvasGroup = GetComponent<CanvasGroup>();
@ -43,7 +61,7 @@ namespace GeometryTD.UI
ResetDragState(); ResetDragState();
} }
public void OnInit(RepoItemContext context) public virtual void OnInit(RepoItemContext context)
{ {
if (context == null) if (context == null)
{ {
@ -52,14 +70,13 @@ namespace GeometryTD.UI
} }
_context = context; _context = context;
_iconArea.OnInit(context.IconAreaContext); _iconArea.OnInit(context.IconAreaContext);
SetSelected(false); SetSelected(false);
ResetDragState(); ResetDragState();
} }
public void OnReset() public virtual void OnReset()
{ {
_context = null; _context = null;
_iconArea.OnReset(); _iconArea.OnReset();
@ -165,6 +182,7 @@ namespace GeometryTD.UI
{ {
_canvasGroup.blocksRaycasts = true; _canvasGroup.blocksRaycasts = true;
} }
DestroyDragGhost(); DestroyDragGhost();
_dragRoot = null; _dragRoot = null;
@ -232,7 +250,7 @@ namespace GeometryTD.UI
return canvas.rootCanvas.transform as RectTransform; return canvas.rootCanvas.transform as RectTransform;
} }
private bool CreateDragGhost() protected virtual bool CreateDragGhost()
{ {
DestroyDragGhost(); DestroyDragGhost();
@ -246,7 +264,6 @@ namespace GeometryTD.UI
Material iconMaterial = _iconArea != null ? _iconArea.CurrentIconMaterial : null; Material iconMaterial = _iconArea != null ? _iconArea.CurrentIconMaterial : null;
Vector2 iconSize = _iconArea != null ? _iconArea.CurrentIconSize : Vector2.zero; Vector2 iconSize = _iconArea != null ? _iconArea.CurrentIconSize : Vector2.zero;
// Towers may not have an icon sprite; fall back to background sprite so drag still works.
if (iconSprite == null && _bgImage != null) if (iconSprite == null && _bgImage != null)
{ {
iconSprite = _bgImage.sprite; iconSprite = _bgImage.sprite;
@ -260,7 +277,8 @@ namespace GeometryTD.UI
return false; return false;
} }
_dragGhostObject = new GameObject("RepoItemDragGhost", typeof(RectTransform), typeof(CanvasGroup), typeof(Image)); _dragGhostObject = new GameObject("RepoItemDragGhost", typeof(RectTransform), typeof(CanvasGroup),
typeof(Image));
_dragGhostObject.layer = gameObject.layer; _dragGhostObject.layer = gameObject.layer;
_dragGhostRect = _dragGhostObject.GetComponent<RectTransform>(); _dragGhostRect = _dragGhostObject.GetComponent<RectTransform>();
@ -273,6 +291,7 @@ namespace GeometryTD.UI
{ {
iconSize = DefaultDragGhostSize; iconSize = DefaultDragGhostSize;
} }
_dragGhostRect.sizeDelta = iconSize; _dragGhostRect.sizeDelta = iconSize;
Image ghostImage = _dragGhostObject.GetComponent<Image>(); Image ghostImage = _dragGhostObject.GetComponent<Image>();
@ -290,7 +309,7 @@ namespace GeometryTD.UI
return true; return true;
} }
private void UpdateDragGhostPosition(PointerEventData eventData) protected virtual void UpdateDragGhostPosition(PointerEventData eventData)
{ {
if (_dragGhostRect == null || _dragRoot == null || eventData == null) if (_dragGhostRect == null || _dragRoot == null || eventData == null)
{ {
@ -304,7 +323,7 @@ namespace GeometryTD.UI
} }
} }
private void DestroyDragGhost() protected virtual void DestroyDragGhost()
{ {
if (_dragGhostObject != null) if (_dragGhostObject != null)
{ {
@ -329,3 +348,4 @@ namespace GeometryTD.UI
} }
} }
} }

View File

@ -0,0 +1,109 @@
using UnityEngine;
using UnityEngine.UI;
namespace GeometryTD.UI
{
public class TowerRepoItem : RepoItem
{
private static readonly Vector2 DefaultTowerDragGhostSize = new Vector2(64f, 64f);
public new TowerRepoItemContext Context => base.Context as TowerRepoItemContext;
public void OnInit(TowerRepoItemContext context)
{
base.OnInit(context);
}
protected override bool CreateDragGhost()
{
DestroyDragGhost();
if (DragRoot == null)
{
return false;
}
TowerIconArea towerIconArea = IconArea as TowerIconArea;
if (towerIconArea == null)
{
return base.CreateDragGhost();
}
_dragGhostObject = new GameObject("TowerRepoItemDragGhost", typeof(RectTransform), typeof(CanvasGroup));
_dragGhostObject.layer = gameObject.layer;
_dragGhostRect = _dragGhostObject.GetComponent<RectTransform>();
_dragGhostRect.SetParent(DragRoot, false);
_dragGhostRect.anchorMin = new Vector2(0.5f, 0.5f);
_dragGhostRect.anchorMax = new Vector2(0.5f, 0.5f);
_dragGhostRect.pivot = new Vector2(0.5f, 0.5f);
Vector2 iconSize = IconArea != null ? IconArea.CurrentIconSize : Vector2.zero;
if (iconSize.x <= 0f || iconSize.y <= 0f)
{
iconSize = BackgroundImage != null ? BackgroundImage.rectTransform.rect.size : DefaultTowerDragGhostSize;
}
if (iconSize.x <= 0f || iconSize.y <= 0f)
{
iconSize = DefaultTowerDragGhostSize;
}
_dragGhostRect.sizeDelta = iconSize;
bool hasAnyLayer = false;
hasAnyLayer |= TryCreateLayer("Base", towerIconArea.BaseIconSprite, towerIconArea.BaseIconColor,
towerIconArea.BaseIconMaterial, _dragGhostRect, 0);
hasAnyLayer |= TryCreateLayer("Bearing", towerIconArea.BearingIconSprite, towerIconArea.BearingIconColor,
towerIconArea.BearingIconMaterial, _dragGhostRect, 1);
hasAnyLayer |= TryCreateLayer("Muzzle", towerIconArea.MuzzleIconSprite, towerIconArea.MuzzleIconColor,
towerIconArea.MuzzleIconMaterial, _dragGhostRect, 2);
if (!hasAnyLayer)
{
DestroyDragGhost();
return base.CreateDragGhost();
}
CanvasGroup ghostCanvasGroup = _dragGhostObject.GetComponent<CanvasGroup>();
ghostCanvasGroup.blocksRaycasts = false;
ghostCanvasGroup.interactable = false;
_dragGhostObject.transform.SetAsLastSibling();
return true;
}
private static bool TryCreateLayer(
string layerName,
Sprite sprite,
Color color,
Material material,
RectTransform parent,
int siblingIndex)
{
if (parent == null || sprite == null)
{
return false;
}
GameObject layerObject = new GameObject($"TowerGhost{layerName}", typeof(RectTransform), typeof(Image));
layerObject.layer = parent.gameObject.layer;
RectTransform layerRect = layerObject.GetComponent<RectTransform>();
layerRect.SetParent(parent, false);
layerRect.anchorMin = Vector2.zero;
layerRect.anchorMax = Vector2.one;
layerRect.offsetMin = Vector2.zero;
layerRect.offsetMax = Vector2.zero;
layerRect.SetSiblingIndex(siblingIndex);
Image layerImage = layerObject.GetComponent<Image>();
layerImage.raycastTarget = false;
layerImage.sprite = sprite;
layerImage.color = color;
layerImage.material = material;
layerImage.preserveAspect = true;
return true;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: caf7b65cc179a5d46828128f574ed63e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,21 @@
using System;
using GeometryTD.Definition;
using UnityEngine;
namespace GeometryTD.UI
{
[Serializable]
public class TowerIconAreaContext : IconAreaContext
{
public Color MuzzleColor = Color.white;
public Color BearingColor = Color.white;
public Color BaseColor = Color.white;
public TowerIconAreaContext()
{
ComponentSlotType = TowerCompSlotType.None;
Color = Color.white;
Icon = null;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e3576597006db5b458566429f98a6f43
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,4 +1,3 @@
using System;
using GeometryTD.Definition; using GeometryTD.Definition;
using UnityEngine; using UnityEngine;
using UnityEngine.UI; using UnityEngine.UI;
@ -14,15 +13,17 @@ namespace GeometryTD.UI
private IconAreaContext _context; private IconAreaContext _context;
public Sprite CurrentIconSprite => _icon != null ? _icon.sprite : null; public virtual Sprite CurrentIconSprite => _icon != null ? _icon.sprite : null;
public Color CurrentIconColor => _icon != null ? _icon.color : Color.white; public virtual Color CurrentIconColor => _icon != null ? _icon.color : Color.white;
public Vector2 CurrentIconSize => _icon != null ? _icon.rectTransform.rect.size : Vector2.zero; public virtual Vector2 CurrentIconSize => _icon != null ? _icon.rectTransform.rect.size : Vector2.zero;
public Material CurrentIconMaterial => _icon != null ? _icon.material : null; public virtual Material CurrentIconMaterial => _icon != null ? _icon.material : null;
public void OnInit(IconAreaContext context) public virtual RectTransform IconRectTransform => _icon != null ? _icon.rectTransform : null;
public virtual void OnInit(IconAreaContext context)
{ {
if (context == null) if (context == null)
{ {
@ -46,9 +47,10 @@ namespace GeometryTD.UI
SetRarity(_context.Rarity); SetRarity(_context.Rarity);
SetIconColor(_context.Color); SetIconColor(_context.Color);
SetIconVisible(true);
} }
public void SetIcon(Sprite sprite) public virtual void SetIcon(Sprite sprite)
{ {
if (_icon != null) if (_icon != null)
{ {
@ -56,7 +58,7 @@ namespace GeometryTD.UI
} }
} }
public void SetRarity(RarityType rarity) public virtual void SetRarity(RarityType rarity)
{ {
if (_board == null) if (_board == null)
{ {
@ -74,7 +76,7 @@ namespace GeometryTD.UI
}; };
} }
public void SetIconColor(Color color) public virtual void SetIconColor(Color color)
{ {
if (_icon == null) if (_icon == null)
{ {
@ -84,11 +86,20 @@ namespace GeometryTD.UI
_icon.color = color; _icon.color = color;
} }
public void OnReset() public virtual void SetIconVisible(bool visible)
{
if (_icon != null)
{
_icon.enabled = visible;
}
}
public virtual void OnReset()
{ {
SetIcon(null); SetIcon(null);
SetRarity(RarityType.None); SetRarity(RarityType.None);
SetIconColor(Color.clear); SetIconColor(Color.clear);
SetIconVisible(true);
} }
} }
} }

View File

@ -0,0 +1,72 @@
using UnityEngine;
using UnityEngine.UI;
namespace GeometryTD.UI
{
public class TowerIconArea : IconArea
{
[SerializeField] private Image _baseIcon;
[SerializeField] private Image _bearingIcon;
[SerializeField] private Image _muzzleIcon;
public Sprite BaseIconSprite => _baseIcon != null ? _baseIcon.sprite : null;
public Sprite BearingIconSprite => _bearingIcon != null ? _bearingIcon.sprite : null;
public Sprite MuzzleIconSprite => _muzzleIcon != null ? _muzzleIcon.sprite : null;
public Color BaseIconColor => _baseIcon != null ? _baseIcon.color : Color.white;
public Color BearingIconColor => _bearingIcon != null ? _bearingIcon.color : Color.white;
public Color MuzzleIconColor => _muzzleIcon != null ? _muzzleIcon.color : Color.white;
public Material BaseIconMaterial => _baseIcon != null ? _baseIcon.material : null;
public Material BearingIconMaterial => _bearingIcon != null ? _bearingIcon.material : null;
public Material MuzzleIconMaterial => _muzzleIcon != null ? _muzzleIcon.material : null;
public override void OnInit(IconAreaContext context)
{
if (!(context is TowerIconAreaContext towerContext))
{
base.OnInit(context);
return;
}
SetRarity(towerContext.Rarity);
SetIconVisible(false);
SetLayerColor(_baseIcon, towerContext.BaseColor);
SetLayerColor(_bearingIcon, towerContext.BearingColor);
SetLayerColor(_muzzleIcon, towerContext.MuzzleColor);
}
public void OnInit(TowerIconAreaContext context)
{
OnInit((IconAreaContext)context);
}
public override void OnReset()
{
base.OnReset();
SetLayerColor(_baseIcon, Color.clear);
SetLayerColor(_bearingIcon, Color.clear);
SetLayerColor(_muzzleIcon, Color.clear);
SetIconVisible(false);
}
private static void SetLayerColor(Image icon, Color color)
{
if (icon == null)
{
return;
}
icon.color = color;
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 33a1436bff53c844e858f3bced1565ca
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,4 +1,4 @@
using System; using System;
using GeometryTD.Definition; using GeometryTD.Definition;
using UnityEngine; using UnityEngine;
@ -162,7 +162,9 @@ namespace GeometryTD.CustomUtility
MuzzleComponentInstanceId = source.MuzzleComponentInstanceId, MuzzleComponentInstanceId = source.MuzzleComponentInstanceId,
BearingComponentInstanceId = source.BearingComponentInstanceId, BearingComponentInstanceId = source.BearingComponentInstanceId,
BaseComponentInstanceId = source.BaseComponentInstanceId, BaseComponentInstanceId = source.BaseComponentInstanceId,
Stats = CloneTowerStats(source.Stats) Stats = CloneTowerStats(source.Stats),
ComposedIconSprite = source.ComposedIconSprite,
ComposedIconKey = source.ComposedIconKey
}; };
} }
@ -205,3 +207,4 @@ namespace GeometryTD.CustomUtility
} }

View File

@ -19,41 +19,12 @@ namespace GeometryTD.CustomUtility
Rarity = RarityType.Green, Rarity = RarityType.Green,
Endurance = 90f, Endurance = 90f,
IsAssembledIntoTower = true, IsAssembledIntoTower = true,
AttackDamage = new[] { 20, 30, 40, 50, 80 }, AttackDamage = new[] { 200, 300, 400, 500, 800 },
DamageRandomRate = 0.05f, DamageRandomRate = 0.05f,
AttackMethodType = AttackMethodType.NormalBullet, AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty, Constraint = string.Empty,
Tags = new[] { TagType.Fire } Tags = new[] { TagType.Fire }
}; };
inventory.MuzzleComponents.Add(muzzle);
inventory.MuzzleComponents.Add(new MuzzleCompItemData
{
InstanceId = 10002,
ConfigId = 2,
Name = "控制枪口",
Rarity = RarityType.Blue,
Endurance = 80,
IsAssembledIntoTower = false,
AttackDamage = new[] { 30, 50, 70, 90, 100 },
DamageRandomRate = 0.01f,
AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.FreezeMask }
});
inventory.MuzzleComponents.Add(new MuzzleCompItemData
{
InstanceId = 10003,
ConfigId = 3,
Name = "穿透枪口",
Rarity = RarityType.Purple,
Endurance = 97f,
IsAssembledIntoTower = false,
AttackDamage = new[] { 50, 55, 60, 80, 90 },
DamageRandomRate = 0.02f,
AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Crit }
});
BearingCompItemData bearing = new BearingCompItemData BearingCompItemData bearing = new BearingCompItemData
{ {
@ -63,38 +34,11 @@ namespace GeometryTD.CustomUtility
Rarity = RarityType.Green, Rarity = RarityType.Green,
Endurance = 1f, Endurance = 1f,
IsAssembledIntoTower = true, IsAssembledIntoTower = true,
RotateSpeed = new[] { 10f, 12f, 13f, 14f, 15f }, RotateSpeed = new[] { 100f, 120f, 130f, 140f, 150f },
AttackRange = new[] { 2f, 2f, 2f, 2f, 2f }, AttackRange = new[] { 3f, 4f, 5f, 6f, 8f },
Constraint = string.Empty, Constraint = string.Empty,
Tags = new[] { TagType.Fire } Tags = new[] { TagType.Fire }
}; };
inventory.BearingComponents.Add(bearing);
inventory.BearingComponents.Add(new BearingCompItemData
{
InstanceId = 20002,
ConfigId = 2,
Name = "控制轴承",
Rarity = RarityType.Blue,
Endurance = 20,
IsAssembledIntoTower = false,
RotateSpeed = new[] { 20f, 25f, 30f, 32f, 35f },
AttackRange = new[] { 6f, 6.5f, 7f, 8f, 8f },
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.Shatter }
});
inventory.BearingComponents.Add(new BearingCompItemData
{
InstanceId = 20003,
ConfigId = 3,
Name = "穿透轴承",
Rarity = RarityType.Purple,
Endurance = 96f,
IsAssembledIntoTower = false,
RotateSpeed = new[] { 60f, 70f, 80f, 90f, 100f },
AttackRange = new[] { 4f, 4.5f, 5f, 5.5f, 6f },
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Overpenetrate }
});
BaseCompItemData baseComp = new BaseCompItemData BaseCompItemData baseComp = new BaseCompItemData
{ {
@ -104,38 +48,11 @@ namespace GeometryTD.CustomUtility
Rarity = RarityType.Green, Rarity = RarityType.Green,
Endurance = 88f, Endurance = 88f,
IsAssembledIntoTower = true, IsAssembledIntoTower = true,
AttackSpeed = new[] { 2f, 1.5f, 1f, 0.8f, 0.7f }, AttackSpeed = new[] { 1f, 2f, 3f, 3.5f, 0.7f },
AttackPropertyType = AttackPropertyType.Fire, AttackPropertyType = AttackPropertyType.Fire,
Constraint = string.Empty, Constraint = string.Empty,
Tags = new[] { TagType.Fire } Tags = new[] { TagType.Fire }
}; };
inventory.BaseComponents.Add(baseComp);
inventory.BaseComponents.Add(new BaseCompItemData
{
InstanceId = 30002,
ConfigId = 2,
Name = "控制底座",
Rarity = RarityType.Blue,
Endurance = 50f,
IsAssembledIntoTower = false,
AttackSpeed = new[] { 4f, 4.2f, 4.4f, 4.6f, 4.8f },
AttackPropertyType = AttackPropertyType.Ice,
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.AbsoluteZero }
});
inventory.BaseComponents.Add(new BaseCompItemData
{
InstanceId = 30003,
ConfigId = 3,
Name = "穿透底座",
Rarity = RarityType.Purple,
Endurance = 30f,
IsAssembledIntoTower = false,
AttackSpeed = new[] { 1f, 1f, 1f, 1f, 1f },
AttackPropertyType = AttackPropertyType.Physics,
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Execution }
});
TowerItemData tower = new TowerItemData TowerItemData tower = new TowerItemData
{ {
@ -151,35 +68,103 @@ namespace GeometryTD.CustomUtility
AttackDamage = new[] { 200, 220, 240, 260, 300 }, AttackDamage = new[] { 200, 220, 240, 260, 300 },
DamageRandomRate = 0f, DamageRandomRate = 0f,
RotateSpeed = new[] { 200f, 210f, 220f, 230f, 240f }, RotateSpeed = new[] { 200f, 210f, 220f, 230f, 240f },
AttackRange = new[] { 4.5f, 4.7f, 4.9f, 5.1f, 5.3f }, AttackRange = new[] { 4.5f, 4.5f, 4.5f, 4.5f, 4.5f },
AttackSpeed = new[] { 1.5f, 1.2f, 1.1f, 1.0f, 0.8f }, AttackSpeed = new[] { 1.0f, 1.2f, 1.3f, 1.4f, 0.5f },
AttackMethodType = AttackMethodType.NormalBullet, AttackMethodType = AttackMethodType.NormalBullet,
AttackPropertyType = AttackPropertyType.Fire, AttackPropertyType = AttackPropertyType.Fire,
Tags = new[] { TagType.Fire, TagType.BurnSpread } Tags = new[] { TagType.Fire, TagType.BurnSpread }
} }
}; };
inventory.MuzzleComponents.Add(muzzle);
inventory.BaseComponents.Add(baseComp);
inventory.BearingComponents.Add(bearing);
inventory.Towers.Add(tower); inventory.Towers.Add(tower);
inventory.Towers.Add(new TowerItemData inventory.MuzzleComponents.Add(new MuzzleCompItemData
{ {
InstanceId = 90002, InstanceId = 10002,
Name = "测试防御塔-B", ConfigId = 2,
Name = "控制枪口",
Rarity = RarityType.Blue, Rarity = RarityType.Blue,
IsParticipatingInCombat = false, Endurance = 80,
MuzzleComponentInstanceId = 0, IsAssembledIntoTower = false,
BearingComponentInstanceId = 0, AttackDamage = new[] { 200, 300, 400, 500, 600 },
BaseComponentInstanceId = 0, DamageRandomRate = 0.01f,
Stats = new TowerStatsData AttackMethodType = AttackMethodType.NormalBullet,
{ Constraint = string.Empty,
AttackDamage = new[] { 200, 220, 240, 260, 300 }, Tags = new[] { TagType.Ice, TagType.FreezeMask }
DamageRandomRate = 0.1f, });
RotateSpeed = new[] { 200f, 210f, 220f, 230f, 240f },
AttackRange = new[] { 4.5f, 4.7f, 4.9f, 5.1f, 5.3f }, inventory.MuzzleComponents.Add(new MuzzleCompItemData
AttackSpeed = new[] { 1.5f, 1.2f, 1.1f, 1.0f, 0.8f }, {
AttackMethodType = AttackMethodType.NormalBullet, InstanceId = 10003,
AttackPropertyType = AttackPropertyType.Physics, ConfigId = 3,
Tags = new[] { TagType.Pierce } Name = "穿透枪口",
} Rarity = RarityType.Purple,
Endurance = 97f,
IsAssembledIntoTower = false,
AttackDamage = new[] { 50, 55, 60, 80, 90 },
DamageRandomRate = 0.02f,
AttackMethodType = AttackMethodType.NormalBullet,
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Crit }
});
inventory.BearingComponents.Add(new BearingCompItemData
{
InstanceId = 20002,
ConfigId = 2,
Name = "控制轴承",
Rarity = RarityType.Blue,
Endurance = 20,
IsAssembledIntoTower = false,
RotateSpeed = new[] { 200f, 250f, 300f, 320f, 350f },
AttackRange = new[] { 6f, 6.5f, 7f, 8f, 8f },
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.Shatter }
});
inventory.BearingComponents.Add(new BearingCompItemData
{
InstanceId = 20003,
ConfigId = 3,
Name = "穿透轴承",
Rarity = RarityType.Purple,
Endurance = 96f,
IsAssembledIntoTower = false,
RotateSpeed = new[] { 60f, 70f, 80f, 90f, 100f },
AttackRange = new[] { 4f, 4.5f, 5f, 5.5f, 6f },
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Overpenetrate }
});
inventory.BaseComponents.Add(new BaseCompItemData
{
InstanceId = 30002,
ConfigId = 2,
Name = "控制底座",
Rarity = RarityType.Blue,
Endurance = 50f,
IsAssembledIntoTower = false,
AttackSpeed = new[] { 4f, 4.2f, 4.4f, 4.6f, 4.8f },
AttackPropertyType = AttackPropertyType.Ice,
Constraint = string.Empty,
Tags = new[] { TagType.Ice, TagType.AbsoluteZero }
});
inventory.BaseComponents.Add(new BaseCompItemData
{
InstanceId = 30003,
ConfigId = 3,
Name = "穿透底座",
Rarity = RarityType.Purple,
Endurance = 30f,
IsAssembledIntoTower = false,
AttackSpeed = new[] { 1f, 1f, 1f, 1f, 1f },
AttackPropertyType = AttackPropertyType.Physics,
Constraint = string.Empty,
Tags = new[] { TagType.Pierce, TagType.Execution }
}); });
inventory.ParticipantTowerInstanceIds.Add(90001); inventory.ParticipantTowerInstanceIds.Add(90001);

View File

@ -0,0 +1,130 @@
using System.Collections.Generic;
using GeometryTD.Definition;
using UnityEngine;
namespace GeometryTD.CustomUtility
{
public static class TowerComposedIconCacheUtility
{
private const string MuzzleAssetName = "Muzzle";
private const string BearingAssetName = "Bearing";
private const string BaseAssetName = "Base";
private static Sprite _muzzleSprite;
private static Sprite _bearingSprite;
private static Sprite _baseSprite;
private static bool s_RequestedMuzzle;
private static bool s_RequestedBearing;
private static bool s_RequestedBase;
public static Sprite ResolveTowerIconSprite(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap)
{
if (tower == null)
{
return null;
}
if (!TryGetComponents(tower, muzzleMap, bearingMap, baseMap,
out MuzzleCompItemData muzzleComp,
out BearingCompItemData bearingComp,
out BaseCompItemData baseComp))
{
return null;
}
Color muzzleColor = IconColorGenerator.GenerateForComponent(muzzleComp);
Color bearingColor = IconColorGenerator.GenerateForComponent(bearingComp);
Color baseColor = IconColorGenerator.GenerateForComponent(baseComp);
string cacheKey = TowerIconComposeUtility.BuildCacheKey(
tower.MuzzleComponentInstanceId,
tower.BearingComponentInstanceId,
tower.BaseComponentInstanceId,
muzzleColor,
bearingColor,
baseColor);
if (tower.ComposedIconSprite != null && string.Equals(tower.ComposedIconKey, cacheKey))
{
return tower.ComposedIconSprite;
}
EnsureBaseSpritesRequested();
if (_muzzleSprite == null || _bearingSprite == null || _baseSprite == null)
{
return null;
}
Sprite composedSprite = TowerIconComposeUtility.Compose(
_muzzleSprite,
muzzleColor,
_bearingSprite,
bearingColor,
_baseSprite,
baseColor);
if (composedSprite == null)
{
return null;
}
tower.ComposedIconSprite = composedSprite;
tower.ComposedIconKey = cacheKey;
return composedSprite;
}
private static bool TryGetComponents(
TowerItemData tower,
IReadOnlyDictionary<long, MuzzleCompItemData> muzzleMap,
IReadOnlyDictionary<long, BearingCompItemData> bearingMap,
IReadOnlyDictionary<long, BaseCompItemData> baseMap,
out MuzzleCompItemData muzzleComp,
out BearingCompItemData bearingComp,
out BaseCompItemData baseComp)
{
muzzleComp = null;
bearingComp = null;
baseComp = null;
if (tower == null || muzzleMap == null || bearingMap == null || baseMap == null)
{
return false;
}
return muzzleMap.TryGetValue(tower.MuzzleComponentInstanceId, out muzzleComp) &&
bearingMap.TryGetValue(tower.BearingComponentInstanceId, out bearingComp) &&
baseMap.TryGetValue(tower.BaseComponentInstanceId, out baseComp) &&
muzzleComp != null && bearingComp != null && baseComp != null;
}
private static void EnsureBaseSpritesRequested()
{
if (GameEntry.SpriteCache == null)
{
return;
}
if (!s_RequestedMuzzle)
{
s_RequestedMuzzle = true;
GameEntry.SpriteCache.GetSprite(MuzzleAssetName, sprite => { _muzzleSprite = sprite; });
}
if (!s_RequestedBearing)
{
s_RequestedBearing = true;
GameEntry.SpriteCache.GetSprite(BearingAssetName, sprite => { _bearingSprite = sprite; });
}
if (!s_RequestedBase)
{
s_RequestedBase = true;
GameEntry.SpriteCache.GetSprite(BaseAssetName, sprite => { _baseSprite = sprite; });
}
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a705ccdd02d2d3440934d4ab06228547
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,148 @@
using System;
using System.Globalization;
using UnityEngine;
namespace GeometryTD.CustomUtility
{
public static class TowerIconComposeUtility
{
public static Sprite Compose(
Sprite muzzleSprite,
Color muzzleColor,
Sprite bearingSprite,
Color bearingColor,
Sprite baseSprite,
Color baseColor)
{
if (muzzleSprite == null || bearingSprite == null || baseSprite == null)
{
return null;
}
Sprite referenceSprite = muzzleSprite ?? bearingSprite ?? baseSprite;
if (referenceSprite == null)
{
return null;
}
int width = Mathf.RoundToInt(referenceSprite.rect.width);
int height = Mathf.RoundToInt(referenceSprite.rect.height);
if (width <= 0 || height <= 0)
{
return null;
}
return ComposeWithRenderTexture(
muzzleSprite,
muzzleColor,
bearingSprite,
bearingColor,
baseSprite,
baseColor,
width,
height,
referenceSprite);
}
public static string BuildCacheKey(
long muzzleId,
long bearingId,
long baseId,
Color muzzleColor,
Color bearingColor,
Color baseColor)
{
return string.Format(
CultureInfo.InvariantCulture,
"v2|{0}|{1}|{2}|{3}|{4}|{5}",
muzzleId,
bearingId,
baseId,
ToColorKey(muzzleColor),
ToColorKey(bearingColor),
ToColorKey(baseColor));
}
private static Sprite ComposeWithRenderTexture(
Sprite muzzleSprite,
Color muzzleColor,
Sprite bearingSprite,
Color bearingColor,
Sprite baseSprite,
Color baseColor,
int width,
int height,
Sprite referenceSprite)
{
RenderTexture rt = RenderTexture.GetTemporary(width, height, 0, RenderTextureFormat.ARGB32);
RenderTexture previous = RenderTexture.active;
try
{
RenderTexture.active = rt;
GL.PushMatrix();
GL.LoadPixelMatrix(0f, width, 0f, height);
GL.Clear(true, true, Color.clear);
DrawSpriteToRenderTarget(baseSprite, baseColor, width, height);
DrawSpriteToRenderTarget(bearingSprite, bearingColor, width, height);
DrawSpriteToRenderTarget(muzzleSprite, muzzleColor, width, height);
GL.PopMatrix();
Texture2D composedTexture = new Texture2D(width, height, TextureFormat.RGBA32, false);
composedTexture.ReadPixels(new Rect(0f, 0f, width, height), 0, 0);
composedTexture.Apply(false, false);
return CreateSprite(composedTexture, referenceSprite);
}
catch (Exception)
{
return null;
}
finally
{
RenderTexture.active = previous;
RenderTexture.ReleaseTemporary(rt);
}
}
private static void DrawSpriteToRenderTarget(Sprite sprite, Color color, int width, int height)
{
if (sprite == null || sprite.texture == null)
{
return;
}
Rect textureRect = sprite.textureRect;
Texture texture = sprite.texture;
Rect uvRect = new Rect(
textureRect.x / texture.width,
textureRect.y / texture.height,
textureRect.width / texture.width,
textureRect.height / texture.height);
Graphics.DrawTexture(new Rect(0f, 0f, width, height), texture, uvRect, 0, 0, 0, 0, color);
}
private static Sprite CreateSprite(Texture2D texture, Sprite referenceSprite)
{
if (texture == null || referenceSprite == null)
{
return null;
}
float width = Mathf.Max(1f, referenceSprite.rect.width);
float height = Mathf.Max(1f, referenceSprite.rect.height);
Vector2 pivot = new Vector2(referenceSprite.pivot.x / width, referenceSprite.pivot.y / height);
return Sprite.Create(texture, new Rect(0f, 0f, texture.width, texture.height), pivot, referenceSprite.pixelsPerUnit);
}
private static string ToColorKey(Color color)
{
Color32 c = color;
return c.r.ToString("X2", CultureInfo.InvariantCulture) +
c.g.ToString("X2", CultureInfo.InvariantCulture) +
c.b.ToString("X2", CultureInfo.InvariantCulture) +
c.a.ToString("X2", CultureInfo.InvariantCulture);
}
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d9256e2c4f74b7448afbdbac8f7cb26f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -976,6 +976,17 @@ PrefabInstance:
serializedVersion: 3 serializedVersion: 3
m_TransformParent: {fileID: 1714606292658179489} m_TransformParent: {fileID: 1714606292658179489}
m_Modifications: m_Modifications:
- target: {fileID: 272351400812969041, guid: b656295a0a0134840bdcd41e203f12c7,
type: 3}
propertyPath: m_Type
value: 1
objectReference: {fileID: 0}
- target: {fileID: 272351400812969041, guid: b656295a0a0134840bdcd41e203f12c7,
type: 3}
propertyPath: m_Sprite
value:
objectReference: {fileID: 21300000, guid: 9f847ec5e66e03e4ead1d3c5f7b510e8,
type: 3}
- target: {fileID: 274828358581623048, guid: b656295a0a0134840bdcd41e203f12c7, - target: {fileID: 274828358581623048, guid: b656295a0a0134840bdcd41e203f12c7,
type: 3} type: 3}
propertyPath: m_Pivot.x propertyPath: m_Pivot.x

View File

@ -52,6 +52,8 @@ MonoBehaviour:
_content: {fileID: 1805918912036091081} _content: {fileID: 1805918912036091081}
_itemTemplate: {fileID: 8394974685918372820, guid: 2ead8e403e355dd4b9296a9d0a871a83, _itemTemplate: {fileID: 8394974685918372820, guid: 2ead8e403e355dd4b9296a9d0a871a83,
type: 3} type: 3}
_towerItemTemplate: {fileID: 4730609612906943122, guid: 81bda3e30070fa34884bafbe9a9c72f9,
type: 3}
_instancePoolCapacity: 64 _instancePoolCapacity: 64
--- !u!1 &2380285751925872027 --- !u!1 &2380285751925872027
GameObject: GameObject:
@ -181,7 +183,7 @@ MonoBehaviour:
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_content: {fileID: 6811784024412969593} _content: {fileID: 6811784024412969593}
_itemTemplate: {fileID: 8394974685918372820, guid: 2ead8e403e355dd4b9296a9d0a871a83, _towerItemTemplate: {fileID: 4730609612906943122, guid: 81bda3e30070fa34884bafbe9a9c72f9,
type: 3} type: 3}
_instancePoolCapacity: 8 _instancePoolCapacity: 8
--- !u!222 &5388327515888957795 --- !u!222 &5388327515888957795

View File

@ -0,0 +1,447 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &177671855419091867
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3323726282767525619}
- component: {fileID: 399955496901366910}
- component: {fileID: 7579875247493712075}
m_Layer: 5
m_Name: TowerIconArea
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3323726282767525619
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 177671855419091867}
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: 1038851730778667217}
- {fileID: 2859743021803601866}
- {fileID: 6845015578436394914}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: -20, y: -20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &399955496901366910
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 177671855419091867}
m_CullTransparentMesh: 1
--- !u!114 &7579875247493712075
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 177671855419091867}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 33a1436bff53c844e858f3bced1565ca, type: 3}
m_Name:
m_EditorClassIdentifier:
_board: {fileID: 1792178769172340962}
_icon: {fileID: 4918346613506060866}
_baseIcon: {fileID: 7285567316465127825}
_bearingIcon: {fileID: 4366841213109481872}
_muzzleIcon: {fileID: 4666251790512386674}
--- !u!1 &803783036851305114
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2859743021803601866}
- component: {fileID: 4968140022138979945}
- component: {fileID: 4918346613506060866}
m_Layer: 5
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2859743021803601866
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803783036851305114}
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: 3323726282767525619}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4968140022138979945
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803783036851305114}
m_CullTransparentMesh: 1
--- !u!114 &4918346613506060866
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 803783036851305114}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 0}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &1636419954436272212
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9145919182730712671}
- component: {fileID: 2651698208426096613}
- component: {fileID: 4366841213109481872}
m_Layer: 5
m_Name: Bearing
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &9145919182730712671
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1636419954436272212}
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: 1
m_Children:
- {fileID: 6782923152009204558}
m_Father: {fileID: 6845015578436394914}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2651698208426096613
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1636419954436272212}
m_CullTransparentMesh: 1
--- !u!114 &4366841213109481872
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1636419954436272212}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: -2413806693520163455, guid: e31321df62f1587469b0733897970679,
type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &2318020840094036371
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6782923152009204558}
- component: {fileID: 3207702065525898594}
- component: {fileID: 4666251790512386674}
m_Layer: 5
m_Name: Muzzle
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6782923152009204558
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2318020840094036371}
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: 1
m_Children: []
m_Father: {fileID: 9145919182730712671}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 29.586662}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.2886667}
--- !u!222 &3207702065525898594
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2318020840094036371}
m_CullTransparentMesh: 1
--- !u!114 &4666251790512386674
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2318020840094036371}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 0.24213827, b: 0.24213827, 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_Sprite: {fileID: 7482667652216324306, guid: 5ba74e3a185274149b15c24b321bead2,
type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5542159351280798647
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1038851730778667217}
- component: {fileID: 2454678530691112152}
- component: {fileID: 1792178769172340962}
m_Layer: 5
m_Name: board
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1038851730778667217
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5542159351280798647}
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: 3323726282767525619}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 20, y: 20}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2454678530691112152
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5542159351280798647}
m_CullTransparentMesh: 1
--- !u!114 &1792178769172340962
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5542159351280798647}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, 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_Sprite: {fileID: 21300000, guid: a8c07bbe04fdaf04b80e27f651a8edd6, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5919608345427997939
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6845015578436394914}
- component: {fileID: 1519331956184262112}
- component: {fileID: 7285567316465127825}
m_Layer: 5
m_Name: Base
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6845015578436394914
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5919608345427997939}
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: 1
m_Children:
- {fileID: 9145919182730712671}
m_Father: {fileID: 3323726282767525619}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1519331956184262112
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5919608345427997939}
m_CullTransparentMesh: 1
--- !u!114 &7285567316465127825
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5919608345427997939}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.13836467, g: 0.13836467, b: 0.13836467, 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_Sprite: {fileID: 7482667652216324306, guid: 80a3790c48fc91d4ebcb4d7e2efbb8c8,
type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: ab6ee7e8b2a678544af490543d99f665
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,356 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &1986516583823050331
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6860417479053386125}
- component: {fileID: 8570341357903165526}
- component: {fileID: 5089068592453588603}
m_Layer: 5
m_Name: bg
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6860417479053386125
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1986516583823050331}
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: 8349727755164431499}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8570341357903165526
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1986516583823050331}
m_CullTransparentMesh: 1
--- !u!114 &5089068592453588603
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1986516583823050331}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300000, guid: 9f847ec5e66e03e4ead1d3c5f7b510e8, type: 3}
m_Type: 1
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &3287359693314616602
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7253748148476290235}
- component: {fileID: 412242389824419156}
- component: {fileID: 4730609612906943122}
m_Layer: 5
m_Name: TowerRepoItem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7253748148476290235
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3287359693314616602}
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: 8349727755164431499}
- {fileID: 884849595327022251}
m_Father: {fileID: 0}
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: 160, y: 160}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &412242389824419156
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3287359693314616602}
m_CullTransparentMesh: 1
--- !u!114 &4730609612906943122
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3287359693314616602}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: caf7b65cc179a5d46828128f574ed63e, type: 3}
m_Name:
m_EditorClassIdentifier:
_bgImage: {fileID: 5089068592453588603}
_iconArea: {fileID: 5428668331781712531}
_context:
InstanceId: 0
CanDrag: 0
EnduranceRate01: 0
ClickActionType: 0
ComponentSlotType: 0
IconAreaContext:
Rarity: 0
ComponentSlotType: 0
Color: {r: 1, g: 1, b: 1, a: 1}
Icon: {fileID: 0}
--- !u!1 &5586290829740215320
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8349727755164431499}
- component: {fileID: 8024563988191439697}
m_Layer: 5
m_Name: CommonButton
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8349727755164431499
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5586290829740215320}
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: 6860417479053386125}
m_Father: {fileID: 7253748148476290235}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &8024563988191439697
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5586290829740215320}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: a5079836f95c2a44b96fa331487ebb70, type: 3}
m_Name:
m_EditorClassIdentifier:
_onHover:
m_PersistentCalls:
m_Calls: []
_onClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 4730609612906943122}
m_TargetAssemblyTypeName: GeometryTD.UI.TowerRepoItem, Assembly-CSharp
m_MethodName: OnClick
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 10001
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
_onHoverEnd:
m_PersistentCalls:
m_Calls: []
_allowFade: 1
--- !u!1001 &2479127645651034712
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 7253748148476290235}
m_Modifications:
- target: {fileID: 177671855419091867, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Name
value: TowerIconArea
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMax.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_SizeDelta.x
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_SizeDelta.y
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ab6ee7e8b2a678544af490543d99f665, type: 3}
--- !u!224 &884849595327022251 stripped
RectTransform:
m_CorrespondingSourceObject: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 2479127645651034712}
m_PrefabAsset: {fileID: 0}
--- !u!114 &5428668331781712531 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 7579875247493712075, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 2479127645651034712}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 33a1436bff53c844e858f3bced1565ca, type: 3}
m_Name:
m_EditorClassIdentifier:

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 81bda3e30070fa34884bafbe9a9c72f9
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,80 +1,5 @@
%YAML 1.1 %YAML 1.1
%TAG !u! tag:unity3d.com,2011: %TAG !u! tag:unity3d.com,2011:
--- !u!1 &5412566102378209566
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4152009404387722330}
- component: {fileID: 3873445585384354699}
- component: {fileID: 272351400812969041}
m_Layer: 5
m_Name: Icon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4152009404387722330
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5412566102378209566}
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: 8201350274026178469}
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: 80, y: 80}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &3873445585384354699
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5412566102378209566}
m_CullTransparentMesh: 1
--- !u!114 &272351400812969041
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5412566102378209566}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Sprite: {fileID: 21300146, guid: 29c9cded5e558164aaf8c9bf08aa1510, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &6361423396692704141 --- !u!1 &6361423396692704141
GameObject: GameObject:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -100,7 +25,7 @@ RectTransform:
m_PrefabInstance: {fileID: 0} m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0} m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6361423396692704141} m_GameObject: {fileID: 6361423396692704141}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
@ -179,8 +104,9 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1} m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0 m_ConstrainProportionsScale: 0
m_Children: m_Children:
- {fileID: 8201350274026178469}
- {fileID: 28444767019028035} - {fileID: 28444767019028035}
- {fileID: 2412538576477069160}
- {fileID: 8201350274026178469}
m_Father: {fileID: 0} m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5} m_AnchorMin: {x: 0.5, y: 0.5}
@ -200,9 +126,158 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 4da5ef45ee18db44ebe3c015dddb61d6, type: 3} m_Script: {fileID: 11500000, guid: 4da5ef45ee18db44ebe3c015dddb61d6, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
_icon: {fileID: 272351400812969041} _icon: {fileID: 5411719625189444569}
_price: {fileID: 6134693184638222351} _price: {fileID: 6134693184638222351}
_button: {fileID: 8644563062325311724} _button: {fileID: 8644563062325311724}
_towerIconArea: {fileID: 7379728654387442000}
--- !u!1001 &1106531443240827291
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 274828358581623048}
m_Modifications:
- target: {fileID: 177671855419091867, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Name
value: TowerIconArea
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMax.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_SizeDelta.x
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_SizeDelta.y
value: -20
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: ab6ee7e8b2a678544af490543d99f665, type: 3}
--- !u!224 &2412538576477069160 stripped
RectTransform:
m_CorrespondingSourceObject: {fileID: 3323726282767525619, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 1106531443240827291}
m_PrefabAsset: {fileID: 0}
--- !u!114 &5411719625189444569 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 4918346613506060866, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 1106531443240827291}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &7379728654387442000 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 7579875247493712075, guid: ab6ee7e8b2a678544af490543d99f665,
type: 3}
m_PrefabInstance: {fileID: 1106531443240827291}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 33a1436bff53c844e858f3bced1565ca, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1001 &5730140866277425490 --- !u!1001 &5730140866277425490
PrefabInstance: PrefabInstance:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -216,6 +291,11 @@ PrefabInstance:
propertyPath: m_Name propertyPath: m_Name
value: CommonButton value: CommonButton
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 1341699087252484061, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_Color.a
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1920576543566152029, guid: 2307f223279813546a43b221ddd496cc, - target: {fileID: 1920576543566152029, guid: 2307f223279813546a43b221ddd496cc,
type: 3} type: 3}
propertyPath: m_text propertyPath: m_text
@ -351,34 +431,24 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z propertyPath: m_LocalEulerAnglesHint.z
value: 0 value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_AnchorMax.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_AnchorMin.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc, - target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3} type: 3}
propertyPath: m_SizeDelta.y propertyPath: m_SizeDelta.y
value: 60 value: -50.000023
objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0} objectReference: {fileID: 0}
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc, - target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
type: 3} type: 3}
propertyPath: m_AnchoredPosition.y propertyPath: m_AnchoredPosition.y
value: -80 value: -75.000015
objectReference: {fileID: 0} objectReference: {fileID: 0}
m_RemovedComponents: [] m_RemovedComponents: []
m_RemovedGameObjects: m_RemovedGameObjects: []
- {fileID: 7888786393168201163, guid: 2307f223279813546a43b221ddd496cc, type: 3} m_AddedGameObjects: []
m_AddedGameObjects:
- targetCorrespondingSourceObject: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
insertIndex: -1
addedObject: {fileID: 4152009404387722330}
m_AddedComponents: [] m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 2307f223279813546a43b221ddd496cc, type: 3} m_SourcePrefab: {fileID: 100100000, guid: 2307f223279813546a43b221ddd496cc, type: 3}
--- !u!114 &6134693184638222351 stripped --- !u!114 &6134693184638222351 stripped