Need help in a script which can distribute & make loop of exiting keys

iEmby wrote on 1/24/2026, 8:12 AM

Hi everyone

hello @jetdv sir..

i just created this script via help of ChatGPT.

only one button is working well.

others are giving errors..

 

✔️Distribute exiting keyframes of PAN & CROP via equal distance. (replacement not adding any new)

✖️Distribute exiting keyframes of OFX via equal distance. (replacement not adding any new)

✖️Making loop from exiting 2 keyframes from both OFX / PAN & CROP via copying both exiting keyframes and placing forward up to user's requirement. if existing keys are A B and user want 5 times loop then (A B A B A B A B A B A) considering A-B-A is one loop

please help me fixing these..

thanks in advance..

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using ScriptPortal.Vegas;

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        Application.EnableVisualStyles();
        Application.Run(new MainForm(vegas));
    }
}

public class MainForm : Form
{
    private Vegas vegas;
    private Button btnPanCrop;
    private Button btnOFX;

    public MainForm(Vegas v)
    {
        vegas = v;

        Text = "Keyframe Redistributor";
        Width = 300;
        Height = 150;
        FormBorderStyle = FormBorderStyle.FixedDialog;
        MaximizeBox = false;

        btnPanCrop = new Button()
        {
            Text = "Redistribute Pan/Crop",
            Width = 220,
            Height = 30,
            Top = 15,
            Left = 30
        };

        Button btnMakeLoop = new Button()
        {
            Text = "Make Pan/Crop Loop",
            Width = 220,
            Height = 30,
            Top = 95,
            Left = 30
        };

        btnMakeLoop.Click += (s, e) => MakePanCropLoop();
        Controls.Add(btnMakeLoop);


        btnOFX = new Button()
        {
            Text = "Redistribute OFX",
            Width = 220,
            Height = 30,
            Top = 55,
            Left = 30
        };

        btnPanCrop.Click += (s, e) => RedistributePanCropKeys();
        btnOFX.Click += (s, e) => RedistributeOFXKeys();

        Controls.Add(btnPanCrop);
        Controls.Add(btnOFX);
    }

    private void MakePanCropLoop()
    {
        string input = PromptLoops();
        if (input == null) return;

        int loops;
        if (!int.TryParse(input, out loops) || loops < 1)
        {
            MessageBox.Show("Invalid loop count.");
            return;
        }

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;

            foreach (VideoEvent ev in track.Events)
            {
                if (!ev.Selected) continue;

                var keys = ev.VideoMotion.Keyframes;

                if (keys.Count < 2)
                {
                    MessageBox.Show("Pan/Crop must have at least 2 keyframes (A & B).");
                    return;
                }

                // base keys
                VideoMotionKeyframe A = keys[0];
                VideoMotionKeyframe B = keys[1];

                // clear all existing keys
                while (keys.Count > 0)
                    keys.RemoveAt(0);

                int totalKeys = loops * 2;
                double step = ev.Length.ToMilliseconds() / (totalKeys - 1);

                for (int i = 0; i < loops; i++)
                {
                    // ---- A ----
                    int idxA = keys.Add(Timecode.FromMilliseconds(step * (i * 2)));
                    keys[idxA].Bounds = A.Bounds;
                    keys[idxA].Rotation = A.Rotation;
                    keys[idxA].Smoothness = A.Smoothness;

                    // ---- B ----
                    int idxB = keys.Add(Timecode.FromMilliseconds(step * (i * 2 + 1)));
                    keys[idxB].Bounds = B.Bounds;
                    keys[idxB].Rotation = B.Rotation;
                    keys[idxB].Smoothness = B.Smoothness;
                }
            }
        }

        MessageBox.Show("Pan/Crop loop created (A B copied & distributed).");
    }




    private string PromptLoops()
    {
        Form f = new Form();
        f.Text = "Make Loop";
        f.Width = 260;
        f.Height = 120;
        f.FormBorderStyle = FormBorderStyle.FixedDialog;
        f.StartPosition = FormStartPosition.CenterScreen;

        Label lbl = new Label();
        lbl.Text = "How many loops? (A B = 1 loop)";
        lbl.Left = 10;
        lbl.Top = 10;
        lbl.Width = 220;

        TextBox tb = new TextBox();
        tb.Left = 10;
        tb.Top = 35;
        tb.Width = 220;
        tb.Text = "3";

        Button ok = new Button();
        ok.Text = "OK";
        ok.Left = 155;
        ok.Top = 65;
        ok.DialogResult = DialogResult.OK;

        f.Controls.Add(lbl);
        f.Controls.Add(tb);
        f.Controls.Add(ok);
        f.AcceptButton = ok;

        return f.ShowDialog() == DialogResult.OK ? tb.Text : null;
    }


    // ================= PAN / CROP =================
    private void RedistributePanCropKeys()
    {
        bool found = false;

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;

            foreach (VideoEvent ev in track.Events)
            {
                if (!ev.Selected) continue;

                var keys = ev.VideoMotion.Keyframes;
                int count = keys.Count;
                if (count < 2) continue;

                double step = ev.Length.ToMilliseconds() / (count - 1);

                for (int i = 0; i < count; i++)
                {
                    keys[i].Position = Timecode.FromMilliseconds(step * i);
                }

                found = true;
            }
        }

        MessageBox.Show(
            found ? "Pan/Crop keyframes redistributed." : "No valid Pan/Crop keys found.",
            "Done",
            MessageBoxButtons.OK,
            MessageBoxIcon.Information
        );
    }

    // ================= OFX =================
    private void RedistributeOFXKeys()
    {
        bool found = false;

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;

            foreach (VideoEvent ev in track.Events)
            {
                if (!ev.Selected) continue;

                foreach (Effect eff in ev.Effects)
                {
                    if (!eff.IsOFX) continue;

                    OFXEffect ofx = null;

                    // 🔥 THIS IS THE FIX
                    try
                    {
                        ofx = eff.OFXEffect;
                    }
                    catch
                    {
                        continue; // skip broken / inaccessible OFX
                    }

                    if (ofx == null) continue;

                    foreach (OFXParameter parm in ofx.Parameters)
                    {
                        if (!parm.IsAnimated) continue;

                        Timecode len = ev.Length;

                        try
                        {
                            switch (parm.ParameterType)
                            {
                                case OFXParameterType.Double:
                                    RedistributeOFX(((OFXDoubleParameter)ofx[parm.Name]).Keyframes, len); found = true; break;

                                case OFXParameterType.Double2D:
                                    RedistributeOFX(((OFXDouble2DParameter)ofx[parm.Name]).Keyframes, len); found = true; break;

                                case OFXParameterType.Double3D:
                                    RedistributeOFX(((OFXDouble3DParameter)ofx[parm.Name]).Keyframes, len); found = true; break;

                                case OFXParameterType.RGB:
                                    RedistributeOFX(((OFXRGBParameter)ofx[parm.Name]).Keyframes, len); found = true; break;

                                case OFXParameterType.RGBA:
                                    RedistributeOFX(((OFXRGBAParameter)ofx[parm.Name]).Keyframes, len); found = true; break;

                                case OFXParameterType.Integer:
                                    RedistributeOFX(((OFXIntegerParameter)ofx[parm.Name]).Keyframes, len); found = true; break;

                                case OFXParameterType.Boolean:
                                    RedistributeOFX(((OFXBooleanParameter)ofx[parm.Name]).Keyframes, len); found = true; break;

                                case OFXParameterType.Choice:
                                    RedistributeOFX(((OFXChoiceParameter)ofx[parm.Name]).Keyframes, len); found = true; break;
                            }
                        }
                        catch
                        {
                            // skip individual broken parameter
                            continue;
                        }
                    }
                }
            }
        }

        MessageBox.Show(
            found ? "OFX keyframes redistributed safely." : "No usable animated OFX parameters found.",
            "Done",
            MessageBoxButtons.OK,
            MessageBoxIcon.Information
        );
    }


    // ================= GENERIC OFX HELPER =================
    private void RedistributeOFX<T>(IList<T> keys, Timecode len) where T : OFXKeyframe
    {
        int count = keys.Count;
        if (count < 2) return;

        double step = len.ToMilliseconds() / (count - 1);

        for (int i = 0; i < count; i++)
        {
            keys[i].Time = Timecode.FromMilliseconds(step * i);
        }
    }
}


 

