Skip to content

Instantly share code, notes, and snippets.

@kamicane
Created April 7, 2022 17:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kamicane/bcf9a80af2fcd0792eecd88f3117b5ba to your computer and use it in GitHub Desktop.
Save kamicane/bcf9a80af2fcd0792eecd88f3117b5ba to your computer and use it in GitHub Desktop.
using System;
using UVtools.Core;
using UVtools.Core.Extensions;
using UVtools.Core.Scripting;
namespace UVtools.ScriptSample;
public class LayerDuper : ScriptGlobals
{
readonly ScriptNumericalInput<ushort> NumClonesInput = new()
{
Label = "Duplicates",
Unit = "layer(s)",
Minimum = 1,
Maximum = 1000,
Increment = 1,
Value = 10,
DecimalPlates = 0
};
readonly ScriptNumericalInput<ushort> EveryLayerInput = new()
{
Label = "Every",
Unit = "layer(s)",
Minimum = 1,
Maximum = 1000,
Increment = 1,
Value = 2,
DecimalPlates = 0
};
public void ScriptInit()
{
Script.Name = "Layer Duper";
Script.Description = "duplicate layers";
Script.Author = "kamicane";
Script.Version = new Version(0, 1);
Script.UserInputs.Add(NumClonesInput);
Script.UserInputs.Add(EveryLayerInput);
}
public string? ScriptValidate()
{
return null;
}
public bool ScriptExecute()
{
int numClones = NumClonesInput.Value;
int sliceIndex = 0;
for (int i = 0; i < numClones; i++) {
var clone = SlicerFile[sliceIndex].Clone();
SlicerFile.Insert(sliceIndex, clone);
sliceIndex+=EveryLayerInput.Value + 1;
}
// return true if not cancelled by user
return !Progress.Token.IsCancellationRequested;
}
}
@sn4k3
Copy link

sn4k3 commented Apr 8, 2022

Calling SlicerFile.Insert in a loop is not efficient due it's allocation and rebuild need.
Consider using SlicerFile.ReallocateStart(numClones) before loop, and then use SlicerFile[sliceIndex] = clone

The reallocate method will not rebuild properties nor recompute layer Z pos, to attain that effect call after the loop: SlicerFile.RebuildLayersProperties()

Edit: However that solution will only work if EveryLayerInput.Value == 1

To be most efficient and work with any EveryLayerInput.Value do:

public bool ScriptExecute()
{

    int numClones = NumClonesInput.Value;
    int sliceIndex = 0;
    var layers = SlicerFile.ToList();
    for (int i = 0; i < numClones; i++) {
      var clone = SlicerFile[sliceIndex].Clone();
      layers.Insert(sliceIndex, clone);
      sliceIndex+=EveryLayerInput.Value + 1;
    }
    
    SlicerFile.Layers = layers.ToArray();
   
    // return true if not cancelled by user
    return !Progress.Token.IsCancellationRequested;
}

Alternative, but previous still better:

public bool ScriptExecute()
{
    int numClones = NumClonesInput.Value;
    int sliceIndex = 0;
    SlicerFile.SuppressRebuildPropertiesWork(() =>
    {
        for (int i = 0; i < numClones; i++) {
          var clone = SlicerFile[sliceIndex].Clone();
          SlicerFile.Insert(sliceIndex, clone);
          sliceIndex+=EveryLayerInput.Value + 1;
        }
    }, true);
    // return true if not cancelled by user
    return !Progress.Token.IsCancellationRequested;
}

That will take a lot of overhead if loop is large

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment