Animating a CALayer with a series of repeating images - cocoa

I have created CALayer objects and am able to animate their movement around the screen. However, now I want to animate them to change through a set of images in a loop to create an animation (like an animated gif)
I'm fairly new to programming and very new to Cocoa so code examples welcome.
I have 15 PNG images.
EDIT: I have code that creates an NSArray of 15 CGImageRef objects.

Have the object that owns the array and layer (I presume there is an object that owns both) also own a timer, which sends the object a message to change the image displayed in the layer. The same object should also have an instance variable containing an index into the array.
To respond to the timer message, check whether there are any images in the array, and, if so, divide the index by the count of the array and take the remainder (% operator). The result is the index to access; get the image from that index in the array and change the image in the layer, then add 1 to the computed index and assign it back to the variable.

Related

How to change key frame values in GDScript (Godot)?

I am trying to play an animation when a scene is instanced. It is a simple animation that translates y from -5 to 5. The animation plays but it plays at x = 0 and z = 0. I understand this is because the translation values for the respective co-ordinates in the animation are set to 0. I have a spatial node on my player scene that can grab transform info and pass it on to my animated scene, but I do not know how to dynamically change the x and z values of the key frames in script.
This answer contains three solutions to the problem...
Target a sub-property
If I understand correctly you want to animate only the y coordinate, and leave the other coordinates unchanged. That is, you don't want to animate the translation vector. You want to animate the y or the translation, a sub-property. This is possible out of the box, but the UI won't offer it to you.
Start by creating a track from the animation editor. You click on "Add Track", select "Property Track", and then on the object you want, and select translation. Now, while the track is empty (no key frame inserted yet), modify the track name to :y at the end.
The track would have been create with a name such as SpatialNodeName:translation, you are going to change it to SpatialNodeName:translation:y.
Afterwards, when you add key frames, they will be for translation.y. Note: doing SpatialNodeName:transform:origin:y or even SpatialNodeName:global_transform:origin:y also works. Similarly, you can imagine how do it for only rotation or scaling, and so on.
Create custom properties and animate them
I'll also mention that another option is using a Tween node (which are easier to create from code).
And also that both Tween and AnimationPlayer can animate any property. Thus, if you need to animate something that is not available, consider adding a property (see setget).
For example:
export var y:float setget set_y, get_y
func set_y(new_value:float) -> void:
transform.origin.y = new_value
func get_y() -> float:
return transform.origin.y
Then you can add a track for the custom property, and animate it like any other.
By the way, also notice the AnimationPlayer can also have "Call Method" tracks.
Modify the animation
Manipulating an animation from code is also possible. I've seen an example elsewhere. You can call get_animation on the AnimationPlayer to get the animation. Then on the returned animation you can call track_get_key_value and track_set_key_value. However, this rarely what you want to do in practice (unless you are making a Godot addon that creates or modifies animations or something like that).

Object 3D rotation using png's

I want to achieve an object 3D rotation in Xcode that instead of using openGL uses a set of prerendered pngs. This would allow for much more complex 3D animations in terms of polygons and light effects. So far I have achieved to build subclass of UIView that contains a UIScrollView and in the scrollViewDidScroll delegate method it scrubs through 360 png images depending on the content offset of the UIScrollView. This does exactly what I want to achieve except a few major problems.
I've tried three different methods to swap the images.
Method 1:
When the View is being initialized I put all UIImages in UIImageViews and those on screen with alpha = 0 and then set the respective imageView's alpha to 1 on scrollViewDidScroll
Method 2:
When the View is being initialized I put all UIImages in an array and put a single UIImageView on screen. In scrollViewDidScroll I set the respective image from the array as the image of the UIImageView
Method 3:
When the View is being initialized I save all imageNames in an Array and put a sing UIImageView on the screen. In scrollViewDidScroll I create a UIImage with the name from the array for the respective index and set this as the image for my UIImageView
All three are very memory consuming and will eventually cause memory warnings or crashes. While method three is slightly less memory expensive it's also a lot laggier.
Is there any method to do this memory efficient and fast without having to use openGL??
Edit: Theodore Gray achieved this in his Elements app in an awesome way and I can't find out how. See here: http://www.youtube.com/watch?v=nHiEqf5wb3g&feature=player_embedded

how to translate and scale a NSImage?

