Title:
Author:
Script:
-- cxi's Element Creator
-- Version 1.0 August 12 2016
-- This code is released under the MIT license
function round(num, dp)
local mult = 10^(dp or 0)
return math.floor(num * mult + 0.5) / mult
end
local element = elem.allocate("CXI", "ELEM")
elem.element(element, elem.element(elem.DEFAULT_PT_DMND))
elem.property(element, "Name", "ELEM")
elem.property(element, "Colour", 0xFFFFFF)
elem.property(element, "Description", "Element created using cxi's element creator. Press N to open.")
elem.property(element, "MenuSection", elem.SC_SPECIAL)
local width = 600
local height = 342
local exportwidth = 570
local exportheight = 88
local window = Window:new(14, 38, width, height)
local exportwindow = Window:new(29, 165, exportwidth, exportheight)
local clrlabel = Label:new(270, 316, 32, 16, "Color:")
window:addComponent(clrlabel)
local colortext = Textbox:new(306, 316, 50, 16, "ffffff", "")
window:addComponent(colortext)
local y = 30
local advlabel = Label:new(10, y, width / 2 - 20, 16, "Advection - how much air movement affects a particle.")
window:addComponent(advlabel)
local advectiontext = Textbox:new(10, y + 20, width / 2 - 20, 16, "0.4", "")
window:addComponent(advectiontext)
y = y + 40
local adrlabel = Label:new(10, y, width / 2 - 20, 16, "AirDrag - how much air a particle moves when moving.")
window:addComponent(adrlabel)
local airdragtext = Textbox:new(10, y + 20, width / 2 - 20, 16, "0.01", "")
window:addComponent(airdragtext)
y = y + 40
local allabel = Label:new(10, y, width / 2 - 20, 16, "AirLoss - how much a particle slows down moving air.")
window:addComponent(allabel)
local airlosstext = Textbox:new(10, y + 20, width / 2 - 20, 16, "0.94", "")
window:addComponent(airlosstext)
y = y + 40
local llabel = Label:new(10, y, width / 2 - 20, 16, "Loss - how much the speed a particle retains each frame.")
window:addComponent(llabel)
local losstext = Textbox:new(10, y + 20, width / 2 - 20, 16, "0.95", "")
window:addComponent(losstext)
y = y + 40
local collabel = Label:new(10, y, width / 2 - 20, 16, "Collision - how a particle moves when it collides.")
window:addComponent(collabel)
local collisiontext = Textbox:new(10, y + 20, width / 2 - 20, 16, "-0.1", "")
window:addComponent(collisiontext)
y = y + 40
local grvlabel = Label:new(10, y, width / 2 - 20, 16, "Gravity - how fast a particle falls.")
window:addComponent(grvlabel)
local gravitytext = Textbox:new(10, y + 20, width / 2 - 20, 16, "-0.1", "")
window:addComponent(gravitytext)
y = y + 40
local diflabel = Label:new(10, y, width / 2 - 20, 16, "Diffusion - how much a particle wiggles.")
window:addComponent(diflabel)
local diffusiontext = Textbox:new(10, y + 20, width / 2 - 20, 16, "0", "")
window:addComponent(diffusiontext)
y = 30
local htalabel = Label:new(width / 2 + 10, y, width / 2 - 20, 16, "HotAir - how much a particle increases the pressure by.")
window:addComponent(htalabel)
local hotairtext = Textbox:new(width / 2 + 10, y + 20, width / 2 - 20, 16, "0", "")
window:addComponent(hotairtext)
y = y + 40
local explabel = Label:new(width / 2 + 10, y, width / 2 - 20, 16, "Explosive - 0: none, 1: fire, 2: pressure > 2.5 or fire.")
window:addComponent(explabel)
local explosivetext = Textbox:new(width / 2 + 10, y + 20, width / 2 - 20, 16, "0", "")
window:addComponent(explosivetext)
y = y + 40
local fllabel = Label:new(width / 2 + 10, y, width / 2 - 20, 16, "Flammable - how well the element burns.")
window:addComponent(fllabel)
local flammabletext = Textbox:new(width / 2 + 10, y + 20, width / 2 - 20, 16, "0", "")
window:addComponent(flammabletext)
y = y + 40
local hdlabel = Label:new(width / 2 + 10, y, width / 2 - 20, 16, "Hardness - how quickly ACID dissolves the element.")
window:addComponent(hdlabel)
local hardnesstext = Textbox:new(width / 2 + 10, y + 20, width / 2 - 20, 16, "0", "")
window:addComponent(hardnesstext)
y = y + 40
local wtlabel = Label:new(width / 2 + 10, y, width / 2 - 20, 16, "Weight - how heavy the element is.")
window:addComponent(wtlabel)
local weighttext = Textbox:new(width / 2 + 10, y + 20, width / 2 - 20, 16, "0", "")
window:addComponent(weighttext)
y = y + 40
local hclabel = Label:new(width / 2 + 10, y, width / 2 - 20, 16, "Heat conductivity - 0 to 255.")
window:addComponent(hclabel)
local heatconducttext = Textbox:new(width / 2 + 10, y + 20, width / 2 - 20, 16, "0", "")
window:addComponent(heatconducttext)
y = y + 40
local itlabel = Label:new(width / 2 + 10, y, width / 2 - 20, 16, "Initial temperature in Kelvin.")
window:addComponent(itlabel)
local temperaturetext = Textbox:new(width / 2 + 10, y + 20, width / 2 - 20, 16, "0", "")
window:addComponent(temperaturetext)
local function updateproperties(sender)
elem.property(element, "Color", tonumber(colortext:text():lower(), 16))
elem.property(element, "Advection", tonumber(advectiontext:text()))
elem.property(element, "AirDrag", tonumber(airdragtext:text()))
elem.property(element, "AirLoss", tonumber(airlosstext:text()))
elem.property(element, "Loss", tonumber(losstext:text()))
elem.property(element, "Collision", tonumber(collisiontext:text()))
elem.property(element, "Gravity", tonumber(gravitytext:text()))
elem.property(element, "Diffusion", tonumber(diffusiontext:text()))
elem.property(element, "HotAir", tonumber(hotairtext:text()))
elem.property(element, "Explosive", tonumber(explosivetext:text()))
elem.property(element, "Flammable", tonumber(flammabletext:text()))
elem.property(element, "Hardness", tonumber(hardnesstext:text()))
elem.property(element, "Weight", tonumber(weighttext:text()))
elem.property(element, "HeatConduct", tonumber(heatconducttext:text()))
elem.property(element, "Temperature", tonumber(temperaturetext:text()))
end
colortext:onTextChanged(updateproperties)
advectiontext:onTextChanged(updateproperties)
airdragtext:onTextChanged(updateproperties)
airlosstext:onTextChanged(updateproperties)
losstext:onTextChanged(updateproperties)
collisiontext:onTextChanged(updateproperties)
gravitytext:onTextChanged(updateproperties)
diffusiontext:onTextChanged(updateproperties)
hotairtext:onTextChanged(updateproperties)
explosivetext:onTextChanged(updateproperties)
flammabletext:onTextChanged(updateproperties)
hardnesstext:onTextChanged(updateproperties)
weighttext:onTextChanged(updateproperties)
heatconducttext:onTextChanged(updateproperties)
temperaturetext:onTextChanged(updateproperties)
local x = 10
local w = 48
local buttons = {}
local solidbutton = Button:new(x, 316, w, 16, "Solid")
window:addComponent(solidbutton)
x = x + w - 1
buttons["Solid"] = solidbutton
local powderbutton = Button:new(x, 316, w, 16, "Powder")
window:addComponent(powderbutton)
x = x + w - 1
buttons["Powder"] = powderbutton
local liquidbutton = Button:new(x, 316, w, 16, "Liquid")
window:addComponent(liquidbutton)
x = x + w - 1
buttons["Liquid"] = liquidbutton
local gasbutton = Button:new(x, 316, w, 16, "Gas")
window:addComponent(gasbutton)
x = x + w - 1
buttons["Gas"] = gasbutton
local energybutton = Button:new(x, 316, w, 16, "Energy")
window:addComponent(energybutton)
x = x + w - 1
buttons["Energy"] = energybutton
local function settype(sender)
if sender:text() == solidbutton:text() then
elem.property(element, "Properties", elem.TYPE_SOLID)
elem.property(element, "Falldown", 0)
end
if sender:text() == powderbutton:text() then
elem.property(element, "Properties", elem.TYPE_PART)
elem.property(element, "Falldown", 1)
end
if sender:text() == liquidbutton:text() then
elem.property(element, "Properties", elem.TYPE_LIQUID)
elem.property(element, "Falldown", 2)
end
if sender:text() == gasbutton:text() then
elem.property(element, "Properties", elem.TYPE_GAS)
elem.property(element, "Falldown", 0)
end
if sender:text() == energybutton:text() then
elem.property(element, "Properties", elem.TYPE_ENERGY)
elem.property(element, "Falldown", 0)
end
for i, button in pairs(buttons) do
if string.find(sender:text(), i) then
button:text("[" .. i .. "]")
else
button:text(i)
end
end
end
solidbutton:action(settype)
powderbutton:action(settype)
liquidbutton:action(settype)
gasbutton:action(settype)
energybutton:action(settype)
local function loadelement(sender)
local e = assert(loadstring("return elem.DEFAULT_PT_" .. sender:text():upper()), nil)()
if e ~= nil then
local type = bit.band(elem.property(e, "Properties"), 31)
elem.property(element, "Properties", type)
if type == elem.TYPE_SOLID then
settype(solidbutton)
elseif type == elem.TYPE_PART then
settype(powderbutton)
elseif type == elem.TYPE_LIQUID then
settype(liquidbutton)
elseif type == elem.TYPE_GAS then
settype(gasbutton)
elseif type == elem.TYPE_ENERGY then
settype(energybutton)
end
elem.property(element, "Falldown", elem.property(e, "Falldown"))
colortext:text(string.format("%x", elem.property(e, "Color")))
advectiontext:text(round(elem.property(e, "Advection"), 7))
airdragtext:text(round(elem.property(e, "AirDrag"), 7))
airlosstext:text(round(elem.property(e, "AirLoss"), 7))
losstext:text(round(elem.property(e, "Loss"), 7))
collisiontext:text(round(elem.property(e, "Collision"), 7))
gravitytext:text(round(elem.property(e, "Gravity"), 7))
diffusiontext:text(round(elem.property(e, "Diffusion"), 7))
hotairtext:text(round(elem.property(e, "HotAir"), 7))
explosivetext:text(round(elem.property(e, "Explosive"), 0))
flammabletext:text(round(elem.property(e, "Flammable"), 0))
hardnesstext:text(round(elem.property(e, "Hardness"), 0))
weighttext:text(round(elem.property(e, "Weight"), 0))
heatconducttext:text(round(elem.property(e, "HeatConduct"), 0))
temperaturetext:text(round(elem.property(e, "Temperature"), 2))
updateproperties()
end
end
local loadlabel = Label:new(10, 10, 180, 16, "Load properties from existing element:")
window:addComponent(loadlabel)
local loadtext = Textbox:new(196, 10, 64, 16, "DUST", "")
loadtext:onTextChanged(loadelement)
window:addComponent(loadtext)
local function export(sender)
ui.showWindow(exportwindow)
end
local exportbutton = Button:new(width - 110, height - 26, 100, 16, "Export code...")
exportbutton:action(export)
window:addComponent(exportbutton)
window:onTryExit(function()
tpt.active_menu(elem.SC_SPECIAL)
ui.closeWindow(window)
end)
local namespace = Textbox:new(10, 10, 120, 16, "", "Namespace")
exportwindow:addComponent(namespace)
local name = Textbox:new(130, 10, 120, 16, "", "1-4 character name")
exportwindow:addComponent(name)
local description = Textbox:new(10, 36, exportwidth - 20, 16, "", "Description")
exportwindow:addComponent(description)
local addtemplates = Checkbox:new(10, 62, exportwidth / 2 - 20, 16, "Include templates for update and graphics functions")
exportwindow:addComponent(addtemplates)
local function exportlua(sender)
local namespacestr = namespace:text():upper()
local namestr = name:text():upper()
if namespacestr:gsub("%s+", "") == "" or namestr:gsub("%s+", "") == "" or description:text():gsub("%s+", "") == "" then
tpt.message_box("Error", "Missing required fields.")
return
end
local elementconstant = "elem." .. namespacestr .. "_PT_" .. namestr
local state = ""
local properties = ""
local type = bit.band(elem.property(element, "Properties"), 31)
if type == elem.TYPE_SOLID then
state = "elem.ST_SOLID"
properties = "elem.TYPE_SOLID"
elseif type == elem.TYPE_PART then
state = "elem.ST_SOLID"
properties = "elem.TYPE_PART"
elseif type == elem.TYPE_LIQUID then
state = "elem.ST_LIQUID"
properties = "elem.TYPE_LIQUID"
elseif type == elem.TYPE_GAS then
state = "elem.ST_GAS"
properties = "elem.TYPE_GAS"
elseif type == elem.TYPE_ENERGY then
state = "elem.ST_NONE"
properties = "elem.TYPE_ENERGY"
end
local code = string.format([[elem.allocate("%s", "%s")
elem.element(%s, elem.element(elem.DEFAULT_PT_DMND))
elem.property(%s, "Name", "%s")
elem.property(%s, "Description", "%s")
elem.property(%s, "Colour", 0x%x)
elem.property(%s, "MenuVisible", 1)
elem.property(%s, "MenuSection", SC_SPECIAL)
elem.property(%s, "Advection", %s)
elem.property(%s, "AirDrag", %s)
elem.property(%s, "AirLoss", %s)
elem.property(%s, "Loss", %s)
elem.property(%s, "Collision", %s)
elem.property(%s, "Gravity", %s)
elem.property(%s, "Diffusion", %s)
elem.property(%s, "HotAir", %s)
elem.property(%s, "Explosive", %s)
elem.property(%s, "Flammable", %s)
elem.property(%s, "Hardness", %s)
elem.property(%s, "Meltable", 0)
elem.property(%s, "Weight", %s)
elem.property(%s, "HeatConduct", %s)
elem.property(%s, "Temperature", %s)
elem.property(%s, "Falldown", %s)
elem.property(%s, "State", %s)
elem.property(%s, "Properties", %s)
elem.property(%s, "LowPressure", IPL)
elem.property(%s, "LowPressureTransition", NT)
elem.property(%s, "HighPressure", IPH)
elem.property(%s, "HighPressureTransition", NT)
elem.property(%s, "LowTemperature", ITL)
elem.property(%s, "LowTemperatureTransition", NT)
elem.property(%s, "HighTemperature", ITH)
elem.property(%s, "HighTemperatureTransition", NT)]], namespacestr, namestr, elementconstant, elementconstant, namestr, elementconstant, description:text(), elementconstant, elem.property(element, "Color"), elementconstant, elementconstant, elementconstant, round(elem.property(element, "Advection"), 7), elementconstant, round(elem.property(element, "AirDrag"), 7), elementconstant, round(elem.property(element, "AirLoss"), 7), elementconstant, round(elem.property(element, "Loss"), 7), elementconstant, round(elem.property(element, "Collision"), 7), elementconstant, round(elem.property(element, "Gravity"), 7), elementconstant, round(elem.property(element, "Diffusion"), 7), elementconstant, round(elem.property(element, "HotAir"), 7), elementconstant, round(elem.property(element, "Explosive"), 0), elementconstant, round(elem.property(element, "Flammable"), 0), elementconstant, round(elem.property(element, "Hardness"), 0), elementconstant, elementconstant, round(elem.property(element, "Weight"), 0), elementconstant, round(elem.property(element, "HeatConduct"), 0), elementconstant, round(elem.property(element, "Temperature"), 2), elementconstant, elem.property(element, "Falldown"), elementconstant, state, elementconstant, properties, elementconstant, elementconstant, elementconstant, elementconstant, elementconstant, elementconstant, elementconstant, elementconstant)
if addtemplates:checked() then
code = code .. string.format([[
function %s_Update(i, x, y, ss, nt)
-- i: particle index
-- x, y: particle x, y coords
end
elements.property(%s, "Update", %s_Update)
function %s_Graphics(i, colr, colg, colb)
-- i: particle index
-- colr, colg, colb: color red, green, and blue channels
-- return cache, pixel mode,
-- alpha, red, green, blue,
-- fire alpha, fire red, fire green, fire blue
return 1, 0x0000001, 255, colr, colg, colb, 0, 0, 0, 0
end
elements.property(%s, "Graphics", %s_Graphics)]], namestr, elementconstant, namestr, namestr, elementconstant, namestr)
end
file = io.open("scripts/" .. namestr .. ".lua", "w")
file:write(code)
file:close()
end
local function exportcpp(sender)
local namestr = name:text():upper()
if namestr:gsub("%s+", "") == "" or description:text():gsub("%s+", "") == "" then
tpt.message_box("Error", "Missing required fields.")
return
end
local properties = ""
local type = bit.band(elem.property(element, "Properties"), 31)
if type == elem.TYPE_SOLID then
properties = "TYPE_SOLID"
elseif type == elem.TYPE_PART then
properties = "TYPE_PART"
elseif type == elem.TYPE_LIQUID then
properties = "TYPE_LIQUID"
elseif type == elem.TYPE_GAS then
properties = "TYPE_GAS"
elseif type == elem.TYPE_ENERGY then
properties = "TYPE_ENERGY"
end
local code = string.format([[#include "simulation/Elements.h"
//#TPT-Directive ElementClass Element_%s PT_%s {INSERT ID HERE}
Element_%s::Element_%s()
{
Identifier = "DEFAULT_PT_%s";
Name = "%s";
Colour = PIXPACK(0x%x);
MenuVisible = 1;
MenuSection = SC_SPECIAL;
Enabled = 1;
Advection = %sf;
AirDrag = %sf * CFDS;
AirLoss = %s;
Loss = %sf;
Collision = %sf;
Gravity = %sf;
Diffusion = %sf;
HotAir = %sf * CFDS;
Falldown = %s;
Flammable = %s;
Explosive = %s;
Meltable = 0;
Hardness = %s;
Weight = %s;
Temperature = %sf;
HeatConduct = %s;
Description = "%s";
Properties = %s;
LowPressure = IPL;
LowPressureTransition = NT;
HighPressure = IPH;
HighPressureTransition = NT;
LowTemperature = ITL;
LowTemperatureTransition = NT;
HighTemperature = ITH;
HighTemperatureTransition = NT;]], namestr, namestr, namestr, namestr, namestr, namestr, elem.property(element, "Color"), round(elem.property(element, "Advection"), 7), round(elem.property(element, "AirDrag"), 7), round(elem.property(element, "AirLoss"), 7), round(elem.property(element, "Loss"), 7), round(elem.property(element, "Collision"), 7), round(elem.property(element, "Gravity"), 7), round(elem.property(element, "Diffusion"), 7), round(elem.property(element, "HotAir"), 7), elem.property(element, "Falldown"), round(elem.property(element, "Flammable"), 0), round(elem.property(element, "Explosive"), 0), round(elem.property(element, "Hardness"), 0), round(elem.property(element, "Weight"), 0), round(elem.property(element, "Temperature"), 2), round(elem.property(element, "HeatConduct"), 0), description:text(), properties)
if addtemplates:checked() then
code = code .. string.format([[
Update = &Element_%s::update;
Graphics = &Element_%s::graphics;]], namestr, namestr)
end
code = code .. [[
}]]
if addtemplates:checked() then
code = code .. string.format([[
// #define UPDATE_FUNC_ARGS Simulation* sim, int i, int x, int y, int surround_space, int nt, Particle *parts, int pmap[YRES][XRES]
//#TPT-Directive ElementHeader Element_%s static int update(UPDATE_FUNC_ARGS)
int Element_%s::update(UPDATE_FUNC_ARGS)
{
}
// #define GRAPHICS_FUNC_ARGS Renderer *ren, Particle *cpart, int nx, int ny,
// int *pixel_mode, int* cola, int *colr, int *colg,
// int *colb, int *firea, int *firer, int *fireg, int *fireb
//#TPT-Directive ElementHeader Element_%s static int graphics(GRAPHICS_FUNC_ARGS)
int Element_%s::graphics(GRAPHICS_FUNC_ARGS)
{
}]], namestr, namestr, namestr, namestr)
end
code = code .. string.format([[
Element_%s::~Element_%s() {}]], namestr, namestr)
file = io.open(namestr .. ".cpp", "w")
file:write(code)
file:close()
end
local exportluabutton = Button:new(exportwidth - 110, exportheight - 26, 100, 16, "Export Lua code")
exportluabutton:action(exportlua)
exportwindow:addComponent(exportluabutton)
local exportcppbutton = Button:new(exportwidth - 220, exportheight - 26, 100, 16, "Export C++ code")
exportcppbutton:action(exportcpp)
exportwindow:addComponent(exportcppbutton)
exportwindow:onTryExit(function()
ui.closeWindow(exportwindow)
end)
local function keypressed(key, keynum, mod, evt)
if evt == 2 and key == "n" then
ui.showWindow(window)
end
end
loadelement(loadtext)
tpt.register_keypress(keypressed)
Description:
Changelog: