Jump to content

ModuleAnimateGeneric disabling other animations.


Recommended Posts

Ok, I'm confused. I've written a plugin that will play an animation when an air intake is opened or closed. And it works great... until I add a second animation with the ModuleAnimateGeneric in the .cfg.

If I have no ModuleAnimateGeneric in my .cfg, my animation plays fine when the intake is toggled even though there are two clips on the part. It finds the right one.

If I add ModuleAnimateGeneric to the .cfg and set it to a clip other than the one for the intake, the intake will not animate UNTIL I toggle the clip assigned to ModuleAnimateGeneric. Once I toggle the ModuleAnimateGeneric, both it and the intake animations work as intended.

If I assign both animations to ModuleAnimateGeneric, they both play properly.

So obviously, ModuleAnimateGeneric is doing something that prevents my other animation from playing. Does anyone know if ModuleAnimateGeneric somehow disables all animations on a part until it's toggled and if so, how can I get around that? I've tried setting the intake animation to enabled and that doesn't seem to work and I've also tried disabling play automatically in Unity and that makes no difference.

Thanks.

Edited by Fengist
Link to comment
Share on other sites

Ok, I'm confused. I've written a plugin that will play an animation when an air intake is opened or closed. And it works great... until I add a second animation with the ModuleAnimateGeneric in the .cfg.

If I have no ModuleAnimateGeneric in my .cfg, my animation plays fine when the intake is toggled even though there are two clips on the part. It finds the right one.

If I add ModuleAnimateGeneric to the .cfg and set it to a clip other than the one for the intake, the intake will not animate UNTIL I toggle the clip assigned to ModuleAnimateGeneric. Once I toggle the ModuleAnimateGeneric, both it and the intake animations work as intended.

If I assign both animations to ModuleAnimateGeneric, they both play properly.

So obviously, ModuleAnimateGeneric is doing something that prevents my other animation from playing. Does anyone know if ModuleAnimateGeneric somehow disables all animations on a part until it's toggled and if so, how can I get around that? I've tried setting the intake animation to enabled and that doesn't seem to work and I've also tried disabling play automatically in Unity and that makes no difference.

Thanks.

It's a bit hard to follow your issue. So you have an animation (clip?) that you animate via a plug-in and another animation (clip?) using moduleanimategeneric. Are they separate animations on separate parts?

I have no issue running multiple animations at the same time in my mod. I do recall something flaky about moduleanimategeneric before.

You could look at Starwaster's layered animations which layers multiple moduleanimategeneric's on a single part. Or ask him if he knows of this problem. Failing that you could try firespitter's animation module which is much better (just the animation module, not the parts). Which can be re-distributed as part of your mod with appropriate license reference, etc.

Perhaps that will help.

Edited by JPLRepo
Link to comment
Share on other sites

It's a bit hard to follow your issue. So you have an animation (clip?) that you animate via a plug-in and another animation (clip?) using moduleanimategeneric. Are they separate animations on separate parts?

Correct and they are on the same part. In unity I added an animation component to my part, created two animations, set the animation size to 2 and then put both animations on the one animation component. If I'm not mistaken, that makes them two separate clips. In the code below I use getClip to choose which one the animation should play.

I have no issue running multiple animations at the same time in my mod. I do recall something flaky about moduleanimategeneric before.

You could look at Starwaster's layered animations which layers multiple moduleanimategeneric's on a single part. Or ask him if he knows of this problem. Failing that you could try firespitter's animation module which is much better (just the animation module, not the parts). Which can be re-distributed as part of your mod with appropriate license reference, etc.

Perhaps that will help.

I'm already using firespitter's spin anyway. But what here's what I'm attempting.

I have two parts. One is an engine. I have a cover over that engine that I want to open and close based on throttle position and whether the engine is running or not. I have the MPanimEngine module on that part and it works perfect.

The other part is an intake. I want an animation to play when the intake is opened and to reverse the animation when it's closed. On the part with the intake, I have another animation that I want to run under ModuleAnimateGeneric. The MPanimEngine doesn't play the animation unless I toggle the AnimateGeneric. Then, it works fine.

