Does somebody know if is it possible somehow to create a custom NSAnimationCurve so that it could be used with NSViewAnimation objects but was different from standard linear, EaseIn/Out?
Actually a have already found an answer to my question. I've created a delegate for my animation NSViewAnimation object and set it using:
[animationObject setDelegate: delegateObject];
Then in header file for my delagateObject I set it to use "NSAnimationDelegate" protocol typing the following string:
#interface delegateObject : NSObject <NSAnimationDelegate> {
After that I create a method
-(float)animation:(NSAnimation *)animation valueForProgress:(NSAnimationProgress)progress;
This should be a function that describes your custom animation curve. So it takes the progress of animation as value from 0.0 to 1.0 and converts it to new value from 0.0 to 1.0 according to function which you use.
I used in my code the following function:
-(float)animation:(NSAnimation *)animation valueForProgress:(NSAnimationProgress)progress {
float value = -1/(20*(progress+0.047)) +1.045;
return value;
}
It is something like EaseOut but working properly without need to change Start and End KeyFrames and with much more significant difference of speed at the beginning and end of animation.
Related
Is there a way to listen for change of image size/aspect ratio in the dji-sdk for objective c either through a delegate or an event listener?
My scenario is that when the aspect ratio is changed, either through the DUXCameraSettingsController or through a secondary remote controller running the dji go app, I can not find adapt to the current viewport of the videofeed.
I am using DJI-SDK-iOS 4.6.1, DJI-UXSDK-iOS 4.6.0 and a Mavic Pro drone.
There are a couple different ways you can go about listening to the aspect ratio changed event. The first approach using purely the SDK would be to do the following:
1.) We create the key we want to listen to.
DJIFlightControllerKey *aspectRatioKey = [DJICameraKey keyWithParam:DJICameraParamPhotoAspectRatio];
2.) From there we register a listener on the key like this:
[[DJISDKManager keyManager] startListeningForChangesOnKey: aspectRatioKey withListener:self andUpdateBlock:^(DJIKeyedValue * _Nullable oldValue, DJIKeyedValue * _Nullable newValue) { }];
3.) You can get the new aspect ratio in the update block by using:(DJICameraPhotoAspectRatio)newValue.unsignedIntegerValue
One thing to note about this approach is that it will not return the current value of the aspectRatio until it updates so you would need to do a getValueForKey right before this if you need the current value.
The second way uses a protocol declared in UXSDK DUXObjectProtocoland will also return the current value of the key immediately as well as when the key updates.
1.) Have the class you want to receive updates conform to the DUXObjectProtocol.
2.) In the implementation you now have to implement 2 methods:
- (nonnull NSArray <__kindof DJIKey *> *)dependentKeys
- (void)transformValue:(nonnull DUXSDKModelValue *)value forKey:(nonnull __kindof DJIKey *)key;
3.) Inside of dependedKeys you return an array of any keys you want to get updates on, so you could return:
return #[[DJICameraKey keyWithParam:DJICameraParamPhotoAspectRatio]];
4.) Inside of the transformValue:ForKey: you can get the value of the aspectRatio when it updates like so:
if ([key.param isEqualToString: DJICameraParamPhotoAspectRatio]) {
self.aspectRatio = (DJICameraPhotoAspectRatio)[value unsignedIntegerValue];
}
5.) Optionally you can also implement the - (void)update method. This method will be called after transform value is called so inside of here you can write your logic to update your user interface or whatever.
6.) The last thing to do is inside your initializer of your class that conforms to the DUXObjectProtocol you need to call:
[[DUXSDKModel defaultSDKModel] registerDependentKeys:[self dependentKeys] forObject:self];
and inside of dealloc call:
[[DUXSDKModel defaultSDKModel] unregisterDependentKeysForObject:self];
Let me know if this helps!
The Problem
I am trying to get the new AUParameterTree and AUParameter's mechanism working in my Audio Unit V3 test project. The problem is that when I gain a reference to it from the Host App and change its value, the Audio Unit extension's parameter doesn't appear to change.
Here is my approach.
I'm using the new Audio Unit V3 API. I've created an AUParameter in my AUAudioUnit's initWithComponentDescription:
Creating the Parameter
AUParameter *param1 = [AUParameterTree createParameterWithIdentifier:#"frequency"
name:#"Frequency"
address:frequencyAddress
min:500
max:5000
unit:kAudioUnitParameterUnit_Hertz
unitName:nil
flags:0
valueStrings:nil
dependentParameters:nil];
Set a default value..
param1.value = 0.5;
some of the arguments to the Parameter constructor come from...
Some State
I have defined the address as a global constants:
const AudioUnitParameterID frequencyAddress = 0;
And a local variable for an AUValue:
AUValue frequency = 1;
Keep in mind at this point I'm just following the three example projects that use Audio Unit V3 on the entire internet. I find it difficult to piece together how this entire AU parameter dance should go only from reading the docs.
Rendering with the parameter
now when it comes to using the AUValue associated with the AUParameter "param1", (I assume thats how it works?)..
I am then capturing this AUValue ( the local variable which I'm unclear on how it is associated with the actual AUParameter ) .. in my Audio Unit rendering block:
- (AUInternalRenderBlock)internalRenderBlock {
AUValue * param1Capture = &frequency;
return ^AUAudioUnitStatus(AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *timestamp, AVAudioFrameCount frameCount, NSInteger outputBusNumber, AudioBufferList *outputData, const AURenderEvent *realtimeEventListHead, AURenderPullInputBlock pullInputBlock) {
// use parameter value
someValue = *param1Capture;
// more dsp stuff..
Controlling Parameter from Host App
This is where the problem arises.
I declare a local reference to an AUParameter:
#interface ViewController (){
AudioEngine *_audioEngine;
AUParameter * _param1;
}
and when my Audio Engine class instantiates my AUAudioUnit it passes it to me:
[_audioEngine setupAUWithComponentDescription:desc andCompletion:^(AUAudioUnit * unit){
_param1 = [unit.parameterTree valueForKey:#"frequency"];
}];
no effect?
Now when I say:
[_param1 setValue: 1000];
The captured AUValue in my rendering block remains the same!
I've either overlooked a bug, a mindless type (I may have introduced a type in this write up of my problem so keep that in mind), or I have fundamentally misunderstood this mechanism.
If I need to provide more context for this problem I can easily push the project to Github.
Thanks in advance.
The problem turned out to have nothing to do with Core Audio and everything to do with a basic language level mistake.
frequency was declared at a file level scope like this:
AUValue frequency = 1;
#implementation MyAudioUnit
#end
My understanding is that frequency is now bound to file scope and not instance scope. Therefore repeated setting of it on different instances was simply overwriting the previous value. Hence, the last assignment was the frequency which would be rendered.
I'm working on iOS 8 custom keyboard extension right now, and there are some issues in using UITextInputDelegate Methods.
Does this right: selectionWillChange: and selectionDidChange: methods should be called when user long-presses typing area? And textWillChange: and textDidChange: methods should be called whenever the text is literally changing?
Actually, what I observed is that, when I changed selection in text input area, textWillChange: and textDidChange: are called, and I cannot get a clue that the other two methods are called in what condition. If anyone knows about the usage of these delegate methods, please let me know.
It's not working for me either... what I am currently doing is just using textWillChange and textDidChange which does get called, as you mentioned, when you change your selection... (they get called BEFORE and AFTER) And then comparing the: self.textDocumentProxy.documentContextBeforeInputself.textDocumentProxy.documentContextAfterInput From BEFORE (textWillChange) to the AFTER (textDidChange) to see if selection range or length changed at all.
Something like this (set the 4 NSStrings below in your .h file of course... haven't tested this exact snippet because I wrote it from scratch just now on SO.com but I'm sure the principle works if I made any errors)
- (void)textWillChange:(id<UITextInput>)textInput {
beforeStringOfTextBehindCursor = self.textDocumentProxy.documentContextBeforeInput;
beforeStringOfTextAfterCursor = self.textDocumentProxy.documentContextAfterInput;
}
- (void)textDidChange:(id<UITextInput>)textInput {
afterStringOfTextBehindCursor = self.textDocumentProxy.documentContextBeforeInput;
afterStringOfTextAfterCursor = self.textDocumentProxy.documentContextAfterInput;
BOOL didSelectionChange = NO;
if (![beforeStringOfTextBehindCursor isEqualToString:afterStringOfTextBehindCursor]) {
didSelectionChange = YES;
}
if (![beforeStringOfTextAfterCursor isEqualToString:afterStringOfTextAfterCursor]) {
didSelectionChange = YES;
}
if (didSelectionChange) {
NSLog(#"Selection Changed!");
}
}
I had the same problem with the functions specified in the UITextInput protocol not being called. The reason as far as I can discern is due to the fact that the inputDelegate is set at runtime. According to the ios docs:
The UIKit provides a private text input delegate, which it assigns at runtime to the inputDelegate property of the object whose class adopts the UITextInput protocol. link
The fix which works in my case is to reset the inputDelegate in the function:
textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
by the following line:
[myUITextField setInputDelegate:self];
where self implements the UITextInputDelegate protocol.
How do I use implemented Animation in LibGDX? I know, that the documentation can be found here, but when I want to get a frame out of the Animation, I need to use stateTime, which isn't explained anywhere in the documentation. So the question is, what is stateTime in terms of LibGDX's Animation?
There is some more doc on the getKeyFrame method documentation:
Returns a TextureRegion based on the so called state time. This is the amount of seconds an object has spent in the state this Animation instance represents, e.g. running, jumping and so on.
(This documentation doesn't really make any sense to me either.)
But, the Animation.java source is readable. It looks like it boils down to
getKeyFrameIndex
which divides the stateTime by frameDuration (which is a parameter of the constructor -- how long each frame lasts) to compute an array index. getKeyFrameIndex does different things for looping or non-looping sequences, but basically it takes the array index to look up the right key frame in the sequence to display.
So the "stateTime" is the input to pick a key frame from your Animation. The documentation is assuming you have one Animation instance for "running" and another for "jumping" (these are the "states" its referring to). To find the right key frame within an Animation, you tell it how long you've been in this "state". So, if you've been in the "running" Animation instance for 1.2 seconds, it does some math to figure out which key frame to show (say you've initialized the instance with 30 frames that show for 0.0333 seconds and loop -- it picks the 6th frame).
The wiki https://github.com/libgdx/libgdx/wiki/2D-Animation has some more details and an example, but doesn't address this directly, either.
animationFrames = walkSheetArray[moveDirection];
animation = new Animation(1f / 5f, animationFrames);
myAnimatedActor = new AnimatedActor(animation);
stage.addActor(myAnimatedActor);
public class AnimatedActor extends Image {
private float stateTime = 0;
Animation animation;
public AnimatedActor(Animation animation) {
super(animation.getKeyFrame(0));
this.animation = animation;
}
#Override
public void act(float delta) {
((TextureRegionDrawable) getDrawable()).setRegion(animation.getKeyFrame(stateTime += delta, true));
super.act(delta);
}
}
I know that jQuery, for example, can do animation of sorts. I also know that at the very core of the animation, there must me some sort of loop doing the animation. What is an example of such a loop?
A complete answer should ideally answer the following questions:
What is a basic syntax for an effective animation recursion that can animate a single property of a particular object at a time? The function should be able to vary its target object and property of the object.
What arguments/parameters should it take?
What is a good range of reiterating the loop? In milliseconds? (Should this be a parameter/argument to the function?)
REMEMBER:
The answer is NOT necessarily language specific, but if you are writing in a specific language, please specify which one.
Error handling is a plus. {Nothing is more irritating (for our purposes) than an animation that does something strange, like stopping halfway through.}
Thanks!
typically (for jQuery at least) this is not done in a loop, but rather in a series of callbacks.
pseudojavascript:
function startAnimation(element, endPosition, duration) {
var startPosition = element.position;
var startTime = getCurrentTime();
function animate() {
var timeElapsed = getCurrentTime() - startTime;
if (timeElapsed > duration) {
element.position = endPosition;
stopTimer();
} else {
// interpolate based on time
element.position = startPosition +
(endPosition - startPosition) * timeElapsed / duration;
}
}
startRepeatingTimerWithCallbackAndInterval(animate, 1.0 / 30.0);
}
It's also possible to use objects to store starting data instead of closures.
This doesn't completely answer all the points in the question, but it's a starting point.