using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.U2D;
using Object = UnityEngine.Object;
namespace BansheeGz.BGDatabase
{
///
/// [IMPORTANT] Using Addressables preloader is not recommended anymore.
/// Use Addressables async API with asset address instead
/// Each Unity asset field implements BGAddressablesAssetI interface. Use it to retrieve asset address (string GetAddressablesAddress(int entityIndex);)
///
// this code is tested against 1.6.2 version
// This script preload all values from database. You can modify it to preload only required part.
public class BGAddressablesPreloader : MonoBehaviour
{
//=====================================================================================
// Field/Properties
//=====================================================================================
protected bool initializing;
protected int count;
protected int Count
{
get => count;
set
{
count = value;
if (count == 0 && !initializing) Completed();
}
}
//=====================================================================================
// Unity callbacks
//=====================================================================================
protected virtual void Start()
{
Preload();
}
//=====================================================================================
// Database iteration
//=====================================================================================
protected virtual void Preload()
{
initializing = true;
var type2Addresses = new Dictionary>();
var type2Field = new Dictionary>();
//iterate all tables
BGRepo.I.ForEachMeta(meta =>
{
//should be included?
if (!IsIncluded(meta)) return;
type2Field.Clear();
//PASS 0: iterate fields and gather all fields with addressables loader
meta.ForEachField(field =>
{
// if not Unity asset field- skip it
if (!(field is BGAssetLoaderA.WithLoaderI) || !(field is BGAddressablesAssetI)) return;
var fieldWithLoader = (BGAssetLoaderA.WithLoaderI) field;
// if not a field with addressables loader- skip it
if (!(fieldWithLoader.AssetLoader is BGAssetLoaderAddressables)) return;
//should be included?
if (!IsIncluded(field)) return;
GetList(type2Field, field.ValueType).Add(field as BGAddressablesAssetI);
});
if (type2Field.Count == 0) return;
//PASS 1: iterate all entities(rows) and gather all addresses
meta.ForEachEntity(entity =>
{
foreach (var pair in type2Field)
{
var type = pair.Key;
var fieldList = pair.Value;
foreach (var storable in fieldList)
{
var fieldWithCustomLoader = storable as BGAddressablesAssetCustomLoaderI;
if (fieldWithCustomLoader == null)
{
var address = storable.GetAssetPath(entity.Index);
//no value- no luck
if (string.IsNullOrEmpty(address)) continue;
//skip if not included
if (!IsIncluded(entity, (BGField) storable, address)) continue;
GetList(type2Addresses, type).Add(address);
}
else
{
//field provide custom address for each separate entity
var addressModel = fieldWithCustomLoader.GetAddressablesLoaderModel(entity.Index);
//no value- no luck
if (addressModel==null) continue;
//skip if not included
if (!IsIncluded(entity, (BGField) storable, addressModel.Address)) continue;
GetList(type2Addresses, addressModel.Type).Add(addressModel.Address);
}
}
}
});
});
//PASS 2: preload all assets using their addresses in batch mode (by type)
if (type2Addresses.Count == 0)
{
initializing = false;
Completed();
}
else
{
foreach (var pair in type2Addresses) Load(pair.Key, pair.Value);
initializing = false;
}
}
private static IList GetList(Dictionary> type2Field, TK key)
{
if (type2Field.TryGetValue(key, out var list)) return list;
list = new List();
type2Field.Add(key, list);
return list;
}
//=====================================================================================
// Load
//=====================================================================================
protected virtual void Load(Type type, IList