223 lines
7.9 KiB
C#
223 lines
7.9 KiB
C#
// Copyright 2016 Google Inc. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using UnityEngine.Events;
|
|
using UnityEngine.EventSystems;
|
|
using System.Collections;
|
|
|
|
// This class is an implementation of Basetile in which the image on each tile
|
|
// zooms inward and scrolls along with the controller retical as it is hovering
|
|
// over the tile. The edges of the image are masked off if they go beyond the
|
|
// bounding rectangle of the tile.
|
|
public class MaskedTile : BaseTile {
|
|
#if UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
private const string OBJ_NAME_MASKED_IMAGE = "MaskedImage";
|
|
|
|
private const float PARENT_CHANGE_THRESHOLD_PERCENT = 0.33f;
|
|
|
|
private Image maskedImage;
|
|
private GameObject maskedImageObject;
|
|
|
|
private Vector3 originalMaskedPosition; // Start position when pointer is not on tile.
|
|
private Vector3 maskedScrollOffset;
|
|
private Vector2 originalImageSize;
|
|
private Vector2 enlargedImageSize;
|
|
private float desiredPositionZ;
|
|
|
|
[Range(0.1f, 0.5f)]
|
|
[Tooltip("Image scroll amount when the pointer over the tile.")]
|
|
public float movementWeight = 0.15f;
|
|
|
|
[Range(1.1f, 2.0f)]
|
|
[Tooltip("Image scale amount when the pointer over the tile.")]
|
|
public float scaleWeight = 1.4f;
|
|
|
|
[Range(0.01f, 0.2f)]
|
|
[Tooltip("Tile forward distance when the pointer over the tile.")]
|
|
public float hoverPositionZMeters = 0.125f;
|
|
|
|
[Range(0.1f, 10.0f)]
|
|
[Tooltip("Speed used for lerping the rotation/scale/position of the tile.")]
|
|
public float interpolationSpeed = 8.0f;
|
|
|
|
protected override void Awake() {
|
|
base.Awake();
|
|
|
|
// Get current image.
|
|
Image image = GetComponent<Image>();
|
|
|
|
// Create mask.
|
|
gameObject.AddComponent<RectMask2D>();
|
|
|
|
// Save size data.
|
|
originalImageSize = image.rectTransform.sizeDelta;
|
|
enlargedImageSize = originalImageSize;
|
|
enlargedImageSize.x *= scaleWeight;
|
|
enlargedImageSize.y *= scaleWeight;
|
|
|
|
// Save position data.
|
|
originalMaskedPosition = new Vector3(originalImageSize.x / 2.0f, -originalImageSize.y / 2.0f, 0);
|
|
|
|
// Set data that varies.
|
|
maskedScrollOffset = Vector3.zero;
|
|
|
|
// Create game object for masked image.
|
|
maskedImageObject = new GameObject(OBJ_NAME_MASKED_IMAGE);
|
|
RectTransform maskedTransform = maskedImageObject.AddComponent<RectTransform>();
|
|
maskedTransform.SetParent(transform); // Set as child of this game object.
|
|
|
|
// Create maskedImage as component of child game object and initialize to base image.
|
|
maskedImage = maskedImageObject.AddComponent<Image>();
|
|
maskedImage.sprite = image.sprite;
|
|
maskedImage.color = image.color;
|
|
maskedImage.material = image.material;
|
|
image.sprite = null;
|
|
|
|
// If this object has a selectable referencing the original image,
|
|
// then we set the selectable to the masked image.
|
|
Selectable selectable = GetComponent<Selectable>();
|
|
if (selectable != null && selectable.image == image) {
|
|
selectable.image = maskedImage;
|
|
}
|
|
|
|
// Set size, scale, rotation and position.
|
|
maskedImage.rectTransform.sizeDelta = originalImageSize;
|
|
maskedImage.rectTransform.localScale = Vector3.one;
|
|
maskedImage.rectTransform.localRotation = Quaternion.identity;
|
|
maskedImage.rectTransform.anchoredPosition3D = originalMaskedPosition;
|
|
|
|
// Set masked image alignment to top-left.
|
|
Vector2 anchor = new Vector2(0, 1);
|
|
maskedImage.rectTransform.anchorMin = anchor;
|
|
maskedImage.rectTransform.anchorMax = anchor;
|
|
maskedImage.rectTransform.pivot = new Vector2(0.5f, 0.5f);
|
|
}
|
|
|
|
void Update() {
|
|
// Make sure to always ignore raycasts.
|
|
// This may be set back to true by BaseTile when the Tile becomes interactable.
|
|
maskedImage.raycastTarget = false;
|
|
|
|
UpdateScrollPosition();
|
|
UpdateFloatPosition();
|
|
UpdateScale();
|
|
}
|
|
#endif // UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
|
|
public override void OnPointerEnter(PointerEventData eventData) {
|
|
#if UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
isHovering = true;
|
|
desiredPositionZ = -hoverPositionZMeters / GetMetersToCanvasScale();
|
|
#endif // UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
}
|
|
|
|
public override void OnPointerExit(PointerEventData eventData) {
|
|
#if UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
isHovering = false;
|
|
maskedScrollOffset = Vector3.zero;
|
|
desiredPositionZ = 0.0f;
|
|
#endif // UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
}
|
|
|
|
public override void OnGvrPointerHover(PointerEventData eventData) {
|
|
#if UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
isHovering = true;
|
|
Vector3 pos = eventData.pointerCurrentRaycast.worldPosition;
|
|
|
|
RectTransform rectTransform = null;
|
|
if (maskedImageObject) {
|
|
rectTransform = maskedImageObject.GetComponent<RectTransform>();
|
|
}
|
|
|
|
if (!rectTransform || !isInteractable) {
|
|
return;
|
|
}
|
|
|
|
Rect rect = rectTransform.rect;
|
|
Vector3 localCenter = rect.center;
|
|
Vector3 worldCenter = maskedImageObject.transform.TransformPoint(localCenter);
|
|
|
|
Vector3 localMin = new Vector3(rect.min.x, rect.min.y, 0.0f);
|
|
Vector3 worldMin = maskedImageObject.transform.TransformPoint(localMin);
|
|
|
|
worldCenter -= worldMin;
|
|
pos -= worldMin;
|
|
|
|
Vector3 direction = pos - worldCenter;
|
|
maskedScrollOffset.x = movementWeight * enlargedImageSize.x * direction.x;
|
|
maskedScrollOffset.y = movementWeight * enlargedImageSize.y * direction.y;
|
|
#endif // UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
}
|
|
|
|
#if UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
private void UpdateScrollPosition() {
|
|
Vector3 desiredPosition = originalMaskedPosition;
|
|
|
|
if (isInteractable && isHovering) {
|
|
desiredPosition.x += maskedScrollOffset.x;
|
|
desiredPosition.y += maskedScrollOffset.y;
|
|
}
|
|
|
|
Vector3 position = maskedImage.rectTransform.anchoredPosition3D;
|
|
position = Vector3.Lerp(position, desiredPosition, Time.deltaTime * interpolationSpeed);
|
|
maskedImage.rectTransform.anchoredPosition3D = position;
|
|
}
|
|
|
|
private void UpdateFloatPosition() {
|
|
float finalDesiredPositionZ = desiredPositionZ;
|
|
|
|
if (!isInteractable) {
|
|
finalDesiredPositionZ = 0.0f;
|
|
}
|
|
|
|
if (finalDesiredPositionZ != transform.localPosition.z) {
|
|
Vector3 localPosition = transform.localPosition;
|
|
Vector3 desiredPosition = localPosition;
|
|
desiredPosition.z = finalDesiredPositionZ;
|
|
localPosition = Vector3.Lerp(localPosition, desiredPosition, Time.deltaTime * interpolationSpeed);
|
|
transform.localPosition = localPosition;
|
|
|
|
TiledPage page = GetPage();
|
|
if (page != null) {
|
|
float diff = Mathf.Abs(localPosition.z);
|
|
|
|
if (diff < ((PARENT_CHANGE_THRESHOLD_PERCENT * hoverPositionZMeters) / GetMetersToCanvasScale()) &&
|
|
transform.parent == page.transform) {
|
|
transform.SetParent(originalParent, true);
|
|
transform.SetAsLastSibling();
|
|
} else if (isHovering && diff >= 0 && transform.parent == originalParent) {
|
|
transform.SetParent(page.transform, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void UpdateScale() {
|
|
Vector2 currentSize = maskedImage.rectTransform.sizeDelta;
|
|
Vector2 desiredSize;
|
|
|
|
if (IsInteractable && isHovering) {
|
|
desiredSize = enlargedImageSize;
|
|
} else {
|
|
desiredSize = originalImageSize;
|
|
}
|
|
|
|
currentSize = Vector2.Lerp(currentSize, desiredSize, Time.deltaTime * interpolationSpeed);
|
|
maskedImage.rectTransform.sizeDelta = currentSize;
|
|
}
|
|
#endif // UNITY_HAS_GOOGLEVR && (UNITY_ANDROID || UNITY_EDITOR)
|
|
}
|