Commit 708d3dee authored by BlackAngle233's avatar BlackAngle233
Browse files

update final design

parent 1444629e
fileFormatVersion: 2
guid: 8c79c0abca06a214f9f7d80ba229ba12
timeCreated: 1566181423
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls <see cref="ImageTarget"/> in the scene, providing a few extensions in the Unity environment. Use <see cref="Target"/> directly when necessary.</para>
/// <para xml:lang="zh">在场景中控制<see cref="ImageTarget"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。如有需要可以直接使用<see cref="Target"/>。</para>
/// </summary>
public class ImageTargetController : TargetController
{
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible after TargetAvailable event.</para>
/// <para xml:lang="zh">EasyAR Sense API,可以在TargetAvailable event之后访问。</para>
/// </summary>
public ImageTarget Target { get; private set; }
/// <summary>
/// <para xml:lang="en">Target data source.</para>
/// <para xml:lang="zh">Target数据来源。</para>
/// </summary>
public DataSource SourceType = DataSource.ImageFile;
/// <summary>
/// <para xml:lang="en">Image data source for target creation. Valid when <see cref="SourceType"/> == <see cref="DataSource.ImageFile"/>.</para>
/// <para xml:lang="zh">创建target的图像数据来源。在<see cref="SourceType"/> == <see cref="DataSource.ImageFile"/>的时候有效。</para>
/// </summary>
[HideInInspector, SerializeField]
public ImageFileSourceData ImageFileSource = new ImageFileSourceData();
/// <summary>
/// <para xml:lang="en">Target data source for target creation. Valid when <see cref="SourceType"/> == <see cref="DataSource.TargetDataFile"/>.</para>
/// <para xml:lang="zh">创建target的target data来源。在<see cref="SourceType"/> == <see cref="DataSource.TargetDataFile"/>的时候有效。</para>
/// </summary>
[HideInInspector, SerializeField]
public TargetDataFileSourceData TargetDataFileSource = new TargetDataFileSourceData();
/// <summary>
/// <para xml:lang="en">Target source when using a target already created. Valid when <see cref="SourceType"/> == <see cref="DataSource.Target"/>.</para>
/// <para xml:lang="zh">直接使用创建好的target时的target来源。在<see cref="SourceType"/> == <see cref="DataSource.Target"/>的时候有效。</para>
/// </summary>
public ImageTarget TargetSource;
#if UNITY_EDITOR
/// <summary>
/// <para xml:lang="en"><see cref="Gizmos"/> data storage.</para>
/// <para xml:lang="zh"><see cref="Gizmos"/>数据存储。</para>
/// </summary>
public GizmoStorage GizmoData = new GizmoStorage();
#endif
[HideInInspector, SerializeField]
private bool trackerHasSet;
[HideInInspector, SerializeField]
private ImageTrackerFrameFilter tracker;
private ImageTrackerFrameFilter loader;
private float scale = 0.1f;
private float scaleX = 0.1f;
private bool preHFlip;
/// <summary>
/// <para xml:lang="en">Event when <see cref="Target"/> can be used.</para>
/// <para xml:lang="zh"><see cref="Target"/> 可以使用的事件。</para>
/// </summary>
public event Action TargetAvailable;
/// <summary>
/// <para xml:lang="en">Target load finish event. The bool value indicates the load success or not.</para>
/// <para xml:lang="zh">Target加载完成的事件。bool值表示加载是否成功。</para>
/// </summary>
public event Action<Target, bool> TargetLoad;
/// <summary>
/// <para xml:lang="en">Target unload finish event. The bool value indicates the unload success or not.</para>
/// <para xml:lang="zh">Target卸载完成的事件。bool值表示卸载是否成功。</para>
/// </summary>
public event Action<Target, bool> TargetUnload;
/// <summary>
/// <para xml:lang="en">Target data source type.</para>
/// <para xml:lang="zh">Target数据来源类型。</para>
/// </summary>
public enum DataSource
{
/// <summary>
/// <para xml:lang="en">Image file (*.jpg, *.png).</para>
/// <para xml:lang="zh">图像文件(*.jpg, *.png)。</para>
/// </summary>
ImageFile,
/// <summary>
/// <para xml:lang="en">Target data file (*.etd).</para>
/// <para xml:lang="zh">Target data文件(*.etd)。</para>
/// </summary>
TargetDataFile,
/// <summary>
/// <para xml:lang="en"><see cref="ImageTarget"/> object.</para>
/// <para xml:lang="zh"><see cref="ImageTarget"/>对象。</para>
/// </summary>
Target,
}
/// <summary>
/// <para xml:lang="en">The <see cref="ImageTrackerFrameFilter"/> which loads the target after <see cref="TargetAvailable"/>. When set to null, the target will be unloaded from tracker previously set. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh">在<see cref="TargetAvailable"/>之后加载target的<see cref="ImageTrackerFrameFilter"/>。如果设为null,target将会被从之前设置的tracker中卸载。可随时修改,立即生效。</para>
/// </summary>
public ImageTrackerFrameFilter Tracker
{
get
{
return tracker;
}
set
{
tracker = value;
UpdateTargetInTracker();
}
}
/// <summary>
/// <para xml:lang="en">Physical size of <see cref="ImageTarget"/> in meter.</para>
/// <para xml:lang="zh"><see cref="ImageTarget"/>的物理大小,单位为米。</para>
/// </summary>
public Vector2 Size
{
get
{
if (Target == null)
{
return new Vector2();
}
return new Vector2(Target.scale(), Target.scale() / Target.aspectRatio());
}
private set { }
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected override void Start()
{
base.Start();
if (!EasyARController.Initialized)
{
return;
}
switch (SourceType)
{
case DataSource.ImageFile:
LoadImageFile(new ImageFileSourceData()
{
PathType = ImageFileSource.PathType,
Path = ImageFileSource.Path,
Name = ImageFileSource.Name,
Scale = ImageFileSource.Scale
});
break;
case DataSource.TargetDataFile:
LoadTargetDataFile(new TargetDataFileSourceData()
{
PathType = TargetDataFileSource.PathType,
Path = TargetDataFileSource.Path
});
break;
case DataSource.Target:
LoadTarget(TargetSource);
break;
default:
break;
}
}
/// <summary>
/// MonoBehaviour Update
/// </summary>
protected virtual void Update()
{
CheckScale();
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (tracker)
{
tracker = null;
UpdateTargetInTracker();
}
if (Target != null)
{
Target.Dispose();
Target = null;
}
}
protected override void OnTracking()
{
CheckScale();
}
private void LoadImageFile(ImageFileSourceData source)
{
EasyARController.Instance.StartCoroutine(FileUtil.LoadFile(source.Path, source.PathType, (Buffer buffer) =>
{
EasyARController.Instance.StartCoroutine(LoadImageBuffer(buffer.Clone(), source));
}));
}
private void LoadTargetDataFile(TargetDataFileSourceData source)
{
EasyARController.Instance.StartCoroutine(FileUtil.LoadFile(source.Path, source.PathType, (Buffer buffer) =>
{
EasyARController.Instance.StartCoroutine(LoadTargetDataBuffer(buffer.Clone()));
}));
}
private void LoadTarget(ImageTarget source)
{
Target = source;
if (Target != null && TargetAvailable != null)
{
TargetAvailable();
}
UpdateScale();
UpdateTargetInTracker();
}
private IEnumerator LoadImageBuffer(Buffer buffer, ImageFileSourceData source)
{
using (buffer)
{
Optional<Image> imageOptional = null;
bool taskFinished = false;
EasyARController.Instance.Worker.Run(() =>
{
imageOptional = ImageHelper.decode(buffer);
taskFinished = true;
});
while (!taskFinished)
{
yield return 0;
}
if (imageOptional.OnNone)
{
throw new Exception("invalid buffer");
}
using (var image = imageOptional.Value)
using (var param = new ImageTargetParameters())
{
param.setImage(image);
param.setName(source.Name);
param.setScale(source.Scale);
param.setUid(Guid.NewGuid().ToString());
param.setMeta(string.Empty);
var targetOptional = ImageTarget.createFromParameters(param);
if (targetOptional.OnSome)
{
Target = targetOptional.Value;
if (Target != null && TargetAvailable != null)
{
TargetAvailable();
}
}
else
{
throw new Exception("invalid parameter");
}
}
}
UpdateTargetInTracker();
}
private IEnumerator LoadTargetDataBuffer(Buffer buffer)
{
using (buffer)
{
Optional<ImageTarget> targetOptional = null;
bool taskFinished = false;
EasyARController.Instance.Worker.Run(() =>
{
targetOptional = ImageTarget.createFromTargetData(buffer);
taskFinished = true;
});
while (!taskFinished)
{
yield return 0;
}
if (targetOptional.OnSome)
{
Target = targetOptional.Value;
if (Target != null && TargetAvailable != null)
{
TargetAvailable();
}
}
else
{
throw new Exception("invalid buffer");
}
}
UpdateTargetInTracker();
}
private void UpdateTargetInTracker()
{
if (Target == null)
{
return;
}
if (loader && loader != tracker)
{
loader.UnloadImageTarget(this, (target, status) =>
{
if (TargetUnload != null)
{
TargetUnload(target, status);
}
if (status)
{
IsLoaded = false;
}
});
loader = null;
}
if (tracker && tracker != loader)
{
var trackerLoad = tracker;
tracker.LoadImageTarget(this, (target, status) =>
{
if (trackerLoad == tracker && !status)
{
loader = null;
}
UpdateScale();
if (TargetLoad != null)
{
TargetLoad(target, status);
}
IsLoaded = status;
});
loader = tracker;
}
}
private void UpdateScale()
{
if (Target == null)
return;
scale = Target.scale();
var vec3Unit = Vector3.one;
if (HorizontalFlip)
{
vec3Unit.x = -vec3Unit.x;
}
transform.localScale = vec3Unit * scale;
scaleX = transform.localScale.x;
preHFlip = HorizontalFlip;
}
private void CheckScale()
{
if (Target == null)
return;
if (scaleX != transform.localScale.x)
{
Target.setScale(Math.Abs(transform.localScale.x));
UpdateScale();
}
else if (scale != transform.localScale.y)
{
Target.setScale(Math.Abs(transform.localScale.y));
UpdateScale();
}
else if (scale != transform.localScale.z)
{
Target.setScale(Math.Abs(transform.localScale.z));
UpdateScale();
}
else if (scale != Target.scale())
{
UpdateScale();
}
else if (preHFlip != HorizontalFlip)
{
UpdateScale();
}
}
/// <summary>
/// <para xml:lang="en">Image data for target creation.</para>
/// <para xml:lang="zh">创建target的图像数据。</para>
/// </summary>
[Serializable]
public class ImageFileSourceData
{
/// <summary>
/// <para xml:lang="en">File path type.</para>
/// <para xml:lang="zh">文件路径类型。</para>
/// </summary>
public PathType PathType = PathType.StreamingAssets;
/// <summary>
/// <para xml:lang="en">File path.</para>
/// <para xml:lang="zh">文件路径。</para>
/// </summary>
public string Path = string.Empty;
/// <summary>
/// <para xml:lang="en">Target name.</para>
/// <para xml:lang="zh">Target名字。</para>
/// </summary>
public string Name = string.Empty;
/// <summary>
/// <para xml:lang="en">Target scale in meter. Reference <see cref="ImageTarget.scale"/>.</para>
/// <para xml:lang="zh">Target图像的缩放比例,单位为米。参考<see cref="ImageTarget.scale"/>。</para>
/// </summary>
public float Scale = 0.1f;
}
/// <summary>
/// <para xml:lang="en">Target data for target creation. Target scale and name are defined in the etd file.</para>
/// <para xml:lang="zh">创建target的target data。Target名字和缩放在etd文件中定义。</para>
/// </summary>
[Serializable]
public class TargetDataFileSourceData
{
/// <summary>
/// <para xml:lang="en">File path type.</para>
/// <para xml:lang="zh">文件路径类型。</para>
/// </summary>
public PathType PathType = PathType.StreamingAssets;
/// <summary>
/// <para xml:lang="en">File path.</para>
/// <para xml:lang="zh">文件路径。</para>
/// </summary>
public string Path = string.Empty;
}
#if UNITY_EDITOR
/// <summary>
/// <para xml:lang="en"><see cref="Gizmos"/> data. Used for <see cref="ImageTarget"/> gizmo display.</para>
/// <para xml:lang="zh"><see cref="Gizmos"/>数据,用于在编辑器中显示<see cref="ImageTarget"/>的gizmo。</para>
/// </summary>
public class GizmoStorage
{
public string Signature;
public Texture2D Texture;
public Material Material;
public float Scale = 0.1f;
public float ScaleX = 0.1f;
public bool HorizontalFlip;
}
#endif
}
}
fileFormatVersion: 2
guid: 7f8c7feab99e861479c02aee5b54b004
timeCreated: 1565145573
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections.Generic;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls <see cref="ImageTracker"/> in the scene, providing a few extensions in the Unity environment. Use <see cref="Tracker"/> directly when necessary.</para>
/// <para xml:lang="zh">在场景中控制<see cref="ImageTracker"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。如有需要可以直接使用<see cref="Tracker"/>。</para>
/// </summary>
public class ImageTrackerFrameFilter : FrameFilter, FrameFilter.IFeedbackFrameSink, FrameFilter.IOutputFrameSource
{
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible after Awake if available.</para>
/// <para xml:lang="zh">EasyAR Sense API,如果功能可以使用,可以在Awake之后访问。</para>
/// </summary>
public ImageTracker Tracker { get; private set; }
/// <summary>
/// <para xml:lang="en"><see cref="ImageTrackerMode"/> used when creating <see cref="Tracker"/>.</para>
/// <para xml:lang="zh">创建<see cref="Tracker"/>时所使用的<see cref="ImageTrackerMode"/>。</para>
/// </summary>
public ImageTrackerMode TrackerMode;
[HideInInspector, SerializeField]
private int simultaneousNum = 1;
private List<int> previousTargetIDs = new List<int>();
private Dictionary<int, TargetController> allTargetController = new Dictionary<int, TargetController>();
private bool isStarted;
/// <summary>
/// <para xml:lang="en">Target load finish event. The bool value indicates the load success or not.</para>
/// <para xml:lang="zh">Target加载完成的事件。bool值表示加载是否成功。</para>
/// </summary>
public event Action<ImageTargetController, Target, bool> TargetLoad;
/// <summary>
/// <para xml:lang="en">Target unload finish event. The bool value indicates the unload success or not.</para>
/// <para xml:lang="zh">Target卸载完成的事件。bool值表示卸载是否成功。</para>
/// </summary>
public event Action<ImageTargetController, Target, bool> TargetUnload;
private event Action SimultaneousNumChanged;
public override int BufferRequirement
{
get { return Tracker.bufferRequirement(); }
}
/// <summary>
/// <para xml:lang="en">The max number of targets which will be the simultaneously tracked by the tracker. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh">最大可被tracker跟踪的目标个数。可随时修改,立即生效。</para>
/// </summary>
public int SimultaneousNum
{
get
{
if (Tracker == null)
return simultaneousNum;
return Tracker.simultaneousNum();
}
set
{
if (Tracker == null)
{
simultaneousNum = value;
return;
}
simultaneousNum = value;
Tracker.setSimultaneousNum(simultaneousNum);
if (SimultaneousNumChanged != null)
{
SimultaneousNumChanged();
}
}
}
/// <summary>
/// <para xml:lang="en"><see cref="TargetController"/> that has been loaded.</para>
/// <para xml:lang="zh">已加载的<see cref="TargetController"/>。</para>
/// </summary>
public List<TargetController> TargetControllers
{
get
{
List<TargetController> list = new List<TargetController>();
foreach (var value in allTargetController.Values)
{
list.Add(value);
}
return list;
}
private set { }
}
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
if (!EasyARController.Initialized)
{
return;
}
if (!ImageTracker.isAvailable())
{
throw new UIPopupException(typeof(ImageTracker) + " not available");
}
Tracker = ImageTracker.createWithMode(TrackerMode);
Tracker.setSimultaneousNum(simultaneousNum);
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected virtual void OnEnable()
{
if (Tracker != null && isStarted)
{
Tracker.start();
}
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
isStarted = true;
if (enabled)
{
OnEnable();
}
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected virtual void OnDisable()
{
if (Tracker != null)
{
Tracker.stop();
}
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
foreach (var value in TargetControllers)
{
if (value is ImageTargetController)
{
UnloadTarget(value as ImageTargetController);
}
}
if (Tracker != null)
{
Tracker.Dispose();
}
}
/// <summary>
/// <para xml:lang="en">Load target.</para>
/// <para xml:lang="zh">加载target。</para>
/// </summary>
public void LoadTarget(ImageTargetController target)
{
if (target.Target != null && TryGetTargetController(target.Target.runtimeID()))
{
return;
}
target.Tracker = this;
}
/// <summary>
/// <para xml:lang="en">Unload target.</para>
/// <para xml:lang="zh">卸载target。</para>
/// </summary>
public void UnloadTarget(ImageTargetController target)
{
if (target.Target != null && !TryGetTargetController(target.Target.runtimeID()))
{
return;
}
target.Tracker = null;
}
public FeedbackFrameSink FeedbackFrameSink()
{
if (Tracker != null)
{
return Tracker.feedbackFrameSink();
}
return null;
}
public OutputFrameSource OutputFrameSource()
{
if (Tracker != null)
{
return Tracker.outputFrameSource();
}
return null;
}
public override void OnAssemble(ARSession session)
{
SimultaneousNumChanged += session.Assembly.ResetBufferCapacity;
}
public List<KeyValuePair<Optional<TargetController>, Matrix44F>> OnResult(Optional<FrameFilterResult> frameFilterResult)
{
var resultControllers = new List<KeyValuePair<Optional<TargetController>, Matrix44F>>();
var targetIDs = new List<int>();
var lostIDs = new List<int>();
if (frameFilterResult.OnSome)
{
var targetTrackerResult = frameFilterResult.Value as TargetTrackerResult;
foreach (var targetInstance in targetTrackerResult.targetInstances())
{
using (targetInstance)
{
if (targetInstance.status() != TargetStatus.Tracked)
{
continue;
}
var targetOptional = targetInstance.target();
if (targetOptional.OnNone)
{
continue;
}
using (var target = targetOptional.Value)
{
var controller = TryGetTargetController(target.runtimeID());
if (controller)
{
targetIDs.Add(target.runtimeID());
resultControllers.Add(new KeyValuePair<Optional<TargetController>, Matrix44F>(controller, targetInstance.pose()));
}
}
}
}
}
foreach (var id in previousTargetIDs)
{
lostIDs.Add(id);
}
foreach (var id in targetIDs)
{
if (lostIDs.Contains(id))
{
lostIDs.Remove(id);
}
var controller = TryGetTargetController(id);
if (controller && controller.IsLoaded)
{
controller.OnTracking(true);
}
}
foreach (var id in lostIDs)
{
var controller = TryGetTargetController(id);
if (controller)
{
controller.OnTracking(false);
}
}
previousTargetIDs = targetIDs;
return resultControllers;
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void LoadImageTarget(ImageTargetController controller, Action<Target, bool> callback)
{
Tracker.loadTarget(controller.Target, EasyARController.Scheduler, (target, status) =>
{
if (TargetLoad != null)
{
TargetLoad(controller, target, status);
}
if (callback != null)
{
callback(target, status);
}
});
allTargetController[controller.Target.runtimeID()] = controller;
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void UnloadImageTarget(ImageTargetController controller, Action<Target, bool> callback)
{
if (allTargetController.Remove(controller.Target.runtimeID()))
{
controller.OnTracking(false);
Tracker.unloadTarget(controller.Target, EasyARController.Scheduler, (target, status) =>
{
if (TargetUnload != null)
{
TargetUnload(controller, target, status);
}
if (callback != null)
{
callback(target, status);
}
});
}
}
protected override void OnHFlipChange(bool hFlip)
{
foreach (var value in allTargetController.Values)
{
value.HorizontalFlip = hFlip;
}
}
private TargetController TryGetTargetController(int runtimeID)
{
TargetController controller;
if (allTargetController.TryGetValue(runtimeID, out controller))
return controller;
return null;
}
}
}
fileFormatVersion: 2
guid: 9f3bd5189df208f4ead26ed7eabd92cf
timeCreated: 1562827993
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls <see cref="ObjectTarget"/> in the scene, providing a few extensions in the Unity environment. Use <see cref="Target"/> directly when necessary.</para>
/// <para xml:lang="zh">在场景中控制<see cref="ObjectTarget"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。如有需要可以直接使用<see cref="Target"/>。</para>
/// </summary>
public class ObjectTargetController : TargetController
{
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible after TargetAvailable event.</para>
/// <para xml:lang="zh">EasyAR Sense API,可以在TargetAvailable event之后访问。</para>
/// </summary>
public ObjectTarget Target { get; private set; }
/// <summary>
/// <para xml:lang="en">Target data source.</para>
/// <para xml:lang="zh">Target数据来源。</para>
/// </summary>
public DataSource SourceType = DataSource.ObjFile;
/// <summary>
/// <para xml:lang="en">Obj file data source for target creation. Valid when <see cref="SourceType"/> == <see cref="DataSource.ObjFile"/>.</para>
/// <para xml:lang="zh">创建target的obj文件数据来源。在<see cref="SourceType"/> == <see cref="DataSource.ObjFile"/>的时候有效。</para>
/// </summary>
[HideInInspector, SerializeField]
public ObjFileSourceData ObjFileSource = new ObjFileSourceData();
/// <summary>
/// <para xml:lang="en">Target source when using a target already created. Valid when <see cref="SourceType"/> == <see cref="DataSource.Target"/>.</para>
/// <para xml:lang="zh">直接使用创建好的target时的target来源。在<see cref="SourceType"/> == <see cref="DataSource.Target"/>的时候有效。</para>
/// </summary>
public ObjectTarget TargetSource;
[HideInInspector, SerializeField]
private bool trackerHasSet;
[HideInInspector, SerializeField]
private ObjectTrackerFrameFilter tracker;
private ObjectTrackerFrameFilter loader;
private float scale = 1;
private float scaleX = 1;
private bool preHFlip;
/// <summary>
/// <para xml:lang="en">Event when <see cref="Target"/> can be used.</para>
/// <para xml:lang="zh"><see cref="Target"/> 可以使用的事件。</para>
/// </summary>
public event Action TargetAvailable;
/// <summary>
/// <para xml:lang="en">Target load finish event. The bool value indicates the load success or not.</para>
/// <para xml:lang="zh">Target加载完成的事件。bool值表示加载是否成功。</para>
/// </summary>
public event Action<Target, bool> TargetLoad;
/// <summary>
/// <para xml:lang="en">Target unload finish event. The bool value indicates the unload success or not.</para>
/// <para xml:lang="zh">Target卸载完成的事件。bool值表示卸载是否成功。</para>
/// </summary>
public event Action<Target, bool> TargetUnload;
/// <summary>
/// <para xml:lang="en">Target data source type.</para>
/// <para xml:lang="zh">Target数据来源类型。</para>
/// </summary>
public enum DataSource
{
/// <summary>
/// <para xml:lang="en">Obj file and other files related.</para>
/// <para xml:lang="zh">obj模型文件及相关其它文件。</para>
/// </summary>
ObjFile,
/// <summary>
/// <para xml:lang="en"><see cref="ImageTarget"/> object.</para>
/// <para xml:lang="zh"><see cref="ImageTarget"/>对象。</para>
/// </summary>
Target,
}
/// <summary>
/// <para xml:lang="en">The <see cref="ImageTrackerFrameFilter"/> which loads the target after <see cref="TargetAvailable"/>. When set to null, the target will be unloaded from tracker previously set. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh">在<see cref="TargetAvailable"/>之后加载target的<see cref="ImageTrackerFrameFilter"/>。如果设为null,target将会被从之前设置的tracker中卸载。可随时修改,立即生效。</para>
/// </summary>
public ObjectTrackerFrameFilter Tracker
{
get
{
return tracker;
}
set
{
tracker = value;
UpdateTargetInTracker();
}
}
/// <summary>
/// <para xml:lang="en">Bounding box of the target.</para>
/// <para xml:lang="zh">Target的包围盒。</para>
/// </summary>
public List<Vector3> BoundingBox
{
get
{
var boundingBox = new List<Vector3>();
if (Target == null)
{
return boundingBox;
}
var boundingBoxVec3F = Target.boundingBox();
foreach (var box in boundingBoxVec3F)
{
boundingBox.Add(box.ToUnityVector());
}
return boundingBox;
}
private set { }
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected override void Start()
{
base.Start();
if (!EasyARController.Initialized)
{
return;
}
switch (SourceType)
{
case DataSource.ObjFile:
LoadObjFile(new ObjFileSourceData()
{
PathType = ObjFileSource.PathType,
ObjPath = ObjFileSource.ObjPath,
ExtraFilePaths = ObjFileSource.ExtraFilePaths,
Name = ObjFileSource.Name,
Scale = ObjFileSource.Scale
});
break;
case DataSource.Target:
LoadTarget(TargetSource);
break;
default:
break;
}
}
/// <summary>
/// MonoBehaviour Update
/// </summary>
protected virtual void Update()
{
CheckScale();
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
if (tracker)
{
tracker = null;
UpdateTargetInTracker();
}
if (Target != null)
{
Target.Dispose();
Target = null;
}
}
protected override void OnTracking()
{
CheckScale();
}
private void LoadObjFile(ObjFileSourceData source)
{
EasyARController.Instance.StartCoroutine(LoadObjFileFromSource(source));
}
private void LoadTarget(ObjectTarget source)
{
Target = source;
if (Target != null && TargetAvailable != null)
{
TargetAvailable();
}
UpdateScale();
UpdateTargetInTracker();
}
private IEnumerator LoadObjFileFromSource(ObjFileSourceData source)
{
using (var objBufferDic = new BufferDictionary())
{
yield return EasyARController.Instance.StartCoroutine(FileUtil.LoadFile(source.ObjPath, source.PathType, (Buffer buffer) =>
{
objBufferDic.set(FileUtil.PathToUrl(source.ObjPath), buffer.Clone());
}));
foreach (var filePath in source.ExtraFilePaths)
{
yield return EasyARController.Instance.StartCoroutine(FileUtil.LoadFile(filePath, source.PathType, (Buffer buffer) =>
{
objBufferDic.set(FileUtil.PathToUrl(filePath), buffer.Clone());
}));
}
using (var param = new ObjectTargetParameters())
{
param.setBufferDictionary(objBufferDic);
param.setObjPath(FileUtil.PathToUrl(source.ObjPath));
param.setName(source.Name);
param.setScale(source.Scale);
param.setUid(Guid.NewGuid().ToString());
param.setMeta(string.Empty);
var targetOptional = ObjectTarget.createFromParameters(param);
if (targetOptional.OnSome)
{
Target = targetOptional.Value;
if (Target != null && TargetAvailable != null)
{
TargetAvailable();
}
}
else
{
throw new Exception("invalid parameter");
}
}
}
UpdateTargetInTracker();
}
private void UpdateTargetInTracker()
{
if (Target == null)
{
return;
}
if (loader && loader != tracker)
{
loader.UnloadObjectTarget(this, (target, status) =>
{
if (TargetUnload != null)
{
TargetUnload(target, status);
}
if (status)
{
IsLoaded = false;
}
});
loader = null;
}
if (tracker && tracker != loader)
{
var trackerLoad = tracker;
tracker.LoadObjectTarget(this, (target, status) =>
{
if (trackerLoad == tracker && !status)
{
loader = null;
}
UpdateScale();
if (TargetLoad != null)
{
TargetLoad(target, status);
}
IsLoaded = status;
});
loader = tracker;
}
}
private void UpdateScale()
{
if (Target == null)
return;
scale = Target.scale();
var vec3Unit = Vector3.one;
if (HorizontalFlip)
{
vec3Unit.x = -vec3Unit.x;
}
transform.localScale = vec3Unit * scale;
scaleX = transform.localScale.x;
preHFlip = HorizontalFlip;
}
private void CheckScale()
{
if (Target == null)
return;
if (scaleX != transform.localScale.x)
{
Target.setScale(Math.Abs(transform.localScale.x));
UpdateScale();
}
else if (scale != transform.localScale.y)
{
Target.setScale(Math.Abs(transform.localScale.y));
UpdateScale();
}
else if (scale != transform.localScale.z)
{
Target.setScale(Math.Abs(transform.localScale.z));
UpdateScale();
}
else if (scale != Target.scale())
{
UpdateScale();
}
else if (preHFlip != HorizontalFlip)
{
UpdateScale();
}
}
/// <summary>
/// <para xml:lang="en">Obj file data for target creation.</para>
/// <para xml:lang="zh">创建target的obj文件数据。</para>
/// </summary>
[Serializable]
public class ObjFileSourceData
{
/// <summary>
/// <para xml:lang="en">File path type.</para>
/// <para xml:lang="zh">文件路径类型。</para>
/// </summary>
public PathType PathType = PathType.StreamingAssets;
/// <summary>
/// <para xml:lang="en">Obj file path.</para>
/// <para xml:lang="zh">Obj文件路径。</para>
/// </summary>
public string ObjPath = string.Empty;
/// <summary>
/// <para xml:lang="en">extra file paths referenced in obj file and other files, like *.mtl, *jpg, *.png. These files are usually multiple textures and mtl files.</para>
/// <para xml:lang="zh">Obj文件及其它文件中引用的额外文件路径,如:*.mtl, *.jpg, *.png等。这些文件一般由多个贴图文件,和mtl组成。</para>
/// </summary>
public List<string> ExtraFilePaths = new List<string>();
/// <summary>
/// <para xml:lang="en">Target name.</para>
/// <para xml:lang="zh">Target名字。</para>
/// </summary>
public string Name = string.Empty;
/// <summary>
/// <para xml:lang="en">Target scale in meter. Reference <see cref="ObjectTarget.scale"/>.</para>
/// <para xml:lang="zh">Target的缩放比例,单位为米。参考<see cref="ObjectTarget.scale"/>。</para>
/// </summary>
public float Scale = 1;
}
}
}
fileFormatVersion: 2
guid: 0ff35655088776a47b310bb584d9ac6e
timeCreated: 1567050081
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections.Generic;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en"><see cref="MonoBehaviour"/> which controls <see cref="ObjectTracker"/> in the scene, providing a few extensions in the Unity environment. Use <see cref="Tracker"/> directly when necessary.</para>
/// <para xml:lang="zh">在场景中控制<see cref="ObjectTracker"/>的<see cref="MonoBehaviour"/>,在Unity环境下提供功能扩展。如有需要可以直接使用<see cref="Tracker"/>。</para>
/// </summary>
public class ObjectTrackerFrameFilter : FrameFilter, FrameFilter.IFeedbackFrameSink, FrameFilter.IOutputFrameSource
{
/// <summary>
/// <para xml:lang="en">EasyAR Sense API. Accessible after Awake if available.</para>
/// <para xml:lang="zh">EasyAR Sense API,如果功能可以使用,可以在Awake之后访问。</para>
/// </summary>
public ObjectTracker Tracker { get; private set; }
[HideInInspector, SerializeField]
private int simultaneousNum = 1;
private List<int> previousTargetIDs = new List<int>();
private Dictionary<int, TargetController> allTargetController = new Dictionary<int, TargetController>();
private bool isStarted;
/// <summary>
/// <para xml:lang="en">Target load finish event. The bool value indicates the load success or not.</para>
/// <para xml:lang="zh">Target加载完成的事件。bool值表示加载是否成功。</para>
/// </summary>
public event Action<ObjectTargetController, Target, bool> TargetLoad;
/// <summary>
/// <para xml:lang="en">Target unload finish event. The bool value indicates the unload success or not.</para>
/// <para xml:lang="zh">Target卸载完成的事件。bool值表示卸载是否成功。</para>
/// </summary>
public event Action<ObjectTargetController, Target, bool> TargetUnload;
private event Action SimultaneousNumChanged;
public override int BufferRequirement
{
get { return Tracker.bufferRequirement(); }
}
/// <summary>
/// <para xml:lang="en">The max number of targets which will be the simultaneously tracked by the tracker. Modify at any time and takes effect immediately.</para>
/// <para xml:lang="zh">最大可被tracker跟踪的目标个数。可随时修改,立即生效。</para>
/// </summary>
public int SimultaneousNum
{
get
{
if (Tracker == null)
return simultaneousNum;
return Tracker.simultaneousNum();
}
set
{
if (Tracker == null)
{
simultaneousNum = value;
return;
}
simultaneousNum = value;
Tracker.setSimultaneousNum(simultaneousNum);
if (SimultaneousNumChanged != null)
{
SimultaneousNumChanged();
}
}
}
/// <summary>
/// <para xml:lang="en"><see cref="TargetController"/> that has been loaded.</para>
/// <para xml:lang="zh">已加载的<see cref="TargetController"/>。</para>
/// </summary>
public List<TargetController> TargetControllers
{
get
{
List<TargetController> list = new List<TargetController>();
foreach (var value in allTargetController.Values)
{
list.Add(value);
}
return list;
}
private set { }
}
/// <summary>
/// MonoBehaviour Awake
/// </summary>
protected virtual void Awake()
{
if (!EasyARController.Initialized)
{
return;
}
if (!ObjectTracker.isAvailable())
{
throw new UIPopupException(typeof(ObjectTracker) + " not available");
}
Tracker = ObjectTracker.create();
Tracker.setSimultaneousNum(simultaneousNum);
}
/// <summary>
/// MonoBehaviour OnEnable
/// </summary>
protected virtual void OnEnable()
{
if (Tracker != null && isStarted)
{
Tracker.start();
}
}
/// <summary>
/// MonoBehaviour Start
/// </summary>
protected virtual void Start()
{
isStarted = true;
if (enabled)
{
OnEnable();
}
}
/// <summary>
/// MonoBehaviour OnDisable
/// </summary>
protected virtual void OnDisable()
{
if (Tracker != null)
{
Tracker.stop();
}
}
/// <summary>
/// MonoBehaviour OnDestroy
/// </summary>
protected virtual void OnDestroy()
{
foreach (var value in TargetControllers)
{
if (value is ObjectTargetController)
{
UnloadTarget(value as ObjectTargetController);
}
}
if (Tracker != null)
{
Tracker.Dispose();
}
}
/// <summary>
/// <para xml:lang="en">Load target.</para>
/// <para xml:lang="zh">加载target。</para>
/// </summary>
public void LoadTarget(ObjectTargetController target)
{
if (target.Target != null && TryGetTargetController(target.Target.runtimeID()))
{
return;
}
target.Tracker = this;
}
/// <summary>
/// <para xml:lang="en">Unload target.</para>
/// <para xml:lang="zh">卸载target。</para>
/// </summary>
public void UnloadTarget(ObjectTargetController target)
{
if (target.Target != null && !TryGetTargetController(target.Target.runtimeID()))
{
return;
}
target.Tracker = null;
}
public FeedbackFrameSink FeedbackFrameSink()
{
if (Tracker != null)
{
return Tracker.feedbackFrameSink();
}
return null;
}
public OutputFrameSource OutputFrameSource()
{
if (Tracker != null)
{
return Tracker.outputFrameSource();
}
return null;
}
public override void OnAssemble(ARSession session)
{
SimultaneousNumChanged += session.Assembly.ResetBufferCapacity;
}
public List<KeyValuePair<Optional<TargetController>, Matrix44F>> OnResult(Optional<FrameFilterResult> frameFilterResult)
{
var resultControllers = new List<KeyValuePair<Optional<TargetController>, Matrix44F>>();
var targetIDs = new List<int>();
var lostIDs = new List<int>();
if (frameFilterResult.OnSome)
{
var targetTrackerResult = frameFilterResult.Value as TargetTrackerResult;
foreach (var targetInstance in targetTrackerResult.targetInstances())
{
using (targetInstance)
{
if (targetInstance.status() != TargetStatus.Tracked)
{
continue;
}
var targetOptional = targetInstance.target();
if (targetOptional.OnNone)
{
continue;
}
using (var target = targetOptional.Value)
{
var controller = TryGetTargetController(target.runtimeID());
if (controller)
{
targetIDs.Add(target.runtimeID());
resultControllers.Add(new KeyValuePair<Optional<TargetController>, Matrix44F>(controller, targetInstance.pose()));
}
}
}
}
}
foreach (var id in previousTargetIDs)
{
lostIDs.Add(id);
}
foreach (var id in targetIDs)
{
if (lostIDs.Contains(id))
{
lostIDs.Remove(id);
}
var controller = TryGetTargetController(id);
if (controller && controller.IsLoaded)
{
controller.OnTracking(true);
}
}
foreach (var id in lostIDs)
{
var controller = TryGetTargetController(id);
if (controller)
{
controller.OnTracking(false);
}
}
previousTargetIDs = targetIDs;
return resultControllers;
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void LoadObjectTarget(ObjectTargetController controller, Action<Target, bool> callback)
{
Tracker.loadTarget(controller.Target, EasyARController.Scheduler, (target, status) =>
{
if (TargetLoad != null)
{
TargetLoad(controller, target, status);
}
if (callback != null)
{
callback(target, status);
}
});
allTargetController[controller.Target.runtimeID()] = controller;
}
/// <summary>
/// <para xml:lang="en">Internal method, do not call directly.</para>
/// <para xml:lang="zh">内部方法,不可直接调用。</para>
/// </summary>
internal void UnloadObjectTarget(ObjectTargetController controller, Action<Target, bool> callback)
{
if (allTargetController.Remove(controller.Target.runtimeID()))
{
controller.OnTracking(false);
Tracker.unloadTarget(controller.Target, EasyARController.Scheduler, (target, status) =>
{
if (TargetUnload != null)
{
TargetUnload(controller, target, status);
}
if (callback != null)
{
callback(target, status);
}
});
}
}
protected override void OnHFlipChange(bool hFlip)
{
foreach (var value in allTargetController.Values)
{
value.HorizontalFlip = hFlip;
}
}
private TargetController TryGetTargetController(int runtimeID)
{
TargetController controller;
if (allTargetController.TryGetValue(runtimeID, out controller))
return controller;
return null;
}
}
}
fileFormatVersion: 2
guid: 94fcb23ff8defe44ba8c666e197fbcb7
timeCreated: 1567050081
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: accc7175cede8514d86612b278185ce8
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
//=============================================================================================================================
//
// EasyAR Sense 4.2.0.8700-7bcbc8b1c
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//=============================================================================================================================
using System;
using System.Collections.Generic;
namespace easyar
{
public class AliasAttribute : Attribute { }
public class RecordAttribute : Attribute { }
public class TaggedUnionAttribute : Attribute { }
public class TagAttribute : Attribute { }
public class TupleAttribute : Attribute { }
[Record]
public struct Unit { }
public enum OptionalTag
{
None = 0,
Some = 1
}
[TaggedUnion]
public struct Optional<T>
{
[Tag] public OptionalTag _Tag;
public Unit None;
public T Some;
public static Optional<T> CreateNone() { return new Optional<T> { _Tag = OptionalTag.None, None = new Unit() }; }
public static Optional<T> CreateSome(T Value) { return new Optional<T> { _Tag = OptionalTag.Some, Some = Value }; }
public Boolean OnNone { get { return _Tag == OptionalTag.None; } }
public Boolean OnSome { get { return _Tag == OptionalTag.Some; } }
public static Optional<T> Empty { get { return CreateNone(); } }
public static implicit operator Optional<T>(T v)
{
if (v == null)
{
return CreateNone();
}
else
{
return CreateSome(v);
}
}
public static explicit operator T(Optional<T> v)
{
if (v.OnNone)
{
throw new InvalidOperationException();
}
return v.Some;
}
public static Boolean operator ==(Optional<T> Left, Optional<T> Right)
{
return Equals(Left, Right);
}
public static Boolean operator !=(Optional<T> Left, Optional<T> Right)
{
return !Equals(Left, Right);
}
public static Boolean operator ==(Optional<T>? Left, Optional<T>? Right)
{
return Equals(Left, Right);
}
public static Boolean operator !=(Optional<T>? Left, Optional<T>? Right)
{
return !Equals(Left, Right);
}
public override Boolean Equals(Object obj)
{
if (obj == null) { return Equals(this, null); }
if (obj.GetType() != typeof(Optional<T>)) { return false; }
var o = (Optional<T>)(obj);
return Equals(this, o);
}
public override Int32 GetHashCode()
{
if (OnNone) { return 0; }
return Some.GetHashCode();
}
private static Boolean Equals(Optional<T> Left, Optional<T> Right)
{
if (Left.OnNone && Right.OnNone)
{
return true;
}
if (Left.OnNone || Right.OnNone)
{
return false;
}
return Left.Some.Equals(Right.Some);
}
private static Boolean Equals(Optional<T>? Left, Optional<T>? Right)
{
if ((!Left.HasValue || Left.Value.OnNone) && (!Right.HasValue || Right.Value.OnNone))
{
return true;
}
if (!Left.HasValue || Left.Value.OnNone || !Right.HasValue || Right.Value.OnNone)
{
return false;
}
return Equals(Left.Value, Right.Value);
}
public T Value
{
get
{
if (OnSome)
{
return Some;
}
else
{
throw new InvalidOperationException();
}
}
}
public T ValueOrDefault(T Default)
{
if (OnSome)
{
return Some;
}
else
{
return Default;
}
}
public override String ToString()
{
if (OnSome)
{
return Some.ToString();
}
else
{
return "-";
}
}
}
}
\ No newline at end of file
fileFormatVersion: 2
guid: 2c1397f7d2f3b3444a269a14e7108300
timeCreated: 1596785131
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 3971d28093524684abbdc6e3c0dce77d
folderAsset: yes
timeCreated: 1575517077
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en">Extend EasyAR Sense API and Unity API for convenience to do operations like data conversion.</para>
/// <para xml:lang="zh">扩展EasyAR Sense API 及 Unity API,为数据转换等操作提供便利。</para>
/// </summary>
public static class APIExtend
{
/// <summary>
/// <para xml:lang="en">Convert <see cref="Matrix44F"/> to <see cref="Matrix4x4"/>.</para>
/// <para xml:lang="zh">将<see cref="Matrix44F"/>转成<see cref="Matrix4x4"/>。</para>
/// </summary>
public static Matrix4x4 ToUnityMatrix(this Matrix44F matrix44F)
{
var matrix4x4 = new Matrix4x4();
matrix4x4.SetRow(0, new Vector4(matrix44F.data_0, matrix44F.data_1, matrix44F.data_2, matrix44F.data_3));
matrix4x4.SetRow(1, new Vector4(matrix44F.data_4, matrix44F.data_5, matrix44F.data_6, matrix44F.data_7));
matrix4x4.SetRow(2, new Vector4(matrix44F.data_8, matrix44F.data_9, matrix44F.data_10, matrix44F.data_11));
matrix4x4.SetRow(3, new Vector4(matrix44F.data_12, matrix44F.data_13, matrix44F.data_14, matrix44F.data_15));
return matrix4x4;
}
/// <summary>
/// <para xml:lang="en">Convert <see cref="Vector2"/> to <see cref="Vec2F"/>.</para>
/// <para xml:lang="zh">将<see cref="Vector2"/>转成<see cref="Vec2F"/>。</para>
/// </summary>
public static Vec2F ToEasyARVector(this Vector2 vec2)
{
return new Vec2F(vec2.x, vec2.y);
}
/// <summary>
/// <para xml:lang="en">Convert <see cref="Vector3"/> to <see cref="Vec3F"/>.</para>
/// <para xml:lang="zh">将<see cref="Vector3"/>转成<see cref="Vec3F"/>。</para>
/// </summary>
public static Vec3F ToEasyARVector(this Vector3 vec3)
{
return new Vec3F(vec3.x, vec3.y, vec3.z);
}
/// <summary>
/// <para xml:lang="en">Convert <see cref="Vec2F"/> to <see cref="Vector2"/>.</para>
/// <para xml:lang="zh">将<see cref="Vec2F"/>转成<see cref="Vector2"/>。</para>
/// </summary>
public static Vector2 ToUnityVector(this Vec2F vec2)
{
return new Vector2(vec2.data_0, vec2.data_1);
}
/// <summary>
/// <para xml:lang="en">Convert <see cref="Vec3F"/> to <see cref="Vector3"/>.</para>
/// <para xml:lang="zh">将<see cref="Vec3F"/>转成<see cref="Vector3"/>。</para>
/// </summary>
public static Vector3 ToUnityVector(this Vec3F vec3)
{
return new Vector3(vec3.data_0, vec3.data_1, vec3.data_2);
}
}
}
fileFormatVersion: 2
guid: d3e13952a6abbd64f8135dfad94045fd
timeCreated: 1575791530
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections;
using UnityEngine;
#if UNITY_2019_2_OR_NEWER
using UnityEngine.Networking;
#endif
namespace easyar
{
/// <summary>
/// <para xml:lang="en">Path type.</para>
/// <para xml:lang="zh">路径类型。</para>
/// </summary>
public enum PathType
{
/// <summary>
/// <para xml:lang="en">Absolute path.</para>
/// <para xml:lang="zh">绝对路径。</para>
/// </summary>
Absolute,
/// <summary>
/// <para xml:lang="en">Unity StreamingAssets path.</para>
/// <para xml:lang="zh">UnityStreamingAssets路径。</para>
/// </summary>
StreamingAssets,
/// <summary>
/// <para xml:lang="en">Not file storage.</para>
/// <para xml:lang="zh">不是文件存储。</para>
/// </summary>
None,
}
/// <summary>
/// <para xml:lang="en">Output file path type.</para>
/// <para xml:lang="zh">文件输出路径类型。</para>
/// </summary>
public enum WritablePathType
{
/// <summary>
/// <para xml:lang="en">Absolute path.</para>
/// <para xml:lang="zh">绝对路径。</para>
/// </summary>
Absolute,
/// <summary>
/// <para xml:lang="en">Unity persistent data path.</para>
/// <para xml:lang="zh">Unity沙盒路径。</para>
/// </summary>
PersistentDataPath,
}
/// <summary>
/// <para xml:lang="en">File utility.</para>
/// <para xml:lang="zh">文件工具。</para>
/// </summary>
public static class FileUtil
{
/// <summary>
/// <para xml:lang="en">Async Load file and return <see cref="Buffer"/> object in the callback.</para>
/// <para xml:lang="zh">异步加载文件,回调返回<see cref="Buffer"/>对象。</para>
/// </summary>
public static IEnumerator LoadFile(string filePath, PathType filePathType, Action<Buffer> onLoad)
{
return LoadFile(filePath, filePathType, (data) =>
{
if (onLoad == null)
{
return;
}
using (var buffer = Buffer.wrapByteArray(data))
{
onLoad(buffer);
}
});
}
/// <summary>
/// <para xml:lang="en">Async Load file and return byte array in the callback.</para>
/// <para xml:lang="zh">异步加载文件,回调返回字节数组。</para>
/// </summary>
public static IEnumerator LoadFile(string filePath, PathType filePathType, Action<byte[]> onLoad, Action<string> onError = null)
{
if (onLoad == null)
{
yield break;
}
var path = filePath;
if (filePathType == PathType.StreamingAssets)
{
path = Application.streamingAssetsPath + "/" + path;
}
byte[] data;
#if UNITY_2019_2_OR_NEWER
using (var handle = new DownloadHandlerBuffer())
{
var webRequest = new UnityWebRequest(PathToUrl(path), "GET", handle, null);
webRequest.Send();
while (!handle.isDone)
{
yield return 0;
}
if (!string.IsNullOrEmpty(webRequest.error))
{
if (onError != null)
{
onError(webRequest.error);
}
else
{
Debug.LogError(webRequest.error);
}
yield break;
}
data = handle.data;
}
#else
using (var www = new WWW(PathToUrl(path)))
{
while (!www.isDone)
{
yield return 0;
}
if (!string.IsNullOrEmpty(www.error))
{
if (onError != null)
{
onError(www.error);
}
else
{
Debug.LogError(www.error);
}
yield break;
}
data = www.bytes;
}
#endif
onLoad(data);
}
/// <summary>
/// <para xml:lang="en">Convert file path to URL.</para>
/// <para xml:lang="zh">将路径转换成URL。</para>
/// </summary>
public static string PathToUrl(string path)
{
if (string.IsNullOrEmpty(path) || path.StartsWith("jar:file://") || path.StartsWith("file://") || path.StartsWith("http://") || path.StartsWith("https://"))
{
return path;
}
if (Application.platform == RuntimePlatform.OSXEditor ||
Application.platform == RuntimePlatform.OSXPlayer ||
Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.Android)
{
path = "file://" + path;
}
else if (Application.platform == RuntimePlatform.WindowsEditor || Application.platform == RuntimePlatform.WindowsPlayer)
{
path = "file:///" + path;
}
return path;
}
}
}
fileFormatVersion: 2
guid: 2706c7d09c0a0dc4db35eaaf2787e84b
timeCreated: 1575791895
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//================================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//================================================================================================================================
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en">Popup for message notification. The popup action can be globally controlled using <see cref="EasyARController.ShowPopupMessage"/>.</para>
/// <para xml:lang="zh">消息提示弹窗。是否需要显示弹窗可以通过<see cref="EasyARController.ShowPopupMessage"/>来进行全局控制。</para>
/// </summary>
public class GUIPopup : MonoBehaviour
{
private static GUIPopup popup;
private readonly Queue<KeyValuePair<string, float>> messageQueue = new Queue<KeyValuePair<string, float>>();
private bool isShowing;
private bool isDisappearing;
private GUISkin skin;
private void Start()
{
skin = Instantiate(Resources.Load<GUISkin>("EasyAR/GUISkin/GUIPopup"));
StartCoroutine(ShowMessage());
}
private void OnDestroy()
{
if (skin)
{
Destroy(skin);
}
}
/// <summary>
/// <para xml:lang="en">Add one message and its duration for display.</para>
/// <para xml:lang="zh">添加一条要显示的消息及时长。</para>
/// </summary>
public static void EnqueueMessage(string message, float seconds)
{
if (EasyARController.Instance && !EasyARController.Instance.ShowPopupMessage)
{
Debug.Log(message);
return;
}
if (popup == null)
{
var go = new GameObject("MessagePopup");
popup = go.AddComponent<GUIPopup>();
}
popup.messageQueue.Enqueue(new KeyValuePair<string, float>(message, seconds));
}
private IEnumerator ShowMessage()
{
while (true)
{
if (EasyARController.Instance && !EasyARController.Instance.ShowPopupMessage)
{
while (messageQueue.Count > 0)
{
var message = messageQueue.Dequeue();
Debug.Log(message);
}
}
if (messageQueue.Count > 0)
{
if (skin)
{
var color = skin.GetStyle("box").normal.textColor;
color.a = 0;
skin.GetStyle("box").normal.textColor = color;
}
isShowing = true;
isDisappearing = false;
var time = messageQueue.Peek().Value;
yield return new WaitForSeconds(time > 1 ? time - 0.5f : time / 2);
isDisappearing = true;
yield return new WaitForSeconds(time > 1 ? 0.5f : time / 2);
messageQueue.Dequeue();
isShowing = false;
}
else
{
yield return 0;
}
}
}
private void OnGUI()
{
if (!isShowing || !skin)
{
return;
}
var color = skin.GetStyle("box").normal.textColor;
color.a += isDisappearing ? -Time.deltaTime * 2 : Time.deltaTime * 2;
color.a = color.a > 1 ? 1 : (color.a < 0 ? 0 : color.a);
skin.GetStyle("box").normal.textColor = color;
GUI.Box(new Rect(0, Screen.height / 2, Screen.width, Math.Min(Screen.height / 4, 160)), messageQueue.Peek().Key, skin.GetStyle("box"));
}
}
/// <summary>
/// <para xml:lang="en">Exception that need popup for notification.</para>
/// <para xml:lang="zh">需要通过弹窗提示的异常。</para>
/// </summary>
public class UIPopupException : Exception
{
public UIPopupException(string message, float seconds) : base(message)
{
GUIPopup.EnqueueMessage(message, seconds);
}
public UIPopupException(string message) : this(message, 10)
{
}
}
}
fileFormatVersion: 2
guid: effd791dd15155143ac1a35656afd27b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
//=============================================================================================================================
//
// Copyright (c) 2015-2021 VisionStar Information Technology (Shanghai) Co., Ltd. All Rights Reserved.
// EasyAR is the registered trademark or trademark of VisionStar Information Technology (Shanghai) Co., Ltd in China
// and other countries for the augmented reality technology developed by VisionStar Information Technology (Shanghai) Co., Ltd.
//
//=============================================================================================================================
using System;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
namespace easyar
{
/// <summary>
/// <para xml:lang="en">Thread worker, to do async tasks in worker thread. All tasks pushed into the worker are ensured to finish before the worker dispose.</para>
/// <para xml:lang="zh">线程工作器,负责在工作线程上处理异步任务。所有推送到工作器的任务会被保证在销毁前运行。</para>
/// </summary>
public class ThreadWorker : IDisposable
{
private Thread thread;
private bool finished;
private Queue<Action> queue = new Queue<Action>();
~ThreadWorker()
{
Finish();
}
/// <summary>
/// <para xml:lang="en">Dispose resources.</para>
/// <para xml:lang="zh">销毁资源。</para>
/// </summary>
public void Dispose()
{
Finish();
GC.SuppressFinalize(this);
}
/// <summary>
/// <para xml:lang="en">Run <paramref name="task"/> in worker thread.</para>
/// <para xml:lang="zh">在工作线程上运行任务<paramref name="task"/>。</para>
/// </summary>
public void Run(Action task)
{
if (thread == null)
{
CreateThread();
}
Monitor.Enter(queue);
try
{
if (finished)
{
return;
}
queue.Enqueue(task);
Monitor.PulseAll(queue);
}
finally
{
Monitor.Exit(queue);
}
}
private void CreateThread()
{
thread = new Thread(() =>
{
while (!finished)
{
Action task = null;
Monitor.Enter(queue);
try
{
while (!finished && queue.Count == 0)
{
Monitor.Wait(queue);
}
if (queue.Count > 0)
{
task = queue.Dequeue();
}
}
finally
{
Monitor.Exit(queue);
}
if (task != null)
{
try
{
task();
}
catch (Exception ex)
{
Debug.LogError(ex.ToString());
}
}
if (finished)
{
while (queue.Count > 0)
{
task = queue.Dequeue();
if (task != null)
{
try
{
task();
}
catch (Exception ex)
{
Debug.LogError(ex.ToString());
}
}
}
}
}
});
thread.Start();
}
private void Finish()
{
if (thread == null || !thread.IsAlive)
{
return;
}
Monitor.Enter(queue);
try
{
finished = true;
Monitor.PulseAll(queue);
}
finally
{
Monitor.Exit(queue);
}
thread.Join();
}
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment