I am designing a Padding struct as follows:
/* Padding. */
struct CGPadding {
CGFloat left;
CGFloat top;
CGFloat right;
CGFloat bottom;
};
typedef struct CGPadding CGPadding;
CG_INLINE CGPadding CGPaddingMake(CGFloat left, CGFloat top, CGFloat right, CGFloat bottom) { CGPadding p; p.left = left; p.top = top; p.right = right; p.bottom = bottom; return p; }
This all works perfectly well, the problem is how can I create a const CGPadding CGPaddingZero? If I do like this:
const CGPadding CGPaddingZero = (CGPadding){0.0, 0.0, 0.0, 0.0};
It doesnt work. So what am I doing wrong?
I find this very interesting because I do it all the time on the iPhone and it works fine. May it have something to do with the typedef afterward to the same name? What if you get rid of the typedef and define your struct like this?
typedef struct CGPadding {
CGFloat left;
CGFloat top;
CGFloat right;
CGFloat bottom;
} CGPadding;
Does it work then? Also, since all 0's is zero for a float as well and you're zero-ing out the whole thing, you could just say
const CGPadding CGPaddingZero = {0};
I do this stuff all the time on the iPhone so I'd be quite surprised if it doesn't work for you.
Related
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;
}
}
After CGPointMake let me down I found out that we can initalise a static const CGPoint like this instead:
static const CGPoint p = { 0.f, 0.f };
It works but what is the curly bracket notation actually doing?
CGPoint is a struct:
struct CGPoint {
CGFloat x;
CGFloat y;
};
It's a valid method to initialize a struct in C. See Struct initialization of the C/C++ programming language?.
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.
i have a struct HLRange with two CGFloat's
struct HOLRange
{
CGFloat min;
CGFloat max;
};
typedef struct HOLRange HOLRange;
but how do i make a function like HLRangeMake(1,2); .. like CGRectMake?
--EDIT--
my header file
#import <Foundation/Foundation.h>
struct HOLRange
{
CGFloat min;
CGFloat max;
};
typedef struct HOLRange HOLRange;
HOLRange HOLRangeMake(CGFloat min, CGFloat max) {
HOLRange range;
range.min = min;
range.max = max;
return range;
}
#interface Structs : NSObject {
}
#end
error message: ld: duplicate symbol _HOLRangeMake in /Users/Documents/projects/iphone/test/catalog/base1/build/base1.build/Debug-iphoneos/base1.build/Objects-normal/armv6/base1AppDelegate.o and /Users/Documents/projects/iphone/test/catalog/base1/build/base1.build/Debug-iphoneos/base1.build/Objects-normal/armv6/main.o
HOLRange HLRangeMake(CGFloat min, CGFloat max) {
HOLRange range;
range.min = min;
range.max = max;
return range;
}
You can see CGRectMake source in CGGeometry.h so you can do the same:
CG_INLINE CGRect
CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)
{
CGRect rect;
rect.origin.x = x; rect.origin.y = y;
rect.size.width = width; rect.size.height = height;
return rect;
}
Edit: You must either define your function as inline or move its implementation to .m file. You're getting linker errors as you function becomes defined in every compile unit that imports HoleRange.h (?) header.
Old post. However, I'd like to share my method of resolving this problem for future viewers.
typdef struct _HOLRange {
CGFloat min;
CGFloat max;
} HOLRange;
static inline HOLRange(CGFloat min, CGFloat max) {
return (HOLRange) {min, max};
}
You can define your stuct and Make function like this. Short and quick.
I like the format of this better. It makes more sense visually and seems more "correct."
typedef struct {
CGFloat min;
CGFloat max;
} HOLRange;
static inline HOLRange HOLRangeMake(CGFloat min, CGFloat max) {
HOLRange range;
range.min = min;
range.max = max;
return range;
}
I'd like to create a simple object that I can access like this:
myobject.floatValue1 = 1.0;
myobject.floatValue2 = 2.0;
It shouldn't have anymore than the two properties. Is it possible to create an enum or typedef with such a simple structure. Or must I create a class?
Sure, just make a C structure:
struct myStruct
{
float floatValue1;
float floatValue2;
};
typedef struct myStruct myType;
Then use it like this:
myType myVariable = {0.0, 0.0}; // optional initialization
myVariable.floatValue1 = 1.0;
myVariable.floatValue2 = 2.0;
Take a look at using a struct, e.g.:
struct MyObjectType {
float floatValue1;
float floatValue2;
};
...
MyObjectType myobject;
myobject.floatValue1 = 1.0;
myobject.floatValue2 = 2.0;