Animate a custom property using CoreAnimation in Monotouch? - iphone

This is essentially the same question as posted here: Animating a custom property in a CALayer
over a year ago and hasn't been answered.
Im creating a custom layer and drawing a circle on it. I'd like to be able to animate the radius of the circle (and other properties later). From what i've read, i've set it up like so:
public class CircleLayer : CALayer
{
//[Export("radius")]
//public float Radius { get;set; }
//EDIT: I've now changed the radius field to what is coded below
public float Radius;
[Export("radius")]
public float getRadius()
{
return Radius;
}
[Export("setRadius:")]
public void setRadius(float val)
{
Radius = val;
}
public float Thickness {get;set;}
public CGColor Color {get;set;}
public float GlowAmount {get;set;}
private SizeF GlowOffset {get;set;}
[Export ("needsDisplayForKey:")]
static bool NeedsDisplayForKey (NSString key)
{
Console.WriteLine(key.ToString());
if(key.Equals("radius"))
{
return true;
}
else
return false;
}
public CircleLayer ()
{
if(GlowAmount == 0.0f)
GlowAmount = 10f;
GlowOffset = new SizeF(0f,0f);
//CALayer.NeedsDisplayForKey("radius");
}
public override void DrawInContext (CGContext context)
{
base.DrawInContext (context);
Console.WriteLine("drawing...........");
PointF centerPoint = new PointF(125,125);//this.Frame.Width/2,this.Frame.Height/2);
//Outer circle
context.AddEllipseInRect(new RectangleF(centerPoint.X - Radius,
centerPoint.Y - Radius,
Radius * 2,
Radius * 2));
//Inner circle
context.AddEllipseInRect(new RectangleF(centerPoint.X - InnerRadius,
centerPoint.Y - InnerRadius,
InnerRadius * 2,
InnerRadius * 2));
//Fill in circle
context.SetFillColor(Color);
context.SetShadowWithColor(GlowOffset,GlowAmount,GlowColor);
context.EOFillPath();
}
}
But it just doesn't work. I never get the radius key reported when NeedsDisplayForKey gets called (and prints them to the console). I can animate standard properties no problem (eg: scale)
Edit: Note that I can now successfully modify the value of the property Radius using SetValueForKey. If I do this I need to call SetNeedsDisplay() to update the screen, however i still cannot get the animation to work at all.
Edit #2: Sample attached: http://dl.dropbox.com/u/8617393/GraphicsTest1.zip

This has unfortunately been impossible to do with MonoTouch - but we've fixed it for the next beta (5.3.3) which will hopefully be released soon.
Once 5.3.3 has been released you can use this sample: https://github.com/xamarin/monotouch-samples/tree/monotouch-5.4/CustomPropertyAnimation to see how to do it.

Related

Unity 2d Camera Scale to Screen Size

I am looking to scale a orthographic camera in unity 2d to screen size.
When you edit your game you orient the camera in a way you want it to be, view all your objects etc.
But then when you maximise it your camera zooms out showing maybe other things you don't want to show
Images for example
Edit Mode View
Maximised
Thank you if you can answer my question
Best Regards
Dawid
Attach the following component to your camera. Make sure to set the target aspect ratio in the inspector (16/9 for example).
using UnityEngine;
[ExecuteAlways]
[RequireComponent(typeof(Camera))]
public class ViewportScaler : MonoBehaviour
{
private Camera _camera;
[Tooltip("Set the target aspect ratio.")]
[SerializeField] private float _targetAspectRatio;
private void Awake()
{
_camera = GetComponent<Camera>();
if (Application.isPlaying)
ScaleViewport();
}
private void Update()
{
#if UNITY_EDITOR
if (_camera)
ScaleViewport();
#endif
}
private void ScaleViewport()
{
// determine the game window's current aspect ratio
var windowaspect = Screen.width / (float) Screen.height;
// current viewport height should be scaled by this amount
var scaleheight = windowaspect / _targetAspectRatio;
// if scaled height is less than current height, add letterbox
if (scaleheight < 1)
{
var rect = _camera.rect;
rect.width = 1;
rect.height = scaleheight;
rect.x = 0;
rect.y = (1 - scaleheight) / 2;
_camera.rect = rect;
}
else // add pillarbox
{
var scalewidth = 1 / scaleheight;
var rect = _camera.rect;
rect.width = scalewidth;
rect.height = 1;
rect.x = (1 - scalewidth) / 2;
rect.y = 0;
_camera.rect = rect;
}
}
}
I'd like to expand on #sean-carey 's very useful answer.
I modified his code in order to add a min and max aspect ratio, so the viewport will be full screen in between those two aspects, and will pillarbox when < min and letterbox when > max
using UnityEngine;
[ExecuteAlways]
[RequireComponent(typeof(Camera))]
public class ViewportController : MonoBehaviour
{
private Camera _camera;
[Tooltip("Set the target aspect ratio.")]
[SerializeField] private float _minAspectRatio;
[SerializeField] private float _maxAspectRatio;
private void Awake()
{
_camera = GetComponent<Camera>();
if (Application.isPlaying)
ScaleViewport();
}
private void Update()
{
#if UNITY_EDITOR
if (_camera)
ScaleViewport();
#endif
}
private void ScaleViewport()
{
// determine the game window's current aspect ratio
var windowaspect = Screen.width / (float) Screen.height;
// current viewport height should be scaled by this amount
var letterboxRatio = windowaspect / _minAspectRatio;
var pillarboxRatio = _maxAspectRatio / windowaspect;
// if max height is less than current height, add letterbox
if (letterboxRatio < 1)
{
SetRect(1, letterboxRatio, 0, (1-letterboxRatio)/2);
}
// if min height is more than current height, add pillarbox
else if (pillarboxRatio < 1)
{
SetRect(pillarboxRatio, 1, (1-pillarboxRatio)/2, 0);
}
// full screen
else
{
SetRect(1, 1, 0, 0);
}
}
private void SetRect(float w, float h, float x, float y)
{
var rect = _camera.rect;
rect.width = w;
rect.height = h;
rect.x = x;
rect.y = y;
_camera.rect = rect;
}
}