Last changed by iEmby

PROCESSOR
     

Operating System: Windows 11 Pro 64-bit (Always Updated)
System Manufacturer: ASUS
12th Gen Intel(R) Core(TM) i7-12700 (20 CPUs), ~2.1GHz - 4.90GHz
Memory: 32GB RAM
Page File: 11134MB used, 7934MB Available
DirectX Version: DirectX 12

-----------------------------------------------

MOTHERBOARD

 

ASUS PRIME H610-CS D4
Intel® H610 (LGA 1700)
Ready for 12th Gen Intel® Processors
Micro-ATX Motherboard with DDR4
Realtek 1 Gb Ethernet
PCH Heatsink
PCIe 4.0 | M.2 slot (32Gbps) 
HDMI® | D-Sub | USB 3.2 Gen 1 ports
SATA 6 Gbps | COM header
LPT header | TPM header
Luminous Anti-Moisture Coating
5X Protection III
(Multiple Hardware Safeguards
For all-round protection)

-----------------------------------------------
EXTERNAL GRAPHIC CARD

-----------------------------------------------

INTERNAL GRAPHIC CARD (iGPU)

------------------------------------------------

LED - MONITOR

Monitor Name: Generic PnP Monitor
Monitor Model: HP 22es
Monitor Id: HWP331B
Native Mode: 1920 x 1080(p) (60.000Hz)
Output Type: HDMI

-----------------------------------------------

STORAGE DRIVE

Drive: C:
Free Space: 182.3 GB
Total Space: 253.9 GB
File System: NTFS
Model: WD Blue SN570 1TB (NVMe)

---------------O----------------

Some useful creations by me including VEGAS Scripts

https://www.getopensofts.in/

My YouTube Channel Dedicated to Only VEGAS Pro Tutorials

EDITROOM : My YouTube Channel (For VEGAS Tutorials)

Comments

zzzzzz9125 wrote on 1/24/2026, 8:29 AM

@iEmby It's indeed a very annoying problem. You can see another post: https://www.vegascreativesoftware.info/us/forum/reverse-pan-crop-keyframes-script--146655/#ca920774

I think it's because in the foreach loop, changing the Position of a keyframe also causes its index in the list to change. That is, the index of the keyframes in the list is completely determined by the Position order of them. This problem is a bit tricky, and too difficult to solve it with normal logic. I wonder if there's a solution.

Finally, I solved this problem by using a temp event: https://www.vegascreativesoftware.info/us/forum/reverse-pan-crop-keyframes-script--146655/#ca920789

VideoEvent tmpEvent = (VideoEvent)vEvent.Copy(myTrack, vEvent.Start);
...
myTrack.Events.Remove(tmpEvent);

I cleared all the keyframes of the current event, and then re-generated the keyframes completely based on the keyframes of tmpEvent.

In your script, you attempted to change the Position of Pan/Crop keyframes within the "for" loop, and this also caused an issue.

This is a hint. You can think about how to revise your script. I don't have more time to test yours yet.

iEmby wrote on 1/24/2026, 12:42 PM

@zzzzzz9125 thankyou so much... i made it.. just now i want same both methods for OFX too... but its not working.

right now, my working script is.
 

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using ScriptPortal.Vegas;

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        Application.EnableVisualStyles();
        Application.Run(new MainForm(vegas));
    }
}

public class MainForm : Form
{
    private Vegas vegas;
    private Button btnPanCrop;
    private Button btnOFX;

    public MainForm(Vegas v)
    {
        vegas = v;

        Text = "Keyframe Redistributor";
        FormBorderStyle = FormBorderStyle.FixedDialog;
        MaximizeBox = false;
        StartPosition = FormStartPosition.CenterScreen;
        AutoSize = true;
        AutoSizeMode = AutoSizeMode.GrowAndShrink;

        FlowLayoutPanel panel = new FlowLayoutPanel();
        panel.FlowDirection = FlowDirection.TopDown;
        panel.Padding = new Padding(15);
        panel.AutoSize = true;

        btnPanCrop = new Button()
        {
            Text = "Redistribute Pan/Crop",
            Width = 220,
            Height = 30
        };
        btnPanCrop.Click += (s, e) => RedistributePanCropKeys();

        Button btnMakeLoop = new Button()
        {
            Text = "Make Pan/Crop Loop",
            Width = 220,
            Height = 30
        };
        btnMakeLoop.Click += (s, e) => MakePanCropLoop();

        panel.Controls.Add(btnPanCrop);
        panel.Controls.Add(btnMakeLoop);
        Controls.Add(panel);
    }


    private void RedistributePanCropKeys()
    {
        bool found = false;

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;

            foreach (VideoEvent ev in track.Events)
            {
                if (!ev.Selected) continue;

                var keys = ev.VideoMotion.Keyframes;
                int count = keys.Count;
                if (count < 2) continue;

                double step = ev.Length.ToMilliseconds() / (count - 1);

                for (int i = 0; i < count; i++)
                {
                    keys[i].Position = Timecode.FromMilliseconds(step * i);
                }

                found = true;
            }
        }

