2026-06-20 뉴페어리
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
public class AutoRotate : MonoBehaviour
|
||||
{
|
||||
public Vector3 eulers = new Vector3(0, 90, 0);
|
||||
public Space space = Space.World;
|
||||
public enum UpdateMode
|
||||
{
|
||||
Update,
|
||||
FixedUpdate,
|
||||
}
|
||||
[SerializeField]
|
||||
private UpdateMode updateMode = UpdateMode.Update;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.1f, 5.0f)]
|
||||
private float interval = 2.0f;
|
||||
|
||||
public bool useSin = true;
|
||||
|
||||
|
||||
private float time = 0;
|
||||
|
||||
protected void FixedUpdate()
|
||||
{
|
||||
if (updateMode == UpdateMode.FixedUpdate)
|
||||
UpdatePosition(Time.fixedDeltaTime);
|
||||
}
|
||||
|
||||
protected void Update()
|
||||
{
|
||||
if (updateMode == UpdateMode.Update)
|
||||
UpdatePosition(Time.deltaTime);
|
||||
}
|
||||
|
||||
void UpdatePosition(float dtime)
|
||||
{
|
||||
if (useSin)
|
||||
{
|
||||
time += dtime;
|
||||
float ang = (time % interval) / interval * Mathf.PI * 2.0f;
|
||||
var t = Mathf.Sin(ang);
|
||||
if (space == Space.World)
|
||||
transform.eulerAngles = eulers * t;
|
||||
else
|
||||
transform.localEulerAngles = eulers * t;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform.Rotate(eulers * dtime, space);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4124c59241137374c9cae45d25683042
|
||||
timeCreated: 1510336570
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/AutoRotate.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,249 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
/// <summary>
|
||||
/// カメラ回転
|
||||
/// </summary>
|
||||
public class CameraOrbit : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private Transform cameraTransform;
|
||||
|
||||
[Header("Camera Target")]
|
||||
public Transform cameraTarget;
|
||||
public Vector3 cameraTargetPos;
|
||||
public Vector3 cameraTargetOffset;
|
||||
|
||||
[Header("Now Position")]
|
||||
[SerializeField]
|
||||
private float cameraDist = 1.5f;
|
||||
[SerializeField]
|
||||
private float cameraPitch = 21.0f;
|
||||
[SerializeField]
|
||||
private float cameraYaw = 180.0f;
|
||||
|
||||
[Header("Parameter")]
|
||||
[SerializeField]
|
||||
private float cameraDistHokanTime = 0.1f;
|
||||
[SerializeField]
|
||||
private float cameraAngleHokanTime = 0.1f;
|
||||
|
||||
[SerializeField]
|
||||
private float cameraDistSpeed = 0.02f;
|
||||
[SerializeField]
|
||||
private float cameraDistMax = 8.0f;
|
||||
[SerializeField]
|
||||
private float cameraDistMin = 0.1f;
|
||||
|
||||
[SerializeField]
|
||||
private float cameraYawSpeed = 0.3f;
|
||||
[SerializeField]
|
||||
private float cameraPitchSpeed = 0.3f;
|
||||
[SerializeField]
|
||||
private float cameraMaxAngleSpeed = 100.0f;
|
||||
[SerializeField]
|
||||
private float cameraPitchMax = 89.0f;
|
||||
[SerializeField]
|
||||
private float cameraPitchMin = -89.0f;
|
||||
|
||||
// 中ボタンドラッグによる移動
|
||||
public enum MoveMode
|
||||
{
|
||||
None,
|
||||
UpDown,
|
||||
Free,
|
||||
}
|
||||
[SerializeField]
|
||||
private MoveMode moveMode = MoveMode.Free;
|
||||
[SerializeField]
|
||||
private float moveSpeed = 0.002f;
|
||||
|
||||
// 自動回転
|
||||
[Header("Auto Rotation")]
|
||||
[SerializeField]
|
||||
private bool useAutoRotation = false;
|
||||
[SerializeField]
|
||||
private float autoRotationSpeed = 90.0f;
|
||||
|
||||
|
||||
// 移動作業用
|
||||
private float setCameraDist;
|
||||
private float setCameraPitch;
|
||||
private float setCameraYaw;
|
||||
private float cameraDistVelocity;
|
||||
private float cameraPitchVelocity;
|
||||
private float cameraYawVelocity;
|
||||
private float offsetYaw;
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
if (cameraTransform == null)
|
||||
{
|
||||
var cam = GetComponent<Camera>();
|
||||
if (cam)
|
||||
cameraTransform = cam.transform;
|
||||
}
|
||||
if (cameraTransform == null)
|
||||
enabled = false;
|
||||
|
||||
setCameraDist = cameraDist;
|
||||
setCameraPitch = cameraPitch;
|
||||
setCameraYaw = cameraYaw;
|
||||
}
|
||||
|
||||
protected void OnEnable()
|
||||
{
|
||||
// 入力イベント登録
|
||||
SimpleInputManager.OnTouchMove += OnTouchMove;
|
||||
SimpleInputManager.OnDoubleTouchMove += OnDoubleTouchMove;
|
||||
SimpleInputManager.OnTouchPinch += OnTouchPinch;
|
||||
}
|
||||
|
||||
protected void OnDisable()
|
||||
{
|
||||
// 入力イベント解除
|
||||
SimpleInputManager.OnTouchMove -= OnTouchMove;
|
||||
SimpleInputManager.OnDoubleTouchMove -= OnDoubleTouchMove;
|
||||
SimpleInputManager.OnTouchPinch -= OnTouchPinch;
|
||||
}
|
||||
|
||||
protected void LateUpdate()
|
||||
{
|
||||
// カメラ更新
|
||||
updateCamera();
|
||||
}
|
||||
|
||||
// カメラ更新
|
||||
private void updateCamera()
|
||||
{
|
||||
if (cameraTransform == null)
|
||||
return;
|
||||
|
||||
// カメラターゲットポジション
|
||||
cameraTargetPos = cameraTarget ? cameraTarget.position : transform.position;
|
||||
|
||||
// 補間
|
||||
cameraDist = Mathf.SmoothDamp(cameraDist, setCameraDist, ref cameraDistVelocity, cameraDistHokanTime);
|
||||
cameraPitch = Mathf.SmoothDampAngle(cameraPitch, setCameraPitch, ref cameraPitchVelocity, cameraAngleHokanTime);
|
||||
cameraYaw = Mathf.SmoothDampAngle(cameraYaw, setCameraYaw, ref cameraYawVelocity, cameraAngleHokanTime);
|
||||
|
||||
// 自動回転
|
||||
if (useAutoRotation)
|
||||
{
|
||||
offsetYaw += autoRotationSpeed * Time.deltaTime;
|
||||
}
|
||||
|
||||
// 座標確定
|
||||
Quaternion q = Quaternion.Euler(cameraPitch, cameraYaw + offsetYaw, 0);
|
||||
q = transform.rotation * q; // コンポーネントの回転
|
||||
Vector3 v = new Vector3(0, 0, -cameraDist);
|
||||
Vector3 pos = q * v;
|
||||
|
||||
// ターゲットポジション
|
||||
Vector3 tarpos = cameraTargetPos + transform.TransformVector(cameraTargetOffset);
|
||||
Vector3 fixpos = tarpos + pos;
|
||||
cameraTransform.position = fixpos;
|
||||
|
||||
// 回転確定
|
||||
Vector3 relativePos = tarpos - cameraTransform.position;
|
||||
Quaternion rot = Quaternion.LookRotation(relativePos, transform.up);
|
||||
cameraTransform.rotation = rot;
|
||||
}
|
||||
|
||||
// 回転操作
|
||||
private void updatePitchYaw(Vector2 speed)
|
||||
{
|
||||
// Yaw
|
||||
setCameraYaw += speed.x * cameraYawSpeed;
|
||||
|
||||
// Pitch
|
||||
setCameraPitch += -speed.y * cameraPitchSpeed;
|
||||
setCameraPitch = Mathf.Clamp(setCameraPitch, cameraPitchMin, cameraPitchMax);
|
||||
}
|
||||
|
||||
// 移動操作
|
||||
private void updateOffset(Vector2 speed)
|
||||
{
|
||||
if (cameraTransform == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (moveMode == MoveMode.UpDown)
|
||||
{
|
||||
cameraTargetOffset.y -= speed.y * moveSpeed;
|
||||
}
|
||||
else if (moveMode == MoveMode.Free)
|
||||
{
|
||||
Vector3 offset = moveSpeed * -speed.y * transform.InverseTransformDirection(cameraTransform.up);
|
||||
offset += moveSpeed * -speed.x * transform.InverseTransformDirection(cameraTransform.right);
|
||||
|
||||
cameraTargetOffset += offset;
|
||||
}
|
||||
}
|
||||
|
||||
// ズーム操作
|
||||
private void updateZoom(float speed)
|
||||
{
|
||||
float value = speed * cameraDistSpeed;
|
||||
float scl = Mathf.InverseLerp(cameraDistMin, cameraDistMax, setCameraDist);
|
||||
scl = Mathf.Clamp(scl, 0.1f, 1.0f);
|
||||
setCameraDist -= value * scl;
|
||||
setCameraDist = Mathf.Clamp(setCameraDist, cameraDistMin, cameraDistMax);
|
||||
}
|
||||
|
||||
//=============================================================================================
|
||||
/// <summary>
|
||||
/// 入力通知:移動
|
||||
/// </summary>
|
||||
/// <param name="screenPos"></param>
|
||||
/// <param name="screenVelocity"></param>
|
||||
private void OnTouchMove(int fid, Vector2 screenPos, Vector2 screenVelocity, Vector2 cmVelocity)
|
||||
{
|
||||
screenVelocity *= SpeedAdjustment();
|
||||
|
||||
if (fid == 2)
|
||||
{
|
||||
// 中ドラッグ
|
||||
updateOffset(screenVelocity);
|
||||
}
|
||||
else if (fid == 0)
|
||||
{
|
||||
// 左ドラッグ
|
||||
// 最大速度
|
||||
screenVelocity = Vector2.ClampMagnitude(screenVelocity, cameraMaxAngleSpeed);
|
||||
updatePitchYaw(screenVelocity);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDoubleTouchMove(int fid, Vector2 screenPos, Vector2 screenVelocity, Vector2 cmVelocity)
|
||||
{
|
||||
screenVelocity *= SpeedAdjustment();
|
||||
|
||||
if (SimpleInputManager.Instance.GetTouchCount() >= 3)
|
||||
updateOffset(screenVelocity);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 入力通知:ピンチイン/アウト
|
||||
/// </summary>
|
||||
/// <param name="speedscr"></param>
|
||||
/// <param name="speedcm"></param>
|
||||
private void OnTouchPinch(float speedscr, float speedcm)
|
||||
{
|
||||
speedcm *= SpeedAdjustment();
|
||||
|
||||
if (SimpleInputManager.Instance.GetTouchCount() < 3)
|
||||
updateZoom(speedcm);
|
||||
}
|
||||
|
||||
private float SpeedAdjustment()
|
||||
{
|
||||
return Time.deltaTime * 60.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1fd18111ed866534a92d0a2a59d1608d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CameraOrbit.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,136 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
/// <summary>
|
||||
/// 基本的なシングルトンテンプレート
|
||||
/// ・シーンに無い場合は作成する
|
||||
/// ・自動初期化呼び出し機能
|
||||
/// ・DontDestroyOnLoad設定
|
||||
/// ・実行前でもInstanceアクセス可能
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class CreateSingleton<T> : MonoBehaviour where T : MonoBehaviour
|
||||
{
|
||||
private static T instance;
|
||||
|
||||
/// <summary>
|
||||
/// 初期化フラグ
|
||||
/// </summary>
|
||||
private static T initInstance;
|
||||
|
||||
private static bool isDestroy;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Reload Domain 対応
|
||||
/// ※残念ながらジェネリッククラスでは[RuntimeInitializeOnLoadMethod]が利用できないため、
|
||||
/// この初期化関数を派生元で[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
/// を使用して呼び出さなければならない
|
||||
/// </summary>
|
||||
protected static void InitMember()
|
||||
{
|
||||
instance = null;
|
||||
initInstance = null;
|
||||
isDestroy = false;
|
||||
}
|
||||
|
||||
public static T Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
// FindObjectOfTypeはそれなりに負荷がかかるので注意!
|
||||
// 非アクティブのオブジェクトは発見できないので注意!
|
||||
#if UNITY_6000_4_OR_NEWER
|
||||
instance = FindAnyObjectByType<T>();
|
||||
#elif UNITY_2023_1_OR_NEWER
|
||||
instance = FindFirstObjectByType<T>();
|
||||
#else
|
||||
instance = FindObjectOfType<T>();
|
||||
#endif
|
||||
|
||||
if (instance == null && Application.isPlaying)
|
||||
{
|
||||
var obj = new GameObject(typeof(T).Name);
|
||||
instance = obj.AddComponent<T>();
|
||||
}
|
||||
}
|
||||
|
||||
// 初期化
|
||||
InitInstance();
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
private static void InitInstance()
|
||||
{
|
||||
if (initInstance == null && instance != null && Application.isPlaying)
|
||||
{
|
||||
// シーン切り替えでもオブジェクトが消えないように設定
|
||||
//DontDestroyOnLoad(instance.gameObject);
|
||||
|
||||
// 初期化呼び出し
|
||||
var s = instance as CreateSingleton<T>;
|
||||
s.InitSingleton();
|
||||
|
||||
initInstance = instance;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// インスタンスが存在する場合にTrueを返します
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsInstance()
|
||||
{
|
||||
return instance != null && isDestroy == false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Awake()でのインスタンス設定
|
||||
/// </summary>
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (instance == null)
|
||||
{
|
||||
instance = this as T;
|
||||
InitInstance();
|
||||
}
|
||||
else if (instance != this)
|
||||
{
|
||||
// 2つ目のコンポーネントを発見
|
||||
var s = instance as CreateSingleton<T>;
|
||||
s.DuplicateDetection(this as T);
|
||||
|
||||
// 2つ目のコンポーネントは破棄する
|
||||
Destroy(this.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
// インスタンスクラスならば無効化フラグを立てる
|
||||
if (instance == this)
|
||||
{
|
||||
isDestroy = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 2つ目の破棄されるコンポーネントを通知
|
||||
/// </summary>
|
||||
/// <param name="duplicate"></param>
|
||||
protected virtual void DuplicateDetection(T duplicate) { }
|
||||
|
||||
/// <summary>
|
||||
/// 内部初期化
|
||||
/// </summary>
|
||||
protected abstract void InitSingleton();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d1b801c369005647ae0e5a315e0bdaf
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/CreateSingleton.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 776d5a1b173ef154c9bef26d30c53fcc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 347fb6ccc378d9442a92b5316d0ff7c9
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "MagicaCloth2UPMImporterShaderGraph",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [
|
||||
"!MC2_SHADERGRAPH"
|
||||
],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.shadergraph",
|
||||
"expression": "12.0.0",
|
||||
"define": "MC2_SHADERGRAPH"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34d2974f64e7a9f49a48b400abf046ff
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/MagicaCloth2UPMImporterShaderGraph.asmdef
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,30 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEditor;
|
||||
using UnityEditor.PackageManager;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2UPMImporterCollections
|
||||
{
|
||||
/// <summary>
|
||||
/// 必要なUnityPackageの自動インストール
|
||||
/// </summary>
|
||||
[InitializeOnLoad]
|
||||
public static class UnityPackageImporter
|
||||
{
|
||||
static UnityPackageImporter()
|
||||
{
|
||||
Install("com.unity.shadergraph");
|
||||
}
|
||||
|
||||
public static bool Install(string id)
|
||||
{
|
||||
Debug.Log($"Install...{id}");
|
||||
var request = Client.Add(id);
|
||||
while (!request.IsCompleted) { };
|
||||
if (request.Error != null) Debug.LogError(request.Error.message);
|
||||
return request.Error == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd5d6386919360640adca6564193a8f5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/Editor/ShaderGraph/UnityPackageImporter.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,44 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
public class GameObjectContainer : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private List<GameObject> gameObjectList = new List<GameObject>();
|
||||
|
||||
|
||||
private Dictionary<string, GameObject> gameObjectDict = new Dictionary<string, GameObject>();
|
||||
|
||||
protected void Awake()
|
||||
{
|
||||
// create dictionary.
|
||||
foreach (var obj in gameObjectList)
|
||||
{
|
||||
if (obj)
|
||||
{
|
||||
gameObjectDict.Add(obj.name, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(string objName)
|
||||
{
|
||||
return gameObjectDict.ContainsKey(objName);
|
||||
}
|
||||
|
||||
public GameObject GetGameObject(string objName)
|
||||
{
|
||||
if (gameObjectDict.ContainsKey(objName))
|
||||
{
|
||||
return gameObjectDict[objName];
|
||||
}
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4357444b3effcf149a7c0557d3c4ddc5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/GameObjectContainer.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "MagicaCloth2Example",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"MagicaClothV2",
|
||||
"Unity.InputSystem"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": true,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": false,
|
||||
"defineConstraints": [
|
||||
"MAGICACLOTH2"
|
||||
],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.inputsystem",
|
||||
"expression": "1.0.0",
|
||||
"define": "MC2_INPUTSYSTEM"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bc0ea054e216f5498d1a84885db7ab1
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/MagicaCloth2Example.asmdef
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,82 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
public class ModelController : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private List<GameObject> characterList = new List<GameObject>();
|
||||
|
||||
[SerializeField]
|
||||
private float slowTime = 0.1f;
|
||||
|
||||
private bool slow;
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
slow = false;
|
||||
}
|
||||
|
||||
private void AnimatorAction(System.Action<Animator> act)
|
||||
{
|
||||
foreach (var chara in characterList)
|
||||
{
|
||||
if (chara && chara.activeInHierarchy)
|
||||
{
|
||||
var animator = chara.GetComponent<Animator>();
|
||||
if (animator)
|
||||
{
|
||||
act(animator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ClothAction(System.Action<MagicaCloth> act)
|
||||
{
|
||||
foreach (var chara in characterList)
|
||||
{
|
||||
if (chara && chara.activeInHierarchy)
|
||||
{
|
||||
var clothList = chara.GetComponentsInChildren<MagicaCloth>(true);
|
||||
if (clothList != null)
|
||||
{
|
||||
foreach (var cloth in clothList)
|
||||
{
|
||||
act(cloth);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnNextButton()
|
||||
{
|
||||
AnimatorAction((ani) => ani.SetTrigger("Next"));
|
||||
}
|
||||
|
||||
public void OnBackButton()
|
||||
{
|
||||
AnimatorAction((ani) => ani.SetTrigger("Back"));
|
||||
}
|
||||
|
||||
public void OnSlowButton()
|
||||
{
|
||||
slow = !slow;
|
||||
|
||||
float timeScale = slow ? slowTime : 1.0f;
|
||||
|
||||
AnimatorAction((ani) => ani.speed = timeScale);
|
||||
ClothAction((cloth) => cloth.SetTimeScale(timeScale));
|
||||
}
|
||||
|
||||
public void OnActiveButton()
|
||||
{
|
||||
ClothAction((cloth) => cloth.gameObject.SetActive(!cloth.gameObject.activeSelf));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 49572a6b5327127438636ad59bdb9226
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/ModelController.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,248 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
/// <summary>
|
||||
/// A sample that builds MagicaCloth at runtime.
|
||||
/// </summary>
|
||||
public class RuntimeBuildDemo : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private GameObject characterPrefab;
|
||||
[SerializeField]
|
||||
private MagicaCloth frontHairSource;
|
||||
[SerializeField]
|
||||
private string ribbonPresetName;
|
||||
[SerializeField]
|
||||
private string skirtName;
|
||||
[SerializeField]
|
||||
private Texture2D skirtPaintMap;
|
||||
|
||||
GameObject character;
|
||||
GameObjectContainer gameObjectContainer;
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
character = null;
|
||||
gameObjectContainer = null;
|
||||
}
|
||||
|
||||
public void OnCreateButton()
|
||||
{
|
||||
if (character)
|
||||
return;
|
||||
|
||||
// Generate a character from a prefab.
|
||||
GenerateCharacter();
|
||||
|
||||
// BoneCloth construction example (1).
|
||||
SetupHairTail_BoneCloth();
|
||||
|
||||
// BoneCloth construction example (2).
|
||||
SetupFrontHair_BoneCloth();
|
||||
|
||||
// BoneCloth construction example (3).
|
||||
SetupRibbon_BoneCloth();
|
||||
|
||||
// MeshCloth construction example (1).
|
||||
SetupSkirt_MeshCloth();
|
||||
}
|
||||
|
||||
public void OnRemoveButton()
|
||||
{
|
||||
if (character)
|
||||
{
|
||||
Destroy(character);
|
||||
character = null;
|
||||
gameObjectContainer = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a character from a prefab.
|
||||
/// A character already contains a<GameObjectContainer> to reference a GameObject.
|
||||
/// This component is optional.
|
||||
/// It's just there to help with data construction.
|
||||
/// </summary>
|
||||
void GenerateCharacter()
|
||||
{
|
||||
if (characterPrefab)
|
||||
{
|
||||
character = Instantiate(characterPrefab, transform);
|
||||
gameObjectContainer = character.GetComponent<GameObjectContainer>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BoneCloth construction example (1).
|
||||
/// Set all parameters from a script.
|
||||
/// </summary>
|
||||
void SetupHairTail_BoneCloth()
|
||||
{
|
||||
if (character == null)
|
||||
return;
|
||||
|
||||
var obj = new GameObject("HairTail_BoneCloth");
|
||||
obj.transform.SetParent(character.transform, false);
|
||||
|
||||
// add Magica Cloth
|
||||
var cloth = obj.AddComponent<MagicaCloth>();
|
||||
var sdata = cloth.SerializeData;
|
||||
|
||||
// bone cloth
|
||||
sdata.clothType = ClothProcess.ClothType.BoneCloth;
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_L_HairTail_00_B").transform);
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_R_HairTail_00_B").transform);
|
||||
|
||||
// setup parameters
|
||||
sdata.gravity = 3.0f;
|
||||
sdata.damping.SetValue(0.05f);
|
||||
sdata.angleRestorationConstraint.stiffness.SetValue(0.15f, 1.0f, 0.15f, true);
|
||||
sdata.angleRestorationConstraint.velocityAttenuation = 0.6f;
|
||||
sdata.tetherConstraint.distanceCompression = 0.5f;
|
||||
sdata.inertiaConstraint.particleSpeedLimit.SetValue(true, 3.0f);
|
||||
sdata.colliderCollisionConstraint.mode = ColliderCollisionConstraint.Mode.None;
|
||||
|
||||
// start build
|
||||
cloth.BuildAndRun();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BoneCloth construction example (2).
|
||||
/// Copy parameters from an existing component.
|
||||
/// </summary>
|
||||
void SetupFrontHair_BoneCloth()
|
||||
{
|
||||
if (character == null || frontHairSource == null)
|
||||
return;
|
||||
|
||||
var obj = new GameObject("HairFront_BoneCloth");
|
||||
obj.transform.SetParent(character.transform, false);
|
||||
|
||||
// add Magica Cloth
|
||||
var cloth = obj.AddComponent<MagicaCloth>();
|
||||
var sdata = cloth.SerializeData;
|
||||
|
||||
// bone cloth
|
||||
sdata.clothType = ClothProcess.ClothType.BoneCloth;
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_L_HairFront_00_B").transform);
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_L_HairSide2_00_B").transform);
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_L_HairSide_00_B").transform);
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_R_HairFront_00_B").transform);
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_R_HairSide2_00_B").transform);
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_R_HairSide_00_B").transform);
|
||||
|
||||
// Normal direction setting for backstop
|
||||
sdata.normalAlignmentSetting.alignmentMode = NormalAlignmentSettings.AlignmentMode.Transform;
|
||||
sdata.normalAlignmentSetting.adjustmentTransform = gameObjectContainer.GetGameObject("HeadCenter").transform;
|
||||
|
||||
// setup parameters
|
||||
// Copy from source settings
|
||||
sdata.Import(frontHairSource, false);
|
||||
|
||||
// start build
|
||||
cloth.BuildAndRun();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// BoneCloth construction example (3).
|
||||
/// Load parameters from saved presets.
|
||||
/// </summary>
|
||||
void SetupRibbon_BoneCloth()
|
||||
{
|
||||
if (character == null || string.IsNullOrEmpty(ribbonPresetName))
|
||||
return;
|
||||
|
||||
var obj = new GameObject("Ribbon_BoneCloth");
|
||||
obj.transform.SetParent(character.transform, false);
|
||||
|
||||
// add Magica Cloth
|
||||
var cloth = obj.AddComponent<MagicaCloth>();
|
||||
var sdata = cloth.SerializeData;
|
||||
|
||||
// bone cloth
|
||||
sdata.clothType = ClothProcess.ClothType.BoneCloth;
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_L_HeadRibbon_00_B").transform);
|
||||
sdata.rootBones.Add(gameObjectContainer.GetGameObject("J_R_HeadRibbon_00_B").transform);
|
||||
|
||||
// setup parameters
|
||||
// Load presets from the Resource folder.
|
||||
// Since presets are in TextAssets format, they can also be used as asset bundles.
|
||||
var presetText = Resources.Load<TextAsset>(ribbonPresetName);
|
||||
sdata.ImportJson(presetText.text);
|
||||
|
||||
// start build
|
||||
cloth.BuildAndRun();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// MeshCloth construction example (1).
|
||||
/// Reads vertex attributes from a paintmap.
|
||||
/// </summary>
|
||||
void SetupSkirt_MeshCloth()
|
||||
{
|
||||
if (character == null || skirtPaintMap == null)
|
||||
return;
|
||||
|
||||
// skirt renderer
|
||||
var sobj = gameObjectContainer.GetGameObject(skirtName);
|
||||
if (sobj == null)
|
||||
return;
|
||||
if (!sobj.TryGetComponent<Renderer>(out var skirtRenderer))
|
||||
return;
|
||||
|
||||
// add Magica Cloth
|
||||
var obj = new GameObject("Skirt_MeshCloth");
|
||||
obj.transform.SetParent(character.transform, false);
|
||||
var cloth = obj.AddComponent<MagicaCloth>();
|
||||
var sdata = cloth.SerializeData;
|
||||
|
||||
// mesh cloth
|
||||
sdata.clothType = ClothProcess.ClothType.MeshCloth;
|
||||
sdata.sourceRenderers.Add(skirtRenderer);
|
||||
|
||||
// reduction settings
|
||||
sdata.reductionSetting.simpleDistance = 0.0212f;
|
||||
sdata.reductionSetting.shapeDistance = 0.0244f;
|
||||
|
||||
// paint map settings
|
||||
// *** Paintmaps must have Read/Write attributes enabled! ***
|
||||
sdata.paintMode = ClothSerializeData.PaintMode.Texture_Fixed_Move;
|
||||
sdata.paintMaps.Add(skirtPaintMap);
|
||||
|
||||
// setup parameters
|
||||
sdata.gravity = 1.0f;
|
||||
sdata.damping.SetValue(0.03f);
|
||||
sdata.angleRestorationConstraint.stiffness.SetValue(0.05f, 1.0f, 0.5f, true);
|
||||
sdata.angleRestorationConstraint.velocityAttenuation = 0.5f;
|
||||
sdata.angleLimitConstraint.useAngleLimit = true;
|
||||
sdata.angleLimitConstraint.limitAngle.SetValue(45.0f, 0.0f, 1.0f, true);
|
||||
sdata.distanceConstraint.stiffness.SetValue(0.5f, 1.0f, 0.5f, true);
|
||||
sdata.tetherConstraint.distanceCompression = 0.9f;
|
||||
sdata.inertiaConstraint.depthInertia = 0.7f;
|
||||
sdata.inertiaConstraint.movementSpeedLimit.SetValue(true, 3.0f);
|
||||
sdata.inertiaConstraint.particleSpeedLimit.SetValue(true, 3.0f);
|
||||
sdata.colliderCollisionConstraint.mode = ColliderCollisionConstraint.Mode.Point;
|
||||
|
||||
// setup collider
|
||||
// UpperLeg L
|
||||
var lobj = new GameObject("CapsuleCollider_L");
|
||||
lobj.transform.SetParent(gameObjectContainer.GetGameObject("Character1_LeftUpLeg").transform);
|
||||
lobj.transform.localPosition = new Vector3(0.0049f, 0.0f, -0.0832f);
|
||||
lobj.transform.localEulerAngles = new Vector3(0.23f, 16.376f, -0.028f);
|
||||
var colliderL = lobj.AddComponent<MagicaCapsuleCollider>();
|
||||
colliderL.direction = MagicaCapsuleCollider.Direction.Z;
|
||||
colliderL.SetSize(0.082f, 0.094f, 0.3f);
|
||||
// UpperLeg R (Symmetry)
|
||||
colliderL.symmetryMode = ColliderSymmetryMode.AutomaticHumanBody;
|
||||
colliderL.UpdateParameters(); // Required when changing parameters.
|
||||
sdata.colliderCollisionConstraint.colliderList.Add(colliderL);
|
||||
|
||||
// start build
|
||||
cloth.BuildAndRun();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d0126e2925cecdf4a933c28a27f415ac
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeBuildDemo.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,210 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
/// <summary>
|
||||
/// Dress-up sample.
|
||||
/// </summary>
|
||||
public class RuntimeDressUpDemo : MonoBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Avatar to change clothes.
|
||||
/// </summary>
|
||||
public GameObject targetAvatar;
|
||||
|
||||
/// <summary>
|
||||
/// Hair prefab with MagicaCloth set in advance.
|
||||
/// </summary>
|
||||
public GameObject hariEqupPrefab;
|
||||
|
||||
/// <summary>
|
||||
/// Clothes prefab with MagicaCloth set in advance.
|
||||
/// </summary>
|
||||
public GameObject bodyEquipPrefab;
|
||||
|
||||
//=========================================================================================
|
||||
/// <summary>
|
||||
/// Bones dictionary of avatars to dress up.
|
||||
/// </summary>
|
||||
Dictionary<string, Transform> targetAvatarBoneMap = new Dictionary<string, Transform>();
|
||||
|
||||
/// <summary>
|
||||
/// Information class for canceling dress-up.
|
||||
/// </summary>
|
||||
class EquipInfo
|
||||
{
|
||||
public GameObject equipObject;
|
||||
public List<ColliderComponent> colliderList;
|
||||
|
||||
public bool IsValid() => equipObject != null;
|
||||
}
|
||||
EquipInfo hairEquipInfo = new EquipInfo();
|
||||
EquipInfo bodyEquipInfo = new EquipInfo();
|
||||
|
||||
//=========================================================================================
|
||||
protected void Start()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
public void OnHairEquipButton()
|
||||
{
|
||||
if (hairEquipInfo.IsValid())
|
||||
Remove(hairEquipInfo);
|
||||
else
|
||||
Equip(hariEqupPrefab, hairEquipInfo);
|
||||
}
|
||||
|
||||
public void OnBodyEquipButton()
|
||||
{
|
||||
if (bodyEquipInfo.IsValid())
|
||||
Remove(bodyEquipInfo);
|
||||
else
|
||||
Equip(bodyEquipPrefab, bodyEquipInfo);
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
/// <summary>
|
||||
/// Create an avatar bone dictionary in advance.
|
||||
/// </summary>
|
||||
void Init()
|
||||
{
|
||||
Debug.Assert(targetAvatar);
|
||||
|
||||
// Create all bone maps for the target avatar
|
||||
foreach (Transform bone in targetAvatar.GetComponentsInChildren<Transform>())
|
||||
{
|
||||
if (targetAvatarBoneMap.ContainsKey(bone.name) == false)
|
||||
{
|
||||
targetAvatarBoneMap.Add(bone.name, bone);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log($"Duplicate bone name :{bone.name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equip clothes.
|
||||
/// </summary>
|
||||
/// <param name="equipPrefab"></param>
|
||||
/// <param name="einfo"></param>
|
||||
void Equip(GameObject equipPrefab, EquipInfo einfo)
|
||||
{
|
||||
Debug.Assert(equipPrefab);
|
||||
|
||||
// Generate a prefab with cloth set up.
|
||||
var gobj = Instantiate(equipPrefab, targetAvatar.transform);
|
||||
|
||||
// All cloth components included in the prefab.
|
||||
var clothList = new List<MagicaCloth>(gobj.GetComponentsInChildren<MagicaCloth>());
|
||||
|
||||
// All collider components included in the prefab.
|
||||
var colliderList = new List<ColliderComponent>(gobj.GetComponentsInChildren<ColliderComponent>());
|
||||
|
||||
// All renderers included in the prefab.
|
||||
var skinList = new List<SkinnedMeshRenderer>(gobj.GetComponentsInChildren<SkinnedMeshRenderer>());
|
||||
|
||||
// First stop the automatic build that is executed with Start().
|
||||
// And just in case, it does some initialization called Awake().
|
||||
foreach (var cloth in clothList)
|
||||
{
|
||||
// Normally it is called with Awake(), but if the component is disabled, it will not be executed, so call it manually.
|
||||
// Ignored if already run with Awake().
|
||||
cloth.Initialize();
|
||||
|
||||
// Turn off auto-build on Start().
|
||||
cloth.DisableAutoBuild();
|
||||
}
|
||||
|
||||
// Swap the bones of the SkinnedMeshRenderer.
|
||||
// This process is a general dress-up process for SkinnedMeshRenderer.
|
||||
// Comment out this series of processes when performing this process with functions such as other assets.
|
||||
foreach (var sren in skinList)
|
||||
{
|
||||
var bones = sren.bones;
|
||||
Transform[] newBones = new Transform[bones.Length];
|
||||
|
||||
for (int i = 0; i < bones.Length; ++i)
|
||||
{
|
||||
Transform bone = bones[i];
|
||||
if (!targetAvatarBoneMap.TryGetValue(bone.name, out newBones[i]))
|
||||
{
|
||||
// Is the bone the renderer itself?
|
||||
if (bone.name == sren.name)
|
||||
{
|
||||
newBones[i] = sren.transform;
|
||||
}
|
||||
else
|
||||
{
|
||||
// bone not found
|
||||
Debug.Log($"[SkinnedMeshRenderer({sren.name})] Unable to map bone [{bone.name}] to target skeleton.");
|
||||
}
|
||||
}
|
||||
}
|
||||
sren.bones = newBones;
|
||||
|
||||
// root bone
|
||||
if (targetAvatarBoneMap.ContainsKey(sren.rootBone != null ? sren.rootBone.name : null))
|
||||
{
|
||||
sren.rootBone = targetAvatarBoneMap[sren.rootBone.name];
|
||||
}
|
||||
}
|
||||
|
||||
// Here, replace the bones used by the MagicaCloth component.
|
||||
foreach (var cloth in clothList)
|
||||
{
|
||||
// Replaces a component's transform.
|
||||
cloth.ReplaceTransform(targetAvatarBoneMap);
|
||||
}
|
||||
|
||||
// Move all colliders to the new avatar.
|
||||
foreach (var collider in colliderList)
|
||||
{
|
||||
Transform parent = collider.transform.parent;
|
||||
if (parent && targetAvatarBoneMap.ContainsKey(parent.name))
|
||||
{
|
||||
Transform newParent = targetAvatarBoneMap[parent.name];
|
||||
|
||||
// After changing the parent, you need to write back the local posture and align it.
|
||||
collider.transform.GetLocalPositionAndRotation(out var localPosition, out var localRotation);
|
||||
collider.transform.SetParent(newParent);
|
||||
collider.transform.SetLocalPositionAndRotation(localPosition, localRotation);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally let's start building the cloth component.
|
||||
foreach (var cloth in clothList)
|
||||
{
|
||||
// I disabled the automatic build, so I build it manually.
|
||||
cloth.BuildAndRun();
|
||||
}
|
||||
|
||||
// Record information for release.
|
||||
einfo.equipObject = gobj;
|
||||
einfo.colliderList = colliderList;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes equipped clothing.
|
||||
/// </summary>
|
||||
/// <param name="einfo"></param>
|
||||
void Remove(EquipInfo einfo)
|
||||
{
|
||||
Destroy(einfo.equipObject);
|
||||
foreach (var c in einfo.colliderList)
|
||||
{
|
||||
Destroy(c.gameObject);
|
||||
}
|
||||
|
||||
einfo.equipObject = null;
|
||||
einfo.colliderList.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e72f8cfc2a22d184e86b4e1905cdf3ec
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/RuntimeDressUpDemo.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,196 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2025 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEngine;
|
||||
#if MC2_INPUTSYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
using UnityEngine.InputSystem.EnhancedTouch;
|
||||
#endif
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
/// <summary>
|
||||
/// InputManager/InputSystem入力切り替えラッパー
|
||||
/// </summary>
|
||||
public class SimpleInput
|
||||
{
|
||||
#if MC2_INPUTSYSTEM
|
||||
// (New) Imput System
|
||||
public static void Init()
|
||||
{
|
||||
EnhancedTouchSupport.Enable();
|
||||
}
|
||||
|
||||
public static int touchCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return UnityEngine.InputSystem.EnhancedTouch.Touch.activeTouches.Count;
|
||||
}
|
||||
}
|
||||
|
||||
public static UnityEngine.Touch GetTouch(int index)
|
||||
{
|
||||
var touchData = new UnityEngine.Touch();
|
||||
|
||||
int count = UnityEngine.InputSystem.EnhancedTouch.Touch.activeTouches.Count;
|
||||
if (index < count)
|
||||
{
|
||||
var touch = UnityEngine.InputSystem.EnhancedTouch.Touch.activeTouches[index];
|
||||
|
||||
// convert
|
||||
touchData.fingerId = touch.finger.index;
|
||||
touchData.position = touch.screenPosition;
|
||||
touchData.deltaPosition = touch.delta;
|
||||
switch (touch.phase)
|
||||
{
|
||||
case UnityEngine.InputSystem.TouchPhase.Canceled:
|
||||
touchData.phase = UnityEngine.TouchPhase.Canceled;
|
||||
break;
|
||||
case UnityEngine.InputSystem.TouchPhase.Ended:
|
||||
touchData.phase = UnityEngine.TouchPhase.Ended;
|
||||
break;
|
||||
case UnityEngine.InputSystem.TouchPhase.Moved:
|
||||
touchData.phase = UnityEngine.TouchPhase.Moved;
|
||||
break;
|
||||
case UnityEngine.InputSystem.TouchPhase.Began:
|
||||
touchData.phase = UnityEngine.TouchPhase.Began;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return touchData;
|
||||
}
|
||||
|
||||
public static bool GetKey(KeyCode key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KeyCode.Escape:
|
||||
return Keyboard.current.escapeKey.isPressed;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetKeyDown(KeyCode key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case KeyCode.Backspace:
|
||||
return Keyboard.current.backspaceKey.wasPressedThisFrame;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetMouseButtonDown(int button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case 0:
|
||||
return Mouse.current.leftButton.wasPressedThisFrame;
|
||||
case 1:
|
||||
return Mouse.current.rightButton.wasPressedThisFrame;
|
||||
case 2:
|
||||
return Mouse.current.middleButton.wasPressedThisFrame;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetMouseButtonUp(int button)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case 0:
|
||||
return Mouse.current.leftButton.wasReleasedThisFrame;
|
||||
case 1:
|
||||
return Mouse.current.rightButton.wasReleasedThisFrame;
|
||||
case 2:
|
||||
return Mouse.current.middleButton.wasReleasedThisFrame;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vector3 mousePosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return Mouse.current.position.ReadValue();
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetMouseScrollWheel()
|
||||
{
|
||||
// 古いInputSystemに不具合あり
|
||||
// ホイールデルタがデフォルトでx120されて返ってくる
|
||||
// これはWindowsのみの挙動でMac/Linuxでは発生しない
|
||||
// そしてUnity 2023.2以降は修正された
|
||||
|
||||
float value = Mouse.current.scroll.ReadValue().y * 0.12f; // base
|
||||
#if UNITY_2023_2_OR_NEWER
|
||||
return value;
|
||||
#else
|
||||
#if UNITY_STANDALONE_WIN || UNITY_EDITOR_WIN
|
||||
return value / 120.0f; // ホイールデルタの不具合を吸収
|
||||
#else
|
||||
return value;
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
// (Old) Imput Manager
|
||||
public static void Init()
|
||||
{
|
||||
}
|
||||
|
||||
public static int touchCount
|
||||
{
|
||||
get
|
||||
{
|
||||
return Input.touchCount;
|
||||
}
|
||||
}
|
||||
|
||||
public static Touch GetTouch(int index)
|
||||
{
|
||||
return Input.GetTouch(index);
|
||||
}
|
||||
|
||||
public static bool GetKey(KeyCode key)
|
||||
{
|
||||
return Input.GetKey(key);
|
||||
}
|
||||
|
||||
public static bool GetKeyDown(KeyCode key)
|
||||
{
|
||||
return Input.GetKeyDown(key);
|
||||
}
|
||||
|
||||
public static bool GetMouseButtonDown(int button)
|
||||
{
|
||||
return Input.GetMouseButtonDown(button);
|
||||
}
|
||||
|
||||
public static bool GetMouseButtonUp(int button)
|
||||
{
|
||||
return Input.GetMouseButtonUp(button);
|
||||
}
|
||||
|
||||
public static Vector3 mousePosition
|
||||
{
|
||||
get
|
||||
{
|
||||
return Input.mousePosition;
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetMouseScrollWheel()
|
||||
{
|
||||
return Input.GetAxis("Mouse ScrollWheel");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ab72fcfec8965ae4181307a06400b57b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInput.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,602 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
/// <summary>
|
||||
/// 入力マネージャ
|
||||
/// ・簡単なタップやフリック判定
|
||||
/// ・PCの場合はマウスによる自動エミュレーション
|
||||
/// </summary>
|
||||
public class SimpleInputManager : CreateSingleton<SimpleInputManager>
|
||||
{
|
||||
// 最大タッチ数
|
||||
private const int MaxFinger = 3;
|
||||
|
||||
/// <summary>
|
||||
/// タップ有効半径(cm)
|
||||
/// </summary>
|
||||
public float tapRadiusCm = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// フリック判定距離(cm)
|
||||
/// </summary>
|
||||
public float flickRangeCm = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// フリック判定速度(cm/s)
|
||||
/// </summary>
|
||||
public float flickCheckSpeed = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// マウスホイールのピンチイン・ピンチアウト速度係数
|
||||
/// </summary>
|
||||
public float mouseWheelSpeed = 5.0f;
|
||||
|
||||
// 入力情報管理
|
||||
private int mainFingerId = -1;
|
||||
private int subFingerId = -1;
|
||||
private Vector2[] downPos; // 入力開始座標(スクリーン)
|
||||
private Vector2[] lastPos;
|
||||
private Vector2[] flickDownPos; // 入力開始座標(スクリーン)
|
||||
private float[] flickDownTime;
|
||||
private float lastTime = 0; // バックボタンの連続入力防止用
|
||||
|
||||
// モバイル情報管理
|
||||
private bool mobilePlatform = false;
|
||||
|
||||
// マウスエミュレーション情報管理
|
||||
private bool[] mouseDown;
|
||||
private Vector2[] mouseOldMovePos;
|
||||
|
||||
// モニタ情報
|
||||
private float screenDpi; // スクリーンDPI値
|
||||
private float screenDpc; // スクリーンDots per cm値(1cm当たりのピクセル数)
|
||||
|
||||
//------------------------------ モバイルタッチパネル/マウスエミュレーション ------------------
|
||||
// タッチ開始通知
|
||||
// タッチされた時に、フィンガーID、その位置(スクリーン)を通知します。
|
||||
public static UnityAction<int, Vector2> OnTouchDown;
|
||||
|
||||
// 移動通知
|
||||
// タッチされたまま移動された場合に、フィンガーID、その位置(スクリーン)、速度(スクリーン比率/s)、速度(cm/s)を通知します。
|
||||
public static UnityAction<int, Vector2, Vector2, Vector2> OnTouchMove;
|
||||
|
||||
// ダブルタッチされたまま移動された場合に、フィンガーID、その位置(スクリーン)、速度(スクリーン比率/s)、速度(cm/s)を通知します。
|
||||
public static UnityAction<int, Vector2, Vector2, Vector2> OnDoubleTouchMove;
|
||||
|
||||
// タッチ終了通知
|
||||
// タッチが離されたフィンガーID、位置(スクリーン)を通知します。
|
||||
public static UnityAction<int, Vector2> OnTouchUp;
|
||||
|
||||
// タッチキャンセル通知
|
||||
// タッチ移動がキャンセル(主に画面外に移動)された場合に、フィンガーID、その最終位置(スクリーン)を通知します。
|
||||
public static UnityAction<int, Vector2> OnTouchMoveCancel;
|
||||
|
||||
// タップ通知
|
||||
// タップされた時に、フィンガーID、その位置(スクリーン)を通知します。
|
||||
public static UnityAction<int, Vector2> OnTouchTap;
|
||||
|
||||
// フリック通知
|
||||
// フリック判定された場合に、フィンガーID、その位置(スクリーン)、フリック速度(スクリーン比率/s)、速度(cm/s)を通知します。
|
||||
public static UnityAction<int, Vector2, Vector2, Vector2> OnTouchFlick;
|
||||
|
||||
// ピンチイン/アウト通知
|
||||
// ピンチイン/アウトの速度(スクリーン比率/s)、速度(cm/s)を通知します。
|
||||
public static UnityAction<float, float> OnTouchPinch;
|
||||
|
||||
// バックボタン通知(Androiddeでは戻るボタン、PCでは BackSpace ボタン)
|
||||
public static UnityAction OnBackButton;
|
||||
|
||||
//=========================================================================================
|
||||
/// <summary>
|
||||
/// Reload Domain 対策
|
||||
/// </summary>
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
|
||||
private static void Init()
|
||||
{
|
||||
InitMember();
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
protected override void InitSingleton()
|
||||
{
|
||||
SimpleInput.Init();
|
||||
|
||||
// スクリーン情報
|
||||
CalcScreenDpi();
|
||||
|
||||
// 情報初期化
|
||||
downPos = new Vector2[MaxFinger];
|
||||
lastPos = new Vector2[MaxFinger];
|
||||
flickDownPos = new Vector2[MaxFinger];
|
||||
flickDownTime = new float[MaxFinger];
|
||||
|
||||
// マウス用
|
||||
mouseDown = new bool[3];
|
||||
mouseOldMovePos = new Vector2[3];
|
||||
|
||||
AllResetTouchInfo();
|
||||
|
||||
// モバイルプラットフォーム判定
|
||||
mobilePlatform = Application.isMobilePlatform;
|
||||
}
|
||||
|
||||
protected void Update()
|
||||
{
|
||||
// 入力タイプ別更新処理
|
||||
if (mobilePlatform)
|
||||
{
|
||||
// モバイル用タッチ入力
|
||||
UpdateMobile();
|
||||
}
|
||||
else
|
||||
{
|
||||
// マウスエミュレーション
|
||||
UpdateMouse();
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
/// <summary>
|
||||
/// スクリーンのDPI値(Dots per inchi)1インチ当たりのピクセル数を取得する
|
||||
/// </summary>
|
||||
public static float ScreenDpi
|
||||
{
|
||||
get
|
||||
{
|
||||
return Instance.screenDpi;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// スクリーンのDPC値(Dots per cm)1cm当たりのピクセル数を取得する
|
||||
/// </summary>
|
||||
public static float ScreenDpc
|
||||
{
|
||||
get
|
||||
{
|
||||
return Instance.screenDpc;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// スクリーンDpi/Dpcの再計算
|
||||
/// </summary>
|
||||
private void CalcScreenDpi()
|
||||
{
|
||||
screenDpi = Screen.dpi;
|
||||
if (screenDpi == 0.0f)
|
||||
{
|
||||
screenDpi = 96; // ダミー
|
||||
}
|
||||
screenDpc = screenDpi / 2.54f; // インチをcmに変換
|
||||
}
|
||||
|
||||
// タッチ入力情報リセット
|
||||
private void AllResetTouchInfo()
|
||||
{
|
||||
mainFingerId = -1;
|
||||
subFingerId = -1;
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
mouseDown[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
public int GetTouchCount()
|
||||
{
|
||||
return SimpleInput.touchCount;
|
||||
}
|
||||
|
||||
public bool IsUI()
|
||||
{
|
||||
if (EventSystem.current == null)
|
||||
return false;
|
||||
|
||||
if (mobilePlatform)
|
||||
{
|
||||
// モバイル用タッチ入力
|
||||
return EventSystem.current.IsPointerOverGameObject(SimpleInput.GetTouch(0).fingerId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// マウスエミュレーション
|
||||
return EventSystem.current.IsPointerOverGameObject();
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
/// <summary>
|
||||
/// モバイル用入力更新
|
||||
/// </summary>
|
||||
private void UpdateMobile()
|
||||
{
|
||||
int count = SimpleInput.touchCount;
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
AllResetTouchInfo();
|
||||
|
||||
// バックボタン
|
||||
if (Application.platform == RuntimePlatform.Android)
|
||||
{
|
||||
if (SimpleInput.GetKey(KeyCode.Escape) && lastTime + 0.2f < Time.time)
|
||||
{
|
||||
lastTime = Time.time;
|
||||
if (OnBackButton != null)
|
||||
{
|
||||
OnBackButton();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// メイン
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
Touch touch = SimpleInput.GetTouch(i);
|
||||
int fid = touch.fingerId;
|
||||
|
||||
// フィンガーIDが0と1以外は無視する
|
||||
if (fid >= 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (touch.phase == TouchPhase.Began)
|
||||
{
|
||||
if (IsUI())
|
||||
continue;
|
||||
// down pos
|
||||
downPos[fid] = touch.position;
|
||||
lastPos[fid] = touch.position;
|
||||
flickDownPos[fid] = touch.position;
|
||||
|
||||
if (fid == 0)
|
||||
{
|
||||
mainFingerId = fid;
|
||||
}
|
||||
else
|
||||
{
|
||||
subFingerId = fid;
|
||||
}
|
||||
|
||||
// Downはメインフィンガーのみ
|
||||
if (fid == 0)
|
||||
{
|
||||
flickDownTime[fid] = Time.time;
|
||||
if (OnTouchDown != null)
|
||||
{
|
||||
OnTouchDown(fid, touch.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (touch.phase == TouchPhase.Moved)
|
||||
{
|
||||
// ピンチイン/アウト判定
|
||||
if (mainFingerId >= 0 && subFingerId >= 0)
|
||||
{
|
||||
Vector2 t1pos = Vector2.zero;
|
||||
Vector2 t2pos = Vector2.zero;
|
||||
Vector2 t1delta = Vector2.zero;
|
||||
Vector2 t2delta = Vector2.zero;
|
||||
|
||||
int setcnt = 0;
|
||||
for (int j = 0; j < count; j++)
|
||||
{
|
||||
Touch t = SimpleInput.GetTouch(j);
|
||||
if (mainFingerId == t.fingerId)
|
||||
{
|
||||
t1pos = t.position;
|
||||
t1delta = t.deltaPosition;
|
||||
setcnt++;
|
||||
}
|
||||
else if (subFingerId == t.fingerId)
|
||||
{
|
||||
t2pos = t.position;
|
||||
t2delta = t.deltaPosition;
|
||||
setcnt++;
|
||||
}
|
||||
}
|
||||
|
||||
if (setcnt == 2)
|
||||
{
|
||||
float nowdist = Vector2.Distance(t1pos, t2pos);
|
||||
float olddist = Vector2.Distance(t1pos - t1delta, t2pos - t2delta);
|
||||
float dist = nowdist - olddist;
|
||||
|
||||
// cm/sに変換
|
||||
float distcm = dist / screenDpc; // 移動量(cm)
|
||||
float speedcm = distcm / Time.deltaTime; // 速度(cm/s)
|
||||
|
||||
// スクリーン比率の速度
|
||||
float speedscr = (dist / (Screen.width + Screen.height) * 0.5f) / Time.deltaTime;
|
||||
|
||||
// ピンチ通知(移動量(cm), 速度(cm/s))
|
||||
if (OnTouchPinch != null)
|
||||
{
|
||||
OnTouchPinch(speedscr, speedcm);
|
||||
}
|
||||
}
|
||||
|
||||
if (fid == 0)
|
||||
{
|
||||
Vector2 distVec2 = touch.position - lastPos[fid];
|
||||
Vector2 distcm = distVec2 / screenDpc; // 移動量(cm)
|
||||
Vector2 speedcm = distcm / Time.deltaTime; // 速度(cm/s)
|
||||
|
||||
// 速度(スクリーン比率)
|
||||
Vector2 speedscr = CalcScreenRatioVector(distVec2) / Time.deltaTime;
|
||||
|
||||
// 移動通知(現在スクリーン座標、速度(スクリーン比率), 速度(cm/s))
|
||||
if (OnDoubleTouchMove != null)
|
||||
{
|
||||
OnDoubleTouchMove(fid, touch.position, speedscr, speedcm);
|
||||
}
|
||||
|
||||
lastPos[fid] = touch.position;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Moveはメインフィンガーのみ
|
||||
if (fid == 0 && mainFingerId >= 0)
|
||||
{
|
||||
Vector2 distVec2 = touch.position - lastPos[fid];
|
||||
Vector2 distcm = distVec2 / screenDpc; // 移動量(cm)
|
||||
Vector2 speedcm = distcm / Time.deltaTime; // 速度(cm/s)
|
||||
|
||||
// 速度(スクリーン比率)
|
||||
Vector2 speedscr = CalcScreenRatioVector(distVec2) / Time.deltaTime;
|
||||
|
||||
// 移動通知(現在スクリーン座標、速度(スクリーン比率), 速度(cm/s))
|
||||
if (OnTouchMove != null)
|
||||
{
|
||||
OnTouchMove(fid, touch.position, speedscr, speedcm);
|
||||
}
|
||||
|
||||
// フリックダウン位置更新
|
||||
flickDownPos[fid] = (flickDownPos[fid] + touch.position) * 0.5f;
|
||||
flickDownTime[fid] = Time.time;
|
||||
}
|
||||
|
||||
lastPos[fid] = touch.position;
|
||||
}
|
||||
}
|
||||
else if (touch.phase == TouchPhase.Ended)
|
||||
{
|
||||
// フィンガーIDのリリース
|
||||
if (fid == 0)
|
||||
{
|
||||
mainFingerId = -1;
|
||||
subFingerId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
subFingerId = -1;
|
||||
}
|
||||
|
||||
// End, Tap はメインフィンガーのみ
|
||||
if (fid == 0)
|
||||
{
|
||||
// タップ判定
|
||||
float dist = Vector2.Distance(downPos[fid], touch.position);
|
||||
float distcm = dist / screenDpc;
|
||||
|
||||
if (distcm <= tapRadiusCm)
|
||||
{
|
||||
// タップ通知
|
||||
if (OnTouchTap != null)
|
||||
{
|
||||
OnTouchTap(fid, touch.position);
|
||||
}
|
||||
}
|
||||
// フリック判定
|
||||
else
|
||||
{
|
||||
CheckFlic(fid, downPos[fid], touch.position, flickDownPos[fid], flickDownTime[fid]);
|
||||
}
|
||||
|
||||
// タップアップ通知
|
||||
if (OnTouchUp != null)
|
||||
{
|
||||
OnTouchUp(fid, touch.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (touch.phase == TouchPhase.Canceled)
|
||||
{
|
||||
// フィンガーIDのリリース
|
||||
if (fid == 0)
|
||||
{
|
||||
mainFingerId = -1;
|
||||
subFingerId = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
subFingerId = -1;
|
||||
}
|
||||
|
||||
// Cancelはメインフィンガーのみ
|
||||
if (fid == 0)
|
||||
{
|
||||
if (OnTouchMoveCancel != null)
|
||||
{
|
||||
OnTouchMoveCancel(fid, touch.position);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// スクリーン比率に変換したベクトルを求める
|
||||
/// </summary>
|
||||
/// <param name="vec"></param>
|
||||
/// <returns></returns>
|
||||
private Vector2 CalcScreenRatioVector(Vector2 vec)
|
||||
{
|
||||
return new Vector2(vec.x / Screen.width, vec.y / Screen.height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// フリック判定
|
||||
/// </summary>
|
||||
/// <param name="oldpos"></param>
|
||||
/// <param name="nowpos"></param>
|
||||
/// <param name="downpos"></param>
|
||||
/// <param name="flicktime"></param>
|
||||
/// <returns></returns>
|
||||
private bool CheckFlic(int fid, Vector2 oldpos, Vector2 nowpos, Vector2 downpos, float flicktime)
|
||||
{
|
||||
// フリック判定
|
||||
float dist = Vector2.Distance(nowpos, downpos);
|
||||
float distcm = dist / screenDpc;
|
||||
if (distcm > flickRangeCm)
|
||||
{
|
||||
{
|
||||
// 移動ピクセルをcm変換し、速度cm/sを割り出す
|
||||
Vector2 distVec = (nowpos - downpos);
|
||||
Vector2 distVec2 = distVec / screenDpc; // cmへ変換(移動量(cm))
|
||||
float timeInterval = Time.time - flicktime;
|
||||
float speedX = distVec2.x / timeInterval; // 速度(cm/s)
|
||||
float speedY = distVec2.y / timeInterval; // 速度(cm/s)
|
||||
|
||||
//Develop.Log("distVec", distVec * 100);
|
||||
//Develop.Log("sppedX:", speedX, " speedY:", speedY);
|
||||
|
||||
if (Mathf.Abs(speedX) >= flickCheckSpeed || Mathf.Abs(speedY) >= flickCheckSpeed)
|
||||
{
|
||||
// フリック通知(スクリーン位置,速度(スクリーン比率/s),速度(cm/s))
|
||||
if (OnTouchFlick != null)
|
||||
{
|
||||
OnTouchFlick(fid, nowpos, CalcScreenRatioVector(distVec) / timeInterval, new Vector2(speedX, speedY));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
/// <summary>
|
||||
/// 入力情報更新(PC用)
|
||||
/// マウスエミュレーション
|
||||
/// ・右クリックは使わない。
|
||||
/// ・ピンチイン/アウトはマウスホイール。
|
||||
/// </summary>
|
||||
private void UpdateMouse()
|
||||
{
|
||||
// BackSpace を Android 端末のバックボタンに割り当てる
|
||||
if (SimpleInput.GetKeyDown(KeyCode.Backspace))
|
||||
{
|
||||
if (OnBackButton != null)
|
||||
OnBackButton();
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
// マウスボタンダウン
|
||||
if (SimpleInput.GetMouseButtonDown(i))
|
||||
{
|
||||
if (IsUI())
|
||||
continue;
|
||||
|
||||
if (mouseDown[i] == false && i == 0)
|
||||
{
|
||||
flickDownTime[i] = Time.time;
|
||||
}
|
||||
mouseDown[i] = true;
|
||||
|
||||
// 入力位置を記録
|
||||
downPos[i] = SimpleInput.mousePosition;
|
||||
mouseOldMovePos[i] = SimpleInput.mousePosition;
|
||||
if (i == 0)
|
||||
flickDownPos[i] = SimpleInput.mousePosition;
|
||||
|
||||
// タッチダウンイベント発行
|
||||
if (OnTouchDown != null)
|
||||
OnTouchDown(i, SimpleInput.mousePosition);
|
||||
}
|
||||
|
||||
// マウスボタンアップ
|
||||
if (SimpleInput.GetMouseButtonUp(i) && mouseDown[i])
|
||||
{
|
||||
mouseDown[i] = false;
|
||||
|
||||
// フリック判定
|
||||
if (i == 0)
|
||||
{
|
||||
CheckFlic(i, mouseOldMovePos[i], SimpleInput.mousePosition, flickDownPos[i], flickDownTime[i]);
|
||||
}
|
||||
|
||||
mouseOldMovePos[i] = Vector2.zero;
|
||||
|
||||
// タッチアップイベント
|
||||
if (OnTouchUp != null)
|
||||
OnTouchUp(i, SimpleInput.mousePosition);
|
||||
|
||||
// タップ判定
|
||||
float distcm = Vector2.Distance(downPos[0], SimpleInput.mousePosition) / screenDpc;
|
||||
if (distcm <= tapRadiusCm)
|
||||
{
|
||||
if (OnTouchTap != null)
|
||||
OnTouchTap(i, SimpleInput.mousePosition);
|
||||
}
|
||||
}
|
||||
|
||||
// 移動
|
||||
if (mouseDown[i])
|
||||
{
|
||||
Vector2 spos = new Vector2(SimpleInput.mousePosition.x, SimpleInput.mousePosition.y);
|
||||
Vector2 delta = spos - mouseOldMovePos[i];
|
||||
|
||||
if (spos != mouseOldMovePos[i])
|
||||
{
|
||||
// 速度
|
||||
Vector3 deltacm = delta / screenDpc; // 移動量(cm)
|
||||
Vector2 speedcm = deltacm / Time.deltaTime; // 速度(cm/s)
|
||||
|
||||
// 移動通知(現在スクリーン座標、速度(スクリーン比率/s)、速度(cm/s))
|
||||
if (OnTouchMove != null)
|
||||
OnTouchMove(i, SimpleInput.mousePosition, CalcScreenRatioVector(delta) / Time.deltaTime, speedcm);
|
||||
}
|
||||
|
||||
mouseOldMovePos[i] = SimpleInput.mousePosition;
|
||||
|
||||
// フリックダウン位置更新
|
||||
flickDownPos[i] = (flickDownPos[i] + spos) * 0.5f;
|
||||
flickDownTime[i] = Time.time;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ピンチイン/アウト
|
||||
float w = SimpleInput.GetMouseScrollWheel();
|
||||
if (Mathf.Abs(w) > 0.01f)
|
||||
{
|
||||
// モバイル入力とスケール感を合わせるために係数を掛ける
|
||||
w *= mouseWheelSpeed;
|
||||
|
||||
float speedcm = w / Time.deltaTime;
|
||||
float speedscr = (w / (Screen.width + Screen.height) * 0.5f) / Time.deltaTime;
|
||||
|
||||
// 通知(速度(スクリーン比率/s)、速度(cm/s)
|
||||
if (OnTouchPinch != null)
|
||||
OnTouchPinch(speedscr, speedcm);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08208c43232950a4f8b6eae1f7919c13
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SimpleInputManager.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,46 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
public class SliderText : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private Text text = null;
|
||||
|
||||
[SerializeField]
|
||||
private string lable = "";
|
||||
|
||||
[SerializeField]
|
||||
private string format = "0.00";
|
||||
|
||||
private string formatString;
|
||||
|
||||
protected void Start()
|
||||
{
|
||||
formatString = "{0} ({1:" + format + "})";
|
||||
|
||||
var slider = GetComponent<Slider>();
|
||||
if (slider)
|
||||
{
|
||||
slider.onValueChanged.AddListener(OnChangeValue);
|
||||
|
||||
var val = slider.value;
|
||||
slider.value = 0.001f;
|
||||
slider.value = val;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnChangeValue(float value)
|
||||
{
|
||||
if (text)
|
||||
{
|
||||
text.text = string.Format(formatString, lable, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 37e7fecf2cf6fff42800da6e57c20d5d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/SliderText.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,19 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
public class TargetFPS : MonoBehaviour
|
||||
{
|
||||
public int frameRate = 60;
|
||||
|
||||
#if !UNITY_EDITOR
|
||||
protected void Start()
|
||||
{
|
||||
Application.targetFrameRate = frameRate;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70abefeafa131dd428880b40bd4c183c
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/TargetFPS.cs
|
||||
uploadId: 893596
|
||||
@@ -0,0 +1,94 @@
|
||||
// Magica Cloth 2.
|
||||
// Copyright (c) 2023 MagicaSoft.
|
||||
// https://magicasoft.jp
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace MagicaCloth2
|
||||
{
|
||||
public class WindDemo : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
private MagicaWindZone magicaWindZone;
|
||||
[SerializeField]
|
||||
private WindZone unityWindZone;
|
||||
[SerializeField]
|
||||
private Renderer arrowRenderer = null;
|
||||
[SerializeField]
|
||||
private Gradient arrowGradient = new Gradient();
|
||||
[SerializeField]
|
||||
private List<Transform> rotationTransforms = new List<Transform>();
|
||||
|
||||
private float angleY = 0.0f;
|
||||
private float angleX = 0.0f;
|
||||
private float main = 0.0f;
|
||||
private float turbulence = 0.0f;
|
||||
|
||||
public void OnDirectionY(float value)
|
||||
{
|
||||
angleY = value;
|
||||
UpdateDirection();
|
||||
}
|
||||
|
||||
public void OnDirectionX(float value)
|
||||
{
|
||||
angleX = value;
|
||||
UpdateDirection();
|
||||
}
|
||||
|
||||
public void OnMain(float value)
|
||||
{
|
||||
main = value;
|
||||
UpdateMagicaWindZone();
|
||||
UpdateUnityWindZone();
|
||||
UpdateArrowColor();
|
||||
}
|
||||
|
||||
public void OnTurbulence(float value)
|
||||
{
|
||||
turbulence = value;
|
||||
UpdateMagicaWindZone();
|
||||
}
|
||||
|
||||
//=========================================================================================
|
||||
void UpdateArrowColor()
|
||||
{
|
||||
if (arrowRenderer)
|
||||
{
|
||||
// color
|
||||
var t = Mathf.Clamp01(Mathf.InverseLerp(0.0f, 20.0f, main));
|
||||
var col = arrowGradient.Evaluate(t);
|
||||
arrowRenderer.material.color = col * 0.7f;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateDirection()
|
||||
{
|
||||
var lrot = Quaternion.Euler(angleX, angleY, 0.0f);
|
||||
foreach (var t in rotationTransforms)
|
||||
if (t)
|
||||
t.localRotation = lrot;
|
||||
|
||||
UpdateMagicaWindZone();
|
||||
}
|
||||
|
||||
void UpdateMagicaWindZone()
|
||||
{
|
||||
if (magicaWindZone)
|
||||
{
|
||||
magicaWindZone.main = main;
|
||||
magicaWindZone.turbulence = turbulence;
|
||||
magicaWindZone.directionAngleX = angleX;
|
||||
magicaWindZone.directionAngleY = angleY;
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateUnityWindZone()
|
||||
{
|
||||
if (unityWindZone)
|
||||
{
|
||||
unityWindZone.windMain = main;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 13f11cb1bd01c684b9a48fd075e6a541
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 242307
|
||||
packageName: Magica Cloth 2
|
||||
packageVersion: 2.18.1
|
||||
assetPath: Assets/MagicaCloth2/Example (Can be deleted)/Common/Scripts/WindDemo.cs
|
||||
uploadId: 893596
|
||||
Reference in New Issue
Block a user