Joystick controls mixed with rotation

I have a problem with the Fixed joystick when I apply rotation to the main camera. The controls are mixed. How can I resolve this problem? Do I need to use other type of joystick? Where I should put "-" ? in front of which number
using System.Collections.Generic;
using UnityEngine;
[AddComponentMenu("Camera-Control/Mouse Look")]
public class MouseLook : MonoBehaviour
{
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
public RotationAxes axes = RotationAxes.MouseXAndY;
public float sensitivityX = 15F;
public float sensitivityY = 15F;
public float minimumX = -360F;
public float maximumX = 360F;
public float minimumY = -60F;
public float maximumY = 60F;
float rotationY = 0F;
void Update()
{
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
float turnAngleChange = (touch.deltaPosition.x / Screen.width) * sensitivityX;
float pitchAngleChange = (touch.deltaPosition.y / Screen.height) * sensitivityY;
// Handle any pitch rotation
if (axes == RotationAxes.MouseXAndY || axes == RotationAxes.MouseY)
{
rotationY = Mathf.Clamp(rotationY + pitchAngleChange, minimumY, maximumY);
transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0f);
}
// Handle any turn rotation
if (axes == RotationAxes.MouseXAndY || axes == RotationAxes.MouseX)
{
transform.Rotate(0f, turnAngleChange, 0f);
}
}
void Start()
{
//if(!networkView.isMine)
//enabled = false;
// Make the rigid body not change rotation
//if (rigidbody)
//rigidbody.freezeRotation = true;
}
}
}
I don't really get your question so I'm gonna answer both of my interpretations.
If the rotation of the camera is inverted (if you put your stick to the left the camera rotates to the right) you just need to add a minus in front of the speed you're rotating the camera with.
If the rotation of the camera happens when you use the left stick and you want to use the right stick. Then you should define in your input a field called something like camera-rotation-x and use the axis shown on the following pictures in the article here: https://gamedev.stackexchange.com/questions/150323/unity3d-how-to-use-controller-joystick-to-look-around If you follow that article, your camera rotation should work.

Indentation messing up Nested Property Drawers

