Modify Component Vectors (Kismet)

#Kismet
Modified @ 2024-02-03 19:13:30

Allows you to modify the translation, rotation, scale, and scale3D values of a component of an actor.


ComponentName - The TEMPLATE NAME of the component you're targetting. Example: Pawns use Mesh0 as their mesh's template name, and CollisionCylinder for their collision.

BlendType - The type of blending you choose if BlendTime is above 0.

  • Direct - A linear blend.
  • EaseInEaseOut - A smooth, linear blend.
  • Overshoot - Overshoots the ending values slightly, depending on your tension.
  • Bounce - Bounces around the ending values before reaching them.
  • Spring - Similar to bounce, albeit slightly different.
  • Decelerate - Starts out linear, then smooths into the ending values.
  • Anticipate - Similar to Curve (Auto) in Matinee, where it'll overshoot both directions.

BlendTime - The time spent adjusting the values. If set to zero, it will insta set values.

BlendTension - A tension value used in several of the blend types. Look in Hat_Math_Base if you wish to see the defaults!

DesiredComponentClass - If set up, will only affect components of the desired class or subclass.

bModifyTranslation/Rotation/Scale - Check these boxes to edit and affect their desired values.

UseShortestRotation - Uses the shortest possible rotation path.

bAddInsteadOfReplace - Adds to the current values instead of replacing them.

A couple things of note:

  • An output will be fired on the tick after components are successfully modified to their ending values.
  • You can affect collision cylinders! Simply set your X/Y values of NewScale to the radius, and Z to the height.
  • Should work with multiple actors at once, provided they share component template names.
  • Use with credit!
Ink_SeqAct_ChangeComponentOffset.uc

[RAW] [Download]

/**
 *
 * Copyright 2012-2015 Gears for Breakfast ApS. All Rights Reserved.
 */
 
 
class Ink_SeqAct_ChangeComponentOffset extends SeqAct_Latent;
 
enum EBlendType
{
    CBlend_Direct,
    CBlend_EaseInEaseOut,
    CBlend_Overshoot,
    CBlend_Bounce,
    CBlend_Spring,
    CBlend_Decelerate,
    CBlend_Anticipate,
};
 
struct ComponentData
{
    var PrimitiveComponent Comp;
    var Vector StartTranslation, StartScale3D;
    var Rotator StartRotation;
    var float StartScale;
};
 
//WORKS OFF THE TEMPLATE NAME!
var() String ComponentName;
var() EBlendType BlendType;
var() float BlendTime;
var() float BlendTension;
var() class<PrimitiveComponent> DesiredComponentClass;
 
var() bool bModifyTranslation;
var() Vector NewTranslation<EditCondition=bModifyTranslation>;
 
var() bool bModifyRotation;
var() Rotator NewRotation<EditCondition=bModifyRotation>;
var() bool UseShortestRotation<EditCondition=bModifyRotation>;
 
var() bool bModifyScale;
var() float NewScale<EditCondition=bModifyScale>;
 
var() bool bModifyScale3D;
var() Vector NewScale3D<EditCondition=bModifyScale3D>;
 
var() bool bAddInsteadOfReplace;
 
var Array<ComponentData> CurrentComps;
var transient float CurrentProgress;
 
event Activated()
{
    CurrentProgress = 0.0;
    InitializeComponents();
    ActivateOutputLink(0);
}
 
event bool Update(float d)
{
    local float alpha;
    local ComponentData CurrentComp;
    local PrimitiveComponent p;
 
    if (CurrentProgress >= BlendTime)
    {
        ActivateOutputLink(1);
        return false;
    }
 
    CurrentProgress = FMin(CurrentProgress + d, BlendTime);
    alpha = GetLerpAlpha(CurrentProgress);
 
    foreach CurrentComps(CurrentComp)
    {
        p = CurrentComp.Comp;
        if (p == None) continue;
        if (bModifyTranslation) p.SetTranslation(VLerp(CurrentComp.StartTranslation, bAddInsteadOfReplace ? (CurrentComp.StartTranslation + NewTranslation) : NewTranslation, alpha));
        if (bModifyRotation) 
        {
            if (UseShortestRotation)
                p.SetRotation(class'Hat_Math'.static.RLerpShortest(CurrentComp.StartRotation, bAddInsteadOfReplace ? (CurrentComp.StartRotation + NewRotation) : NewRotation, alpha));
            else
                p.SetRotation(RLerp(CurrentComp.StartRotation, bAddInsteadOfReplace ? (CurrentComp.StartRotation + NewRotation) : NewRotation, alpha));
        }
        if (bModifyScale) p.SetScale(Lerp(CurrentComp.StartScale, bAddInsteadOfReplace ? (CurrentComp.StartScale + NewScale) : NewScale, alpha));
        if (bModifyScale3D)
        {
            if (CylinderComponent(p) != None)
            {
                if (bAddInsteadOfReplace)
                    CylinderComponent(p).SetCylinderSize((Lerp(CurrentComp.StartScale3D.X, CurrentComp.StartScale3D.X + NewScale3D.X, alpha) + Lerp(CurrentComp.StartScale3D.Y, CurrentComp.StartScale3D.Y + NewScale3D.Y, alpha)) / 2.0, Lerp(CurrentComp.StartScale3D.Z, CurrentComp.StartScale3D.Z + NewScale3D.Z, alpha));
                else
                    CylinderComponent(p).SetCylinderSize((Lerp(CurrentComp.StartScale3D.X, NewScale3D.X, alpha) + Lerp(CurrentComp.StartScale3D.Y, NewScale3D.Y, alpha)) / 2.0, Lerp(CurrentComp.StartScale3D.Z, NewScale3D.Z, alpha));
            }
            else
                p.SetScale3D(VLerp(CurrentComp.StartScale3D, NewScale3D, alpha));
        }
    }
 
    return true;
}
 