        MessageBox.Show(
            found ? "Pan/Crop keyframes redistributed." : "No valid Pan/Crop keys found.",
            "Done",
            MessageBoxButtons.OK,
            MessageBoxIcon.Information
        );
    }

    private void MakePanCropLoop()
    {
        int? loopsNullable = PromptLoops();
        if (!loopsNullable.HasValue)
            return;

        int loops = loopsNullable.Value;

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;

            foreach (TrackEvent evnt in track.Events)
            {
                if (!evnt.Selected) continue;

                VideoEvent vEvent = (VideoEvent)evnt;
                VideoMotionKeyframes kfs = vEvent.VideoMotion.Keyframes;

                if (kfs.Count < 2)
                {
                    MessageBox.Show("Pan/Crop must have at least 2 keyframes (A & B).");
                    return;
                }

                // 🔑 STEP 1: TEMP COPY (critical)
                VideoEvent tmpEvent = (VideoEvent)vEvent.Copy(track, vEvent.Start);
                VideoMotionKeyframes srcKeys = tmpEvent.VideoMotion.Keyframes;

                // cache A & B
                VideoMotionKeyframe A = srcKeys[0];
                VideoMotionKeyframe B = srcKeys[1];

                // 🔑 STEP 2: CLEAR ORIGINAL
                kfs.Clear();

                int totalKeys = loops * 2 + 1; // 🔑 first == last
                double step = vEvent.Length.ToMilliseconds() / (totalKeys - 1);


                // 🔑 STEP 3: REBUILD FROM SCRATCH
                for (int i = 0; i < totalKeys; i++)
                {
                    // even index → A, odd → B
                    VideoMotionKeyframe src = (i % 2 == 0) ? A : B;

                    Timecode pos = Timecode.FromMilliseconds(step * i);
                    VideoMotionKeyframe kf = new VideoMotionKeyframe(vegas.Project, pos);
                    kfs.Add(kf);

                    kf.Bounds = src.Bounds;
                    kf.Center = src.Center;
                    kf.Rotation = src.Rotation;
                    kf.Type = src.Type;
                    kf.Smoothness = src.Smoothness;
                }


                // 🔑 STEP 4: DELETE TEMP EVENT
                track.Events.Remove(tmpEvent);
            }
        }

        MessageBox.Show("Pan/Crop loop created (safe rebuild).");
    }

    private void CopyPanCrop(VideoMotionKeyframe src, VideoMotionKeyframe dst)
    {
        dst.Bounds = src.Bounds;
        dst.Center = src.Center;
        dst.Rotation = src.Rotation;
        dst.Type = src.Type;
        dst.Smoothness = src.Smoothness;
    }

    private int? PromptLoops()
    {
        Form f = new Form();
        f.Text = "Make Loop";
        f.FormBorderStyle = FormBorderStyle.FixedDialog;
        f.StartPosition = FormStartPosition.CenterScreen;

        f.Width = 180;
        f.Height = 140;

        f.MinimizeBox = false;
        f.MaximizeBox = false;
        f.ShowInTaskbar = false;

        Label lbl = new Label();
        lbl.Text = "Loop Count";
        lbl.Left = 10;
        lbl.Top = 10;
        lbl.Width = 160;
        lbl.TextAlign = ContentAlignment.MiddleCenter;

        NumericUpDown num = new NumericUpDown();
        num.Minimum = 1;
        num.Maximum = 100;
        num.Value = 3;
        num.Left = 50;
        num.Top = 40;
        num.Width = 80;
        num.TextAlign = HorizontalAlignment.Center;

        Button ok = new Button();
        ok.Text = "OK";
        ok.Width = 80;
        ok.Left = 50;
        ok.Top = 75;
        ok.DialogResult = DialogResult.OK;

        f.Controls.Add(lbl);
        f.Controls.Add(num);
        f.Controls.Add(ok);

        f.AcceptButton = ok;

        return f.ShowDialog() == DialogResult.OK ? (int?)num.Value : null;
    }
}

 

PROCESSOR
     

Operating System: Windows 11 Pro 64-bit (Always Updated)
System Manufacturer: ASUS
12th Gen Intel(R) Core(TM) i7-12700 (20 CPUs), ~2.1GHz - 4.90GHz
Memory: 32GB RAM
Page File: 11134MB used, 7934MB Available
DirectX Version: DirectX 12

-----------------------------------------------

MOTHERBOARD

 

ASUS PRIME H610-CS D4
Intel® H610 (LGA 1700)
Ready for 12th Gen Intel® Processors
Micro-ATX Motherboard with DDR4
Realtek 1 Gb Ethernet
PCH Heatsink
PCIe 4.0 | M.2 slot (32Gbps) 
HDMI® | D-Sub | USB 3.2 Gen 1 ports
SATA 6 Gbps | COM header
LPT header | TPM header
Luminous Anti-Moisture Coating
5X Protection III
(Multiple Hardware Safeguards
For all-round protection)

-----------------------------------------------
EXTERNAL GRAPHIC CARD

-----------------------------------------------

INTERNAL GRAPHIC CARD (iGPU)

------------------------------------------------

LED - MONITOR

Monitor Name: Generic PnP Monitor
Monitor Model: HP 22es
Monitor Id: HWP331B
Native Mode: 1920 x 1080(p) (60.000Hz)
Output Type: HDMI

-----------------------------------------------

STORAGE DRIVE

Drive: C:
Free Space: 182.3 GB
Total Space: 253.9 GB
File System: NTFS
Model: WD Blue SN570 1TB (NVMe)

---------------O----------------

Some useful creations by me including VEGAS Scripts

https://www.getopensofts.in/

My YouTube Channel Dedicated to Only VEGAS Pro Tutorials

EDITROOM : My YouTube Channel (For VEGAS Tutorials)

jetdv wrote on 1/24/2026, 1:01 PM

@iEmby, Try this: change

for (int i = 0; i < count; i++)

to

for (int i = count - 1; i <= 0; i--)

If you're moving keyframes right (and they're staying in the SAME order but an earlier one could pass a later one) you must go through the list backwards.

iEmby wrote on 1/24/2026, 11:35 PM

@iEmby, Try this: change

for (int i = 0; i < count; i++)

to

for (int i = count - 1; i <= 0; i--)

If you're moving keyframes right (and they're staying in the SAME order but an earlier one could pass a later one) you must go through the list backwards.

No sir it is not working.
i have to revert back to

for (int i = 0; i < count; i++)

get it work.

 

so in my case this one is working very well..

  private void RedistributePanCropKeys()
  {
      bool found = false;

      foreach (Track track in vegas.Project.Tracks)
      {
          if (!track.IsVideo()) continue;

          foreach (VideoEvent ev in track.Events)
          {
              if (!ev.Selected) continue;

              var keys = ev.VideoMotion.Keyframes;
              int count = keys.Count;
              if (count < 2) continue;

              double step = ev.Length.ToMilliseconds() / (count - 1);

              for (int i = 0; i < count; i++)
              {
                  keys[i].Position = Timecode.FromMilliseconds(step * i);
              }

              found = true;
          }
      }

      MessageBox.Show(
          found ? "Pan/Crop keyframes redistributed." : "No valid Pan/Crop keys found.",
          "Done",
          MessageBoxButtons.OK,
          MessageBoxIcon.Information
      );
  }

 

Last changed by iEmby on 1/24/2026, 11:35 PM, changed a total of 1 times.

PROCESSOR
     

Operating System: Windows 11 Pro 64-bit (Always Updated)
System Manufacturer: ASUS
12th Gen Intel(R) Core(TM) i7-12700 (20 CPUs), ~2.1GHz - 4.90GHz
Memory: 32GB RAM
Page File: 11134MB used, 7934MB Available
DirectX Version: DirectX 12

-----------------------------------------------

MOTHERBOARD

 

ASUS PRIME H610-CS D4
Intel® H610 (LGA 1700)
Ready for 12th Gen Intel® Processors
Micro-ATX Motherboard with DDR4
Realtek 1 Gb Ethernet
PCH Heatsink
PCIe 4.0 | M.2 slot (32Gbps) 
HDMI® | D-Sub | USB 3.2 Gen 1 ports
SATA 6 Gbps | COM header
LPT header | TPM header
Luminous Anti-Moisture Coating
5X Protection III
(Multiple Hardware Safeguards
For all-round protection)

-----------------------------------------------
EXTERNAL GRAPHIC CARD

-----------------------------------------------

INTERNAL GRAPHIC CARD (iGPU)

------------------------------------------------

LED - MONITOR

Monitor Name: Generic PnP Monitor
Monitor Model: HP 22es
Monitor Id: HWP331B
Native Mode: 1920 x 1080(p) (60.000Hz)
Output Type: HDMI

-----------------------------------------------

STORAGE DRIVE

Drive: C:
Free Space: 182.3 GB
Total Space: 253.9 GB
File System: NTFS
Model: WD Blue SN570 1TB (NVMe)

---------------O----------------

Some useful creations by me including VEGAS Scripts

https://www.getopensofts.in/

My YouTube Channel Dedicated to Only VEGAS Pro Tutorials

EDITROOM : My YouTube Channel (For VEGAS Tutorials)

jetdv wrote on 1/25/2026, 7:33 AM

Sorry, the second one should have read:

for (int i = count - 1; i >= 0; i--)

I remembered the = but forgot to change the < to >

GJeffrey wrote on 1/25/2026, 6:11 PM

I would use a list to save the keyframe data instead of creating a temp event.

Both way should work though.

iEmby wrote on 1/26/2026, 11:56 AM

Thankyou so much for help..

I Completed my Script

This is it..

Please check it for any improvision

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
using ScriptPortal.Vegas;

public class EntryPoint
{
    public void FromVegas(Vegas vegas)
    {
        try
        {
            // Initialize Logger (Clean old file)
            DeepLogger.Init();
            Application.EnableVisualStyles();
            Application.Run(new MainForm(vegas));
        }
        catch (Exception ex)
        {
            DeepLogger.LogError("CRITICAL STARTUP ERROR: " + ex.Message);
            MessageBox.Show("Critical Error.\n" + ex.Message);
        }
    }
}

// --- SMART LOGGER CLASS ---
public static class DeepLogger
{
    private static string logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), "Vegas_Script_Log.txt");
    public static bool EnableTrace = false; // Controlled by Checkbox

    public static void Init()
    {
        try
        {
            if (File.Exists(logPath)) File.Delete(logPath);
        }
        catch { }
    }

    // Sirf tab likhega jab Checkbox ON ho
    public static void LogTrace(string msg)
    {
        if (!EnableTrace) return;
        WriteToFile("[TRACE] " + msg);
    }

    // Hamesha likhega (Errors ke liye)
    public static void LogError(string msg)
    {
        WriteToFile("[ERROR] " + msg);
    }

    private static void WriteToFile(string text)
    {
        try
        {
            using (StreamWriter sw = File.AppendText(logPath))
            {
                sw.WriteLine("[" + DateTime.Now.ToString("HH:mm:ss") + "] " + text);
            }
        }
        catch { }
    }
}

public class MainForm : Form
{
    private Vegas vegas;
    private CheckBox chkTraceLog; // New Checkbox
    private Button btnPanCrop;
    private Button btnOFX;
    private Button btnOFXLoop;
    private Button btnMakeLoop;

    public MainForm(Vegas v)
    {
        vegas = v;
        Text = "Keyframe Master";
        FormBorderStyle = FormBorderStyle.FixedDialog;
        MaximizeBox = false;
        StartPosition = FormStartPosition.CenterScreen;
        AutoSize = true;
        AutoSizeMode = AutoSizeMode.GrowAndShrink;

        FlowLayoutPanel panel = new FlowLayoutPanel();
        panel.FlowDirection = FlowDirection.TopDown;
        panel.Padding = new Padding(15);
        panel.AutoSize = true;

        // --- CHECKBOX FOR LOGGING ---
        chkTraceLog = new CheckBox();
        chkTraceLog.Text = "Trace Process Log";
        chkTraceLog.Width = 220;
        chkTraceLog.Checked = false; // Default OFF
        // Update Logger setting immediately when changed
        chkTraceLog.CheckedChanged += (s, e) => { DeepLogger.EnableTrace = chkTraceLog.Checked; };

        // Buttons
        btnPanCrop = new Button() { Text = "Redistribute Pan/Crop", Width = 220, Height = 30 };
        btnPanCrop.Click += (s, e) => SafeExecute(RedistributePanCropKeys, "Redistribute Pan/Crop");

        btnOFX = new Button() { Text = "Redistribute OFX Keys", Width = 220, Height = 30 };
        btnOFX.Click += (s, e) => SafeExecute(RedistributeOFXKeys, "Redistribute OFX");

        btnMakeLoop = new Button() { Text = "Make Pan/Crop Loop", Width = 220, Height = 30 };
        btnMakeLoop.Click += (s, e) => SafeExecute(MakePanCropLoop, "Make Pan/Crop Loop");

        btnOFXLoop = new Button() { Text = "Make OFX Loop", Width = 220, Height = 30 };
        btnOFXLoop.Click += (s, e) => SafeExecute(MakeOFXLoop, "Make OFX Loop");

        // Add to Panel
        panel.Controls.Add(chkTraceLog); // Add Checkbox first
        panel.Controls.Add(btnPanCrop);
        panel.Controls.Add(btnOFX);
        panel.Controls.Add(btnMakeLoop);
        panel.Controls.Add(btnOFXLoop);
        Controls.Add(panel);
    }

    private void SafeExecute(Action action, string name)
    {
        try
        {
            DeepLogger.LogTrace("--- Action Started: " + name + " ---");
            action();
            DeepLogger.LogTrace("--- Action Completed: " + name + " ---");
        }
        catch (Exception ex)
        {
            // Asli Error always log hoga
            DeepLogger.LogError("ERROR in " + name + ": " + ex.Message);
            DeepLogger.LogError("STACK: " + ex.StackTrace);
            MessageBox.Show("Error! Check Log on Desktop.\n" + ex.Message);
        }
    }