Perhaps if I show you all the details, that would help.

Here's the config for the part with the intake.

MODULE

{

name = ModuleAnimateGeneric

animationName = coverAnim

startEventGUIName = Raise Cover

endEventGUIName = Lower Cover

}

MODULE

{

name=MPanimEngine

partType=Intake

animationName = intakeAnim

syncThrottle = false

smoothThrottle = false

}

And here's the code for the class MPanimEngine... keep in mind I'm a total noob at C# and an 'old school' programmer.


public class MPanimEngine : PartModule
{
[KSPField]
public string animationName = "null"; //the name of the animation stored in the .cfg

[KSPField]
public string partType = "null"; //the type of part (Engine or Intake)

[KSPField]
public bool syncThrottle = false; //is the animation synced to the throttle position

[KSPField]
public bool smoothThrottle = false; //should smoothing be used when the throttle position changes rapidly

public Animation aniEngine = null; //the animation
private ModuleEngines myEngine = new ModuleEngines(); //the first or default engine found in the part
private ModuleResourceIntake myIntake = new ModuleResourceIntake(); //the first or default Intake found in the part
public float lastThrottle = 0; //tracks the last throttle position. Always 0 or 1 for non sync'd engines
public bool faultFound = false; //set to true if no engine or animation is found on the part so this can be bypassed.

public override void OnStart(StartState state)
{
foreach (var anim in part.FindModelAnimators(animationName))
{
aniEngine = anim;
print("[Maritime Pack] (aniEngine) Found animation: " + animationName);
}
if (partType == "Engine")
{
myEngine = this.part.Modules.OfType<ModuleEngines>().FirstOrDefault();
}
if (partType == "Intake")
{
myIntake = this.part.Modules.OfType<ModuleResourceIntake>().FirstOrDefault();
}
}

public void FixedUpdate()
{
if (faultFound || FlightGlobals.ActiveVessel == null) { return; }
if (aniEngine == null || myEngine == null && myIntake == null || animationName == "null")
{
if (aniEngine == null)
{
print("[Maritime Pack] (aniEngine) Animation not found.");
}
else
{
print("[Maritime Pack] (aniEngine) "+partType+" not found.");
}
faultFound = true;
}
else
{
aniEngine.clip = aniEngine.GetClip(animationName);
if ((partType == "Engine" && !myEngine.EngineIgnited) || (partType == "Intake" && !myIntake.intakeEnabled)) //Intake or Engine shut down, reverse animation
{
if (lastThrottle != 0.0f)
{
if (syncThrottle)
{
if (smoothThrottle)
{
lastThrottle = lastThrottle - 0.02f;
if (lastThrottle < 0.0f)
{
lastThrottle = 0.0f;
}
}
else
{
lastThrottle = 0.0f;
}
foreach (AnimationState state in aniEngine)
{
state.normalizedTime = lastThrottle;
state.speed = 0.0f;
}
}
else
{
foreach (AnimationState state in aniEngine)
{
state.speed = -1.0f;
state.normalizedTime = 1.0f;
lastThrottle = 0.0f;
}
}
aniEngine.Play();
}
}
else //engine ignited, run animation
{
if (syncThrottle)
{
if (smoothThrottle)
{
if (FlightInputHandler.state.mainThrottle > lastThrottle)
{
if (FlightInputHandler.state.mainThrottle + lastThrottle > 0.02f)
{
lastThrottle = lastThrottle + 0.02f;
if (lastThrottle > 1.0f)
{
lastThrottle = 1.0f;
}
}
else
{
lastThrottle = FlightInputHandler.state.mainThrottle;
}
}
if (FlightInputHandler.state.mainThrottle < lastThrottle)
{
if (lastThrottle - FlightInputHandler.state.mainThrottle > 0.02f || FlightInputHandler.state.mainThrottle == 0 && lastThrottle != 0)
{
lastThrottle = lastThrottle - 0.02f;
if (lastThrottle < 0.0f)
{
lastThrottle = 0.0f;
}
}
else
{
lastThrottle = FlightInputHandler.state.mainThrottle;
}
}
}
foreach (AnimationState state in aniEngine)
{
state.speed = 0.0f;
state.normalizedTime = FlightInputHandler.state.mainThrottle;
if (smoothThrottle)
{
state.normalizedTime = lastThrottle;
}
}
aniEngine.Play();
}
else
{
if (!aniEngine.isPlaying && lastThrottle != 1.0f)
{
foreach (AnimationState state in aniEngine)
{
if (state.time != 1.0f)
{
state.speed = 1.0f;
state.normalizedTime = 0.0f;
aniEngine.Play();
lastThrottle = 1.0f;
}
}
}
}
}
}
}
}