function InitializeComponents()
{
    local Object Obj;
    local Actor TargetActor;
    local PrimitiveComponent p;
    local ComponentData NewData;
 
    CurrentComps.Length = 0;
 
    foreach Targets(Obj)
    {
        if (Obj.IsA('Controller'))
            TargetActor = Controller(Obj).Pawn;
        else
            TargetActor = Actor(Obj);
 
        if (TargetActor != None)
        {
            foreach TargetActor.ComponentList(class'PrimitiveComponent', p)
            {
                if (!(String(p.TemplateName) ~= ComponentName)) continue;
                if (DesiredComponentClass != None && !ClassIsChildOf(p.class, DesiredComponentClass)) continue;
 
                if (BlendTime > 0)
                {
                    NewData.Comp = p;
                    NewData.StartTranslation = p.Translation;
                    NewData.StartRotation = p.Rotation;
                    NewData.StartScale = p.Scale;
 
                    if (CylinderComponent(p) != None)
                        NewData.StartScale3D = Vect(1,1,0)*CylinderComponent(p).CollisionRadius + Vect(0,0,1)*CylinderComponent(p).CollisionHeight;
                    else
                        NewData.StartScale3D = p.Scale3D;
 
                    CurrentComps.AddItem(NewData);
                }
                else
                {
                    if (bModifyTranslation) p.SetTranslation(bAddInsteadOfReplace ? (p.Translation + NewTranslation) : NewTranslation);
                    if (bModifyRotation) p.SetRotation(bAddInsteadOfReplace ? (p.Rotation + NewRotation) : NewRotation);
                    if (bModifyScale) p.SetScale(bAddInsteadOfReplace ? (p.Scale + NewScale) : NewScale);
 
                    if (bModifyScale3D)
                    {
                        if (CylinderComponent(p) != None)
                        {
                            if (bAddInsteadOfReplace)
                                CylinderComponent(p).SetCylinderSize(CylinderComponent(p).CollisionRadius + (NewScale3D.X + NewScale3D.Y) / 2.0, CylinderComponent(p).CollisionHeight + NewScale3D.Z);
                            else
                                CylinderComponent(p).SetCylinderSize((NewScale3D.X + NewScale3D.Y) / 2.0, NewScale3D.Z);
                        }
                        else
                            p.SetScale3D(bAddInsteadOfReplace ? (p.Scale3D + NewScale3D) : NewScale3D);
                    }
                }
            }
        }
    }
}
 
function float GetLerpAlpha(float InProgress)
{
    switch (BlendType)
    {
        case CBlend_EaseInEaseOut: return class'Hat_Math'.static.InterpolationEaseInEaseOutJonas(0.0, 1.0, FClamp(InProgress / BlendTime, 0.0, 1.0), BlendTension);
        case CBlend_Overshoot: return class'Hat_Math'.static.InterpolationOvershoot(0.0, 1.0, FClamp(InProgress / BlendTime, 0.0, 1.0), BlendTension);
        case CBlend_Bounce: return class'Hat_Math'.static.InterpolationBounce(0.0, 1.0, FClamp(InProgress / BlendTime, 0.0, 1.0), BlendTension);
        case CBlend_Spring: return class'Hat_Math'.static.InterpolationSpring(0.0, 1.0, FClamp(InProgress / BlendTime, 0.0, 1.0), BlendTension);
        case CBlend_Decelerate: return class'Hat_Math'.static.InterpolationDecelerate(0.0, 1.0, FClamp(InProgress / BlendTime, 0.0, 1.0), BlendTension);
        case CBlend_Anticipate: return class'Hat_Math'.static.InterpolationAnticipate(0.0, 1.0, FClamp(InProgress / BlendTime, 0.0, 1.0), BlendTension);
    }
 
    return FClamp(InProgress / BlendTime, 0.0, 1.0);
}
 
static event int GetObjClassVersion()
{
    return Super.GetObjClassVersion() + 0;
}
 
defaultproperties
{
    ObjName="Set Component Offset"
    ObjCategory="Ink Kismet"
 
    bAutoActivateOutputLinks=false;
    bCallHandler=false;
 
    OutputLinks(0)=(LinkDesc="Out")
    OutputLinks(1)=(LinkDesc="Finished")
 
    VariableLinks.Empty;
    VariableLinks(0)=(ExpectedType=class'SeqVar_Object',LinkDesc="Targets",PropertyName=Targets)
 
    BlendType = CBlend_Direct;
    BlendTime = 0.1;
    BlendTension = 3.0;
    UseShortestRotation = true;
}