I have built so far an application that allows the user to drag and drop images onto a NSImageView. However, I want to be able to move these images by simply clicking on any image and hold down the mouse button to move it's location.
How can I manipulate NSImageView to translate/scale after setting the images down? Is that possible? I've read about the NSAffineTransform, but it seems like that is moving the images before creating the image itself. I already have the images on the canvas, and simply want to click and hold the image and move it with my mouse. Please help anyone!
There are two sides to this.
NSImage is the model object, which you might want to display in different ways, save to disk/archive, etc. If you want to actually change the model (scaling, rotating, etc.), implying a permanent change, then you are going to probably want to look at NSAffineTransform, Quartz drawing, etc.
But you probably didn't mean that. Instead you probably are interested in NSImageView, which is a view object, displaying the contents of the NSImage model object using whatever display attributes are desired. If you only want to change how an image is displayed, not what the actual bytes in the image are, then you are going to manipulate the NSImageView at run-time. You can use NSAffineTransform here as well, but it's somewhat uncommon (and usually unnecessary).
The key thing to note that is the NSImageView inherits from NSView, so you have all its power at your disposal. Take a look at certain methods, such as:
-setFrameSize: - useful for changing the view size, and thus the image display scale
-setFrameOrigin: - useful for changing the view position, and thus the apparent image position
Note again that these have nothing to do with images per se, and apply to all Cocoa views. You may want to take a look at a book like Cocoa Programming for Mac OS X to get you past the basics. (You can then do more interesting things, like rotation, animation, etc.)

Creating images from views, strings, etc

Ok so I have a problem. I have a method that is called imageFromText, it requires one parameter, the string itself, and it returns a NSImage. I also have another one which is called: imageFromView, this one basically have to "take a screenshot" of the view and return a NSImage, it also has only one parameter, the view itself. So it looks like this:
-(NSImage*)imageFromText: (NSString*)text {
}
-(NSImage*)imageFromView: (NSView*)view {
}
There's only one problem, I have no idea how to do this. Well so, I spent my afternoon searching around and I didn't find nothing. I've tried, to the second one, a method dataWithPDFInsideRect, but obviously, this method was not made to this propose. Please help me out!.
PLEASE NOT: I'M NOT ASKING FOR THE CODE READY. LIKE THE OLD DICTATION (IN MY COUNTY): DON'T GIVE THEM THE FISH, THEACH THEM HOW TO FISH. (TRANSLATED).
An alternative way is to lock focus on the view, then create a bitmap image rep with the contents of the view's bounds. You can then create a blank image whose size is the size of the bounds, and add the image rep to it.
The third way is dataWithPDFInsideRect:. Yes, the one you tried and couldn't get to work (I wish you'd explained what problem you had with it instead of just dismissing it!). Pass the view's bounds, then pass the data to NSImage's initWithData:.
As for imageFromView: check the Organizer Documentation for Screen Capture.
And imageFromText: You want an image (PNG I assume) that just shows a text? Don't you want to specify things like image size, font size, font color, background color, ...?
Summarizing, lock focus on the image, then draw. The NSImage docs should have more if you search for lockFocus.
The methods you're interested in are:
-[NSImage lockFocus]
+[NSGraphicsContext currentContext]
-[NSView displayRectIgnoringOpacity:inContext:]
-[NSImage lockFocus]
To draw to an image, allocate one, and then lock focus on it, then issue drawing calls and then unlock focus.
To draw a view into an image, lock focus on an image, get the current graphic context (which is now the image), and pass that to -[NSView displayRectIgnoringOpacity:inContext:].

Cocoa: Remove NSView

I'm doing an exercise in learning and at the same time making a game for my kid. He has one of those card games (like Pokemon) and we scanned a bunch in and are attempting to make a game where he can play against the "computer". So the game process is you need to start by selecting your cards. What I've done is have a class (Card (sub of NSView) that gets instantiated by an IBOutlet (button) and drops the first card on the screen as well as scroll buttons - each time a scroll button is clicked it determines what the next card should be and then calls a method (makeCard) which also instantiates a new Card.
I'm fuzzy about what cocoa is doing here. Card basically has, in its drawRect a call to a texture atlas and I pass in the coordinates of the current card to display. That means that each time I instantiate Card a new NSView is being made, correct? I am essentially building a stack of NSViews in my app (since the x, y, w h) of each card is the same I can't tell but that seems like logically what is happening. It doesn't have an effect on app speed but it seems like unnecessary clutter.
Is there a way that I can just update the image in one instance of a view rather than instantiating a Card for each one I want to show? And regardless of that answer, how do I then remove the view from the window once the set up process is complete? [view removeFromSuperview]?
To be clear, I do not want a visual representation of the card anymore. There just the eye candy for the set up part of the game as all the card data (including texture atlas coordinates) are stored in a dictionary.
Also, since I am asking questions here, how would I, without an NSImage, be able to scale the images from the texture atlas. They are 180x250px each but down the road they'll be represented in a holding area and I'd rather they can't be that size.
An answer to part of your question, since I can't figure out the rest of it:
CGImageCreateWithImageInRect will let you create a reference to a part of a larger image, as in your texture atlas. You can then create a NSImage from that (if you're using 10.6 or later, with -[NSImage initWIthCGImage:size:], otherwise you'll need to create a NSBitmapImageRep first). Then you can display the NSImage in a NSTableView cell, NSCollectionView or NSImageView.

Resources