I have this Class called ToggledFloat. It wraps a float but also adds a bool telling if it is enabled or not.
[System.Serializable]
public class ToggledFloat
{
public float value;
public bool enabled = false;
}
[System.Serializable]
public class ClassWIthNestedProp
{
public ToggledFloat aTogFloat;
}
public class Test : MonoBehaviour
{
public ClassWIthNestedProp eCA;
public ToggledFloat tF;
}
I can easily make a Custom Property Drawer for this, and it looks right, when the editor draws this property at indentation level "0". However when I look at ToggledFloat properties nested inside another property they look wrong.
My propertyDrawer looks like this:
[CustomPropertyDrawer(typeof(ToggledFloat))]
public class ToggledPropertyEditor : PropertyDrawer
{
public override float GetPropertyHeight (SerializedProperty property, GUIContent label)
{
var propVal = property.FindPropertyRelative("value");
float contentUnfoldedHeight = EditorGUI.GetPropertyHeight (propVal, label);
return contentUnfoldedHeight;
}
// Draw the property inside the given rect
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
int iL = EditorGUI.indentLevel;
//EditorGUI.indentLevel = 0; //- Set this to "0" to make thing work but non-indented
SerializedProperty valueProp = property.FindPropertyRelative("value");
SerializedProperty enabledProp = property.FindPropertyRelative("enabled");
//Label left of checkbox
float labelWidth = GUI.skin.label.CalcSize(label).x;
Rect labelRect = new Rect(0/*position.x*/, position.y, labelWidth, 16);
EditorGUI.LabelField(labelRect, label, GUIContent.none);
EditorGUI.DrawRect(labelRect, new Color(0,0,1,.1f));
//Checkbox
Rect enableRect = new Rect();
enableRect.xMin = labelRect.xMax;
enableRect.yMin = labelRect.yMin;
enableRect.width = 16;
enableRect.height = 16;
EditorGUI.PropertyField(enableRect, enabledProp, GUIContent.none);
EditorGUI.DrawRect(enableRect, new Color(0,1,0,.1f));
//Value
Rect valueRect = new Rect();
valueRect.xMin = enableRect.xMax;
valueRect.yMin = enableRect.yMin;
valueRect.xMax = position.xMax;
valueRect.yMax = position.yMax;
EditorGUI.DrawRect(valueRect, new Color(1,0,0,.1f));
bool enabled = GUI.enabled;
GUI.enabled = enabledProp.boolValue;
EditorGUI.PropertyField(valueRect, valueProp, new GUIContent(""), true);
GUI.enabled = enabled;
EditorGUI.indentLevel = iL;
}
}
When the inspector draws an instance of class Test, it looks like this:
The Colored rects are only there for allowing me to debug where those rects actually are. The weird thing is that the text-labels are offset from the coloured rects, even though they get the same rect as argument. This is of course only a problem if I want coloured rects in my inspector - but the real problem is that it seems that this offset problem causes nested checkboxes to not work. I cannot click checkboxes on a nested property.
If I then explicitly set EditorGUI.IndenLevel = 0, then the coloured rects and the labels coincide and the toggle buttons work properly - but I then loose the automatic indentation, that I would really like to use.
Can someone tell me what I am overlooking
The DrawRect method doesn't consider the indent level. You have to adjust rect yourself to draw indented rectangle. Fortunately, There is a function to get the intented rect.
From UnityCsReference EditorGUI
static void DrawIndentedRect(Rect rect, Color color)
{
EditorGUI.DrawRect(EditorGUI.IndentedRect(rect), color);
}
Captured Inspector IndentedRect
However it doesn't work properly.
From the implementation of IndentedRect, it reduces the width of rect.
static void DrawIndentedRect(Rect rect, Color color)
{
// Indent per level is 15
rect.x += EditorGUI.indentLevel * 15;
EditorGUI.DrawRect(rect, color);
}
or
static void DrawIndentedRect(Rect rect, Color color)
{
var indentedRect = EditorGUI.IndentedRect(rect);
indentedRect.width = rect.width;
EditorGUI.DrawRect(indentedRect, color);
}
Captured Inspector DrawIndentedRect

What is causing my camera to zoom in on my character? [unity]

