TPT Script Server

This page is used for previewing and submitting scripts for use with the Script Manager

Available Scripts

(2) TPTMulti by LBPHacker
(3) set wifi v2 by jacob1
(4) Script Paste by jacob1
(5) Random Element by jacob1
(6) Magical Merge Master 3000 by nucular
(7) More Fuel Mod-heavy by jward212
(9) Breakpoints (BRPT) by boxmein
(10) Cockroaches! by boxmein
(11) Random tree by ssccsscc
(12) Element with random properties by ssccsscc
(15) Minimalistic Element Dehider by nucular
(16) FPS Gauge by mniip
(17) TPT Radio by jward212
(18) Print Debugger by FeynmanLogomaker
(19) Powered BHOL by jacob1
(20) Light and lamps by electronic_steve
(21) Extremely Durable TTAN by QuentinADay
(22) New Buttons by QuentinADay
(23) Pure Energy by QuentinADay
(25) RCA's HUD XV Update I by RCAProduction
(27) 123456787654 vols by mjpowder
(28) Singularity Bomb by QuentinADay
(29) ES wifi set by electronic_steve
(30) Lua Elements Pack by FeynmanLogomaker
(31) stkm gun by jward212
(32) space building materials by kjack1111
(34) Rust bomb by Damian97
(35) Simple command block by ssccsscc
(36) Everlasting Fusion by QuentinADay
(37) Screenshot Organiser by mecha-man
(38) Napalm mod by cccp3
(39) Rocket fuel mod v0.15 by cccp3
(41) Useful web links by jward212
(42) TPT Logic Gates Mod by iamdumb
(43) ESTools by electronic_steve
(44) Head Crabs-HL2 by jward212
(45) Procedural Save Generator by boxmein
(46) smooth colours for nametag by jward212
(47) ZAKPACK by zak03
(49) Performance Monitor by FeynmanLogomaker
(51) Texter by byzod
(52) Texter default fonts by byzod
(53) Schicko's Font Pack for Texter by Schicko
(54) Realistic Element Names by Atomic10
(55) TPT's Mod V.3 Update 1 by Amy
(56) Temporaryaccount-Decorator by Temporaryaccount
(57) random save loader by jward212
(58) Tmp gradient display by ssccsscc
(59) particle re-orderer by mniip
(60) Electric Glow by jacob1
(61) More Fuel Mod-lite by jward212
(63) Rythidium by janekbe04
(64) Simple FPS GUI by Sfsjunior
(65) Enhanced Element Dehider by ChargedCreeper
(66) Graph of average temp by ssccsscc
(67) Template save loader by jacob1
(68) Lua Text Generator by jBot-42
(70) Pixel's Freezer by Pixelguru26
(71) Thingy | Fusion For Ever by TheChosenEvilOne
(72) op explosions by zolly_bro
(73) Scar by DorkyBobster
(74) ScreenShotMod by lill74
(77) Useful Things by TheEvilChosenOne
(78) Alchemy Mod by _MrN_
(79) Nuke v2 by Fnaf65
(80) Compressor mod by TheChosenEvilOne
(81) Custom Render Mode Loader by jacob1
(82) Spacewars by JosephMA
(83) MOAR - Alpha 0.1 by TheChosenEvilOne
(86) Element Creator by cxi
(88) Soapworm by LBPHacker
(90) Pressure Bomb by God_Kra
(91) SMFB by wntjq69
(92) Potato by cxi
(93) Subatomic Pack (BDS) by TPT_PL
(94) Acidic Pack (BDS) by TPT_PL
(95) Starbound Building Materials by Sanpypr
(96) Factory problems by TPT_PL
(97) Gamma Ray-diation by Kostia4381
(98) Magic by livingfossil
(99) Cross-window Copy/Cut/Paste by LBPHacker
(100) Langton's Ant with variations by LBPHacker
(101) Remote particle creator/deleter by TPT_PL
(102) Force fields by electronic_steve
(103) Reinforced Concrete by 12Me21
(105) TPT_PL's Lua Mod by TPT_PL
(106) Nuke v4 by Fnaf65
(107) CHEMMOD V1 by KevAK
(108) Chemicals by Ligan
(109) VonDaniel's Template by VonDaniel
(110) The Inaccurate Radioactivity Toy Mod by TuDoR2007
(112) textmonsterPack by textmonster404
(113) Meteor by TheScienceKid
(114) Tgpm by TuDoR2007
(115) Civilizations by TPT_PL
(116) RAD-MOD 1.2.1B by Kev_AK
(117) MicroLua by RamiLego4Game
(118) Extra customizable HUD by djy0212
(119) Ingame brush editor by ssccsscc
(120) Window Maker by Paul_31415
(121) CHEM-MOD V1.2B by Kev_AK
(122) Rainbow PHOT by Mrprocom
(123) stronger stickmanv by yuval
(124) 3D Pressure Visualizer by mniip
(125) Arkadian Liquid by JanKaszanka
(126) Fuel by nukers473
(127) Immersive Radioactivity v2.1 by Potbelly
(128) ElementLaunchingTool by juh9870
(129) CHEM-MOD_v1.2.2b by KevAK
(130) Slingshot by Mrprocom
(131) Perlin Noise Generator by DoubleF
(132) Element Replace by TomW1605
(133) Flooder V2 by TheAwesomeMutant
(134) Link Sign GUI by QuanTech
(135) Element dehider by 4e616d65
(136) Subphoton ROM Builder by mad-cow
(137) Hardened Dust by Liftski
(138) Bio-Vir by TheAwesomeMutant
(140) Orbit Simulator by Mrprocom
(141) johnnyou's Font for Texter by johnnyou (49796346)
(142) auto_wifi by phisically
(143) Layering helper by ssccsscc
(144) Layering Helper Extended by LuaMaster
(145) TPT Remade by TuDoR2007
(146) All-seeing sampler by djy0212
(147) Layering helper remastered by ssccsscc
(148) Eraser by thepowdertoy12
(149) EXPLOSIONS by olix3001
(150) Simple rocket fuel mod by ArseniyPlotnikov2006
(151) Pure Fission by Fnaf65
(154) Graph by ssccsscc
(155) Little's Pack! by LittleProgramming
(156) Lead by LoftisGaming
(157) WIFI Tuner by ssccsscc
(158) Previous Brush by TomW1605
(159) HUD Auto-Hider by Tim
(161) Stack tool by thepowdertoy12
(162) Oil and plastic by ArseniyPlotnikov2006
(163) Colored Ember by DUC
(164) Timer by ssccsscc
(165) Bacteria Mod by TuDoR2007
(166) Noise filter by LBPHacker
(167) Future-proof element dehider by LBPHacker
(168) RadioactiveNuke by DreamingWarlord
(169) Only Hot Element by DreamingWarlord
(170) Philosopher's Stone by Godhydra
(171) Conic section generator by LBPHacker
(172) Interface API by ssccsscc
(173) Metals&Materials by Ferrous26
(174) tpt.all by LBPHacker
(175) The Visual Elements Pack by Goblin01, vvv331
(176) Layering Helper Reforged by PowderNotSolid
(177) SNOWified SING by LBPHacker
(178) FPS Chart by Goblin01
(179) TPT font writer by Goblin01
(180) Simple Ruler by PowderNotSolid
(181) Heat Modifier by DreamingWarlord
(182) TPT Remade II by TuDoR2007
(183) Gravity simulator by ArseniyPlotnikov2k6
(184) Unobtainium by christheboss894
(185) TPTMIDI noteblock in tpt by djy0212
(186) DreamingWarlord's Lua Tool by DreamingWarlord
(187) Elements Tooltip by Goblin01
(189) Explodium script by 0d15ea5ebe57c0debadc0ffee0ddf00d
(190) more powered force elements by 6nop6nop
(191) Yzaak1Scifire Modpack by Yzaak1Scifire
(194) Fluor and more modpack! by galaktor
(195) Hot Powder by lieve_blendi
(196) Star by TUANMINHVIETNAM
(197) Heat Powders by lieve_blendi
(200) Tangeriinium (thx 2 cxi 4 code) by LostEditor
(201) Freezer by lieve_blendi
(202) Powder Power! by TPTSortaGuy
(203) PowderPlus v1.4 by PowderPlus Team
(204) fire by ME
(205) Stacked Goo Animations by Maticzpl
(206) Stickman Control for Android Version by PhauloRiquelme
(207) Spark Removal Button by Xyz
(208) More HEAC's! by Maxhd1234
(209) Immersive Radioactivity v3.0 by Potbelly
(210) Subframe Chipmaker Script by Maticzpl
(211) Realistic Propellants by ArseniyPlotnikov2k6
(212) Mass Equals Gravity by Maticzpl
(213) PhiMod v1 by ArolaunTech
(214) PC Controls for Android by Cracker1000
(217) Single-pixel pipe configurator by LBPHacker
(218) Omega Death Laser Gun by Dogeoum
(219) Notifications by Maticzpl
(221) Powderizer by ArolaunTech
(222) ElemDehider 1.2 by Inventor70
(223) Unobtainum V2 by DoomKittyAttack
(224) Organics Mod v0.2B by PowderPlus Team
(225) Gravity distortion by Avolte55
(226) tmp Wifi by PhauloRiquelme
(227) Alchemagica Mod v1.0 by RebMiami
(228) Fan Elements Mod by RebMiami
(229) Impossibilities by ArolaunTech
(230) Realistic Explosives by ArseniyPlotnikov2k6
(231) libactivation by anamorphic
(232) Alloy Brushes by Maticzpl
(233) Gravity bender by pres
(234) Slow Tick by Pixel
(235) Paste ID by Maticzpl
(236) many things by jadenflp2
(237) Territect by Rebmiami
(238) Better Descriptions v1.0.5 by ashyboi2022
(239) LIGHTNING SPRK by GOLmaster10101
(240) Small Bombs by juh9870
(241) Save Shop by aaccbb
(242) Moving solids v1.3.0 Beta by ArolaunTech
(244) Alchemistry by rdococ
(245) ETRD (Formerly PowderIM) by aaccbb
(246) RadonX by Justadirtblock
(248) Water-X by deuterium_oxide
(250) Indestructible INSL by CheekyRand0m
(252) Console's Mod by Console/Compec
(255) Slow motion by LBPHacker
(256) Powered Repeller by Hythonia
(257) Zeta's Electric Tools. by Zetalasis
(258) Azure serum (AZSR) by ALumpOfPowderToy
(259) COLORFULSAND by xert
(260) Lightning Circle by defaultuser0
(261) Powder Future Tech by JonaHungary
(262) TPTGlowingSolids by DestinyDyson
(263) Volcano Bomb by I_am_the_NugsWorld
(264) Neon Lights by Rebmiami
(265) Radioactive Materials by xyz
(266) Eater mod by VIPERGAMEZ
(267) the biology mod by someone
(268) Atomic Physics by qe
(269) Pure Radiation by ronansb
(270) Fake Elements by That_PowderToy_Guy
(271) Tachyons and MISC by RamenNoods
(272) Exotic Particles by rdococ
(273) FPS Slider by aaccbb
(274) Enphosian's Radioactive mod pack by Enphosian
(276) ROM Builder by QnpfvTPz

