2025-10-10 14:31:51 +02:00
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using AppleHills.Data.CardSystem ;
2025-11-06 21:31:16 +01:00
using AppleHills.Editor.Utilities ;
2025-10-28 14:31:17 +01:00
using UI.CardSystem ;
2025-10-10 14:31:51 +02:00
using UnityEditor ;
using UnityEngine ;
using UnityEngine.UI ;
2025-10-28 14:31:17 +01:00
namespace Editor.CardSystem
2025-10-10 14:31:51 +02:00
{
/// <summary>
2025-11-05 23:50:15 +01:00
/// Editor utility for managing card definitions with live preview using the same UI as in-game.
2025-10-10 14:31:51 +02:00
/// </summary>
public class CardEditorWindow : EditorWindow
{
// Paths
private const string CardDefinitionsPath = "Assets/Data/Cards" ;
private const string MenuPath = "AppleHills/Card Editor" ;
2025-11-06 21:31:16 +01:00
private const string CardUIPrefabPath = "Assets/Prefabs/UI/CardsSystem/Cards/Card.prefab" ;
2025-10-10 14:31:51 +02:00
private const string CardVisualConfigPath = CardDefinitionsPath + "/CardVisualConfig.asset" ;
2025-11-05 23:50:15 +01:00
// Preview settings
private static readonly Vector2 PreviewCardSize = new Vector2 ( 200f , 300f ) ;
private const float CameraPaddingFactor = 1.2f ;
2025-10-10 14:31:51 +02:00
// Editor state
private List < CardDefinition > _cards = new List < CardDefinition > ( ) ;
private CardDefinition _selectedCard ;
2025-11-05 23:50:15 +01:00
private CardDefinition _editingCard ;
2025-10-10 14:31:51 +02:00
private Vector2 _cardListScrollPosition ;
private Vector2 _cardEditScrollPosition ;
private string _searchQuery = "" ;
private bool _showPreview = true ;
private bool _isDirty = false ;
2025-11-05 23:50:15 +01:00
// Preview state
private PreviewRenderUtility _previewUtility ;
private GameObject _previewRoot ;
private CardDisplay _previewCardDisplay ;
2025-10-10 14:31:51 +02:00
private GameObject _cardUIPrefab ;
private CardVisualConfig _cardVisualConfig ;
2025-11-05 23:50:15 +01:00
private float _zoomLevel = 1.0f ;
2025-10-10 14:31:51 +02:00
[MenuItem(MenuPath)]
public static void ShowWindow ( )
{
var window = GetWindow < CardEditorWindow > ( "Card Editor" ) ;
2025-11-05 23:50:15 +01:00
window . minSize = new Vector2 ( 1000 , 700 ) ;
2025-10-10 14:31:51 +02:00
window . Show ( ) ;
}
private void OnEnable ( )
{
LoadCardDefinitions ( ) ;
InitializePreview ( ) ;
Undo . undoRedoPerformed + = OnUndoRedo ;
}
private void OnDisable ( )
{
CleanupPreview ( ) ;
Undo . undoRedoPerformed - = OnUndoRedo ;
}
private void OnUndoRedo ( )
{
LoadCardDefinitions ( ) ;
Repaint ( ) ;
}
private void LoadCardDefinitions ( )
{
_cards . Clear ( ) ;
2025-11-05 23:50:15 +01:00
// Ensure directory exists
2025-10-10 14:31:51 +02:00
if ( ! Directory . Exists ( CardDefinitionsPath ) )
{
Directory . CreateDirectory ( CardDefinitionsPath ) ;
AssetDatabase . Refresh ( ) ;
}
2025-11-05 23:50:15 +01:00
// Find all card definitions
2025-10-10 14:31:51 +02:00
string [ ] guids = AssetDatabase . FindAssets ( "t:CardDefinition" , new [ ] { CardDefinitionsPath } ) ;
foreach ( string guid in guids )
{
string path = AssetDatabase . GUIDToAssetPath ( guid ) ;
CardDefinition card = AssetDatabase . LoadAssetAtPath < CardDefinition > ( path ) ;
if ( card ! = null )
{
_cards . Add ( card ) ;
}
}
_cards = _cards . OrderBy ( c = > c . Name ) . ToList ( ) ;
2025-11-05 23:50:15 +01:00
// Restore selection if possible
2025-10-10 14:31:51 +02:00
if ( _selectedCard ! = null )
{
_selectedCard = _cards . FirstOrDefault ( c = > c . Id = = _selectedCard . Id ) ;
if ( _selectedCard ! = null )
{
_editingCard = CloneCard ( _selectedCard ) ;
UpdatePreview ( ) ;
}
}
}
private void InitializePreview ( )
{
if ( _previewUtility = = null )
{
_previewUtility = new PreviewRenderUtility ( ) ;
var cam = _previewUtility . camera ;
2025-11-05 23:50:15 +01:00
cam . clearFlags = CameraClearFlags . SolidColor ;
cam . backgroundColor = new Color ( 0.2f , 0.2f , 0.2f ) ;
cam . orthographic = true ;
// Calculate ortho size based on card height with padding
float baseOrthoSize = ( PreviewCardSize . y / 2f ) * CameraPaddingFactor ;
cam . orthographicSize = baseOrthoSize ;
2025-10-10 14:31:51 +02:00
cam . nearClipPlane = 0.01f ;
cam . farClipPlane = 100f ;
2025-11-05 23:50:15 +01:00
cam . transform . position = new Vector3 ( 0 , 0 , - 10 ) ;
2025-10-10 14:31:51 +02:00
cam . transform . rotation = Quaternion . identity ;
}
2025-11-05 23:50:15 +01:00
// Load prefab and config
2025-10-10 14:31:51 +02:00
_cardUIPrefab = AssetDatabase . LoadAssetAtPath < GameObject > ( CardUIPrefabPath ) ;
if ( _cardUIPrefab = = null )
{
2025-11-05 23:50:15 +01:00
Debug . LogError ( $"[CardEditorWindow] Card UI prefab not found at {CardUIPrefabPath}" ) ;
2025-10-10 14:31:51 +02:00
}
_cardVisualConfig = AssetDatabase . LoadAssetAtPath < CardVisualConfig > ( CardVisualConfigPath ) ;
if ( _cardVisualConfig = = null )
{
2025-11-05 23:50:15 +01:00
Debug . LogWarning ( $"[CardEditorWindow] Card visual config not found at {CardVisualConfigPath}" ) ;
2025-10-10 14:31:51 +02:00
}
CreatePreviewCardObject ( ) ;
}
2025-11-05 23:50:15 +01:00
2025-10-10 14:31:51 +02:00
private void CreatePreviewCardObject ( )
{
CleanupPreviewInstance ( ) ;
2025-11-05 23:50:15 +01:00
if ( _cardUIPrefab = = null | | _previewUtility = = null )
2025-10-10 14:31:51 +02:00
return ;
try
{
2025-11-05 23:50:15 +01:00
// Create root and canvas
_previewRoot = new GameObject ( "PreviewRoot" ) ;
_previewRoot . hideFlags = HideFlags . HideAndDontSave ;
GameObject canvasGO = new GameObject ( "PreviewCanvas" ) ;
canvasGO . transform . SetParent ( _previewRoot . transform , false ) ;
Canvas canvas = canvasGO . AddComponent < Canvas > ( ) ;
canvas . renderMode = RenderMode . WorldSpace ;
canvas . worldCamera = _previewUtility . camera ;
RectTransform canvasRect = canvasGO . GetComponent < RectTransform > ( ) ;
canvasRect . sizeDelta = new Vector2 ( 20f , 20f ) ;
canvasRect . localPosition = Vector3 . zero ;
CanvasScaler scaler = canvasGO . AddComponent < CanvasScaler > ( ) ;
scaler . uiScaleMode = CanvasScaler . ScaleMode . ConstantPixelSize ;
scaler . scaleFactor = 1f ;
canvasGO . AddComponent < GraphicRaycaster > ( ) ;
// Instantiate card prefab
GameObject cardInstance = Instantiate ( _cardUIPrefab , canvasGO . transform , false ) ;
RectTransform cardRect = cardInstance . GetComponent < RectTransform > ( ) ;
if ( cardRect ! = null )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
// Set explicit size for preview
cardRect . sizeDelta = PreviewCardSize ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
// Anchor to center
cardRect . anchorMin = new Vector2 ( 0.5f , 0.5f ) ;
cardRect . anchorMax = new Vector2 ( 0.5f , 0.5f ) ;
cardRect . pivot = new Vector2 ( 0.5f , 0.5f ) ;
cardRect . anchoredPosition = Vector2 . zero ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
// Get CardDisplay component
_previewCardDisplay = cardInstance . GetComponent < CardDisplay > ( ) ;
if ( _previewCardDisplay = = null )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
_previewCardDisplay = cardInstance . GetComponentInChildren < CardDisplay > ( ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
if ( _previewCardDisplay ! = null & & _cardVisualConfig ! = null )
{
_previewCardDisplay . SetVisualConfig ( _cardVisualConfig ) ;
}
_previewUtility . AddSingleGO ( _previewRoot ) ;
// Update camera
UpdatePreviewCamera ( ) ;
2025-10-10 14:31:51 +02:00
}
catch ( System . Exception e )
{
2025-11-05 23:50:15 +01:00
Debug . LogError ( $"[CardEditorWindow] Error creating preview: {e.Message}" ) ;
2025-10-10 14:31:51 +02:00
}
}
2025-11-05 23:50:15 +01:00
private void UpdatePreviewCamera ( )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
if ( _previewUtility = = null ) return ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
Camera cam = _previewUtility . camera ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
// Calculate base ortho size from card height with padding
float baseOrthoSize = ( PreviewCardSize . y / 2f ) * CameraPaddingFactor ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
// Apply zoom as divisor (higher zoom = smaller ortho size = more zoomed in)
cam . orthographicSize = baseOrthoSize / _zoomLevel ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
2025-10-10 14:31:51 +02:00
private void CleanupPreviewInstance ( )
{
2025-11-05 23:50:15 +01:00
if ( _previewRoot ! = null )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
DestroyImmediate ( _previewRoot ) ;
_previewRoot = null ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
_previewCardDisplay = null ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
2025-10-10 14:31:51 +02:00
private void CleanupPreview ( )
{
CleanupPreviewInstance ( ) ;
if ( _previewUtility ! = null )
{
_previewUtility . Cleanup ( ) ;
_previewUtility = null ;
}
}
private void UpdatePreview ( )
{
2025-11-05 23:50:15 +01:00
if ( _editingCard = = null | | _previewCardDisplay = = null | | ! _showPreview )
2025-10-10 14:31:51 +02:00
return ;
2025-11-05 23:50:15 +01:00
2025-10-10 14:31:51 +02:00
try
{
2025-11-05 23:50:15 +01:00
// Create CardData from definition and setup the display
CardData previewData = _editingCard . CreateCardData ( ) ;
_previewCardDisplay . SetupCard ( previewData ) ;
Repaint ( ) ;
2025-10-10 14:31:51 +02:00
}
catch ( System . Exception ex )
{
2025-11-05 23:50:15 +01:00
Debug . LogError ( $"[CardEditorWindow] Error updating preview: {ex.Message}" ) ;
2025-10-10 14:31:51 +02:00
}
}
private void OnGUI ( )
{
2025-11-05 23:50:15 +01:00
EditorGUILayout . BeginHorizontal ( ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
// Left panel - Card list
DrawCardList ( ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
// Middle panel - Card editor
DrawCardEditor ( ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
// Right panel - Preview
if ( _showPreview )
{
DrawPreview ( ) ;
}
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
EditorGUILayout . EndHorizontal ( ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
private void DrawCardList ( )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
EditorGUILayout . BeginVertical ( GUILayout . Width ( 250 ) ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
EditorGUILayout . LabelField ( "Card List" , EditorStyles . boldLabel ) ;
2025-10-10 14:31:51 +02:00
// Search bar
2025-11-05 23:50:15 +01:00
EditorGUILayout . BeginHorizontal ( ) ;
_searchQuery = EditorGUILayout . TextField ( _searchQuery , EditorStyles . toolbarSearchField ) ;
if ( GUILayout . Button ( "X" , GUILayout . Width ( 20 ) ) )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
_searchQuery = "" ;
GUI . FocusControl ( null ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
EditorGUILayout . EndHorizontal ( ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
// New card button
2025-10-10 14:31:51 +02:00
if ( GUILayout . Button ( "Create New Card" ) )
{
CreateNewCard ( ) ;
}
// Card list
_cardListScrollPosition = EditorGUILayout . BeginScrollView ( _cardListScrollPosition ) ;
2025-11-05 23:50:15 +01:00
var filteredCards = string . IsNullOrEmpty ( _searchQuery )
? _cards
: _cards . Where ( c = > c . Name . ToLower ( ) . Contains ( _searchQuery . ToLower ( ) ) ) . ToList ( ) ;
2025-10-10 14:31:51 +02:00
foreach ( var card in filteredCards )
{
2025-11-05 23:50:15 +01:00
bool isSelected = _selectedCard = = card ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
GUI . backgroundColor = isSelected ? Color . cyan : Color . white ;
if ( GUILayout . Button ( card . Name , EditorStyles . miniButton ) )
2025-10-10 14:31:51 +02:00
{
SelectCard ( card ) ;
}
2025-11-05 23:50:15 +01:00
GUI . backgroundColor = Color . white ;
2025-10-10 14:31:51 +02:00
}
EditorGUILayout . EndScrollView ( ) ;
2025-11-05 23:50:15 +01:00
EditorGUILayout . EndVertical ( ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
private void DrawCardEditor ( )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
EditorGUILayout . BeginVertical ( GUILayout . Width ( 350 ) ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
if ( _editingCard = = null )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
EditorGUILayout . HelpBox ( "Select a card from the list or create a new one." , MessageType . Info ) ;
EditorGUILayout . EndVertical ( ) ;
return ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
EditorGUILayout . LabelField ( "Card Editor" , EditorStyles . boldLabel ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
_cardEditScrollPosition = EditorGUILayout . BeginScrollView ( _cardEditScrollPosition ) ;
2025-10-10 14:31:51 +02:00
EditorGUI . BeginChangeCheck ( ) ;
2025-11-05 23:50:15 +01:00
// Basic Info
EditorGUILayout . LabelField ( "Basic Information" , EditorStyles . boldLabel ) ;
_editingCard . Name = EditorGUILayout . TextField ( "Name" , _editingCard . Name ) ;
// Custom file name option
_editingCard . UseCustomFileName = EditorGUILayout . Toggle ( "Use Custom File Name" , _editingCard . UseCustomFileName ) ;
GUI . enabled = _editingCard . UseCustomFileName ;
_editingCard . CustomFileName = EditorGUILayout . TextField ( "Custom File Name" , _editingCard . CustomFileName ) ;
GUI . enabled = true ;
_editingCard . Description = EditorGUILayout . TextArea ( _editingCard . Description , GUILayout . Height ( 60 ) ) ;
EditorGUILayout . Space ( ) ;
// Properties
EditorGUILayout . LabelField ( "Properties" , EditorStyles . boldLabel ) ;
_editingCard . Rarity = ( CardRarity ) EditorGUILayout . EnumPopup ( "Rarity" , _editingCard . Rarity ) ;
_editingCard . Zone = ( CardZone ) EditorGUILayout . EnumPopup ( "Zone" , _editingCard . Zone ) ;
EditorGUILayout . Space ( ) ;
// Visuals
EditorGUILayout . LabelField ( "Visuals" , EditorStyles . boldLabel ) ;
_editingCard . CardImage = ( Sprite ) EditorGUILayout . ObjectField ( "Card Image" , _editingCard . CardImage , typeof ( Sprite ) , false ) ;
EditorGUILayout . Space ( ) ;
EditorGUILayout . HelpBox ( "Card visuals (frames, overlays, backgrounds, shapes) are configured in CardVisualConfig asset based on rarity and zone." , MessageType . Info ) ;
// Collection
EditorGUILayout . Space ( ) ;
EditorGUILayout . LabelField ( "Collection" , EditorStyles . boldLabel ) ;
_editingCard . CollectionIndex = EditorGUILayout . IntField ( "Collection Index" , _editingCard . CollectionIndex ) ;
EditorGUILayout . Space ( ) ;
// Identification
EditorGUILayout . LabelField ( "Identification" , EditorStyles . boldLabel ) ;
GUI . enabled = false ;
EditorGUILayout . TextField ( "ID" , _editingCard . Id ) ;
GUI . enabled = true ;
2025-10-10 14:31:51 +02:00
if ( EditorGUI . EndChangeCheck ( ) )
{
2025-11-05 23:50:15 +01:00
_isDirty = true ;
UpdatePreview ( ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
EditorGUILayout . EndScrollView ( ) ;
// Action buttons
EditorGUILayout . Space ( ) ;
EditorGUILayout . BeginHorizontal ( ) ;
GUI . enabled = _isDirty ;
if ( GUILayout . Button ( "Apply Changes" ) )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
ApplyChanges ( ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
GUI . enabled = true ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
if ( GUILayout . Button ( "Revert" ) )
{
RevertChanges ( ) ;
}
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
EditorGUILayout . EndHorizontal ( ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
EditorGUILayout . BeginHorizontal ( ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
if ( GUILayout . Button ( "Duplicate" ) )
{
DuplicateCard ( ) ;
}
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
GUI . backgroundColor = Color . red ;
if ( GUILayout . Button ( "Delete" ) )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
DeleteCard ( ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
GUI . backgroundColor = Color . white ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
EditorGUILayout . EndHorizontal ( ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
EditorGUILayout . EndVertical ( ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
private void DrawPreview ( )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
EditorGUILayout . BeginVertical ( ) ;
EditorGUILayout . BeginHorizontal ( ) ;
EditorGUILayout . LabelField ( "Preview" , EditorStyles . boldLabel ) ;
_zoomLevel = EditorGUILayout . Slider ( "Zoom" , _zoomLevel , 0.5f , 2.0f ) ;
EditorGUILayout . EndHorizontal ( ) ;
if ( Event . current . type = = EventType . Repaint & & _zoomLevel ! = _previewUtility . camera . orthographicSize )
{
UpdatePreviewCamera ( ) ;
}
Rect previewRect = GUILayoutUtility . GetRect ( 400 , 600 ) ;
if ( _previewUtility ! = null & & _editingCard ! = null )
{
_previewUtility . BeginPreview ( previewRect , GUIStyle . none ) ;
_previewUtility . camera . Render ( ) ;
Texture resultTexture = _previewUtility . EndPreview ( ) ;
GUI . DrawTexture ( previewRect , resultTexture , ScaleMode . ScaleToFit , false ) ;
}
else
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
EditorGUI . DrawRect ( previewRect , new Color ( 0.2f , 0.2f , 0.2f ) ) ;
EditorGUI . LabelField ( previewRect , "No Preview Available" , EditorStyles . centeredGreyMiniLabel ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
EditorGUILayout . EndVertical ( ) ;
2025-10-10 14:31:51 +02:00
}
private void SelectCard ( CardDefinition card )
{
if ( _isDirty & & _selectedCard ! = null )
{
2025-11-05 23:50:15 +01:00
if ( EditorUtility . DisplayDialog ( "Unsaved Changes" ,
"You have unsaved changes. Apply them before switching cards?" ,
"Apply" , "Discard" ) )
2025-10-10 14:31:51 +02:00
{
ApplyChanges ( ) ;
}
}
_selectedCard = card ;
_editingCard = CloneCard ( card ) ;
_isDirty = false ;
2025-11-05 23:50:15 +01:00
UpdatePreview ( ) ;
2025-10-10 14:31:51 +02:00
}
private void CreateNewCard ( )
{
CardDefinition newCard = CreateInstance < CardDefinition > ( ) ;
newCard . Id = System . Guid . NewGuid ( ) . ToString ( ) ;
newCard . Name = "New Card" ;
2025-11-05 23:50:15 +01:00
newCard . Description = "Card description" ;
newCard . Rarity = CardRarity . Normal ;
2025-10-10 14:31:51 +02:00
newCard . Zone = CardZone . AppleHills ;
newCard . CollectionIndex = _cards . Count ;
string path = $"{CardDefinitionsPath}/Card_{newCard.Name}.asset" ;
path = AssetDatabase . GenerateUniqueAssetPath ( path ) ;
2025-11-05 23:50:15 +01:00
2025-10-10 14:31:51 +02:00
AssetDatabase . CreateAsset ( newCard , path ) ;
AssetDatabase . SaveAssets ( ) ;
AssetDatabase . Refresh ( ) ;
2025-11-06 21:31:16 +01:00
// Add to Addressables group "BlokkemonCards" and apply "BlokkemonCard" label
if ( AddressablesUtility . EnsureAssetInGroupWithLabel ( path , "BlokkemonCards" , "BlokkemonCard" ) )
{
AddressablesUtility . SaveAddressableAssets ( ) ;
Debug . Log ( $"[CardEditorWindow] Added new card to Addressables with 'BlokkemonCard' label" ) ;
}
else
{
Debug . LogWarning ( "[CardEditorWindow] Failed to add new card to Addressables. Please ensure Addressables are set up in this project." ) ;
}
2025-10-10 14:31:51 +02:00
LoadCardDefinitions ( ) ;
SelectCard ( newCard ) ;
}
2025-11-05 23:50:15 +01:00
private void ApplyChanges ( )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
if ( _selectedCard = = null | | _editingCard = = null )
2025-10-10 14:31:51 +02:00
return ;
2025-11-05 23:50:15 +01:00
Undo . RecordObject ( _selectedCard , "Modify Card" ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
string oldPath = AssetDatabase . GetAssetPath ( _selectedCard ) ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
EditorUtility . CopySerialized ( _editingCard , _selectedCard ) ;
EditorUtility . SetDirty ( _selectedCard ) ;
2025-10-10 14:31:51 +02:00
AssetDatabase . SaveAssets ( ) ;
2025-11-05 23:50:15 +01:00
// Rename file if needed
string desiredFileName = _selectedCard . UseCustomFileName & & ! string . IsNullOrEmpty ( _selectedCard . CustomFileName )
? _selectedCard . CustomFileName
: _selectedCard . Name ;
2025-11-06 21:31:16 +01:00
string finalPath = oldPath ;
2025-11-05 23:50:15 +01:00
if ( ! string . IsNullOrEmpty ( desiredFileName ) )
{
// Strip spaces from file name
desiredFileName = desiredFileName . Replace ( " " , "" ) ;
string directory = Path . GetDirectoryName ( oldPath ) ;
string extension = Path . GetExtension ( oldPath ) ;
string currentFileName = Path . GetFileNameWithoutExtension ( oldPath ) ;
string expectedFileName = $"Card_{desiredFileName}" ;
// Only rename if the current file name doesn't match the expected name
if ( currentFileName ! = expectedFileName )
{
string newPath = Path . Combine ( directory , $"{expectedFileName}{extension}" ) ;
string uniquePath = AssetDatabase . GenerateUniqueAssetPath ( newPath ) ;
string error = AssetDatabase . MoveAsset ( oldPath , uniquePath ) ;
if ( ! string . IsNullOrEmpty ( error ) )
{
Debug . LogError ( $"[CardEditorWindow] Failed to rename asset: {error}" ) ;
}
else
2025-11-06 21:31:16 +01:00
finalPath = uniquePath ;
2025-11-05 23:50:15 +01:00
{
AssetDatabase . SaveAssets ( ) ;
AssetDatabase . Refresh ( ) ;
}
}
}
2025-11-06 21:31:16 +01:00
// Add to Addressables group "BlokkemonCards" and apply "BlokkemonCard" label
if ( ! string . IsNullOrEmpty ( finalPath ) )
{
if ( AddressablesUtility . EnsureAssetInGroupWithLabel ( finalPath , "BlokkemonCards" , "BlokkemonCard" ) )
{
AddressablesUtility . SaveAddressableAssets ( ) ;
Debug . Log ( $"[CardEditorWindow] Added {_selectedCard.Name} to Addressables with 'BlokkemonCard' label" ) ;
}
else
{
Debug . LogError ( "[CardEditorWindow] Failed to add card to Addressables. Please ensure Addressables are set up in this project." ) ;
}
}
2025-11-05 23:50:15 +01:00
_isDirty = false ;
Debug . Log ( $"[CardEditorWindow] Applied changes to {_selectedCard.Name}" ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
private void RevertChanges ( )
2025-10-10 14:31:51 +02:00
{
if ( _selectedCard = = null )
return ;
2025-11-05 23:50:15 +01:00
_editingCard = CloneCard ( _selectedCard ) ;
_isDirty = false ;
UpdatePreview ( ) ;
}
private void DuplicateCard ( )
{
if ( _selectedCard = = null )
return ;
2025-10-10 14:31:51 +02:00
2025-11-05 23:50:15 +01:00
CardDefinition duplicate = Instantiate ( _selectedCard ) ;
duplicate . Id = System . Guid . NewGuid ( ) . ToString ( ) ;
duplicate . Name = _selectedCard . Name + " (Copy)" ;
string path = $"{CardDefinitionsPath}/Card_{duplicate.Name}.asset" ;
path = AssetDatabase . GenerateUniqueAssetPath ( path ) ;
AssetDatabase . CreateAsset ( duplicate , path ) ;
2025-10-10 14:31:51 +02:00
AssetDatabase . SaveAssets ( ) ;
AssetDatabase . Refresh ( ) ;
LoadCardDefinitions ( ) ;
2025-11-05 23:50:15 +01:00
SelectCard ( duplicate ) ;
2025-10-10 14:31:51 +02:00
}
2025-11-05 23:50:15 +01:00
private void DeleteCard ( )
2025-10-10 14:31:51 +02:00
{
2025-11-05 23:50:15 +01:00
if ( _selectedCard = = null )
2025-10-10 14:31:51 +02:00
return ;
2025-11-05 23:50:15 +01:00
if ( ! EditorUtility . DisplayDialog ( "Delete Card" ,
$"Are you sure you want to delete '{_selectedCard.Name}'?" ,
"Delete" , "Cancel" ) )
2025-10-21 10:05:49 +02:00
{
2025-11-05 23:50:15 +01:00
return ;
2025-10-21 10:05:49 +02:00
}
2025-11-05 23:50:15 +01:00
string path = AssetDatabase . GetAssetPath ( _selectedCard ) ;
AssetDatabase . DeleteAsset ( path ) ;
AssetDatabase . SaveAssets ( ) ;
AssetDatabase . Refresh ( ) ;
_selectedCard = null ;
_editingCard = null ;
2025-10-10 14:31:51 +02:00
_isDirty = false ;
2025-11-05 23:50:15 +01:00
LoadCardDefinitions ( ) ;
CleanupPreviewInstance ( ) ;
CreatePreviewCardObject ( ) ;
2025-10-10 14:31:51 +02:00
}
private CardDefinition CloneCard ( CardDefinition original )
{
CardDefinition clone = CreateInstance < CardDefinition > ( ) ;
EditorUtility . CopySerialized ( original , clone ) ;
return clone ;
}
}
}
2025-11-05 23:50:15 +01:00