    // =========================================================
    // REDISTRIBUTE PAN/CROP
    // =========================================================
    private void RedistributePanCropKeys()
    {
        bool found = false;
        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;
            foreach (VideoEvent ev in track.Events)
            {
                if (!ev.Selected) continue;
                var keys = ev.VideoMotion.Keyframes;
                if (keys.Count < 2) continue;

                DeepLogger.LogTrace("Processing Pan/Crop on Event: " + ev.ActiveTake.Name);

                double step = ev.Length.ToMilliseconds() / (keys.Count - 1);
                for (int i = keys.Count - 1; i >= 0; i--) keys[i].Position = Timecode.FromMilliseconds(step * i);
                found = true;
            }
        }
        if (!found) MessageBox.Show("No valid Pan/Crop keys found.", "Info");
    }

    // =========================================================
    // REDISTRIBUTE OFX
    // =========================================================
    private void RedistributeOFXKeys()
    {
        bool found = false;
        List<TrackEvent> selectedEvents = GetSelectedEvents(vegas);
        if (selectedEvents == null || selectedEvents.Count == 0) { MessageBox.Show("Select an event."); return; }

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;
            foreach (VideoEvent videoevent in track.Events)
            {
                if (!videoevent.Selected) continue;
                foreach (Effect eff in videoevent.Effects)
                {
                    if (!eff.IsOFX) continue;
                    OFXEffect ofx = null;

                    // --- PLUG-IN CHECK ---
                    try { ofx = eff.OFXEffect; }
                    catch
                    {
                        // Yeh Error Log mein nahi jayega, bas user ko dikhega
                        string pName = "Unknown";
                        try { pName = eff.PlugIn.Name; } catch { }
                        MessageBox.Show("This effect is not applicable: " + pName, "Skipped", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        continue;
                    }

                    if (ofx == null) continue;

                    try
                    {
                        foreach (OFXParameter ofxparm in ofx.Parameters)
                        {
                            if (!ofxparm.IsAnimated) continue;
                            string type = ofxparm.ParameterType.ToString();
                            if (type == "Page" || type == "PushButton") continue;

                            DeepLogger.LogTrace("Redistributing Param: " + ofxparm.Name);

                            if (type == "Double")
                            {
                                var kfs = ((OFXDoubleParameter)ofxparm).Keyframes;
                                int c = kfs.Count;
                                if (c > 1)
                                {
                                    double step = videoevent.Length.ToMilliseconds() / (c - 1);
                                    for (int i = 0; i < c; i++) kfs[i].Time = Timecode.FromMilliseconds((i == c - 1) ? videoevent.Length.ToMilliseconds() : step * i);
                                    found = true;
                                }
                            }
                            else if (type == "Integer")
                            {
                                var kfs = ((OFXIntegerParameter)ofxparm).Keyframes;
                                int c = kfs.Count;
                                if (c > 1)
                                {
                                    double step = videoevent.Length.ToMilliseconds() / (c - 1);
                                    for (int i = 0; i < c; i++) kfs[i].Time = Timecode.FromMilliseconds((i == c - 1) ? videoevent.Length.ToMilliseconds() : step * i);
                                    found = true;
                                }
                            }
                        }
                    }
                    catch (Exception ex) { DeepLogger.LogError("Param Error: " + ex.Message); }
                }
            }
        }
        if (!found) MessageBox.Show("No valid animated OFX keys found.", "Info");
    }

    // =========================================================
    // MAKE PAN/CROP LOOP
    // =========================================================
    private void MakePanCropLoop()
    {
        int? loopsNullable = PromptLoops();
        if (!loopsNullable.HasValue) return;
        int loops = loopsNullable.Value;

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;
            foreach (TrackEvent evnt in track.Events)
            {
                if (!evnt.Selected) continue;
                VideoEvent vEvent = (VideoEvent)evnt;
                VideoMotionKeyframes kfs = vEvent.VideoMotion.Keyframes;
                if (kfs.Count < 2) { MessageBox.Show("Pan/Crop must have 2 keys."); return; }

                DeepLogger.LogTrace("Creating Loop for Pan/Crop");

                VideoEvent tmpEvent = (VideoEvent)vEvent.Copy(track, vEvent.Start);
                VideoMotionKeyframes srcKeys = tmpEvent.VideoMotion.Keyframes;
                VideoMotionKeyframe A = srcKeys[0];
                VideoMotionKeyframe B = srcKeys[1];
                kfs.Clear();

                int totalKeys = loops * 2 + 1;
                double step = vEvent.Length.ToMilliseconds() / (totalKeys - 1);

                for (int i = 0; i < totalKeys; i++)
                {
                    VideoMotionKeyframe src = (i % 2 == 0) ? A : B;
                    Timecode pos = Timecode.FromMilliseconds(step * i);
                    VideoMotionKeyframe kf = new VideoMotionKeyframe(vegas.Project, pos);
                    kfs.Add(kf);
                    kf.Bounds = src.Bounds; kf.Center = src.Center; kf.Rotation = src.Rotation; kf.Type = src.Type; kf.Smoothness = src.Smoothness;
                }
                track.Events.Remove(tmpEvent);
            }
        }
        MessageBox.Show("Pan/Crop loop created.");
    }

    // =========================================================
    // MAKE OFX LOOP
    // =========================================================
    private void MakeOFXLoop()
    {
        bool found = false;
        List<TrackEvent> selectedEvents = GetSelectedEvents(vegas);

        if (selectedEvents == null || selectedEvents.Count == 0)
        {
            MessageBox.Show("Select an event."); return;
        }

        int? loopsNullable = PromptLoops();
        if (!loopsNullable.HasValue) return;
        int loops = loopsNullable.Value;

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo()) continue;
            foreach (VideoEvent videoevent in track.Events)
            {
                if (!videoevent.Selected) continue;

                foreach (Effect eff in videoevent.Effects)
                {
                    if (!eff.IsOFX) continue;
                    OFXEffect ofx = null;

                    // --- PLUG-IN CHECK (Log Skip Logic) ---
                    try
                    {
                        ofx = eff.OFXEffect;
                    }
                    catch
                    {
                        // ERROR LOG NOT CREATED HERE
                        string pName = "Unknown";
                        try { pName = eff.PlugIn.Name; } catch { }
                        MessageBox.Show("This effect is not applicable: " + pName, "Skipped", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        continue;
                    }

                    if (ofx == null) continue;

                    try
                    {
                        foreach (OFXParameter ofxparm in ofx.Parameters)
                        {
                            if (!ofxparm.IsAnimated) continue;
                            string type = ofxparm.ParameterType.ToString();
                            if (type == "Page" || type == "PushButton" || type == "Group") continue;

                            DeepLogger.LogTrace("Looping Param: " + ofxparm.Name);
                            HandleOFXLoopCreation(ofxparm, loops, videoevent.Length.ToMilliseconds(), ref found);
                        }
                    }
                    catch (Exception loopEx)
                    {
                        DeepLogger.LogError("Loop Error in Param: " + loopEx.Message);
                    }
                }
            }
        }

        if (found) MessageBox.Show("OFX Loop Created!");
        else MessageBox.Show("No animated OFX parameters found.");
    }

    private void HandleOFXLoopCreation(OFXParameter p, int loops, double lenMs, ref bool found)
    {
        string type = p.ParameterType.ToString();
        int totalKeys = loops * 2 + 1;
        double step = lenMs / (totalKeys - 1);

        try
        {
            if (type == "Double")
            {
                OFXDoubleParameter dp = (OFXDoubleParameter)p;
                if (dp.Keyframes.Count < 2) return;
                double valA = dp.Keyframes[0].Value;
                double valB = dp.Keyframes[1].Value;
                dp.Keyframes.Clear();
                for (int i = 0; i < totalKeys; i++)
                {
                    Timecode t = Timecode.FromMilliseconds(step * i);
                    double val = (i % 2 == 0) ? valA : valB;
                    dp.SetValueAtTime(t, val);
                }
                found = true;
            }
            else if (type == "RGB")
            {
                OFXRGBParameter rp = (OFXRGBParameter)p;
                if (rp.Keyframes.Count < 2) return;
                OFXColor valA = rp.Keyframes[0].Value;
                OFXColor valB = rp.Keyframes[1].Value;
                rp.Keyframes.Clear();
                for (int i = 0; i < totalKeys; i++)
                {
                    Timecode t = Timecode.FromMilliseconds(step * i);
                    OFXColor val = (i % 2 == 0) ? valA : valB;
                    rp.SetValueAtTime(t, val);
                }
                found = true;
            }
            else if (type == "RGBA")
            {
                OFXRGBAParameter rap = (OFXRGBAParameter)p;
                if (rap.Keyframes.Count < 2) return;
                OFXColor valA = rap.Keyframes[0].Value;
                OFXColor valB = rap.Keyframes[1].Value;
                rap.Keyframes.Clear();
                for (int i = 0; i < totalKeys; i++)
                {
                    Timecode t = Timecode.FromMilliseconds(step * i);
                    OFXColor val = (i % 2 == 0) ? valA : valB;
                    rap.SetValueAtTime(t, val);
                }
                found = true;
            }
            else if (type == "Integer")
            {
                OFXIntegerParameter ip = (OFXIntegerParameter)p;
                if (ip.Keyframes.Count < 2) return;
                int valA = ip.Keyframes[0].Value;
                int valB = ip.Keyframes[1].Value;
                ip.Keyframes.Clear();
                for (int i = 0; i < totalKeys; i++)
                {
                    Timecode t = Timecode.FromMilliseconds(step * i);
                    int val = (i % 2 == 0) ? valA : valB;
                    ip.SetValueAtTime(t, val);
                }
                found = true;
            }
            else if (type == "Double2D")
            {
                OFXDouble2DParameter d2p = (OFXDouble2DParameter)p;
                if (d2p.Keyframes.Count < 2) return;
                OFXDouble2D valA = d2p.Keyframes[0].Value;
                OFXDouble2D valB = d2p.Keyframes[1].Value;
                d2p.Keyframes.Clear();
                for (int i = 0; i < totalKeys; i++)
                {
                    Timecode t = Timecode.FromMilliseconds(step * i);
                    OFXDouble2D val = (i % 2 == 0) ? valA : valB;
                    d2p.SetValueAtTime(t, val);
                }
                found = true;
            }
            else if (type == "Double3D")
            {
                OFXDouble3DParameter d3p = (OFXDouble3DParameter)p;
                if (d3p.Keyframes.Count < 2) return;
                OFXDouble3D valA = d3p.Keyframes[0].Value;
                OFXDouble3D valB = d3p.Keyframes[1].Value;
                d3p.Keyframes.Clear();
                for (int i = 0; i < totalKeys; i++)
                {
                    Timecode t = Timecode.FromMilliseconds(step * i);
                    OFXDouble3D val = (i % 2 == 0) ? valA : valB;
                    d3p.SetValueAtTime(t, val);
                }
                found = true;
            }
            else if (type == "Boolean")
            {
                OFXBooleanParameter bp = (OFXBooleanParameter)p;
                if (bp.Keyframes.Count < 2) return;
                bool valA = bp.Keyframes[0].Value;
                bool valB = bp.Keyframes[1].Value;
                bp.Keyframes.Clear();
                for (int i = 0; i < totalKeys; i++)
                {
                    Timecode t = Timecode.FromMilliseconds(step * i);
                    bool val = (i % 2 == 0) ? valA : valB;
                    bp.SetValueAtTime(t, val);
                }
                found = true;
            }
        }
        catch (Exception ex)
        {
            DeepLogger.LogError("HandleLoop Error: " + ex.Message);
        }
    }

    private List<TrackEvent> GetSelectedEvents(Vegas vegas)
    {
        List<TrackEvent> selectedEvents = new List<TrackEvent>();
        foreach (Track track in vegas.Project.Tracks)
        {
            foreach (TrackEvent ev in track.Events)
            {
                if (ev.Selected) selectedEvents.Add(ev);
            }
        }
        return selectedEvents;
    }

    private int? PromptLoops()
    {
        Form f = new Form();
        f.Text = "Loop Count";
        f.FormBorderStyle = FormBorderStyle.FixedDialog;
        f.StartPosition = FormStartPosition.CenterScreen;
        f.Width = 200; f.Height = 140;
        f.MinimizeBox = false; f.MaximizeBox = false; f.ShowInTaskbar = false;

        Label lbl = new Label() { Text = "Number of Loops:", Left = 10, Top = 10, Width = 160 };
        NumericUpDown num = new NumericUpDown() { Minimum = 1, Maximum = 100, Value = 3, Left = 50, Top = 35, Width = 80, TextAlign = HorizontalAlignment.Center };
        Button ok = new Button() { Text = "Loop It!", Width = 80, Left = 50, Top = 70, DialogResult = DialogResult.OK };

        f.Controls.Add(lbl); f.Controls.Add(num); f.Controls.Add(ok);
        f.AcceptButton = ok;

        return f.ShowDialog() == DialogResult.OK ? (int?)num.Value : null;
    }
}

Its Both for Pan & Crop & OFX .. just not for some plugins..

like WAVE & DEFORM type which have one common keyframe timeline.

even @jetdv your SetOFXLastKey to end script also crash for these plugins.

by the way

thanks for everything

PROCESSOR
     

Operating System: Windows 11 Pro 64-bit (Always Updated)
System Manufacturer: ASUS
12th Gen Intel(R) Core(TM) i7-12700 (20 CPUs), ~2.1GHz - 4.90GHz
Memory: 32GB RAM
Page File: 11134MB used, 7934MB Available
DirectX Version: DirectX 12

-----------------------------------------------

MOTHERBOARD

 

ASUS PRIME H610-CS D4
Intel® H610 (LGA 1700)
Ready for 12th Gen Intel® Processors
Micro-ATX Motherboard with DDR4
Realtek 1 Gb Ethernet
PCH Heatsink
PCIe 4.0 | M.2 slot (32Gbps) 
HDMI® | D-Sub | USB 3.2 Gen 1 ports
SATA 6 Gbps | COM header
LPT header | TPM header
Luminous Anti-Moisture Coating
5X Protection III
(Multiple Hardware Safeguards
For all-round protection)

-----------------------------------------------
EXTERNAL GRAPHIC CARD

-----------------------------------------------

INTERNAL GRAPHIC CARD (iGPU)

------------------------------------------------

LED - MONITOR

Monitor Name: Generic PnP Monitor
Monitor Model: HP 22es
Monitor Id: HWP331B
Native Mode: 1920 x 1080(p) (60.000Hz)
Output Type: HDMI

-----------------------------------------------

STORAGE DRIVE

Drive: C:
Free Space: 182.3 GB
Total Space: 253.9 GB
File System: NTFS
Model: WD Blue SN570 1TB (NVMe)

---------------O----------------

Some useful creations by me including VEGAS Scripts

https://www.getopensofts.in/

My YouTube Channel Dedicated to Only VEGAS Pro Tutorials

EDITROOM : My YouTube Channel (For VEGAS Tutorials)

iEmby wrote on 1/27/2026, 4:09 AM

@zzzzzz9125 @jetdv
can you take some spare time of u and help me to fix this issue...
its is working now well but for unsupported plugins it crashed.
plugins like WAVE / DEFORM

pls whenever you will be free

thanks in advance

    private void OFXKeysDistribute(Vegas vegas)
    {
        var selectedEvents = GetSelectedEvents(vegas);
        if (selectedEvents == null || selectedEvents.Count == 0)
        {
            MessageBox.Show("Select an event.", "Oops!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            return;
        }

        bool found = false;

        foreach (Track track in vegas.Project.Tracks)
        {
            if (!track.IsVideo())
                continue;

            foreach (VideoEvent videoevent in track.Events)
            {
                if (!videoevent.Selected)
                    continue;

                Timecode eventLen = videoevent.Length;
                double lenMs = eventLen.ToMilliseconds();

                foreach (Effect eff in videoevent.Effects)
                {
                    if (!eff.IsOFX)
                        continue;

                    OFXEffect ofx = null;

                    // 🔒 CRITICAL COM-SAFE ACCESS
                    try
                    {
                        ofx = eff.OFXEffect;
                        if (ofx == null)
                            continue;
                    }
                    catch
                    {
                        // ❌ THIS OFX PLUGIN IS BROKEN / UNSUPPORTED
                        // ❌ SKIP SILENTLY
                        continue;
                    }

                    foreach (OFXParameter ofxparm in ofx.Parameters)
                    {
                        if (!ofxparm.IsAnimated)
                            continue;

                        dynamic p = ofxparm;

                        try
                        {
                            var keyframes = p.Keyframes;
                            if (keyframes == null)
                                continue;

                            int c = keyframes.Count;
                            if (c < 2)
                                continue;

                            double step = lenMs / (c - 1);

                            for (int i = 0; i < c; i++)
                            {
                                keyframes[i].Time =
                                    (i == c - 1)
                                    ? eventLen
                                    : Timecode.FromMilliseconds(step * i);
                            }

                            found = true;
                        }
                        catch
                        {
                            // ❌ parameter has no Keyframes or is unsupported
                            continue;
                        }
                    }
                }
            }
        }

        if (!found)
        {
            MessageBox.Show(
                "No valid animated OFX parameters found.",
                "Info",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information
            );
        }
    }

 

PROCESSOR
     

Operating System: Windows 11 Pro 64-bit (Always Updated)
System Manufacturer: ASUS
12th Gen Intel(R) Core(TM) i7-12700 (20 CPUs), ~2.1GHz - 4.90GHz
Memory: 32GB RAM
Page File: 11134MB used, 7934MB Available
DirectX Version: DirectX 12

-----------------------------------------------

MOTHERBOARD

 

ASUS PRIME H610-CS D4
Intel® H610 (LGA 1700)
Ready for 12th Gen Intel® Processors
Micro-ATX Motherboard with DDR4
Realtek 1 Gb Ethernet
PCH Heatsink
PCIe 4.0 | M.2 slot (32Gbps) 
HDMI® | D-Sub | USB 3.2 Gen 1 ports
SATA 6 Gbps | COM header
LPT header | TPM header
Luminous Anti-Moisture Coating
5X Protection III
(Multiple Hardware Safeguards
For all-round protection)

-----------------------------------------------
EXTERNAL GRAPHIC CARD

-----------------------------------------------

INTERNAL GRAPHIC CARD (iGPU)

------------------------------------------------

LED - MONITOR

Monitor Name: Generic PnP Monitor
Monitor Model: HP 22es
Monitor Id: HWP331B
Native Mode: 1920 x 1080(p) (60.000Hz)
Output Type: HDMI

-----------------------------------------------

STORAGE DRIVE

Drive: C:
Free Space: 182.3 GB
Total Space: 253.9 GB
File System: NTFS
Model: WD Blue SN570 1TB (NVMe)

---------------O----------------

Some useful creations by me including VEGAS Scripts

https://www.getopensofts.in/

My YouTube Channel Dedicated to Only VEGAS Pro Tutorials

EDITROOM : My YouTube Channel (For VEGAS Tutorials)

zzzzzz9125 wrote on 1/27/2026, 5:30 AM

can you take some spare time of u and help me to fix this issue...
its is working now well but for unsupported plugins it crashed.
plugins like WAVE / DEFORM

@iEmby It's a bug in the VEGAS Pro script API. In short, instead of:

if (!eff.IsOFX)
    continue;

use:

if (!eff.PlugIn.IsOFX)
    continue;

For non-OFX effects (that is, DXT effects, whose full name is DirectX Transform), accessing effect.IsOFX will throw an error, while effect.PlugIn.IsOFX works well.

 

By the way, if you want to access the keyframes of DXT effects, it's also possible. Their keyframe systems are completely different. You can take a look at some of the open-source codes I wrote before: https://github.com/zzzzzz9125/Miscz/blob/main/Scripts/LayerRepeater/LayerRepeaterCommon.cs

foreach (Effect ef in newEvent.Effects)
{
    if (ef.Bypass || ef.Index >= fxSplitBools.Length || !fxSplitBools[ef.Index])
    {
        continue;
    }

    if (!ef.PlugIn.IsOFX)
    {
        Keyframe ekf = new Keyframe(pos);
        bool success = false;

        foreach (Keyframe k in ef.Keyframes)
        {
            if (k.Position == pos)
            {
                ekf = k;
                success = true;
                break;
            }
        }

        if (!success)
        {
            ef.Keyframes.Add(ekf);
        }

        if (ef.Keyframes[0].Position < ekf.Position)
        {
            ef.Keyframes.RemoveAt(0);
        }
        ekf.Position = new Timecode(0);
        for (int j = ef.Keyframes.Count - 1; j >= 1; j--)
        {
            ef.Keyframes.RemoveAt(j);
        }
    }
    else
    {
        if (ef.PlugIn != vEvent.Effects[ef.Index].PlugIn)
        {
            continue;
        }
        foreach (OFXParameter p in ef.OFXEffect.Parameters)
        {
            if (!p.IsAnimated || !p.Enabled || ef.Index >= vEvent.Effects.Count)
            {
                continue;
            }

            OFXParameter p2 = vEvent.Effects[ef.Index].OFXEffect.FindParameterByName(p.Name);

            p.IsAnimated = false;

            switch (p.ParameterType)
            {
                //case...
            }
        }
    }
}

It does this:

iEmby wrote on 1/28/2026, 10:41 AM

@zzzzzz9125

Thankyou so much sir....

You are a GOD to me..

I fix my code with ur instructions about DXT.

Distribute Keys works well but Loop keys not working where it have to copy paste same keys after knowing values and paramerters of DXT keys..

Google GEMINI is saying ... looping can not be done on DXT keys..

what do u think?

Thanks again by the way...

sir 💯💯💯

 

   private void OFXKeysLoop(Vegas vegas)
   {
       int? loopsNullable = PromptLoopCount("OFX Loop Count");
       if (!loopsNullable.HasValue) return;

       int loops = loopsNullable.Value;
       bool dxtWarningShown = false; // Flag to show warning only once

       foreach (Track track in vegas.Project.Tracks)
       {
           if (!track.IsVideo()) continue;

           foreach (VideoEvent ev in track.Events)
           {
               if (!ev.Selected) continue;
               double lenMs = ev.Length.ToMilliseconds();

               foreach (Effect eff in ev.Effects)
               {
                   // 1. Check if Plugin is valid
                   if (eff.PlugIn == null) continue;

                   // 2. Handling DXT (Standard Effects) - SHOW WARNING
                   if (!eff.PlugIn.IsOFX)
                   {
                       // Agar user ne galti se DXT effect select kiya hai aur usme keyframes hain
                       if (eff.Keyframes.Count > 0 && !dxtWarningShown)
                       {
                           MessageBox.Show(
                               "Loop feature is only compatible with OFX plugins.\n" +
                               "Standard (DXT) effects cannot be looped via script because their values are hidden.",
                               "Compatibility Info",
                               MessageBoxButtons.OK,
                               MessageBoxIcon.Warning
                           );
                           dxtWarningShown = true; // Ek baar dikha diya, bas kaafi hai
                       }
                       continue;
                   }

                   // 3. Handling OFX (Modern Effects) - EXECUTE LOOP
                   if (!eff.IsOFX) continue;

                   OFXEffect ofx;
                   try { ofx = eff.OFXEffect; }
                   catch { continue; }

                   foreach (OFXParameter p in ofx.Parameters)
                   {
                       if (!p.IsAnimated) continue;

                       string type = p.ParameterType.ToString();
                       if (type == "Page" || type == "PushButton" || type == "Group")
                           continue;

                       HandleOFXLoopCreation(p, loops, lenMs, ref _dummyFound);
                   }
               }
           }
       }
   }

 

Last changed by iEmby on 1/28/2026, 10:42 AM, changed a total of 1 times.

PROCESSOR
     

Operating System: Windows 11 Pro 64-bit (Always Updated)
System Manufacturer: ASUS
12th Gen Intel(R) Core(TM) i7-12700 (20 CPUs), ~2.1GHz - 4.90GHz
Memory: 32GB RAM
Page File: 11134MB used, 7934MB Available
DirectX Version: DirectX 12

-----------------------------------------------

MOTHERBOARD

 

ASUS PRIME H610-CS D4
Intel® H610 (LGA 1700)
Ready for 12th Gen Intel® Processors
Micro-ATX Motherboard with DDR4
Realtek 1 Gb Ethernet
PCH Heatsink
PCIe 4.0 | M.2 slot (32Gbps) 
HDMI® | D-Sub | USB 3.2 Gen 1 ports
SATA 6 Gbps | COM header
LPT header | TPM header
Luminous Anti-Moisture Coating
5X Protection III
(Multiple Hardware Safeguards
For all-round protection)

-----------------------------------------------
EXTERNAL GRAPHIC CARD

-----------------------------------------------

INTERNAL GRAPHIC CARD (iGPU)

------------------------------------------------

LED - MONITOR

Monitor Name: Generic PnP Monitor
Monitor Model: HP 22es
Monitor Id: HWP331B
Native Mode: 1920 x 1080(p) (60.000Hz)
Output Type: HDMI

-----------------------------------------------

STORAGE DRIVE

Drive: C:
Free Space: 182.3 GB
Total Space: 253.9 GB
File System: NTFS
Model: WD Blue SN570 1TB (NVMe)

---------------O----------------

Some useful creations by me including VEGAS Scripts

https://www.getopensofts.in/

My YouTube Channel Dedicated to Only VEGAS Pro Tutorials

EDITROOM : My YouTube Channel (For VEGAS Tutorials)

zzzzzz9125 wrote on 1/28/2026, 10:17 PM

Distribute Keys works well but Loop keys not working where it have to copy paste same keys after knowing values and paramerters of DXT keys..

Google GEMINI is saying ... looping can not be done on DXT keys..

what do u think?

@iEmby A handy tip is that you can add, move and delete DXT keyframes at any position on the timeline. This actually provides some interesting ideas. For instance, you can add an additional keyframe very, very close to your existing keyframe. The value of this new keyframe is almost exactly the same as that one. After that, move the new keyframe to the position where you want it to be.

After discovering this matter, I also informed it to Martin, the creator of VPFlow. Based on this idea, he implemented the keyframe interpolation for DXT effects in the latest version of VPFlow.

iEmby wrote on 1/29/2026, 4:23 AM

@zzzzzz9125

wow this is very cleverly & smart idea.

but need a little math for this. But thanks now we have AI.

thanks a lot sir..

PROCESSOR
     

Operating System: Windows 11 Pro 64-bit (Always Updated)
System Manufacturer: ASUS
12th Gen Intel(R) Core(TM) i7-12700 (20 CPUs), ~2.1GHz - 4.90GHz
Memory: 32GB RAM
Page File: 11134MB used, 7934MB Available
DirectX Version: DirectX 12

-----------------------------------------------

MOTHERBOARD

 

ASUS PRIME H610-CS D4
Intel® H610 (LGA 1700)
Ready for 12th Gen Intel® Processors
Micro-ATX Motherboard with DDR4
Realtek 1 Gb Ethernet
PCH Heatsink
PCIe 4.0 | M.2 slot (32Gbps) 
HDMI® | D-Sub | USB 3.2 Gen 1 ports
SATA 6 Gbps | COM header
LPT header | TPM header
Luminous Anti-Moisture Coating
5X Protection III
(Multiple Hardware Safeguards
For all-round protection)

-----------------------------------------------
EXTERNAL GRAPHIC CARD

-----------------------------------------------

INTERNAL GRAPHIC CARD (iGPU)

------------------------------------------------

LED - MONITOR

Monitor Name: Generic PnP Monitor
Monitor Model: HP 22es
Monitor Id: HWP331B
Native Mode: 1920 x 1080(p) (60.000Hz)
Output Type: HDMI

-----------------------------------------------

STORAGE DRIVE

Drive: C:
Free Space: 182.3 GB
Total Space: 253.9 GB
File System: NTFS
Model: WD Blue SN570 1TB (NVMe)

---------------O----------------

Some useful creations by me including VEGAS Scripts

https://www.getopensofts.in/

My YouTube Channel Dedicated to Only VEGAS Pro Tutorials

EDITROOM : My YouTube Channel (For VEGAS Tutorials)

iEmby wrote on 1/29/2026, 8:18 AM
        private void HandleDXTLoop(Effect eff, int loops, double lenMs, Timecode eventLength)
        {
            try
            {
                // =================================================
                // STEP 1: PREPARATION
                // =================================================
                if (eff.Keyframes.Count < 2) return;

                Keyframe kStart = eff.Keyframes[0];
                Keyframe kEnd = eff.Keyframes[eff.Keyframes.Count - 1];

                // Remove existing middle keys (Clean Slate)
                for (int i = eff.Keyframes.Count - 2; i > 0; i--)
                {
                    eff.Keyframes.RemoveAt(i);
                }

                // Precision timing vars
                Timecode oneTick = new Timecode(1);
                Timecode srcTimeA = kStart.Position + oneTick; // Source for ALL 'A' clones
                Timecode srcTimeB = kEnd.Position - oneTick;   // Source for ALL 'B' clones

                int totalPoints = (loops * 2) + 1;
                double step = lenMs / (totalPoints - 1);

                for (int i = totalPoints - 1; i >= 2; i--)
                {
                    // 1. Calculate Target Position
                    Timecode targetTime = (i == totalPoints - 1)
                        ? eventLength
                        : Timecode.FromMilliseconds(step * i);

                    // 2. Decide: Need A or Need B?
                    // Even (2, 4, 6) = A, Odd (3, 5, 7) = B
                    bool needStartVal = (i % 2 == 0);

                    // 3. CREATE AT EXACT SOURCE (Accuracy: 100%)
                    Timecode birthPlace = needStartVal ? srcTimeA : srcTimeB;

                    // Safety Bounds check
                    if (birthPlace >= kEnd.Position) birthPlace = kStart.Position;
                    if (birthPlace <= kStart.Position) birthPlace = kEnd.Position;

                    Keyframe k = new Keyframe(birthPlace);

                    // 4. ADD & INSTANT MOVE
                    eff.Keyframes.Add(k);    // Vegas copies exact value
                    k.Position = targetTime; // Move immediately to secure position
                }

                // =================================================
                // STEP 3: SET ORIGINAL KEYS (Start & End)
                // =================================================

                Timecode pos1 = Timecode.FromMilliseconds(step * 1);
                kEnd.Position = pos1;

                // Note: Vegas automatically sorts keys by time. 
            }
            catch
            {
                // Silent fail logic
            }
        }

GREAT...
MISSION SUCCESSFUL
Thanks alot @zzzzzz9125

PROCESSOR
     

Operating System: Windows 11 Pro 64-bit (Always Updated)
System Manufacturer: ASUS
12th Gen Intel(R) Core(TM) i7-12700 (20 CPUs), ~2.1GHz - 4.90GHz
Memory: 32GB RAM
Page File: 11134MB used, 7934MB Available
DirectX Version: DirectX 12

-----------------------------------------------

MOTHERBOARD

 

ASUS PRIME H610-CS D4
Intel® H610 (LGA 1700)
Ready for 12th Gen Intel® Processors
Micro-ATX Motherboard with DDR4
Realtek 1 Gb Ethernet
PCH Heatsink
PCIe 4.0 | M.2 slot (32Gbps) 
HDMI® | D-Sub | USB 3.2 Gen 1 ports
SATA 6 Gbps | COM header
LPT header | TPM header
Luminous Anti-Moisture Coating
5X Protection III
(Multiple Hardware Safeguards
For all-round protection)

-----------------------------------------------
EXTERNAL GRAPHIC CARD

-----------------------------------------------

INTERNAL GRAPHIC CARD (iGPU)

------------------------------------------------

LED - MONITOR

Monitor Name: Generic PnP Monitor
Monitor Model: HP 22es
Monitor Id: HWP331B
Native Mode: 1920 x 1080(p) (60.000Hz)
Output Type: HDMI

-----------------------------------------------

STORAGE DRIVE

Drive: C:
Free Space: 182.3 GB
Total Space: 253.9 GB
File System: NTFS
Model: WD Blue SN570 1TB (NVMe)

---------------O----------------

Some useful creations by me including VEGAS Scripts

https://www.getopensofts.in/

My YouTube Channel Dedicated to Only VEGAS Pro Tutorials

EDITROOM : My YouTube Channel (For VEGAS Tutorials)