*edit

Well, I sorta, but not completely, figured it out but don't get it.

I have this line in the code if (!aniEngine.isPlaying && lastThrottle != 1.0f). The if-then below that handles the animation if smoothing and sync to throttle is turned off.

I put that in there to make sure that whenever the animation begins playing that it's allowed to finish before it resets the animation time back to 0. That way, if the user toggles the engine or intake, it's not half way through animating before suddenly resetting. I took the aniEngine.isPlaying out and now it works (but not quite perfectly) and I don't have to toggle the AnimateGeneric first.

That seems to indicate that ModuleAnimateGeneric initially sets the attached animation to play even though it's really not playing.

Edited by Fengist
Link to comment
Share on other sites

Why don't you just animate the cover in your partmodule?


[[COLOR=#2B91AF]KSPEvent[/COLOR](active = [COLOR=blue]false[/COLOR], guiActive = [COLOR=blue]true[/COLOR], guiActiveUnfocused = [COLOR=blue]true[/COLOR], guiActiveEditor = [COLOR=blue]true[/COLOR], unfocusedRange = 5f, name = [COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise_Cover[/COLOR][COLOR=#A31515]"[/COLOR], guiName = [COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise Cover[/COLOR][COLOR=#A31515]"[/COLOR])]
[COLOR=blue]public[/COLOR] [COLOR=blue]void[/COLOR] [COLOR=#3E3E3E]Raise_Cover[/COLOR]()
{
Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]false[/COLOR];
[COLOR=blue]try[/COLOR]
{
[COLOR=#2B91AF]Animation[/COLOR] anim;
[COLOR=#2B91AF]Animation[/COLOR][] animators = [COLOR=blue]this[/COLOR].part.internalModel.FindModelAnimators([COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]coverAnim[/COLOR][COLOR=#A31515]"[/COLOR]);
[COLOR=blue]if[/COLOR] (animators.Length > 0)
{
anim = animators[0];
anim[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]coverAnim[/COLOR][COLOR=#A31515]"[/COLOR]].speed = [COLOR=#0000ff]1f[/COLOR];
anim[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]coverAnim[/COLOR][COLOR=#A31515]"[/COLOR]].normalizedTime = 0;
anim.Play([COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]coverAnim[/COLOR][COLOR=#A31515]"[/COLOR]);
Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Lower_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]true[/COLOR];
}
}
[COLOR=blue]catch[/COLOR] ([COLOR=#2B91AF]Exception[/COLOR] ex)
{
Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]true[/COLOR];
[COLOR=#2B91AF] Debug[/COLOR].Log([COLOR=#A31515]"Exception trying to run the Raise_Cover animation"[/COLOR]);
[COLOR=#2B91AF]Debug[/COLOR].Log([COLOR=#A31515]"Err: "[/COLOR] + ex);
}
}

[COLOR=black][[COLOR=#2b91af]KSPEvent[/COLOR](active = [COLOR=blue]false[/COLOR], guiActive = [COLOR=blue]true[/COLOR], guiActiveUnfocused = [COLOR=blue]true[/COLOR], guiActiveEditor = [COLOR=blue]true[/COLOR], unfocusedRange = 5f, name = [COLOR=#a31515]"Lower_Cover"[/COLOR], guiName = [COLOR=#a31515]"Lower Cover"[/COLOR])]
[COLOR=blue]public[/COLOR] [COLOR=blue]void[/COLOR] Lower_Cover()
{
Events[[COLOR=#a31515]"[/COLOR]Lower_Cover[COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]false[/COLOR];
[COLOR=blue]try[/COLOR]
{
[COLOR=#2b91af]Animation[/COLOR] anim;
[COLOR=#2b91af]Animation[/COLOR][] animators = [COLOR=blue]this[/COLOR].part.internalModel.FindModelAnimators([COLOR=#a31515]"[/COLOR][COLOR=#3E3E3E][FONT=Verdana]coverAnim[/FONT][/COLOR][COLOR=#a31515]"[/COLOR]);
[COLOR=blue]if[/COLOR] (animators.Length > 0)
{
anim = animators[0];
anim[[COLOR=#a31515]"[/COLOR][COLOR=#3E3E3E][FONT=Verdana]coverAnim[/FONT][/COLOR][COLOR=#a31515]"[/COLOR]].speed = [/COLOR][COLOR=#0000ff]-1f[/COLOR][COLOR=#000000];
anim[[/COLOR][COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E][FONT=Verdana]coverAnim[/FONT][/COLOR][COLOR=#A31515]"[/COLOR][COLOR=#000000]].normalizedTime = 1;
anim.Play([/COLOR][COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E][FONT=Verdana]coverAnim[/FONT][/COLOR][COLOR=#A31515]"[/COLOR][COLOR=#000000]);
[/COLOR] Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]true[/COLOR];
[COLOR=#000000] }
}
[/COLOR][COLOR=blue]catch[/COLOR][COLOR=#000000] ([/COLOR][COLOR=#2B91AF]Exception[/COLOR][COLOR=#000000] ex)
{
[/COLOR]Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Lower_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]true[/COLOR]; [COLOR=#000000]
[/COLOR][COLOR=#2B91AF] Debug[/COLOR][COLOR=#000000].Log([/COLOR][COLOR=#A31515]"Exception trying to run the Lower_Cover animation"[/COLOR][COLOR=#000000]);
[/COLOR][COLOR=#2B91AF]Debug[/COLOR][COLOR=#000000].Log([/COLOR][COLOR=#A31515]"Err: "[/COLOR][COLOR=#000000] + ex);
}
}
[/COLOR]

I just hand typed this code.. so it may have a bug or two.. anyway, KSPEvent's allow you to have part right click events to animate the cover.. which I assume is the only reason you are using moduleanimategeneric.

IF you add this to your partmodule you don't need moduleanimategeneric in your config any more. Just keep the MPanimEngine and add the above to that partmodule code.

EDIT: I added a couple of lines to the code, you have to enable the opposite event - so when Raise_Cover runs you must turn the Lower_Cover event on and vice versa.

Edited by JPLRepo
Link to comment
Share on other sites

Why don't you just animate the cover in your partmodule?


[[COLOR=#2B91AF]KSPEvent[/COLOR](active = [COLOR=blue]false[/COLOR], guiActive = [COLOR=blue]true[/COLOR], guiActiveUnfocused = [COLOR=blue]true[/COLOR], guiActiveEditor = [COLOR=blue]true[/COLOR], unfocusedRange = 5f, name = [COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise_Cover[/COLOR][COLOR=#A31515]"[/COLOR], guiName = [COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise Cover[/COLOR][COLOR=#A31515]"[/COLOR])]
[COLOR=blue]public[/COLOR] [COLOR=blue]void[/COLOR] [COLOR=#3E3E3E]Raise_Cover[/COLOR]()
{
Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]false[/COLOR];
[COLOR=blue]try[/COLOR]
{
[COLOR=#2B91AF]Animation[/COLOR] anim;
[COLOR=#2B91AF]Animation[/COLOR][] animators = [COLOR=blue]this[/COLOR].part.internalModel.FindModelAnimators([COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]coverAnim[/COLOR][COLOR=#A31515]"[/COLOR]);
[COLOR=blue]if[/COLOR] (animators.Length > 0)
{
anim = animators[0];
anim[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]coverAnim[/COLOR][COLOR=#A31515]"[/COLOR]].speed = [COLOR=#0000ff]1f[/COLOR];
anim[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]coverAnim[/COLOR][COLOR=#A31515]"[/COLOR]].normalizedTime = 0;
anim.Play([COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]coverAnim[/COLOR][COLOR=#A31515]"[/COLOR]);
Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Lower_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]true[/COLOR];
}
}
[COLOR=blue]catch[/COLOR] ([COLOR=#2B91AF]Exception[/COLOR] ex)
{
Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]true[/COLOR];
[COLOR=#2B91AF] Debug[/COLOR].Log([COLOR=#A31515]"Exception trying to run the Raise_Cover animation"[/COLOR]);
[COLOR=#2B91AF]Debug[/COLOR].Log([COLOR=#A31515]"Err: "[/COLOR] + ex);
}
}

[COLOR=black][[COLOR=#2b91af]KSPEvent[/COLOR](active = [COLOR=blue]false[/COLOR], guiActive = [COLOR=blue]true[/COLOR], guiActiveUnfocused = [COLOR=blue]true[/COLOR], guiActiveEditor = [COLOR=blue]true[/COLOR], unfocusedRange = 5f, name = [COLOR=#a31515]"Lower_Cover"[/COLOR], guiName = [COLOR=#a31515]"Lower Cover"[/COLOR])]
[COLOR=blue]public[/COLOR] [COLOR=blue]void[/COLOR] Lower_Cover()
{
Events[[COLOR=#a31515]"[/COLOR]Lower_Cover[COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]false[/COLOR];
[COLOR=blue]try[/COLOR]
{
[COLOR=#2b91af]Animation[/COLOR] anim;
[COLOR=#2b91af]Animation[/COLOR][] animators = [COLOR=blue]this[/COLOR].part.internalModel.FindModelAnimators([COLOR=#a31515]"[/COLOR][COLOR=#3E3E3E][FONT=Verdana]coverAnim[/FONT][/COLOR][COLOR=#a31515]"[/COLOR]);
[COLOR=blue]if[/COLOR] (animators.Length > 0)
{
anim = animators[0];
anim[[COLOR=#a31515]"[/COLOR][COLOR=#3E3E3E][FONT=Verdana]coverAnim[/FONT][/COLOR][COLOR=#a31515]"[/COLOR]].speed = [/COLOR][COLOR=#0000ff]-1f[/COLOR][COLOR=#000000];
anim[[/COLOR][COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E][FONT=Verdana]coverAnim[/FONT][/COLOR][COLOR=#A31515]"[/COLOR][COLOR=#000000]].normalizedTime = 1;
anim.Play([/COLOR][COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E][FONT=Verdana]coverAnim[/FONT][/COLOR][COLOR=#A31515]"[/COLOR][COLOR=#000000]);
[/COLOR] Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Raise_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]true[/COLOR];
[COLOR=#000000] }
}
[/COLOR][COLOR=blue]catch[/COLOR][COLOR=#000000] ([/COLOR][COLOR=#2B91AF]Exception[/COLOR][COLOR=#000000] ex)
{
[/COLOR]Events[[COLOR=#A31515]"[/COLOR][COLOR=#3E3E3E]Lower_Cover[/COLOR][COLOR=#A31515]"[/COLOR]].active = [COLOR=blue]true[/COLOR]; [COLOR=#000000]
[/COLOR][COLOR=#2B91AF] Debug[/COLOR][COLOR=#000000].Log([/COLOR][COLOR=#A31515]"Exception trying to run the Lower_Cover animation"[/COLOR][COLOR=#000000]);
[/COLOR][COLOR=#2B91AF]Debug[/COLOR][COLOR=#000000].Log([/COLOR][COLOR=#A31515]"Err: "[/COLOR][COLOR=#000000] + ex);
}
}
[/COLOR]

I just hand typed this code.. so it may have a bug or two.. anyway, KSPEvent's allow you to have part right click events to animate the cover.. which I assume is the only reason you are using moduleanimategeneric.

IF you add this to your partmodule you don't need moduleanimategeneric in your config any more. Just keep the MPanimEngine and add the above to that partmodule code.

EDIT: I added a couple of lines to the code, you have to enable the opposite event - so when Raise_Cover runs you must turn the Lower_Cover event on and vice versa.

Thanks JP, while this code didn't work (it didn't show it in the GUI) it did put me on the right track to solving another issue with my code. I'm still learning and I apparently misunderstand how animations and clips work. My code works great if there's just one animation on the part (I also figured out how to get ModuleAnimateGeneric to work with it, I count the number of clips and if it's > 1 then I do a Stop() to all animations which seems to work, so yes, ModuleAnimateGeneric plays the animation without even moving it.). When there's 2 or more animations, it gets a bit confused as I'm playing and setting states for the entire animation, not just the specific clip.

Also, I'm hoping to keep this rather generic rather than hard coding in animation names so that others can use it once it's done. I am going to work with your code tho and try to get all that straightened out. Thank you.

*edit

Ok, rewrote most of my class and I got it working with your code. The only bug I found (other than the GUI not showing up which I didn't attempt to fix) is I had to change this.part.internalModel.FindModelAnimators to this.part.FindModelAnimators. The internalModel for some reason gave null refs.

So, it's now working but, like my code it's apparently setting the state and speed for the entire animation an not just a specific clip. This is a problem when two animations attempt to play at the same time or I manually set the state.time, both clips are affected.

Here's the updated code


public class MPanimEngine : PartModule
{
[KSPField]
public string animationName = "null"; //the name of the animation stored in the .cfg

[KSPField]
public string partType = "null"; //the part type that it's connected to (Engine / Intake)

[KSPField]
public bool syncThrottle = false; //is the animation synced to the throttle position

[KSPField]
public bool smoothThrottle = false; //should smoothing be used when the throttle position changes rapidly

public Animation aniEngine = null; //the animation
private ModuleEngines myEngine = new ModuleEngines(); //the first or default engine found in the part
private ModuleResourceIntake myIntake = new ModuleResourceIntake();
public float lastThrottle = 0; //tracks the last throttle position. Always 0 or 1 for non sync'd engines
public bool faultFound = false; //set to true if no engine or animation is found on the part
public string oldClip = "null";

public void Play_Anim(string aname, float aspeed, float atime)
{
try
{
Animation anim;
Animation[] animators = this.part.FindModelAnimators(aname);
if (animators.Length > 0)
{
anim = animators[0];
anim[aname].speed = aspeed;
anim[aname].normalizedTime = atime;
anim.Play(aname);
}
}
catch (Exception ex)
{
Debug.Log("[Maritime Pack]Exception in Play_Anim");
Debug.Log("[Maritime Pack]Err: " + ex);
}
}

public override void OnStart(StartState state)
{
foreach (var anim in part.FindModelAnimators(animationName))
{
aniEngine = anim;
if (aniEngine.GetClipCount() > 1)
{
aniEngine.Stop(); //stopping any animations loaded by ModuleAnimateGeneric
}
print("[Maritime Pack] (aniEngine) Found animation: " + animationName);
}
if (partType == "Engine")
{
myEngine = this.part.Modules.OfType<ModuleEngines>().FirstOrDefault();
}
if (partType == "Intake")
{
myIntake = this.part.Modules.OfType<ModuleResourceIntake>().FirstOrDefault();
}
}

public void FixedUpdate()
{
if (faultFound || FlightGlobals.ActiveVessel == null) { return; }
if (myEngine == null && myIntake == null || animationName == "null")
{
if (aniEngine == null)
{
print("[Maritime Pack] (aniEngine) Animation not found.");
}
else
{
print("[Maritime Pack] (aniEngine) "+partType+" not found.");
}
faultFound = true;
}
else
{
if ((partType == "Engine" && !myEngine.EngineIgnited) || (partType == "Intake" && !myIntake.intakeEnabled)) //Intake or Engine shut down, reverse animation
{
if (lastThrottle != 0.0f)
{
if (syncThrottle)
{
if (smoothThrottle)
{
lastThrottle = lastThrottle - 0.02f;
if (lastThrottle < 0.0f)
{
lastThrottle = 0.0f;
}
}
else
{
lastThrottle = 0.0f;
}
Play_Anim(animationName, 0.0f, lastThrottle);
}
else //not synced to play at full speed from the end to the beginning
{
Play_Anim(animationName, -1.0f, 1.0f);
lastThrottle = 0.0f;
}
}
}
else //engine ignited, run animation
{
if (syncThrottle)
{
if (smoothThrottle)
{
if (FlightInputHandler.state.mainThrottle > lastThrottle)
{
if (FlightInputHandler.state.mainThrottle + lastThrottle > 0.02f)
{
lastThrottle = lastThrottle + 0.02f;
if (lastThrottle > 1.0f)
{
lastThrottle = 1.0f;
}
}
else
{
lastThrottle = FlightInputHandler.state.mainThrottle;
}
}
if (FlightInputHandler.state.mainThrottle < lastThrottle)
{
if (lastThrottle - FlightInputHandler.state.mainThrottle > 0.02f || FlightInputHandler.state.mainThrottle == 0 && lastThrottle != 0)
{
lastThrottle = lastThrottle - 0.02f;
if (lastThrottle < 0.0f)
{
lastThrottle = 0.0f;
}
}
else
{
lastThrottle = FlightInputHandler.state.mainThrottle;
}
}
Play_Anim(animationName, 0.0f, lastThrottle);
}
else
{
Play_Anim(animationName, 0.0f, FlightInputHandler.state.mainThrottle);
}
}
else //not synced so play at full speed from the beginning
{
if (!aniEngine.isPlaying && lastThrottle != 1.0f)
{
Play_Anim(animationName,1.0f,0.0f);
lastThrottle = 1.0f;
}
}
}
}
}
}

*another edit

Ok, I got it all working as it should with ModuleAnimateGeneric but I had to essentially avoid the problem rather than fixing it.

Orignally, on my root node in the Unity Editor I had one animation with two clips. Since you can't add 2 animations to one node, that seemed like a logical solution. Unfortunately, controlling the time and speed of multiple clips on one animation was becoming a major headache. So...

I deleted the one on the root node and created a new one on the node that contains the 'cover' and another animation on the node that contains the 'intake' Now, each animation has one clip and... the code above works with ModuleAnimateGeneric and the two animations can run simultaneously without getting 'confused.' It feels like cheating but, it works and I'm NOT going to complain.

Thanks again JP, you put me on the right track and... gave me a much nicer method of animating those parts.

Edited by Fengist
Link to comment
Share on other sites

No Probs. Sorry I was thinking internalmodel. Yes your change to this.part.FindModelAnimators would be correct. Internalmodel would be if animating the internal IVA model which is what I have been doing a lot of lately. Also I put active = false in the KPSEvent, which is why they didn't appear in the menu. you should make at least one of them true for it to appear (so raisecover if the part starts with the cover closed).

I put the KSPEvent code there because I thought you wanted the cover player controlled which is what KSPEvent's allow (by adding to the part right click menu).

Told you it probably had a few bugs. :D

As for multiple clips on one animation. I have done this and it works just fine. AS well as changing the speed. So not sure why you couldn't get that to work.

the Anim array will have each clip in it. anim [0] = the first clip. anim[1] the second clip and so on.

Anyway, as long as you have it working now that's great! well done! :)

Edited by JPLRepo
Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...