// Magica Cloth.
// Copyright (c) MagicaSoft, 2020-2022.
// https://magicasoft.jp
using System.Collections.Generic;
using UnityEngine;
namespace MagicaCloth
{
///
/// クロス選択データ
///
[System.Serializable]
public class SelectionData : ShareDataObject
{
///
/// データバージョン
///
private const int DATA_VERSION = 2;
///
/// 頂点選択データタイプ
///
public const int Invalid = 0;
public const int Move = 1;
public const int Fixed = 2;
public const int Extend = 3; // 固定としてマークするがローテーションライン計算からは除外する
///
/// レンダーデフォーマーごとの選択データ
///
[System.Serializable]
public class DeformerSelection : IDataHash
{
///
/// レンダーデフォーマーの頂点と1対1に対応
///
public List selectData = new List();
///
/// 頂点ハッシュリスト(オプション)
///
public List vertexHashList = new List();
public int GetDataHash()
{
return selectData.GetDataHash();
}
public bool Compare(DeformerSelection data)
{
if (selectData.Count != data.selectData.Count)
return false;
for (int i = 0; i < selectData.Count; i++)
{
if (selectData[i] != data.selectData[i])
return false;
}
if (vertexHashList.Count != data.vertexHashList.Count)
return false;
for (int i = 0; i < vertexHashList.Count; i++)
{
if (vertexHashList[i] != data.vertexHashList[i])
return false;
}
return true;
}
}
public List selectionList = new List();
//=========================================================================================
public int DeformerCount
{
get
{
return selectionList.Count;
}
}
//=========================================================================================
///
/// データハッシュ計算
///
///
public override int GetDataHash()
{
int hash = 0;
hash += selectionList.GetDataHash();
return hash;
}
//=========================================================================================
public override int GetVersion()
{
return DATA_VERSION;
}
///
/// 現在のデータが正常(実行できる状態)か返す
///
///
public override Define.Error VerifyData()
{
if (dataHash == 0)
return Define.Error.InvalidDataHash;
//if (dataVersion != GetVersion())
// return Define.Error.DataVersionMismatch;
if (selectionList.Count == 0)
return Define.Error.SelectionCountZero;
return Define.Error.None;
}
//=========================================================================================
///
/// 引数の選択データの内容を比較する
///
///
///
public bool Compare(SelectionData sel)
{
if (selectionList.Count != sel.selectionList.Count)
return false;
for (int i = 0; i < selectionList.Count; i++)
{
if (selectionList[i].Compare(sel.selectionList[i]) == false)
return false;
}
return true;
}
///
/// メッシュデータの各頂点の選択情報を取得する
///
///
///
public List GetSelectionData(MeshData meshData, List childMeshDataList)
{
List selects = new List();
if (meshData != null)
{
// 親頂点に影響する子頂点情報
Dictionary> dict = meshData.GetVirtualToChildVertexDict();
// 現在の選択データの頂点ハッシュ辞書リスト
var hashList = GetSelectionVertexHashList();
int vcnt = meshData.VertexCount;
for (int i = 0; i < vcnt; i++)
{
int data = GetSelection(meshData, i, dict, childMeshDataList, hashList);
selects.Add(data);
}
}
else
{
// そのまま
if (selectionList.Count > 0)
{
selects = new List(selectionList[0].selectData);
}
}
return selects;
}
///
/// メッシュデータの指定インデクスの選択情報を取得する
///
///
///
///
private int GetSelection(MeshData meshData, int vindex, Dictionary> dict, List childMeshDataList, List> hashList)
{
int data = Invalid;
// セレクションデータ読み込み
if (meshData != null && meshData.ChildCount > 0)
{
// 親頂点に影響する子頂点情報から取得
if (dict.ContainsKey(vindex))
{
foreach (var pack in dict[vindex])
{
int cmindex = DataUtility.Unpack16Hi(pack);
int cvindex = DataUtility.Unpack16Low(pack);
if (cmindex < selectionList.Count && cvindex < selectionList[cmindex].selectData.Count)
{
// 頂点ハッシュがある場合はハッシュからインデックスを取得する
// 現在メッシュの頂点ハッシュ
ulong vhash = 0;
if (childMeshDataList != null && cmindex < childMeshDataList.Count)
{
var cmdata = childMeshDataList[cmindex];
if (cmdata != null && cvindex < cmdata.VertexHashCount)
{
vhash = cmdata.vertexHashList[cvindex];
}
}
// セレクションデータに頂点ハッシュが記録されているならば照合する
if (vhash != 0 && cmindex < hashList.Count)
{
if (hashList[cmindex].ContainsKey(vhash))
{
// ハッシュ値に紐づく頂点ペイントデータに入れ替える
cvindex = hashList[cmindex][vhash];
}
}
data = Mathf.Max(selectionList[cmindex].selectData[cvindex], data);
}
}
}
}
else
{
// そのまま
int dindex = 0;
if (dindex < selectionList.Count)
{
if (vindex < selectionList[dindex].selectData.Count)
data = selectionList[dindex].selectData[vindex];
}
}
return data;
}
///
/// メッシュ頂点の選択データを設定する
///
///
///
public void SetSelectionData(MeshData meshData, List selects, List childMeshDataList)
{
// 選択データ初期化
selectionList.Clear();
if (meshData != null && meshData.ChildCount > 0)
{
for (int i = 0; i < meshData.ChildCount; i++)
{
var dsel = new DeformerSelection();
int cvcnt = meshData.childDataList[i].VertexCount;
for (int j = 0; j < cvcnt; j++)
{
dsel.selectData.Add(Invalid);
dsel.vertexHashList.Add(0); // ハッシュ0=無効
}
selectionList.Add(dsel);
}
}
else
{
// そのまま
var dsel = new DeformerSelection();
int cvcnt = selects.Count;
for (int j = 0; j < cvcnt; j++)
{
dsel.selectData.Add(Invalid);
dsel.vertexHashList.Add(0); // ハッシュ0=無効
}
selectionList.Add(dsel);
}
// 選択データに追加
for (int i = 0; i < selects.Count; i++)
{
int data = selects[i];
if (meshData != null && meshData.ChildCount > 0)
{
// 親頂点に影響する子頂点情報
Dictionary> dict = meshData.GetVirtualToChildVertexDict();
// 親頂点に影響する子頂点に記録
if (dict.ContainsKey(i))
{
foreach (var pack in dict[i])
{
int cmindex = DataUtility.Unpack16Hi(pack);
int cvindex = DataUtility.Unpack16Low(pack);
selectionList[cmindex].selectData[cvindex] = data;
// 頂点ハッシュも記録
if (cmindex < childMeshDataList.Count)
{
var cmdata = childMeshDataList[cmindex];
if (cmdata != null && cvindex < cmdata.VertexHashCount)
{
selectionList[cmindex].vertexHashList[cvindex] = cmdata.vertexHashList[cvindex];
}
}
}
}
}
else
{
// そのまま
selectionList[0].selectData[i] = data;
}
}
// データハッシュ設定
CreateVerifyData();
}
///
/// セレクションデータに格納されている子メッシュの頂点ハッシュを辞書にして返す
///
///
///
private List> GetSelectionVertexHashList()
{
var hashList = new List>();
foreach (var sel in selectionList)
{
Dictionary hashDict = new Dictionary();
for (int i = 0; i < sel.vertexHashList.Count; i++)
{
hashDict[sel.vertexHashList[i]] = i;
}
hashList.Add(hashDict);
}
return hashList;
}
}
}