+ Submit new script!

Title: Author:
Script:
------------------- Configuration -------------------
local rquiredAPIVersion = 2.42

local resizingGridSize = 30
local safeModeByDefault = true
-----------------------------------------------------
pcall(dofile,"scripts/ssccssccAPI.lua")
if not interface_s or interface_s.Version < rquiredAPIVersion then
  if tpt.confirm("Download and install file", "Layering Helper Remastered script is required (scripts/ssccssccAPI.lua) to run. Download it now?") then
    fs.makeDirectory("scripts")
    tpt.getscript(172, "scripts/ssccssccAPI.lua", 1, 0)
  else
    tpt.log("Layering Helper Remastered script is unavailable due to lack of required files.")
    return
  end
end
--=================================================================--
--                    CODE IS BELOW THIS LINE                      --
--=================================================================--
local DefaultTheme = interface_s.DefaultTheme
--local mouseEvents = interface_s.mouseEvents       --Only for 2.43+
--local mouseButtons = interface_s.mouseButtons     --
local mouseEvents = {
  Down = 1,
  Up = 2
}
local mouseButtons = {
    Left = 1,
    Middle = 2,
    Right = 3
}

local TransparentWindow = {}
TransparentWindow.BackColor = gfx.getHexColor(0,0,0,150)
TransparentWindow.UnfocusedBackColor = gfx.getHexColor(0,0,0,150)
TransparentWindow.BorderColor = gfx.getHexColor(255,255,255,150)
TransparentWindow.UnfocusedBorderColor = gfx.getHexColor(150,150,150,150)
TransparentWindow.HeaderColor = gfx.getHexColor(150,150,255,150)
TransparentWindow.UnfocusedHeaderColor = gfx.getHexColor(32,32,55,150)