I am having a few strange issues with the way my camera is working. I am trying to do a perspective view of the player to allow for multiple layers to act like a parallaxing effect.
Here is the code I am using on the camera. ( I have dragged the Player onto the Transform target)
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool followBehind = true;
public float rotationDamping = 10.0f;
void Update()
{
Vector3 wantedPosition;
if (followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
transform.position = Vector3.Lerp(transform.position, wantedPosition, Time.deltaTime * damping);
}
Here is what is happening:
If you look at the Scale it is set to .5 , but when I press play it looks like this:
My ultimate goal is to follow the player. Be some distance away and then be able to adjust the height of the camera, so that my player is towards the ground. Any help would be awesome.
wantedPosition probably has a different z axis and is changing the z axis of your camera. I suggest you get the z axis of the camera then store it somewhere else. Always change the z axis of wantedPosition to that default value before assigning it to the camera.
public Transform target;
public float distance = 3.0f;
public float height = 3.0f;
public float damping = 5.0f;
public bool followBehind = true;
public float rotationDamping = 10.0f;
float defaultZPos = 0;
void Start()
{
Vector3 tempCamPos = Camera.main.transform.position;
defaultZPos = tempCamPos.z;
}
void Update()
{
Vector3 wantedPosition;
if (followBehind)
wantedPosition = target.TransformPoint(0, height, -distance);
else
wantedPosition = target.TransformPoint(0, height, distance);
//Change the z pos to the deafult vale
wantedPosition.z = defaultZPos;
transform.position = Vector3.Lerp(transform.position, wantedPosition, Time.deltaTime * damping);
}

Decouple controller logic from Unity3D GUI controls using C#, like fade OnGUI

I'm failing to understand how to decouple business logic of a controller and view for Unity3D GUI controls.
For example, if I have a GUI.Box, how would I implement a controller to fade in or out from the OnGUI lifecycle stage of the view?
View
using UnityEngine;
public class ExampleView : MonoBehaviour {
protected void OnGUI () {
GUI.Box(new Rect(0, 0, 100, 100), "Title");
}
}
If I instantiate a controller to change alpha of GUI.color it would need notification of Update() from the main view thread.
To roughly encapsulate functionality, if this were a single script it could be implemented as:
using UnityEngine;
public class ExampleView : MonoBehaviour {
private Color color;
protected void Start () {
color = Color.white;
}
protected void OnGUI () {
GUI.color = color;
GUI.Box(new Rect(0, 0, 100, 100), "Title");
}
protected void Update () {
if(color.a > 0)
color.a -= Time.deltaTime / 3;
}
}
Akin to how iTween animates changes to properties using iTween.fadeTo(gameObject, ... how can this be implemented for Unity3d GUI controls using statements like FadeOut()?
There's probably no way to target individual GUI controls unless multiple controller instances are specified OnGUI(). However, it would be cool to control isolated GUI instances such as fading in a GUI.Box followed by GUI.Label.
Are you looking for something like this?:
using UnityEngine;
public class ExampleView : MonoBehaviour {
private Color color;
private bool bFadeIn = false;
private bool bFadeOut = false;
protected void Start () {
color = Color.white;
}
public void FadeOut(){
bFadeOut = true;
bFadeIn = false;
}
public void FadeIn(){
bFadeIn = true;
bFadeOut = false;
}
protected void OnGUI () {
GUI.color = color;
GUI.Box(new Rect(0, 0, 100, 100), "Title");
}
protected void Update () {
if(bFadeOut && color.a > 0.0)color.a -= Time.deltaTime / 3;
if(bFadeIn && color.a < 1.0)color.a += Time.deltaTime / 3;
}
}
You might also want to include a flag to determine when the control is invisible and, if invisible, skip the full GuiRender function.
Dont know if this is what you are looking for, but its a simple way to add fade effect to gui..
using UnityEngine;
using System.Collections;
/**Fade In/Out Instructions:
* 1.Create bool fadeIn. Create float alpha.
* 2.Call Fade() method at start of OnGUI().
* 3.Put 'GUI.color = new Color(1,1,1,alpha)' above the elements you want to fade'.
* 4.To fade in, fadeIn = true.
* 5.To fade out, fadeIn = false.
* 6.To deactivate buttons on fade out, wrap gui in 'if(alpha > 0)'
**/
public class MainMenuGUI : MonoBehaviour {
int buttonWidth;
int buttonHeight;
public float alpha;
public bool fadeIn;
// Use this for initialization
void Start () {
buttonWidth = 100;
buttonHeight = 50;
fadeIn = true;
}
void OnGUI(){
Fade();
GUI.color = new Color(1,1,1,alpha);
if(alpha > 0)
{
if (GUI.Button (new Rect ((Screen.width/2)-50, (Screen.height/2)-(buttonHeight*4/2), 100, 50), "PLAY"))
{
fadeIn = false;
Debug.Log("Play pressed");
}
if (GUI.Button (new Rect ((Screen.width/2)-50, ((Screen.height/2)-(buttonHeight*4/2)+ buttonHeight), 100, 50), "SCORES"))
{
Debug.Log("Scores pressed");
}
if (GUI.Button (new Rect ((Screen.width/2)-50, ((Screen.height/2)-(buttonHeight*4/2)+ buttonHeight*2), 100, 50), "OPTIONS"))
{
Debug.Log("Options pressed");
}
if (GUI.Button (new Rect ((Screen.width/2)-50, ((Screen.height/2)-(buttonHeight*4/2)+ buttonHeight*3), 100, 50), "EXIT"))
{
Debug.Log("Exit pressed");
}
}
}
void Fade(){
if(fadeIn){
alpha = Mathf.Clamp(alpha+0.01f,0,1);
}else{
alpha = Mathf.Clamp(alpha-0.01f,0,1);
}
}
}
Good luck on your game :)