#VRML_SIM R2022b utf8
# license: Copyright Cyberbotics Ltd. Licensed for use only with Webots.
# license url: https://cyberbotics.com/webots_assets_license
# tags: nonDeterministic
# Simple and configurable wooden pallet stack.
# template language: javascript

EXTERNPROTO "WoodenPallet.proto"

PROTO WoodenPalletStack [
  field SFVec3f    translation              0 0 0
  field SFRotation rotation                 0 0 1 0
  field SFString   name                     "wooden pallet stack"
  field SFInt32    palletNumber             8                      # Defines the number of pallet in the stack (vertically).
  field SFVec3f    palletSize               1.2 0.8 0.14           # Defines the size of one pallet.
  field SFInt32    palletLathNumber         6                      # Defines the number of lath of each pallets.
  field SFFloat    palletLathWidth          0.08                   # Defines the width of the pallet laths.
  field SFFloat    lateralMisalignment      0.1                    # Defines the maximum lateral misalignment between two pallets.
  field SFFloat    longitudinalMisalignment 0.05                   # Defines the maximum longitudinal misalignment between two pallets.
  field SFFloat    palletMass               0                      # Defines the mass of one pallet in kg. A value smaller or equal to 0 remove the physics of the stack.
  field SFBool     boundingObject           TRUE                   # Defines whether the bounding object should be enabled.
  field SFBool     locked                   FALSE                  # Is `Solid.locked`.
]
{
%<
  import * as wbrandom from 'wbrandom.js';
  wbrandom.seed(context.id);

  let palletSize = fields.palletSize.value;
  if (palletSize.x <= 0 || palletSize.y <= 0 || palletSize.z <= 0) {
    palletSize = fields.palletSize.defaultValue;
    console.error('\'palletSize\' should be strictly positive. Value reset to (' + palletSize.x + ', ' + palletSize.y + ', ' + palletSize.z + ').');
  }

  let palletNumber = fields.palletNumber.value;
  if (palletNumber <= 0) {
    palletNumber = fields.palletNumber.defaultValue;
    console.error('\'palletNumber\' must be strictly positive. Value reset to ' + palletNumber + '.');
  }

  let lateralMisalignment = fields.lateralMisalignment.value;
  if (lateralMisalignment < 0) {
    lateralMisalignment = 0;
    console.error('\'lateralMisalignment\' must be positive or zero. Value set to ' + lateralMisalignment + '.');
  } else if (lateralMisalignment > palletSize.y * 0.5) {
    lateralMisalignment = palletSize.y * 0.5;
    console.error('\'lateralMisalignment\' must be smaller than half of second component of \'size\'. Value reset to ' + lateralMisalignment + '.');
  }

  let longitudinalMisalignment = fields.longitudinalMisalignment.value;
  if (longitudinalMisalignment < 0) {
    longitudinalMisalignment = 0;
    console.error('\'longitudinalMisalignment\' must be positive or zero. Value set to ' + longitudinalMisalignment + '.');
  } else if (longitudinalMisalignment > palletSize.x * 0.5) {
    longitudinalMisalignment = palletSize.x * 0.5;
    console.error('\'longitudinalMisalignment\' must be smaller than half of first component of \'size\'. Value reset to ' + longitudinalMisalignment + '.');
  }

  let maxLateralMisalignment = 0;
  let maxLongitudinalMisalignment = 0;

  const palletMass = fields.palletMass.value;
>%
Solid {
  translation IS translation
  rotation IS rotation
  children [
    %< for (let i = 0; i <= palletNumber - 1; ++i) { >%
      WoodenPallet {
        %<
          const yOffset = lateralMisalignment * wbrandom.real(-0.5, 0.5);
          const xOffset = longitudinalMisalignment * wbrandom.real(-0.5, 0.5);
          if (Math.abs(yOffset) > maxLateralMisalignment)
            maxLateralMisalignment = yOffset;
          if (Math.abs(xOffset) > maxLongitudinalMisalignment)
            maxLongitudinalMisalignment = xOffset;
        >%
        translation %<= xOffset >% %<= yOffset >% %<= i * palletSize.z >%
        name %<= '"wooden pallet' + i + '"' >%
        size %<= palletSize.x >% %<= palletSize.y >% %<= palletSize.z >%
        lathNumber IS palletLathNumber
        lathWidth IS palletLathWidth
        mass 0
        boundingObject FALSE
      }
    %< } >%
  ]
  name IS name
  model "wooden pallet stack"
  %< if (fields.boundingObject.value) { >%
  boundingObject Transform {
    translation 0 0 %<= palletSize.z * palletNumber * 0.5 >%
    children
    [
      Box {
        size %<= palletSize.x + maxLongitudinalMisalignment >% %<= palletSize.y + maxLateralMisalignment >% %<= palletSize.z * palletNumber >%
      }
    ]
  }
  %< } >%
  %< if (palletMass > 0) { >%
  physics Physics {
    density -1
    mass %<= palletMass * palletNumber >%
  }
  %< } >%
  locked IS locked
}
}