local function round(n)
  return math.floor(n+0.5)
end
--==========================Zoom gfx============================--
local isZoomActive = false
local zoomPixelSize = -1
local zoomWidthInRealPixels = -1
local zoomRealPositionX = -1
local zoomRealPositionY = -1
local zoomWindowPositionX = -1
local zoomWindowPositionY = -1
local zoomWindowSize = -1
local function getZoomInfo()
  isZoomActive=false
  if sim.adjustCoords(sim.XRES-1,5)~=sim.XRES-1 then
    isZoomActive=true
    local x,y = sim.adjustCoords(sim.XRES-1,2)
    zoomRealPositionX = x
    zoomRealPositionY = y
    local i=sim.XRES-2
    while x==sim.adjustCoords(i,2) do
      i=i-1
    end
    zoomPixelSize = sim.XRES-i-1
    i=zoomPixelSize
    while sim.adjustCoords(sim.XRES-i,2)~=sim.XRES-i do
      i=i+zoomPixelSize
    end
    zoomWidthInRealPixels = (i-zoomPixelSize)/zoomPixelSize
    zoomRealPositionX=zoomRealPositionX-zoomWidthInRealPixels+1
    zoomWindowPositionX = sim.XRES-i+zoomPixelSize
    if tpt.version.jacob1s_mod~=nil then
      zoomWindowPositionY = 1
    else
      zoomWindowPositionY = 0
    end
    zoomWindowSize = zoomPixelSize*zoomWidthInRealPixels
  else
    if sim.adjustCoords(1,5)~=1 then
      isZoomActive=true
      local x,y = sim.adjustCoords(1,2)
      zoomRealPositionX = x
      zoomRealPositionY = y
      local i=2
      while x==sim.adjustCoords(i,2) do
        i=i+1
      end
      if tpt.version.jacob1s_mod~=nil then
        zoomPixelSize = i-1
      else
        zoomPixelSize = i
      end
      i=zoomPixelSize
      while sim.adjustCoords(i,2)~=i do
        i=i+zoomPixelSize
      end
      zoomWidthInRealPixels = (i-zoomPixelSize)/zoomPixelSize
      if tpt.version.jacob1s_mod~=nil then
        zoomWindowPositionX = 1
        zoomWindowPositionY = 1
      else
        zoomWindowPositionX = 0
        zoomWindowPositionY = 0
      end
      zoomWindowSize = zoomPixelSize*zoomWidthInRealPixels+1
    end
  end
end

local function CoordinatesToZoomWindow(x,y)
  return zoomWindowPositionX+(x-zoomRealPositionX)*zoomPixelSize,zoomWindowPositionY+(y-zoomRealPositionY)*zoomPixelSize
end

local function drawPixelInZoomWindow(x,y,r,g,b,a)
  if isZoomActive then
    x = round(x)
    y = round(y)
    if x>=zoomRealPositionX and x<zoomRealPositionX+zoomWidthInRealPixels and y>=zoomRealPositionY and y<zoomRealPositionY+zoomWidthInRealPixels then
      local posX,posY = CoordinatesToZoomWindow(x,y)
      graphics.fillRect(posX,posY,zoomPixelSize-1,zoomPixelSize-1,r,g,b,a)
    end
  end
end

local function drawRectangleInZoomWindow(x,y,w,h,r,g,b,a)
  if isZoomActive then
    local leftX = math.max(x,zoomRealPositionX)
    local rightX = math.min(x+w,zoomRealPositionX+zoomWidthInRealPixels)
    local topY = math.max(y,zoomRealPositionY)
    local bottomY = math.min(y+h,zoomRealPositionY+zoomWidthInRealPixels)
    if leftX < rightX and topY < bottomY then
      local posX,posY = CoordinatesToZoomWindow(leftX,topY)
      graphics.fillRect(posX,posY,(rightX-leftX)*(zoomPixelSize),(bottomY-topY)*(zoomPixelSize),r,g,b,a)
    end
  end
end
--==========================Zoom gfx end========================--

local function clone(org)
  local temp = {}
  for i=1, #org do
    temp[i]={}
    for k, v in pairs(org[i]) do
      temp[i][k]=v
    end
  end
  return temp
end

local function HSVToRGB( hue, saturation, value )
  if saturation == 0 then
    return value
  end
  local hue_sector = math.floor( hue / 60 )
  local hue_sector_offset = ( hue / 60 ) - hue_sector
  local p = value * ( 1 - saturation )
  local q = value * ( 1 - saturation * hue_sector_offset )
  local t = value * ( 1 - saturation * ( 1 - hue_sector_offset ) )
  if hue_sector == 0 then
    return value, t, p
  elseif hue_sector == 1 then
    return q, value, p
  elseif hue_sector == 2 then
    return p, value, t
  elseif hue_sector == 3 then
    return p, q, value
  elseif hue_sector == 4 then
    return t, p, value
  elseif hue_sector == 5 then
    return value, p, q
  end
end

function layer()
  Layer()
end

function Layer()
  tpt.log("Press \"Select\" to start.")
  local pause = false
  if tpt.set_pause() == 1 then
    pause = true
  end
  tpt.set_pause(1)

  local selectionMover = nil
  local selection = nil
  local particlesIndexes = {}
  local virtualParticles = {}
  local virtualParticlesbackup = {}
  local selectionMenu = nil

  local function resetVars()
    selectionMover = nil
    selection = nil
    particlesIndexes = {}
    virtualParticles = {}
    virtualParticlesbackup = {}
  end
  
  local rotateButton = interface_s.Components.Button:new(2, 2, 12, 12,"R", DefaultTheme.Button)
  local resizeButton = interface_s.Components.Button:new(15, 2, 12, 12,"S", DefaultTheme.Button)
  resizeButton.Enabled = not safeModeByDefault

  local startangle = 0
  local lastangle = 0
  local currentangle = 0
  local isfirst = true
  local info = interface_s.ComponentsHelpers.Hint:new()
  local ignoreClicks = false
  local safeMode = safeModeByDefault
  local layerMode = true

  local function copyPart(i,dx,dy,vx,vy)
    local props = {"life","ctype","temp","flags","tmp","tmp2","dcolour","pavg0","pavg1"}
    local t = sim.partProperty(i,"type")
    local ni = sim.partCreate(-3,dx,dy,t)
    sim.partProperty(ni,"vx",vx)
    sim.partProperty(ni,"vy",vy)
    for k,v in pairs(props) do
      sim.partProperty(ni,v,sim.partProperty(i,v))
    end
    return ni
  end

  local function getIndexUsageCount()
    local usageCount = {}
    for i=0, #virtualParticles do
      if virtualParticles[i]~=nil then
        usageCount[virtualParticles[i]["i"]] = (usageCount[virtualParticles[i]["i"]] or 0) + 1
      end
    end
    return usageCount
  end

  local function virtualParticlesToReal()
    sim.takeSnapshot()
    local usageCount = getIndexUsageCount()
    for i=1, #virtualParticles do
      if usageCount[virtualParticles[i]["i"]]==1 then
        sim.partPosition(virtualParticles[i]["i"],virtualParticles[i]["x"],virtualParticles[i]["y"])
        sim.partProperty(virtualParticles[i]["i"],"vx",virtualParticles[i]["vx"])
        sim.partProperty(virtualParticles[i]["i"],"vy",virtualParticles[i]["vy"])
      else
        local id = copyPart(virtualParticles[i]["i"],virtualParticles[i]["x"],virtualParticles[i]["y"],virtualParticles[i]["vx"],virtualParticles[i]["vy"])
        usageCount[id] = 1 -- Prevent part from delete if not in layer mode
      end
    end
    for i=1, #particlesIndexes do
      if usageCount[particlesIndexes[i]]~=1 then
        simulation.partKill(particlesIndexes[i])
      end
    end
    if not layerMode then
      local tempGrid = {}
      for i in sim.parts() do
        local cx,cy = sim.partPosition(i)
        cx,cy=round(cx),round(cy)
        if tempGrid[cx]==nil then tempGrid[cx]={} end
        if tempGrid[cx][cy]==nil then tempGrid[cx][cy]={} end
        tempGrid[cx][cy][#(tempGrid[cx][cy])+1]=i
      end
      for i=1, #virtualParticles do
        if tempGrid[virtualParticles[i]["x"]]~=nil and tempGrid[virtualParticles[i]["x"]][virtualParticles[i]["y"]]~=nil then
          for j=1,#tempGrid[virtualParticles[i]["x"]][virtualParticles[i]["y"]] do
            if usageCount[tempGrid[virtualParticles[i]["x"]][virtualParticles[i]["y"]][j]]==nil or usageCount[tempGrid[virtualParticles[i]["x"]][virtualParticles[i]["y"]][j]]==0 then
              sim.partKill(tempGrid[virtualParticles[i]["x"]][virtualParticles[i]["y"]][j])
            end
          end
        end
      end
    end
  end

  local hue = 0

  local function drawOverOriginal()
    for i=1, #particlesIndexes do
      local r,g,b = HSVToRGB(hue,1,190)
      local cx,cy = sim.partPosition(particlesIndexes[i])
      if cx==nil or cy==nil then
        return
      end
      if not isZoomActive or not (cx>=zoomWindowPositionX and cx<=zoomWindowPositionX+zoomWindowSize and cy>=zoomWindowPositionY and cy<=zoomWindowPositionY+zoomWindowSize) then
        graphics.fillRect(cx,cy,1,1,r,g,b,170)
      end
      drawPixelInZoomWindow(cx,cy,r,g,b,170)
    end
  end

  local function drawVirtualParticles()
    getZoomInfo()
    for i=1, #virtualParticles do
      local r,g,b = HSVToRGB(hue,1,190)
      if not isZoomActive or not (virtualParticles[i]["x"]>=zoomWindowPositionX and virtualParticles[i]["x"]<=zoomWindowPositionX+zoomWindowSize and virtualParticles[i]["y"]>=zoomWindowPositionY and virtualParticles[i]["y"]<=zoomWindowPositionY+zoomWindowSize) then
        graphics.fillRect(virtualParticles[i]["x"],virtualParticles[i]["y"],1,1,r,g,b,170)
      end
      drawPixelInZoomWindow(virtualParticles[i]["x"],virtualParticles[i]["y"],r,g,b,170)
    end
    drawOverOriginal()
    hue = hue+1
    if hue>359 then
      hue=0
    end
  end

  local function saveToVirtual()
    virtualParticles = {}
    for i=1, #particlesIndexes do
      local cx,cy = sim.partPosition(particlesIndexes[i])
      virtualParticles[i]={}
      if selectionMover~=nil then
        virtualParticles[i]["x"] = cx+selectionMover.SumDX
        virtualParticles[i]["y"] = cy+selectionMover.SumDY
      else
        virtualParticles[i]["x"] = cx
        virtualParticles[i]["y"] = cy
      end
      virtualParticles[i]["i"]=particlesIndexes[i]
      virtualParticles[i]["vx"] = sim.partProperty(particlesIndexes[i], "vx") or 0
      virtualParticles[i]["vy"] = sim.partProperty(particlesIndexes[i], "vy") or 0
    end
  end

  local function adjustSelection()
    local maxX = 0
    local maxY = 0
    for i=1, #virtualParticles do
      if virtualParticles[i]~=nil then
        if maxX<virtualParticles[i]["x"] then maxX=virtualParticles[i]["x"] end
        if maxY<virtualParticles[i]["y"] then maxY=virtualParticles[i]["y"] end
      end
    end
    selectionMover.Height = maxY-selectionMover.Y+10
    selectionMover.Width = maxX-selectionMover.X+10
    selectionMenu.X=selectionMover.X+selectionMover.Width
  end

  --==========================Rotation============================--

  local virtualParticlesGrid = {}

  local function toTempGrid()
    virtualParticlesGrid = {}
    for i=1, #virtualParticles do
      local cx,cy=round(virtualParticles[i]["x"]),round(virtualParticles[i]["y"])
      if virtualParticlesGrid[cx]==nil then virtualParticlesGrid[cx]={} end
      if virtualParticlesGrid[cx][cy]==nil then virtualParticlesGrid[cx][cy]={} end
      virtualParticlesGrid[cx][cy][#(virtualParticlesGrid[cx][cy])+1] = {}
      virtualParticlesGrid[cx][cy][#(virtualParticlesGrid[cx][cy])]["i"] = virtualParticles[i]["i"]
      virtualParticlesGrid[cx][cy][#(virtualParticlesGrid[cx][cy])]["vx"] = virtualParticles[i]["vx"]
      virtualParticlesGrid[cx][cy][#(virtualParticlesGrid[cx][cy])]["vy"] = virtualParticles[i]["vy"]
    end
  end

  local function rot(a)
    if safeMode then
      for i=1, #virtualParticles do
        local cx = virtualParticles[i]["x"]
        local cy = virtualParticles[i]["y"]
        cx=cx-selectionMover.X-selectionMover.Width/2
        cy=cy-selectionMover.Y-selectionMover.Height/2
        local cx2 = cx
        cx = -cy*math.sin(math.rad(a))+cx*math.cos(math.rad(a))
        cy = cy*math.cos(math.rad(a))+cx2*math.sin(math.rad(a))
        cx=cx+selectionMover.X+selectionMover.Width/2
        cy=cy+selectionMover.Y+selectionMover.Height/2
        virtualParticles[i]["x"] = cx
        virtualParticles[i]["y"] = cy
        local vx = virtualParticles[i]["vx"]
        local vy = virtualParticles[i]["vy"]
        local vx2 = vx
        vx = -vy*math.sin(math.rad(a))+vx*math.cos(math.rad(a))
        vy = vy*math.cos(math.rad(a))+vx2*math.sin(math.rad(a))
        virtualParticles[i]["vx"] = vx
        virtualParticles[i]["vy"] = vy
      end
    else
      local minX, maxX, minY, maxY = 0, 0, 0, 0
      for i=1, #virtualParticlesbackup do
        local cx = virtualParticlesbackup[i]["x"]
        local cy = virtualParticlesbackup[i]["y"]
        cx=cx-selectionMover.X-selectionMover.Width/2
        cy=cy-selectionMover.Y-selectionMover.Height/2
        local cx2 = cx
        cx = round(-cy*math.sin(math.rad(-currentangle))+cx*math.cos(math.rad(-currentangle)))
        if minX>cx then minX = cx end
        if maxX<cx then maxX = cx end
        cy = round(cy*math.cos(math.rad(-currentangle))+cx2*math.sin(math.rad(-currentangle)))
        if minY>cy then minY = cy end
        if maxY<cy then maxY = cy end
      end
      minX = minX-2
      maxX = maxX+2
      minY = minY-2
      maxY = maxY+2
      virtualParticles={}
      for x=minX,maxX do
        for y=minY,maxY do
          local x2=x+selectionMover.X+selectionMover.Width/2
          local y2=y+selectionMover.Y+selectionMover.Height/2
          x2 = round(x2)
          y2 = round(y2)
          local cx = -y*math.sin(math.rad(currentangle))+x*math.cos(math.rad(currentangle))
          local cy = y*math.cos(math.rad(currentangle))+x*math.sin(math.rad(currentangle))
          cx=cx+selectionMover.X+selectionMover.Width/2
          cy=cy+selectionMover.Y+selectionMover.Height/2
          cx = round(cx)
          cy = round(cy)
          if virtualParticlesGrid[cx]~=nil and virtualParticlesGrid[cx][cy]~=nil then
            for i=1,#virtualParticlesGrid[cx][cy] do
              virtualParticles[#virtualParticles+1]={}
              virtualParticles[#virtualParticles]["x"]=x2
              virtualParticles[#virtualParticles]["y"]=y2
              virtualParticles[#virtualParticles]["i"]=virtualParticlesGrid[cx][cy][i]["i"]
              local vx = virtualParticlesGrid[cx][cy][i]["vx"]
              local vy = virtualParticlesGrid[cx][cy][i]["vy"]
              local vx2 = vx
              vx = -vy*math.sin(math.rad(-currentangle))+vx*math.cos(math.rad(-currentangle))
              vy = vy*math.cos(math.rad(-currentangle))+vx2*math.sin(math.rad(-currentangle))
              virtualParticles[#virtualParticles]["vx"] = vx
              virtualParticles[#virtualParticles]["vy"] = vy
            end
          end
        end
      end
    end
  end

  local function onStepRotate(x,y)
    local angle = currentangle
    if angle<0 then angle=angle+360 end
    info:MouseOver(x,y,"Rotating ("..angle.."). Press RMB to cancel. Press LMB to save.")
    currentangle = math.floor(math.deg(math.atan2(tpt.mousex-selectionMover.X-selectionMover.Width/2,tpt.mousey-selectionMover.Y-selectionMover.Height/2)))-startangle
    if isfirst then
      isfirst = false
    else
      rot(lastangle-currentangle)
    end
    lastangle = currentangle
  end

  local function onClickRotate(x,y,e,b)
    if e==mouseEvents.Up and b==mouseButtons.Left then
      interface_s.RemoveOnClickAction(onClickRotate)
      interface_s.RemoveOnStepAction(onStepRotate)
      ignoreClicks = false
      rotateButton.Enabled = true
      resizeButton.Enabled = not safeMode
    end
    if e==mouseEvents.Up and (b==mouseButtons.Right or b==4) then --Reset
      virtualParticles = clone(virtualParticlesbackup)
      interface_s.RemoveOnClickAction(onClickRotate)
      interface_s.RemoveOnStepAction(onStepRotate)
      ignoreClicks = false
      rotateButton.Enabled = true
      resizeButton.Enabled = not safeMode
    end
    return true
  end

  rotateButton.OnPressed = (function()
    toTempGrid()
    virtualParticlesbackup = clone(virtualParticles)
    startangle = math.floor(math.deg(math.atan2(tpt.mousex-selectionMover.X-selectionMover.Width/2,tpt.mousey-selectionMover.Y-selectionMover.Height/2)))
    lastangle = startangle
    isfirst = true
    info.HintFrames = 41
    interface_s.AddOnStepAction(onStepRotate)
    interface_s.AddOnClickAction(onClickRotate)
    ignoreClicks = true
    rotateButton.Enabled = false
    resizeButton.Enabled = false
  end)
  --=================================================================--
  
  --=============================Resize==============================--
  local resizePosX = -1
  local resizePosY = -1
  local SizeX = 1
  local SizeY = 1

  local function removeDeletedFromTable(tbl)
    local newTable = {}
    for i=1,#tbl do
      if tbl[i]~=123 then
        newTable[#newTable+1]=tbl[i]
      end
    end
    return newTable
  end

  local function onStepResize(x,y)
    SizeX = math.ceil((x-resizePosX)/resizingGridSize)+1
    SizeY = math.ceil((y-resizePosY)/resizingGridSize)+1
    local sizeXStr = SizeX
    local sizeYStr = SizeY
    if sizeXStr==0 then sizeXStr=1 end
    if sizeYStr==0 then sizeYStr=1 end
    if sizeXStr<0 then
      sizeXStr="1/"..math.abs(sizeXStr-1)
    end
    if sizeYStr<0 then
      sizeYStr="1/"..math.abs(sizeYStr-1)
    end
    info:MouseOver(tpt.mousex,tpt.mousey,"Resizing ("..sizeXStr.."x, "..sizeYStr.."y). Press RMB to cancel. Press LMB to save.")
    virtualParticles = clone(virtualParticlesbackup)
    local minX = 900
    local minY = 900
    
    for i=1, #virtualParticles do
      if minX>virtualParticles[i]["x"] then minX=virtualParticles[i]["x"] end
      if minY>virtualParticles[i]["y"] then minY=virtualParticles[i]["y"] end
    end
    if SizeX>0 then
      for i=1, #virtualParticles do
        virtualParticles[i]["x"]=math.ceil(minX+(virtualParticles[i]["x"]-minX)*(SizeX))
        for j=virtualParticles[i]["x"]+1,virtualParticles[i]["x"]+SizeX-1 do
          virtualParticles[#virtualParticles+1]={}
          virtualParticles[#virtualParticles]["x"]=j
          virtualParticles[#virtualParticles]["y"]=virtualParticles[i]["y"]
          virtualParticles[#virtualParticles]["i"]=virtualParticles[i]["i"]
          virtualParticles[#virtualParticles]["vx"]=virtualParticles[i]["vx"]
          virtualParticles[#virtualParticles]["vy"]=virtualParticles[i]["vy"]
        end
      end
    else
      local s = 1/math.abs(SizeX-1)
      for i=1, #virtualParticles do
        if (virtualParticles[i]["x"]-minX)%math.abs(SizeX-1)~= 0 then 
          virtualParticles[i]=123
        else
          virtualParticles[i]["x"]=math.ceil(minX+(virtualParticles[i]["x"]-minX)*s)
          for j=virtualParticles[i]["x"]+1,virtualParticles[i]["x"]+s-1 do
            virtualParticles[#virtualParticles+1]={}
            virtualParticles[#virtualParticles]["x"]=j
            virtualParticles[#virtualParticles]["y"]=virtualParticles[i]["y"]
            virtualParticles[#virtualParticles]["i"]=virtualParticles[i]["i"]
            virtualParticles[#virtualParticles]["vx"]=virtualParticles[i]["vx"]
            virtualParticles[#virtualParticles]["vy"]=virtualParticles[i]["vy"]
          end
        end
      end
      virtualParticles=removeDeletedFromTable(virtualParticles)
    end
    if SizeY>0 then
      for i=1, #virtualParticles do
        virtualParticles[i]["y"]=math.ceil(minY+(virtualParticles[i]["y"]-minY)*(SizeY))
        for j=virtualParticles[i]["y"]+1,virtualParticles[i]["y"]+SizeY-1 do
          virtualParticles[#virtualParticles+1]={}
          virtualParticles[#virtualParticles]["y"]=j
          virtualParticles[#virtualParticles]["x"]=virtualParticles[i]["x"]
          virtualParticles[#virtualParticles]["i"]=virtualParticles[i]["i"]
          virtualParticles[#virtualParticles]["vx"]=virtualParticles[i]["vx"]
          virtualParticles[#virtualParticles]["vy"]=virtualParticles[i]["vy"]
        end
      end
    else
      local s = 1/math.abs(SizeY-1)
      for i=1, #virtualParticles do
        if (virtualParticles[i]["y"]-minY)%math.abs(SizeY-1) ~= 0 then 
          virtualParticles[i]=123
        else
          virtualParticles[i]["y"]=math.ceil(minY+(virtualParticles[i]["y"]-minY)*(s))
          for j=virtualParticles[i]["y"]+1,virtualParticles[i]["y"]+s-1 do
            virtualParticles[#virtualParticles+1]={}
            virtualParticles[#virtualParticles]["y"]=j
            virtualParticles[#virtualParticles]["x"]=virtualParticles[i]["x"]
            virtualParticles[#virtualParticles]["i"]=virtualParticles[i]["i"]
            virtualParticles[#virtualParticles]["vx"]=virtualParticles[i]["vx"]
            virtualParticles[#virtualParticles]["vy"]=virtualParticles[i]["vy"]
          end
        end
      end
      virtualParticles=removeDeletedFromTable(virtualParticles)
    end
    adjustSelection()
  end

  local function onClickResize(x,y,e,b)
    if e==mouseEvents.Up and b==mouseButtons.Left then
      interface_s.RemoveOnClickAction(onClickResize)
      interface_s.RemoveOnStepAction(onStepResize)
      rotateButton.Enabled = true
      resizeButton.Enabled = not safeMode
      ignoreClicks = false
    end
    if e==mouseEvents.Up and (b==mouseButtons.Right or b==4) then --Reset
      virtualParticles = clone(virtualParticlesbackup)
      adjustSelection()
      interface_s.RemoveOnClickAction(onClickResize)
      interface_s.RemoveOnStepAction(onStepResize)
      rotateButton.Enabled = true
      resizeButton.Enabled = not safeMode
      ignoreClicks = false
    end
    return true
  end
  
  resizeButton.OnPressed = (function(x,y)
    virtualParticlesbackup = clone(virtualParticles)
    resizePosX=tpt.mousex
    resizePosY=tpt.mousey
    interface_s.AddOnStepAction(onStepResize)
    interface_s.AddOnClickAction(onClickResize)
    ignoreClicks = true
    rotateButton.Enabled = false
    resizeButton.Enabled = false
  end)
  --=================================================================--

  --=================================================================--
  local Zkey = false
  local function ZKeyPress(key, scan, r, ctrl, shift, alt)
    if key==122 then
      Zkey = true
    end
  end
  local function ZKeyRelease(key, scan, r, ctrl, shift, alt)
    if key==122 then
      Zkey = false
    end
  end
  
  local function ZkeyforOldAPI(a,b,c,d)
    if d==1 then
      ZKeyPress(b)
    else
      ZKeyRelease(b)
    end
  end

  if tpt.version.major<=93 and tpt.version.jacob1s_mod==nil or tpt.version.jacob1s_mod~=nil and tpt.version.jacob1s_mod<42 then
    tpt.register_keypress(ZkeyforOldAPI)
  else
    event.register(event.keyrelease, ZKeyRelease)
    event.register(event.keypress, ZKeyPress)
  end
  --=================================================================--
  selectionMenu = interface_s.Components.Window:new(10, 10, 65, 40,false, TransparentWindow)
  selectionMenu.IsShowing = false
  selectionMenu.AlwaysFocused = true
  selectionMenu.AllowResize = false
  interface_s.addComponent(selectionMenu)

  local layerModeCheckbox = interface_s.Components.Checkbox:new(2, 27, 10, "Layer", DefaultTheme.Checkbox)
  layerModeCheckbox.Checked = layerMode
  layerModeCheckbox.OnStateChanged = function(checked)
    layerMode = checked
  end

  local safeModeCheckbox = interface_s.Components.Checkbox:new(2, 15, 10, "Safe mode", DefaultTheme.Checkbox)
  safeModeCheckbox.Checked = safeMode
  safeModeCheckbox.OnStateChanged = function(checked)
    safeMode = checked
    resizeButton.Enabled = not safeMode
  end

  local mainWindow = interface_s.Components.Window:new(10, 10, 60, 60,true, DefaultTheme.Window)
  mainWindow.AllowResize = false
  interface_s.addComponent(mainWindow)

  local blockClicks = false
  local function blockAllClicks()
    if blockClicks and not Zkey then
      return true
    end
  end
  interface_s.AddOnClickAction(blockAllClicks)

  local Exit = interface_s.Components.Button:new(5, 40, 50, 15,"Exit", DefaultTheme.Button)
  Exit.OnPressed = (function()
    interface_s.RemoveComponent(mainWindow)
    interface_s.RemoveComponent(selectionMover)
    interface_s.RemoveComponent(selection)
    interface_s.RemoveComponent(selectionMenu)
    interface_s.RemoveOnClickAction(onClickRotate)
    interface_s.RemoveOnStepAction(onStepRotate)
    interface_s.RemoveOnClickAction(blockAllClicks)
    interface_s.RemoveOnStepAction(drawVirtualParticles)
    if pause == true then
      tpt.set_pause(1)
    else
      tpt.set_pause(0)
    end
    if tpt.version.major<=93 and tpt.version.jacob1s_mod==nil or tpt.version.jacob1s_mod~=nil and tpt.version.jacob1s_mod<42 then
      tpt.unregister_keypress(ZkeyforOldAPI)
    else
      event.unregister(event.keyrelease, ZKeyRelease)
      event.unregister(event.keypress, ZKeyPress)
    end
  end)

  local selectButton = interface_s.Components.Button:new(5, 10, 50, 15,"Select", DefaultTheme.Button)
  selectButton.OnPressed = (function()
    selectButton.Enabled = false
    tpt.log("Select area that you need to layer.")
    resetVars()
    if selectionMover ~= nil then
      interface_s.RemoveComponent(selectionMover)
    end
    selection = interface_s.Components.Selection:new(50, 50, DefaultTheme.Selection) 
    selection.OnDraw = function(IsFocused,x,y)
      x,y = sim.adjustCoords(x,y)
      if selection.IsPointSet then
        getZoomInfo()
        local x2,y2 = sim.adjustCoords(selection.V2StartX,selection.V2StartY)
        drawRectangleInZoomWindow(x2,y2,selection.V2EndWidth,selection.V2EndHeight,gfx.getColors(selection.Theme.BackColor))
      end
      return IsFocused,x,y
    end
    selection.OnClick = function(x,y,e,b)
      if b==3 then    --
        b=4           -- To make it correctly work while 2.43 interface API update is not approved
      end             --
      x,y = sim.adjustCoords(x,y)
      return x,y,e,b
    end
    selection.OnSelected = function(x,y,x2,y2,v2x,v2y,v2w,v2h)
      if v2w<5 or v2h<5 then
        interface_s.RemoveComponent(selection)
        selectButton.Enabled=true
        return
      end
      interface_s.AddOnStepAction(drawVirtualParticles)
      tpt.log("Now move the selection on the other particles. Press RMB to cancel. Press LMB to finish.")
      interface_s.RemoveComponent(selection)
      selectionMenu.X = v2x+v2w
      selectionMenu.Y = v2y
      selectionMenu:Show()
      particlesIndexes={}
      for i in sim.parts() do
        local cx,cy = sim.partPosition(i)
        cx = round(cx)
        cy = round(cy)
        if (cx>v2x) and (cx<v2x+v2w) and (cy>v2y) and (cy<v2y+v2h) then
          particlesIndexes[#particlesIndexes+1]=i
        end
      end

      blockClicks = true

      saveToVirtual()

      selectionMover = interface_s.Components.SelectionMover:new(v2x,v2y,v2w,v2h, DefaultTheme.Selection) 
      selectionMover.OnClick = (function(x,y,e,b)
        if Zkey or ignoreClicks then return nil end
        if b==3 then    --
          b=4           -- To make it correctly work while 2.43 interface API update is not approved
        end             --
        x,y = sim.adjustCoords(x,y)
        return x,y,e,b
      end)
      selectionMover.OnMove = (function(x,y,e,b)
        if Zkey then return nil end
        x,y = sim.adjustCoords(x,y)
        return x,y,e,b
      end)
      selectionMover.OnDraw = (function(f,x,y)
        drawRectangleInZoomWindow(selectionMover.X,selectionMover.Y,selectionMover.Width,selectionMover.Height,gfx.getColors(selectionMover.Theme.BackColor))
      end)
      selectionMover.OnDone = (function()
        interface_s.RemoveComponent(selectionMover)
        interface_s.RemoveOnStepAction(drawVirtualParticles)
        virtualParticlesToReal()
        selectionMenu:Hide()
        blockClicks = false
        selectButton.Enabled=true
      end)
      selectionMover.OnAbort = (function(tdx,tdy)
        interface_s.RemoveOnStepAction(drawVirtualParticles)
        interface_s.RemoveComponent(selectionMover)
        selectionMenu:Hide()
        blockClicks = false
        selectButton.Enabled=true
      end)
      selectionMover.OnMovement = (function(xd,yd)
        selectionMenu.X=selectionMenu.X+xd
        selectionMenu.Y=selectionMenu.Y+yd
          for i=0, #virtualParticles do
            if virtualParticles[i]~=nil then
              virtualParticles[i]["x"] = virtualParticles[i]["x"]+xd
              virtualParticles[i]["y"] = virtualParticles[i]["y"]+yd
            end
          end
        end)
        interface_s.addComponent(selectionMover)
    end
    selection.OnSelectionAborted = function()
      interface_s.RemoveComponent(selection)
      selectButton.Enabled=true
    end
    interface_s.addComponent(selection)
  end)
  mainWindow:AddComponent(selectButton)
  mainWindow:AddComponent(Exit)
  selectionMenu:AddComponent(rotateButton)
  selectionMenu:AddComponent(resizeButton)
  selectionMenu:AddComponent(safeModeCheckbox)
  selectionMenu:AddComponent(layerModeCheckbox)
end
--=================================================================--
--                    CODE IS ABOVE THIS LINE                      --
--=================================================================--

Description:

Changelog: