feat: 패시브 트리 레이아웃 자동화 및 UI 정리
- 패시브 트리 노드 배치를 삼각형 기반 자동 배치 구조로 전환하고 축 및 브릿지 반경을 재정리\n- 패시브 UI 프리팹과 런타임 렌더링을 수정해 노드 겹침, 링크 관통, 상태별 간격 변화, 하단 여백 문제를 정리\n- 프로토타입 패시브 노드, 트리, 프리셋 자산을 재생성해 최신 레이아웃과 확장 노드 구성을 반영
This commit is contained in:
@@ -35,6 +35,7 @@ namespace Colosseum.Editor
|
||||
private static readonly Color ButtonColor = new(0.20f, 0.20f, 0.24f, 0.96f);
|
||||
private static readonly Color TextColor = new(0.90f, 0.88f, 0.82f, 1f);
|
||||
private static readonly Color NodeColor = new(0.16f, 0.16f, 0.18f, 0.98f);
|
||||
private static readonly Color NodeFillColor = new(0.08f, 0.08f, 0.10f, 0.98f);
|
||||
private static readonly Color NodeOutlineColor = new(0f, 0f, 0f, 0.45f);
|
||||
|
||||
[MenuItem("Tools/Colosseum/Passives/Rebuild Passive UI Prefabs")]
|
||||
@@ -71,7 +72,7 @@ namespace Colosseum.Editor
|
||||
try
|
||||
{
|
||||
RectTransform rect = root.GetComponent<RectTransform>();
|
||||
rect.sizeDelta = new Vector2(70f, 70f);
|
||||
rect.sizeDelta = new Vector2(62f, 62f);
|
||||
|
||||
Image background = root.GetComponent<Image>();
|
||||
background.sprite = LoadPassiveNodeSprite(false);
|
||||
@@ -86,11 +87,23 @@ namespace Colosseum.Editor
|
||||
Button button = root.GetComponent<Button>();
|
||||
button.targetGraphic = background;
|
||||
|
||||
GameObject fillObject = CreateUiObject("Fill", root.transform, typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
||||
RectTransform fillRect = fillObject.GetComponent<RectTransform>();
|
||||
StretchRect(fillRect);
|
||||
fillRect.offsetMin = new Vector2(17f, 17f);
|
||||
fillRect.offsetMax = new Vector2(-17f, -17f);
|
||||
|
||||
Image fillImage = fillObject.GetComponent<Image>();
|
||||
fillImage.sprite = GetBuiltinSprite();
|
||||
fillImage.type = Image.Type.Sliced;
|
||||
fillImage.color = NodeFillColor;
|
||||
fillImage.raycastTarget = false;
|
||||
|
||||
GameObject innerObject = CreateUiObject("InnerIcon", root.transform, typeof(RectTransform), typeof(CanvasRenderer), typeof(Image));
|
||||
RectTransform innerRect = innerObject.GetComponent<RectTransform>();
|
||||
StretchRect(innerRect);
|
||||
innerRect.offsetMin = new Vector2(10f, 10f);
|
||||
innerRect.offsetMax = new Vector2(-10f, -10f);
|
||||
innerRect.offsetMin = new Vector2(9f, 9f);
|
||||
innerRect.offsetMax = new Vector2(-9f, -9f);
|
||||
|
||||
Image innerImage = innerObject.GetComponent<Image>();
|
||||
innerImage.sprite = LoadPassiveNodeSprite(false);
|
||||
@@ -102,6 +115,7 @@ namespace Colosseum.Editor
|
||||
PassiveTreeNodeView references = root.GetComponent<PassiveTreeNodeView>();
|
||||
SetSerializedReference(references, "rootRect", rect);
|
||||
SetSerializedReference(references, "backgroundImage", background);
|
||||
SetSerializedReference(references, "fillImage", fillImage);
|
||||
SetSerializedReference(references, "innerImage", innerImage);
|
||||
SetSerializedReference(references, "button", button);
|
||||
SetSerializedReference(references, "outline", outline);
|
||||
@@ -143,7 +157,7 @@ namespace Colosseum.Editor
|
||||
panelRect.anchorMin = new Vector2(0.5f, 0.5f);
|
||||
panelRect.anchorMax = new Vector2(0.5f, 0.5f);
|
||||
panelRect.pivot = new Vector2(0.5f, 0.5f);
|
||||
panelRect.sizeDelta = new Vector2(1380f, 820f);
|
||||
panelRect.sizeDelta = new Vector2(1440f, 900f);
|
||||
|
||||
Image panelImage = panelObject.GetComponent<Image>();
|
||||
panelImage.sprite = GetBuiltinSprite();
|
||||
@@ -308,14 +322,14 @@ namespace Colosseum.Editor
|
||||
|
||||
RectTransform graphSection = CreateSectionRoot(bodyObject.transform, "Section_Graph", 0f);
|
||||
graphSection.GetComponent<LayoutElement>().flexibleWidth = 1f;
|
||||
graphSection.GetComponent<LayoutElement>().minWidth = 760f;
|
||||
graphSection.GetComponent<LayoutElement>().minWidth = 820f;
|
||||
CreateSectionTitle(graphSection, "트리 그래프");
|
||||
|
||||
GameObject graphSurface = CreateUiObject("GraphSurface", graphSection, typeof(RectTransform), typeof(LayoutElement), typeof(Image));
|
||||
graphRect = graphSurface.GetComponent<RectTransform>();
|
||||
LayoutElement graphLayout = graphSurface.GetComponent<LayoutElement>();
|
||||
graphLayout.flexibleHeight = 1f;
|
||||
graphLayout.minHeight = 560f;
|
||||
graphLayout.minHeight = 640f;
|
||||
|
||||
Image graphImage = graphSurface.GetComponent<Image>();
|
||||
graphImage.sprite = GetBuiltinSprite();
|
||||
@@ -385,7 +399,7 @@ namespace Colosseum.Editor
|
||||
statusText.text = string.Empty;
|
||||
statusText.textWrappingMode = TextWrappingModes.NoWrap;
|
||||
statusText.overflowMode = TextOverflowModes.Ellipsis;
|
||||
footerObject.SetActive(false);
|
||||
footerObject.SetActive(true);
|
||||
}
|
||||
|
||||
private static RectTransform CreateSectionRoot(Transform parent, string name, float preferredWidth)
|
||||
|
||||
@@ -32,18 +32,35 @@ namespace Colosseum.Editor
|
||||
|
||||
private const string HubNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Hub.asset";
|
||||
private const string DefenseEntryNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Tank_Entry.asset";
|
||||
private const string DefenseFrameNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Tank_Frame.asset";
|
||||
private const string DefenseGuardNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Tank_Guard.asset";
|
||||
private const string DefenseResolveNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Tank_Resolve.asset";
|
||||
private const string DefenseCoreNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Tank_Core.asset";
|
||||
private const string DefenseCapstoneNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Tank_Capstone.asset";
|
||||
private const string SupportEntryNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Support_Entry.asset";
|
||||
private const string SupportInsightNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Support_Insight.asset";
|
||||
private const string SupportWellNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Support_Well.asset";
|
||||
private const string SupportFocusNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Support_Focus.asset";
|
||||
private const string SupportCoreNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Support_Core.asset";
|
||||
private const string SupportCapstoneNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Support_Capstone.asset";
|
||||
private const string AttackEntryNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Dps_Entry.asset";
|
||||
private const string AttackStrengthNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Dps_Strength.asset";
|
||||
private const string AttackPrecisionNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Dps_Precision.asset";
|
||||
private const string AttackArcanaNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Dps_Arcana.asset";
|
||||
private const string AttackCoreNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Dps_Core.asset";
|
||||
private const string AttackCapstoneNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_Dps_Capstone.asset";
|
||||
private const string AttackDefenseBridgeNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_AttackDefense_Bridge.asset";
|
||||
private const string DefenseSupportBridgeNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_DefenseSupport_Bridge.asset";
|
||||
private const string SupportAttackBridgeNodeAssetPath = PassiveNodeFolderPath + "/Data_PassiveNode_Player_SupportAttack_Bridge.asset";
|
||||
|
||||
private const float AxisEntryRadius = 0.24f;
|
||||
private const float AxisCoreRadius = 0.56f;
|
||||
private const float AxisOuterStatRadius = 0.88f;
|
||||
private const float AxisCenterStatRadius = 0.78f;
|
||||
private const float AxisCapstoneRadius = 1.0f;
|
||||
private const float AxisStatSideOffset = 0.32f;
|
||||
private const float BridgeRadius = 0.70f;
|
||||
|
||||
[MenuItem("Tools/Colosseum/Debug/Passive/Bootstrap Prototype Assets")]
|
||||
private static void BootstrapPrototypeAssets()
|
||||
{
|
||||
@@ -54,23 +71,61 @@ namespace Colosseum.Editor
|
||||
|
||||
PassiveNodeData hubNode = CreateOrLoadNode(HubNodeAssetPath);
|
||||
PassiveNodeData defenseEntryNode = CreateOrLoadNode(DefenseEntryNodeAssetPath);
|
||||
PassiveNodeData defenseFrameNode = CreateOrLoadNode(DefenseFrameNodeAssetPath);
|
||||
PassiveNodeData defenseGuardNode = CreateOrLoadNode(DefenseGuardNodeAssetPath);
|
||||
PassiveNodeData defenseResolveNode = CreateOrLoadNode(DefenseResolveNodeAssetPath);
|
||||
PassiveNodeData defenseCoreNode = CreateOrLoadNode(DefenseCoreNodeAssetPath);
|
||||
PassiveNodeData defenseCapstoneNode = CreateOrLoadNode(DefenseCapstoneNodeAssetPath);
|
||||
PassiveNodeData supportEntryNode = CreateOrLoadNode(SupportEntryNodeAssetPath);
|
||||
PassiveNodeData supportInsightNode = CreateOrLoadNode(SupportInsightNodeAssetPath);
|
||||
PassiveNodeData supportWellNode = CreateOrLoadNode(SupportWellNodeAssetPath);
|
||||
PassiveNodeData supportFocusNode = CreateOrLoadNode(SupportFocusNodeAssetPath);
|
||||
PassiveNodeData supportCoreNode = CreateOrLoadNode(SupportCoreNodeAssetPath);
|
||||
PassiveNodeData supportCapstoneNode = CreateOrLoadNode(SupportCapstoneNodeAssetPath);
|
||||
PassiveNodeData attackEntryNode = CreateOrLoadNode(AttackEntryNodeAssetPath);
|
||||
PassiveNodeData attackStrengthNode = CreateOrLoadNode(AttackStrengthNodeAssetPath);
|
||||
PassiveNodeData attackPrecisionNode = CreateOrLoadNode(AttackPrecisionNodeAssetPath);
|
||||
PassiveNodeData attackArcanaNode = CreateOrLoadNode(AttackArcanaNodeAssetPath);
|
||||
PassiveNodeData attackCoreNode = CreateOrLoadNode(AttackCoreNodeAssetPath);
|
||||
PassiveNodeData attackCapstoneNode = CreateOrLoadNode(AttackCapstoneNodeAssetPath);
|
||||
PassiveNodeData attackDefenseBridgeNode = CreateOrLoadNode(AttackDefenseBridgeNodeAssetPath);
|
||||
PassiveNodeData defenseSupportBridgeNode = CreateOrLoadNode(DefenseSupportBridgeNodeAssetPath);
|
||||
PassiveNodeData supportAttackBridgeNode = CreateOrLoadNode(SupportAttackBridgeNodeAssetPath);
|
||||
|
||||
Vector2 attackDirection = Vector2.up;
|
||||
Vector2 defenseDirection = RotateLayout(Vector2.up, 120f);
|
||||
Vector2 supportDirection = RotateLayout(Vector2.up, -120f);
|
||||
|
||||
Vector2 attackEntryPosition = BuildAxisLayoutPosition(attackDirection, AxisEntryRadius);
|
||||
Vector2 attackCorePosition = BuildAxisLayoutPosition(attackDirection, AxisCoreRadius);
|
||||
Vector2 attackStrengthPosition = BuildAxisLayoutPosition(attackDirection, AxisOuterStatRadius, AxisStatSideOffset);
|
||||
Vector2 attackPrecisionPosition = BuildAxisLayoutPosition(attackDirection, AxisCenterStatRadius);
|
||||
Vector2 attackArcanaPosition = BuildAxisLayoutPosition(attackDirection, AxisOuterStatRadius, -AxisStatSideOffset);
|
||||
Vector2 attackCapstonePosition = BuildAxisLayoutPosition(attackDirection, AxisCapstoneRadius);
|
||||
|
||||
Vector2 defenseEntryPosition = BuildAxisLayoutPosition(defenseDirection, AxisEntryRadius);
|
||||
Vector2 defenseCorePosition = BuildAxisLayoutPosition(defenseDirection, AxisCoreRadius);
|
||||
Vector2 defenseFramePosition = BuildAxisLayoutPosition(defenseDirection, AxisOuterStatRadius, AxisStatSideOffset);
|
||||
Vector2 defenseResolvePosition = BuildAxisLayoutPosition(defenseDirection, AxisCenterStatRadius);
|
||||
Vector2 defenseGuardPosition = BuildAxisLayoutPosition(defenseDirection, AxisOuterStatRadius, -AxisStatSideOffset);
|
||||
Vector2 defenseCapstonePosition = BuildAxisLayoutPosition(defenseDirection, AxisCapstoneRadius);
|
||||
|
||||
Vector2 supportEntryPosition = BuildAxisLayoutPosition(supportDirection, AxisEntryRadius);
|
||||
Vector2 supportCorePosition = BuildAxisLayoutPosition(supportDirection, AxisCoreRadius);
|
||||
Vector2 supportInsightPosition = BuildAxisLayoutPosition(supportDirection, AxisOuterStatRadius, AxisStatSideOffset);
|
||||
Vector2 supportWellPosition = BuildAxisLayoutPosition(supportDirection, AxisCenterStatRadius);
|
||||
Vector2 supportFocusPosition = BuildAxisLayoutPosition(supportDirection, AxisOuterStatRadius, -AxisStatSideOffset);
|
||||
Vector2 supportCapstonePosition = BuildAxisLayoutPosition(supportDirection, AxisCapstoneRadius);
|
||||
|
||||
Vector2 attackDefenseBridgePosition = RotateLayout(Vector2.up * BridgeRadius, 60f);
|
||||
Vector2 defenseSupportBridgePosition = RotateLayout(Vector2.up * BridgeRadius, 180f);
|
||||
Vector2 supportAttackBridgePosition = RotateLayout(Vector2.up * BridgeRadius, -60f);
|
||||
|
||||
ConfigureNode(
|
||||
hubNode,
|
||||
"hub",
|
||||
"중심 허브",
|
||||
"패시브 트리의 시작점입니다.",
|
||||
string.Empty,
|
||||
string.Empty,
|
||||
PassiveNodeBranch.Common,
|
||||
PassiveNodeKind.Hub,
|
||||
PassiveAxisMask.None,
|
||||
@@ -91,14 +146,68 @@ namespace Colosseum.Editor
|
||||
PassiveAxisMask.Attack,
|
||||
1,
|
||||
1,
|
||||
new Vector2(0f, 0.34f),
|
||||
attackEntryPosition,
|
||||
new[] { hubNode },
|
||||
new[] { hubNode, attackCoreNode, attackDefenseBridgeNode, supportAttackBridgeNode },
|
||||
new[] { hubNode, attackCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Strength, StatModType.PercentAdd, 0.1f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Dexterity, StatModType.PercentAdd, 0.1f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Intelligence, StatModType.PercentAdd, 0.1f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Strength, StatModType.PercentAdd, 0.05f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Dexterity, StatModType.PercentAdd, 0.05f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Intelligence, StatModType.PercentAdd, 0.05f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
attackStrengthNode,
|
||||
"attack_strength",
|
||||
"근력 단련",
|
||||
"직접적인 무기 화력을 높이기 위한 힘의 기반을 다집니다.",
|
||||
PassiveNodeBranch.Attack,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Attack,
|
||||
2,
|
||||
1,
|
||||
attackStrengthPosition,
|
||||
new[] { attackCoreNode },
|
||||
new[] { attackCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Strength, StatModType.Flat, 4f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
attackPrecisionNode,
|
||||
"attack_precision",
|
||||
"민첩 연마",
|
||||
"정확한 움직임과 타격 빈도를 위해 민첩을 끌어올립니다.",
|
||||
PassiveNodeBranch.Attack,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Attack,
|
||||
2,
|
||||
1,
|
||||
attackPrecisionPosition,
|
||||
new[] { attackCoreNode },
|
||||
new[] { attackCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Dexterity, StatModType.Flat, 4f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
attackArcanaNode,
|
||||
"attack_arcana",
|
||||
"지능 예열",
|
||||
"공세 축에서도 주문 계열 화력을 포기하지 않도록 지능 기반을 보강합니다.",
|
||||
PassiveNodeBranch.Attack,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Attack,
|
||||
2,
|
||||
1,
|
||||
attackArcanaPosition,
|
||||
new[] { attackCoreNode },
|
||||
new[] { attackCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Intelligence, StatModType.Flat, 4f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
@@ -109,14 +218,14 @@ namespace Colosseum.Editor
|
||||
PassiveNodeBranch.Attack,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Attack,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
new Vector2(0f, 0.6f),
|
||||
attackCorePosition,
|
||||
new[] { attackEntryNode },
|
||||
new[] { attackEntryNode, attackCapstoneNode },
|
||||
new[] { attackEntryNode, attackStrengthNode, attackPrecisionNode, attackArcanaNode, attackCapstoneNode, attackDefenseBridgeNode, supportAttackBridgeNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.DamageMultiplier, 1.12f, SkillRoleType.Attack),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.DamageMultiplier, 1.10f, SkillRoleType.Attack),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
@@ -127,15 +236,15 @@ namespace Colosseum.Editor
|
||||
PassiveNodeBranch.Attack,
|
||||
PassiveNodeKind.Capstone,
|
||||
PassiveAxisMask.Attack,
|
||||
3,
|
||||
4,
|
||||
2,
|
||||
new Vector2(0f, 0.84f),
|
||||
attackCapstonePosition,
|
||||
new[] { attackCoreNode },
|
||||
new[] { attackCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.DamageMultiplier, 1.10f, SkillRoleType.Attack),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ManaCostMultiplier, 0.90f, SkillRoleType.Attack),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.DamageMultiplier, 1.08f, SkillRoleType.Attack),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ManaCostMultiplier, 0.92f, SkillRoleType.Attack),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
@@ -148,12 +257,66 @@ namespace Colosseum.Editor
|
||||
PassiveAxisMask.Defense,
|
||||
1,
|
||||
1,
|
||||
new Vector2(-0.34f, -0.1f),
|
||||
defenseEntryPosition,
|
||||
new[] { hubNode },
|
||||
new[] { hubNode, defenseCoreNode, attackDefenseBridgeNode, defenseSupportBridgeNode },
|
||||
new[] { hubNode, defenseCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Vitality, StatModType.PercentAdd, 0.2f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Vitality, StatModType.PercentAdd, 0.10f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
defenseFrameNode,
|
||||
"defense_frame",
|
||||
"활력 축적",
|
||||
"방어 축의 기본 체력을 두텁게 확보합니다.",
|
||||
PassiveNodeBranch.Defense,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Defense,
|
||||
2,
|
||||
1,
|
||||
defenseFramePosition,
|
||||
new[] { defenseCoreNode },
|
||||
new[] { defenseCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Vitality, StatModType.Flat, 6f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
defenseGuardNode,
|
||||
"defense_guard",
|
||||
"굳센 육체",
|
||||
"기본 활력을 비율로 증폭해 전투 지속력을 높입니다.",
|
||||
PassiveNodeBranch.Defense,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Defense,
|
||||
2,
|
||||
1,
|
||||
defenseGuardPosition,
|
||||
new[] { defenseCoreNode },
|
||||
new[] { defenseCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Vitality, StatModType.PercentAdd, 0.12f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
defenseResolveNode,
|
||||
"defense_resolve",
|
||||
"전투 호흡",
|
||||
"전열에서 스킬을 굴릴 여유를 위해 정신을 함께 보강합니다.",
|
||||
PassiveNodeBranch.Defense,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Defense,
|
||||
2,
|
||||
1,
|
||||
defenseResolvePosition,
|
||||
new[] { defenseCoreNode },
|
||||
new[] { defenseCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Spirit, StatModType.Flat, 4f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
@@ -164,15 +327,15 @@ namespace Colosseum.Editor
|
||||
PassiveNodeBranch.Defense,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Defense,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
new Vector2(-0.58f, -0.34f),
|
||||
defenseCorePosition,
|
||||
new[] { defenseEntryNode },
|
||||
new[] { defenseEntryNode, defenseCapstoneNode },
|
||||
new[] { defenseEntryNode, defenseFrameNode, defenseGuardNode, defenseResolveNode, defenseCapstoneNode, attackDefenseBridgeNode, defenseSupportBridgeNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ThreatGeneratedMultiplier, 1.30f),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ShieldReceivedMultiplier, 1.15f),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ThreatGeneratedMultiplier, 1.25f),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ShieldReceivedMultiplier, 1.10f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
@@ -183,14 +346,14 @@ namespace Colosseum.Editor
|
||||
PassiveNodeBranch.Defense,
|
||||
PassiveNodeKind.Capstone,
|
||||
PassiveAxisMask.Defense,
|
||||
3,
|
||||
4,
|
||||
2,
|
||||
new Vector2(-0.82f, -0.58f),
|
||||
defenseCapstonePosition,
|
||||
new[] { defenseCoreNode },
|
||||
new[] { defenseCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.IncomingDamageMultiplier, 0.88f),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.IncomingDamageMultiplier, 0.90f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
@@ -203,12 +366,66 @@ namespace Colosseum.Editor
|
||||
PassiveAxisMask.Support,
|
||||
1,
|
||||
1,
|
||||
new Vector2(0.34f, -0.1f),
|
||||
supportEntryPosition,
|
||||
new[] { hubNode },
|
||||
new[] { hubNode, supportCoreNode, defenseSupportBridgeNode, supportAttackBridgeNode },
|
||||
new[] { hubNode, supportCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Wisdom, StatModType.PercentAdd, 0.2f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Wisdom, StatModType.PercentAdd, 0.10f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
supportInsightNode,
|
||||
"support_insight",
|
||||
"지혜 응축",
|
||||
"회복량의 기초가 되는 지혜를 직접 보강합니다.",
|
||||
PassiveNodeBranch.Support,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Support,
|
||||
2,
|
||||
1,
|
||||
supportInsightPosition,
|
||||
new[] { supportCoreNode },
|
||||
new[] { supportCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Wisdom, StatModType.Flat, 4f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
supportWellNode,
|
||||
"support_well",
|
||||
"정신 샘",
|
||||
"지원 축 운용을 위해 마나 기반을 단단히 합니다.",
|
||||
PassiveNodeBranch.Support,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Support,
|
||||
2,
|
||||
1,
|
||||
supportWellPosition,
|
||||
new[] { supportCoreNode },
|
||||
new[] { supportCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Spirit, StatModType.Flat, 6f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
supportFocusNode,
|
||||
"support_focus",
|
||||
"집중 순환",
|
||||
"지속적인 보조를 위해 정신을 비율로 확장합니다.",
|
||||
PassiveNodeBranch.Support,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Support,
|
||||
2,
|
||||
1,
|
||||
supportFocusPosition,
|
||||
new[] { supportCoreNode },
|
||||
new[] { supportCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Spirit, StatModType.PercentAdd, 0.12f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
@@ -219,15 +436,15 @@ namespace Colosseum.Editor
|
||||
PassiveNodeBranch.Support,
|
||||
PassiveNodeKind.Axis,
|
||||
PassiveAxisMask.Support,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
new Vector2(0.58f, -0.34f),
|
||||
supportCorePosition,
|
||||
new[] { supportEntryNode },
|
||||
new[] { supportEntryNode, supportCapstoneNode },
|
||||
new[] { supportEntryNode, supportInsightNode, supportWellNode, supportFocusNode, supportCapstoneNode, defenseSupportBridgeNode, supportAttackBridgeNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.HealMultiplier, 1.15f, SkillRoleType.Support),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ShieldDoneMultiplier, 1.15f, SkillRoleType.Support),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.HealMultiplier, 1.12f, SkillRoleType.Support),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ShieldDoneMultiplier, 1.12f, SkillRoleType.Support),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
@@ -238,72 +455,72 @@ namespace Colosseum.Editor
|
||||
PassiveNodeBranch.Support,
|
||||
PassiveNodeKind.Capstone,
|
||||
PassiveAxisMask.Support,
|
||||
3,
|
||||
4,
|
||||
2,
|
||||
new Vector2(0.82f, -0.58f),
|
||||
supportCapstonePosition,
|
||||
new[] { supportCoreNode },
|
||||
new[] { supportCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateStat(StatType.Spirit, StatModType.PercentAdd, 0.2f),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ManaCostMultiplier, 0.85f, SkillRoleType.Support),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ManaCostMultiplier, 0.88f, SkillRoleType.Support),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ShieldDoneMultiplier, 1.08f, SkillRoleType.Support),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
attackDefenseBridgeNode,
|
||||
"attack_defense_bridge",
|
||||
"압박 방벽",
|
||||
"공격과 방어를 연결하는 브릿지로, 압박 유지력과 전투 안정성을 함께 챙깁니다.",
|
||||
"공격과 방어를 연결하는 브릿지로, 힘과 활력을 함께 보강합니다.",
|
||||
PassiveNodeBranch.Bridge,
|
||||
PassiveNodeKind.Bridge,
|
||||
PassiveAxisMask.Attack | PassiveAxisMask.Defense,
|
||||
2,
|
||||
1,
|
||||
new Vector2(-0.24f, 0.14f),
|
||||
new[] { attackEntryNode, defenseEntryNode },
|
||||
new[] { attackEntryNode, defenseEntryNode },
|
||||
attackDefenseBridgePosition,
|
||||
new[] { attackCoreNode },
|
||||
new[] { attackCoreNode, defenseCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.DamageMultiplier, 1.06f, SkillRoleType.Attack),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.IncomingDamageMultiplier, 0.95f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Strength, StatModType.Flat, 3f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Vitality, StatModType.Flat, 3f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
defenseSupportBridgeNode,
|
||||
"defense_support_bridge",
|
||||
"수호 순환",
|
||||
"방어와 지원을 연결하는 브릿지로, 보호막과 회복 기여를 함께 끌어올립니다.",
|
||||
"방어와 지원을 연결하는 브릿지로, 활력과 지혜를 함께 끌어올립니다.",
|
||||
PassiveNodeBranch.Bridge,
|
||||
PassiveNodeKind.Bridge,
|
||||
PassiveAxisMask.Defense | PassiveAxisMask.Support,
|
||||
2,
|
||||
1,
|
||||
new Vector2(0f, -0.28f),
|
||||
new[] { defenseEntryNode, supportEntryNode },
|
||||
new[] { defenseEntryNode, supportEntryNode },
|
||||
defenseSupportBridgePosition,
|
||||
new[] { defenseCoreNode },
|
||||
new[] { defenseCoreNode, supportCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ShieldReceivedMultiplier, 1.10f),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.HealMultiplier, 1.08f, SkillRoleType.Support),
|
||||
PassiveEffectConfig.CreateStat(StatType.Vitality, StatModType.Flat, 3f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Wisdom, StatModType.Flat, 3f),
|
||||
});
|
||||
|
||||
ConfigureNode(
|
||||
supportAttackBridgeNode,
|
||||
"support_attack_bridge",
|
||||
"전술 증폭",
|
||||
"지원과 공격을 연결하는 브릿지로, 화력과 유지 효율을 함께 보조합니다.",
|
||||
"지원과 공격을 연결하는 브릿지로, 지혜와 지능 기반을 함께 높입니다.",
|
||||
PassiveNodeBranch.Bridge,
|
||||
PassiveNodeKind.Bridge,
|
||||
PassiveAxisMask.Support | PassiveAxisMask.Attack,
|
||||
2,
|
||||
1,
|
||||
new Vector2(0.24f, 0.14f),
|
||||
new[] { supportEntryNode, attackEntryNode },
|
||||
new[] { supportEntryNode, attackEntryNode },
|
||||
supportAttackBridgePosition,
|
||||
new[] { supportCoreNode },
|
||||
new[] { supportCoreNode, attackCoreNode },
|
||||
new[]
|
||||
{
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.DamageMultiplier, 1.06f, SkillRoleType.Attack),
|
||||
PassiveEffectConfig.CreateScalar(PassiveEffectType.ManaCostMultiplier, 0.95f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Wisdom, StatModType.Flat, 3f),
|
||||
PassiveEffectConfig.CreateStat(StatType.Intelligence, StatModType.Flat, 3f),
|
||||
});
|
||||
|
||||
PassiveTreeData tree = CreateOrLoadTree();
|
||||
@@ -311,18 +528,27 @@ namespace Colosseum.Editor
|
||||
tree,
|
||||
"player_prototype_tree",
|
||||
"플레이어 패시브 프로토타입",
|
||||
"공격 / 방어 / 지원 3축과 브릿지 노드로 구성된 드로그전 밸런싱 검증용 트리입니다.",
|
||||
8,
|
||||
"공격 / 방어 / 지원 3축에 다수의 스탯 노드와 연결 노드를 배치한 드로그전 밸런싱 검증용 트리입니다.",
|
||||
12,
|
||||
new[]
|
||||
{
|
||||
hubNode,
|
||||
attackEntryNode,
|
||||
attackStrengthNode,
|
||||
attackPrecisionNode,
|
||||
attackArcanaNode,
|
||||
attackCoreNode,
|
||||
attackCapstoneNode,
|
||||
defenseEntryNode,
|
||||
defenseFrameNode,
|
||||
defenseGuardNode,
|
||||
defenseResolveNode,
|
||||
defenseCoreNode,
|
||||
defenseCapstoneNode,
|
||||
supportEntryNode,
|
||||
supportInsightNode,
|
||||
supportWellNode,
|
||||
supportFocusNode,
|
||||
supportCoreNode,
|
||||
supportCapstoneNode,
|
||||
attackDefenseBridgeNode,
|
||||
@@ -340,52 +566,64 @@ namespace Colosseum.Editor
|
||||
CreateOrUpdatePreset(
|
||||
DefensePresetAssetPath,
|
||||
"방어형 패시브",
|
||||
"방어 축 완성과 함께 공격/지원 브릿지를 가볍게 여는 프리셋입니다.",
|
||||
"방어 축의 스탯 노드와 핵심 유지 노드를 우선 확보하는 프리셋입니다.",
|
||||
tree,
|
||||
new[]
|
||||
{
|
||||
hubNode,
|
||||
defenseEntryNode,
|
||||
defenseCoreNode,
|
||||
defenseFrameNode,
|
||||
defenseGuardNode,
|
||||
defenseResolveNode,
|
||||
defenseCapstoneNode,
|
||||
attackEntryNode,
|
||||
attackCoreNode,
|
||||
supportEntryNode,
|
||||
attackDefenseBridgeNode,
|
||||
defenseSupportBridgeNode,
|
||||
supportCoreNode,
|
||||
});
|
||||
|
||||
CreateOrUpdatePreset(
|
||||
SupportPresetAssetPath,
|
||||
"지원형 패시브",
|
||||
"지원 축 완성과 함께 공격/방어 브릿지를 가볍게 여는 프리셋입니다.",
|
||||
"지원 축의 스탯 노드와 유지 효율 노드를 우선 확보하는 프리셋입니다.",
|
||||
tree,
|
||||
new[]
|
||||
{
|
||||
hubNode,
|
||||
supportEntryNode,
|
||||
supportCoreNode,
|
||||
supportInsightNode,
|
||||
supportWellNode,
|
||||
supportFocusNode,
|
||||
supportCapstoneNode,
|
||||
defenseEntryNode,
|
||||
defenseCoreNode,
|
||||
attackEntryNode,
|
||||
defenseSupportBridgeNode,
|
||||
supportAttackBridgeNode,
|
||||
attackCoreNode,
|
||||
});
|
||||
|
||||
CreateOrUpdatePreset(
|
||||
AttackPresetAssetPath,
|
||||
"공격형 패시브",
|
||||
"공격 축 완성과 함께 방어/지원 브릿지를 가볍게 여는 프리셋입니다.",
|
||||
"공격 축의 스탯 노드와 화력 노드를 우선 확보하는 프리셋입니다.",
|
||||
tree,
|
||||
new[]
|
||||
{
|
||||
hubNode,
|
||||
attackEntryNode,
|
||||
attackCoreNode,
|
||||
attackStrengthNode,
|
||||
attackPrecisionNode,
|
||||
attackArcanaNode,
|
||||
attackCapstoneNode,
|
||||
defenseEntryNode,
|
||||
defenseCoreNode,
|
||||
supportEntryNode,
|
||||
attackDefenseBridgeNode,
|
||||
supportAttackBridgeNode,
|
||||
supportCoreNode,
|
||||
});
|
||||
|
||||
PassivePrototypeCatalogData catalog = CreateOrLoadCatalog();
|
||||
@@ -643,6 +881,29 @@ namespace Colosseum.Editor
|
||||
EditorUtility.SetDirty(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 기준 축 템플릿 좌표를 실제 축 방향으로 회전합니다.
|
||||
/// </summary>
|
||||
private static Vector2 BuildAxisLayoutPosition(Vector2 axisDirection, float radialDistance, float lateralOffset = 0f)
|
||||
{
|
||||
Vector2 normalizedDirection = axisDirection.normalized;
|
||||
Vector2 perpendicularDirection = new Vector2(-normalizedDirection.y, normalizedDirection.x);
|
||||
return normalizedDirection * radialDistance + perpendicularDirection * lateralOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 2D 평면 좌표를 각도 기준으로 회전합니다.
|
||||
/// </summary>
|
||||
private static Vector2 RotateLayout(Vector2 value, float degrees)
|
||||
{
|
||||
float radians = degrees * Mathf.Deg2Rad;
|
||||
float cosine = Mathf.Cos(radians);
|
||||
float sine = Mathf.Sin(radians);
|
||||
return new Vector2(
|
||||
value.x * cosine - value.y * sine,
|
||||
value.x * sine + value.y * cosine);
|
||||
}
|
||||
|
||||
private static void CreateOrUpdatePreset(
|
||||
string assetPath,
|
||||
string presetName,
|
||||
|
||||
@@ -10,12 +10,14 @@ namespace Colosseum.UI
|
||||
{
|
||||
[SerializeField] private RectTransform rootRect;
|
||||
[SerializeField] private Image backgroundImage;
|
||||
[SerializeField] private Image fillImage;
|
||||
[SerializeField] private Image innerImage;
|
||||
[SerializeField] private Button button;
|
||||
[SerializeField] private Outline outline;
|
||||
|
||||
public RectTransform RootRect => rootRect;
|
||||
public Image BackgroundImage => backgroundImage;
|
||||
public Image FillImage => fillImage;
|
||||
public Image InnerImage => innerImage;
|
||||
public Button Button => button;
|
||||
public Outline Outline => outline;
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace Colosseum.UI
|
||||
public RectTransform RectTransform;
|
||||
public Button Button;
|
||||
public Image Image;
|
||||
public Image FillImage;
|
||||
public Image InnerImage;
|
||||
public Outline Outline;
|
||||
}
|
||||
@@ -69,9 +70,10 @@ namespace Colosseum.UI
|
||||
[SerializeField] private Color statusErrorColor = new Color(1f, 0.52f, 0.45f, 1f);
|
||||
[SerializeField] private Color lineColor = new Color(0.72f, 0.67f, 0.53f, 0.4f);
|
||||
[SerializeField] private Color activeLineColor = new Color(0.98f, 0.9f, 0.7f, 0.92f);
|
||||
[SerializeField] private float graphCenterYOffset = -118f;
|
||||
private const float LeftPanelWidth = 292f;
|
||||
private const float RightPanelWidth = 308f;
|
||||
private const float GraphPadding = 52f;
|
||||
private const float GraphPadding = 24f;
|
||||
private const float ConnectionThickness = 7f;
|
||||
|
||||
private readonly Dictionary<PassiveNodeData, NodeVisual> nodeVisuals = new();
|
||||
@@ -399,8 +401,8 @@ namespace Colosseum.UI
|
||||
|
||||
Rect canvasRect = canvasRectTransform.rect;
|
||||
panelRectTransform.sizeDelta = new Vector2(
|
||||
Mathf.Max(1120f, canvasRect.width - 48f),
|
||||
Mathf.Max(680f, canvasRect.height - 48f));
|
||||
Mathf.Max(1160f, canvasRect.width - 24f),
|
||||
Mathf.Max(720f, canvasRect.height - 24f));
|
||||
}
|
||||
|
||||
private void CreateToggleButton()
|
||||
@@ -884,6 +886,11 @@ namespace Colosseum.UI
|
||||
image.sprite = GetNodeSprite(node);
|
||||
image.type = Image.Type.Simple;
|
||||
image.preserveAspect = true;
|
||||
Image fillImage = nodeView.FillImage;
|
||||
if (fillImage != null)
|
||||
{
|
||||
fillImage.type = Image.Type.Sliced;
|
||||
}
|
||||
Image innerImage = nodeView.InnerImage;
|
||||
if (innerImage != null)
|
||||
{
|
||||
@@ -913,6 +920,7 @@ namespace Colosseum.UI
|
||||
RectTransform = rectTransform,
|
||||
Button = button,
|
||||
Image = image,
|
||||
FillImage = fillImage,
|
||||
InnerImage = innerImage,
|
||||
Outline = nodeView.Outline != null ? nodeView.Outline : button.GetComponent<Outline>(),
|
||||
};
|
||||
@@ -943,7 +951,11 @@ namespace Colosseum.UI
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.AppendLine($"<size=30><b>{focusedNode.DisplayName}</b></size>");
|
||||
if (!string.IsNullOrWhiteSpace(focusedNode.DisplayName))
|
||||
{
|
||||
builder.AppendLine($"<size=30><b>{focusedNode.DisplayName}</b></size>");
|
||||
}
|
||||
|
||||
builder.AppendLine($"<size=18>{PassivePresentationUtility.GetBranchLabel(focusedNode.Branch)} | {PassivePresentationUtility.GetNodeKindLabel(focusedNode.NodeKind)} | 축 {PassivePresentationUtility.GetAxisSummary(focusedNode.AxisMask)}</size>");
|
||||
builder.AppendLine($"<size=18>비용 {focusedNode.Cost}</size>");
|
||||
|
||||
@@ -1091,12 +1103,16 @@ namespace Colosseum.UI
|
||||
visual.Button.interactable = true;
|
||||
visual.Image.sprite = GetNodeSprite(node);
|
||||
visual.Image.color = fillColor;
|
||||
if (visual.FillImage != null)
|
||||
{
|
||||
visual.FillImage.color = GetNodeFillColor(selected, selectable, focused);
|
||||
}
|
||||
if (visual.InnerImage != null)
|
||||
{
|
||||
visual.InnerImage.sprite = GetInnerNodeSprite();
|
||||
visual.InnerImage.color = GetInnerNodeColor(selected, selectable, focused);
|
||||
}
|
||||
visual.RectTransform.localScale = selected ? new Vector3(1.05f, 1.05f, 1f) : focused ? new Vector3(1.03f, 1.03f, 1f) : Vector3.one;
|
||||
visual.RectTransform.localScale = Vector3.one;
|
||||
|
||||
Outline outline = visual.Outline != null ? visual.Outline : visual.Button.GetComponent<Outline>();
|
||||
if (outline == null)
|
||||
@@ -1125,12 +1141,11 @@ namespace Colosseum.UI
|
||||
private Vector2 GetGraphAnchoredPosition(Vector2 layoutPosition)
|
||||
{
|
||||
Rect rect = graphRectTransform != null ? graphRectTransform.rect : new Rect(0f, 0f, 640f, 480f);
|
||||
float halfWidth = Mathf.Max(0f, rect.width * 0.5f - GraphPadding);
|
||||
float halfHeight = Mathf.Max(0f, rect.height * 0.5f - GraphPadding);
|
||||
float halfExtent = Mathf.Max(0f, Mathf.Min(rect.width, rect.height) * 0.5f - GraphPadding);
|
||||
|
||||
return new Vector2(
|
||||
Mathf.Clamp(layoutPosition.x, -1f, 1f) * halfWidth,
|
||||
Mathf.Clamp(layoutPosition.y, -1f, 1f) * halfHeight);
|
||||
Mathf.Clamp(layoutPosition.x, -1f, 1f) * halfExtent,
|
||||
Mathf.Clamp(layoutPosition.y, -1f, 1f) * halfExtent + graphCenterYOffset);
|
||||
}
|
||||
|
||||
private static string BuildConnectionKey(PassiveNodeData leftNode, PassiveNodeData rightNode)
|
||||
@@ -1142,7 +1157,7 @@ namespace Colosseum.UI
|
||||
|
||||
private Sprite GetNodeSprite(PassiveNodeData node)
|
||||
{
|
||||
bool useSpecialSprite = node != null && (node.NodeKind == PassiveNodeKind.Hub || node.NodeKind == PassiveNodeKind.Bridge || node.NodeKind == PassiveNodeKind.Capstone);
|
||||
bool useSpecialSprite = node != null && (node.NodeKind == PassiveNodeKind.Bridge || node.NodeKind == PassiveNodeKind.Capstone);
|
||||
Sprite fallbackSprite = useSpecialSprite ? normalNodeSprite : specialNodeSprite;
|
||||
Sprite preferredSprite = useSpecialSprite ? specialNodeSprite : normalNodeSprite;
|
||||
return preferredSprite != null ? preferredSprite : fallbackSprite;
|
||||
@@ -1170,6 +1185,20 @@ namespace Colosseum.UI
|
||||
return new Color(0.3f, 0.3f, 0.32f, 0.34f);
|
||||
}
|
||||
|
||||
private static Color GetNodeFillColor(bool selected, bool selectable, bool focused)
|
||||
{
|
||||
if (selected)
|
||||
return new Color(0.09f, 0.09f, 0.11f, 0.96f);
|
||||
|
||||
if (focused)
|
||||
return new Color(0.08f, 0.08f, 0.10f, 0.94f);
|
||||
|
||||
if (selectable)
|
||||
return new Color(0.07f, 0.07f, 0.09f, 0.92f);
|
||||
|
||||
return new Color(0.06f, 0.06f, 0.08f, 0.90f);
|
||||
}
|
||||
|
||||
private Color GetNodeBaseColor(PassiveNodeData node)
|
||||
{
|
||||
if (node.Branch == PassiveNodeBranch.Bridge)
|
||||
@@ -1198,19 +1227,21 @@ namespace Colosseum.UI
|
||||
{
|
||||
return node.NodeKind switch
|
||||
{
|
||||
PassiveNodeKind.Hub => new Vector2(88f, 88f),
|
||||
PassiveNodeKind.Capstone => new Vector2(78f, 78f),
|
||||
PassiveNodeKind.Bridge => new Vector2(64f, 64f),
|
||||
_ => new Vector2(70f, 70f),
|
||||
PassiveNodeKind.Hub => new Vector2(78f, 78f),
|
||||
PassiveNodeKind.Capstone => new Vector2(70f, 70f),
|
||||
PassiveNodeKind.Bridge => new Vector2(56f, 56f),
|
||||
_ => new Vector2(62f, 62f),
|
||||
};
|
||||
}
|
||||
|
||||
private static float GetConnectionInset(PassiveNodeData node)
|
||||
{
|
||||
Vector2 size = GetNodeSize(node);
|
||||
float radius = Mathf.Min(size.x, size.y) * 0.42f;
|
||||
float radius = Mathf.Min(size.x, size.y) * 0.5f + ConnectionThickness * 0.5f + 2f;
|
||||
if (node != null && node.NodeKind == PassiveNodeKind.Bridge)
|
||||
radius += 3f;
|
||||
radius += 4f;
|
||||
else if (node != null && (node.NodeKind == PassiveNodeKind.Hub || node.NodeKind == PassiveNodeKind.Capstone))
|
||||
radius += 2f;
|
||||
|
||||
return radius;
|
||||
}
|
||||
@@ -1380,7 +1411,13 @@ namespace Colosseum.UI
|
||||
Transform footerTransform = statusText.transform.parent;
|
||||
if (footerTransform != null)
|
||||
{
|
||||
footerTransform.gameObject.SetActive(hasMessage);
|
||||
Image footerImage = footerTransform.GetComponent<Image>();
|
||||
if (footerImage != null)
|
||||
{
|
||||
Color color = sectionBackgroundColor;
|
||||
color.a = hasMessage ? sectionBackgroundColor.a : 0f;
|
||||
footerImage.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
statusText.text = hasMessage ? lastStatusMessage : string.Empty;
|
||||
|
||||
Reference in New Issue
Block a user