Get computed properties :)
parent
9aec996b74
commit
2cf3e7aaea
|
@ -94,14 +94,6 @@ ivec2 Gui::Element::getComputedScreenPos() const {
|
|||
bool Gui::Element::handleMouseHover(ivec2 mousePos, bool& pointer) {
|
||||
bool childIntersects = false;
|
||||
for (let& child : children) if (child->handleMouseHover(mousePos, pointer)) childIntersects = true;
|
||||
|
||||
// if (childIntersects) {
|
||||
// if (hovered) {
|
||||
// hovered = false;
|
||||
// updateElement();
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
ivec2 size = getComputedSize();
|
||||
ivec2 pos = getComputedScreenPos();
|
||||
|
|
|
@ -201,10 +201,10 @@ namespace Gui {
|
|||
return def;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Returns an ExpressionInfo object for evaluating Lengths. */
|
||||
virtual ExpressionInfo getExpr() const;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* Called by the root when the mouse position changes.
|
||||
|
|
|
@ -57,8 +57,43 @@ void MenuSandbox::load(const SubgameDef& subgame) {
|
|||
reset();
|
||||
subgameName = subgame.config.name;
|
||||
|
||||
loadAndRunMod(subgame.subgamePath + "/../../assets/base");
|
||||
loadAndRunMod(subgame.subgamePath + "/menu");
|
||||
try {
|
||||
loadAndRunMod(subgame.subgamePath + "/../../assets/base");
|
||||
loadAndRunMod(subgame.subgamePath + "/menu");
|
||||
}
|
||||
catch (sol::error e) {
|
||||
string err = static_cast<sol::error>(e).what();
|
||||
|
||||
vec<string> lines;
|
||||
{
|
||||
string line;
|
||||
std::stringstream textStream(err);
|
||||
while (std::getline(textStream, line, '\n')) lines.emplace_back(line);
|
||||
}
|
||||
|
||||
for (const let& line : lines) {
|
||||
usize lineNumStart = line.find(':');
|
||||
if (lineNumStart == string::npos) continue;
|
||||
usize lineNumEnd = line.find(':', lineNumStart + 1);
|
||||
if (lineNumEnd == string::npos) continue;
|
||||
|
||||
string fileName = line.substr(0, lineNumStart);
|
||||
fileName.erase(std::remove_if(fileName.begin(), fileName.end(), isspace), fileName.end());
|
||||
|
||||
for (const let& file : mod.files) {
|
||||
if (file.path != fileName) continue;
|
||||
|
||||
let msg = ErrorFormatter::formatError(fileName,
|
||||
std::stoi(line.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)),
|
||||
err, file.file);
|
||||
|
||||
showError(msg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
showError(err);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuSandbox::update(double delta) {
|
||||
|
@ -79,8 +114,10 @@ sol::protected_function_result MenuSandbox::runFileSandboxed(const string& file)
|
|||
env["_FILE"] = f.path;
|
||||
env["_MODNAME"] = mod.config.name;
|
||||
|
||||
return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback,
|
||||
this, std::placeholders::_2), "@" + f.path, sol::load_mode::text);
|
||||
using Pfr = sol::protected_function_result;
|
||||
return lua.safe_script(f.file, env,
|
||||
[](lua_State*, Pfr pfr) -> Pfr { throw static_cast<sol::error>(pfr); },
|
||||
"@" + f.path, sol::load_mode::text);
|
||||
}
|
||||
throw std::runtime_error("Error opening '" + file + "', file not found.");
|
||||
}
|
||||
|
@ -91,8 +128,8 @@ void MenuSandbox::loadAndRunMod(const string& modPath) {
|
|||
LuaMod mod;
|
||||
string root = modPath + "/script";
|
||||
|
||||
std::list<string> dirsToScan{ root };
|
||||
std::list<string> luaFiles{};
|
||||
std::list<string> dirsToScan { root };
|
||||
std::list<string> luaFiles {};
|
||||
|
||||
cf_dir_t dir;
|
||||
while (!dirsToScan.empty()) {
|
||||
|
@ -158,41 +195,4 @@ void MenuSandbox::showError(const string& err) {
|
|||
{ Gui::Prop::SIZE, array<Expr, 2> { Expr("100dp"), Expr("-1") } },
|
||||
{ Gui::Prop::MARGIN, array<Expr, 4> { Expr("4dp"), Expr("4dp"), Expr("4dp"), Expr("4dp") } }
|
||||
}});
|
||||
}
|
||||
|
||||
sol::protected_function_result MenuSandbox::errorCallback(sol::protected_function_result r) {
|
||||
string err = static_cast<sol::error>(r).what();
|
||||
|
||||
std::cout << Log::err << err << Log::endl;
|
||||
|
||||
vec<string> lines;
|
||||
{
|
||||
string line;
|
||||
std::stringstream textStream(err);
|
||||
while (std::getline(textStream, line, '\n')) lines.emplace_back(line);
|
||||
}
|
||||
|
||||
for (const let& line : lines) {
|
||||
usize lineNumStart = line.find(':');
|
||||
if (lineNumStart == string::npos) continue;
|
||||
usize lineNumEnd = line.find(':', lineNumStart + 1);
|
||||
if (lineNumEnd == string::npos) continue;
|
||||
|
||||
string fileName = line.substr(0, lineNumStart);
|
||||
fileName.erase(std::remove_if(fileName.begin(), fileName.end(), isspace), fileName.end());
|
||||
|
||||
for (const let& file : mod.files) {
|
||||
if (file.path != fileName) continue;
|
||||
|
||||
let msg = ErrorFormatter::formatError(fileName,
|
||||
std::stoi(line.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1)),
|
||||
err, file.file);
|
||||
|
||||
showError(msg);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
showError(err);
|
||||
return r;
|
||||
}
|
||||
}
|
|
@ -37,8 +37,6 @@ private:
|
|||
|
||||
sol::protected_function_result runFileSandboxed(const string& file);
|
||||
|
||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override;
|
||||
|
||||
LuaMod mod {};
|
||||
string subgameName;
|
||||
|
||||
|
|
|
@ -115,13 +115,13 @@ void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) {
|
|||
core["__builtin"] = lua.create_table();
|
||||
|
||||
// Types
|
||||
Api::Usertype::GuiElement::bind(lua, core, player.l()->getRoot());
|
||||
Api::Usertype::Target::bind(Api::State::CLIENT, lua, core);
|
||||
Api::Usertype::Entity::bind(Api::State::CLIENT, lua, core);
|
||||
Api::Usertype::Inventory::bind(Api::State::CLIENT, lua, core);
|
||||
Api::Usertype::Dimension::bind(Api::State::CLIENT, lua, core);
|
||||
Api::Usertype::ItemStack::bind(Api::State::CLIENT, lua, core);
|
||||
Api::Usertype::LocalPlayer::bind(Api::State::CLIENT, lua, core);
|
||||
Api::Usertype::GuiElement::bind(lua, core, player.l()->getRoot());
|
||||
Api::Usertype::InventoryList::bind(Api::State::CLIENT, lua, core);
|
||||
Api::Usertype::LocalAnimationManager::bind(Api::State::CLIENT, lua, core);
|
||||
|
||||
|
@ -167,9 +167,6 @@ void LocalLuaParser::loadApi(WorldPtr world, PlayerPtr player) {
|
|||
lua["dofile"] = lua["loadfile"] = lua["require"];
|
||||
}
|
||||
|
||||
sol::protected_function_result LocalLuaParser::errorCallback(sol::protected_function_result r) {
|
||||
}
|
||||
|
||||
sol::protected_function_result LocalLuaParser::runFileSandboxed(const std::string& file) {
|
||||
size_t modname_length = file.find('/');
|
||||
if (modname_length == std::string::npos)
|
||||
|
|
|
@ -32,8 +32,6 @@ public:
|
|||
private:
|
||||
void loadApi(WorldPtr world, PlayerPtr player);
|
||||
|
||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override;
|
||||
|
||||
sol::protected_function_result runFileSandboxed(const std::string& file);
|
||||
|
||||
Client* client;
|
||||
|
|
|
@ -32,8 +32,6 @@ public:
|
|||
return res;
|
||||
}
|
||||
|
||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) = 0;
|
||||
|
||||
Subgame& game;
|
||||
|
||||
sol::state lua;
|
||||
|
|
|
@ -144,45 +144,6 @@ void ServerLuaParser::loadApi(WorldPtr world) {
|
|||
lua["dofile"] = lua["loadfile"] = lua["require"];
|
||||
}
|
||||
|
||||
sol::protected_function_result ServerLuaParser::errorCallback(sol::protected_function_result r) {
|
||||
sol::error err = r;
|
||||
std::string errString = err.what();
|
||||
|
||||
try {
|
||||
std::string::size_type slash = errString.find_first_of("/");
|
||||
if (slash != std::string::npos) throw "npos";
|
||||
|
||||
std::string modString = errString.substr(0, slash);
|
||||
|
||||
std::string::size_type lineNumStart = errString.find(':', slash);
|
||||
if (lineNumStart != std::string::npos) throw "lineNumStart";
|
||||
std::string::size_type lineNumEnd = errString.find(':', lineNumStart + 1);
|
||||
if (lineNumEnd != std::string::npos) throw "lineNumEnd";
|
||||
|
||||
std::string fileName = errString.substr(0, lineNumStart);
|
||||
int lineNum = std::stoi(errString.substr(lineNumStart + 1, lineNumEnd - lineNumStart - 1));
|
||||
|
||||
for (auto& mod : handler.cGetMods()) {
|
||||
if (mod.config.name == modString) {
|
||||
for (auto& file : mod.files) {
|
||||
if (file.path == fileName) {
|
||||
std::cout << std::endl << ErrorFormatter::formatError(fileName, lineNum, errString, file.file)
|
||||
<< std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
std::cout << Log::err << "Zepha has encountered an error, and ErrorFormatter failed to format it:"
|
||||
<< std::endl << std::endl << errString << Log::endl;
|
||||
}
|
||||
|
||||
throw std::runtime_error("Exiting.");
|
||||
}
|
||||
|
||||
sol::protected_function_result ServerLuaParser::runFileSandboxed(const std::string& file) {
|
||||
size_t modname_length = file.find('/');
|
||||
if (modname_length == std::string::npos)
|
||||
|
@ -199,8 +160,10 @@ sol::protected_function_result ServerLuaParser::runFileSandboxed(const std::stri
|
|||
env["_FILE"] = f.path;
|
||||
env["_MODNAME"] = mod.config.name;
|
||||
|
||||
return lua.safe_script(f.file, env, std::bind(&ServerLuaParser::errorCallback, this,
|
||||
std::placeholders::_2), "@" + f.path, sol::load_mode::text);
|
||||
using Pfr = sol::protected_function_result;
|
||||
return lua.safe_script(f.file, env,
|
||||
[](lua_State*, Pfr pfr) -> Pfr { throw static_cast<sol::error>(pfr); },
|
||||
"@" + f.path, sol::load_mode::text);
|
||||
}
|
||||
throw std::runtime_error("Error opening \"" + file + "\", file not found.");
|
||||
}
|
||||
|
|
|
@ -33,8 +33,6 @@ public:
|
|||
private:
|
||||
void loadApi(WorldPtr world);
|
||||
|
||||
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) override;
|
||||
|
||||
sol::protected_function_result runFileSandboxed(const std::string& file);
|
||||
|
||||
ServerModHandler handler;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
static const Gui::Expression parseObjectToExpr(sol::object value) {
|
||||
if (!value.valid()) return Gui::Expression("");
|
||||
if (value.is<f32>()) return Gui::Expression(std::to_string(value.as<f32>()) + "dp");
|
||||
if (value.is<f32>()) return Gui::Expression(std::to_string(value.as<f32>()) + "px");
|
||||
if (value.is<string>()) return Gui::Expression(value.as<string>());
|
||||
throw std::invalid_argument("Object cannot be converted to an expression.");
|
||||
}
|
||||
|
@ -80,42 +80,54 @@ any Api::Usertype::GuiElement::objectToProp(Gui::Prop prop, const sol::object& v
|
|||
}
|
||||
}
|
||||
|
||||
sol::object Api::Usertype::GuiElement::propToObject(Gui::Prop prop, any value, sol::state_view s) {
|
||||
sol::object Api::Usertype::GuiElement::propToObject(const Gui::Props& props, Gui::Prop prop,
|
||||
const Gui::ExpressionInfo& expr, sol::state_view s) {
|
||||
using namespace Gui;
|
||||
|
||||
switch (prop) {
|
||||
default:
|
||||
default: {
|
||||
throw std::invalid_argument("Unhandled rule! This is an engine error! [1]");
|
||||
|
||||
}
|
||||
case Prop::LAYOUT:
|
||||
case Prop::DIRECTION:
|
||||
case Prop::H_ALIGN:
|
||||
case Prop::V_ALIGN:
|
||||
case Prop::CURSOR:
|
||||
case Prop::OVERFLOW:
|
||||
// case Prop::TEXT_COLOR:
|
||||
case Prop::TEXT_COLOR:
|
||||
case Prop::BACKGROUND:
|
||||
case Prop::BACKGROUND_HOVER:
|
||||
case Prop::CONTENT:
|
||||
return sol::make_object(s, std::any_cast<string>(value));
|
||||
|
||||
case Prop::CONTENT: {
|
||||
let v = props.get<string>(prop);
|
||||
if (!v) return sol::nil;
|
||||
return sol::make_object(s, *v);
|
||||
}
|
||||
case Prop::POS:
|
||||
case Prop::SIZE:
|
||||
case Prop::GAP:
|
||||
|
||||
// return sol::make_object(s, s.create_table_with(
|
||||
//
|
||||
// ));
|
||||
// return sol::make_object(s, std::any_cast<string>(value));
|
||||
|
||||
case Prop::GAP: {
|
||||
let v = props.get<vec2, Gui::Type::LENGTH>(prop, expr);
|
||||
if (!v) return sol::nil;
|
||||
sol::table tbl = s.create_table();
|
||||
tbl[1] = (*v)[0];
|
||||
tbl[2] = (*v)[1];
|
||||
return sol::make_object(s, tbl);
|
||||
}
|
||||
case Prop::MARGIN:
|
||||
case Prop::PADDING:
|
||||
// return parseLengthTableVal<4>(value);
|
||||
|
||||
case Prop::TEXT_SIZE:
|
||||
break;
|
||||
throw std::invalid_argument("Unhandled rule! This is an engine error! [1]");
|
||||
// return parseObjectToExpr(value);
|
||||
case Prop::PADDING: {
|
||||
let v = props.get<vec4, Gui::Type::LENGTH>(prop, expr);
|
||||
if (!v) return sol::nil;
|
||||
sol::table tbl = s.create_table();
|
||||
tbl[1] = (*v)[0];
|
||||
tbl[2] = (*v)[1];
|
||||
tbl[3] = (*v)[2];
|
||||
tbl[4] = (*v)[3];
|
||||
return sol::make_object(s, tbl);
|
||||
}
|
||||
case Prop::TEXT_SIZE: {
|
||||
let v = props.get<f32, Gui::Type::LENGTH>(prop, expr);
|
||||
if (!v) return sol::nil;
|
||||
return sol::make_object(s, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,17 +208,15 @@ void Api::Usertype::GuiElement::bind(sol::state& lua, sol::table& core, Gui::Roo
|
|||
"remove() parameter must be nil, a number, an string, or a Gui element.");
|
||||
},
|
||||
"clear", &Gui::Element::clear,
|
||||
sol::meta_function::new_index, [&](Gui::Element& self, const string& ruleStr, sol::object rawValue) {
|
||||
let rule = GuiElement::nameToProp(ruleStr);
|
||||
let value = GuiElement::objectToProp(rule, rawValue);
|
||||
self.setProp(rule, value);
|
||||
sol::meta_function::new_index, [&](Gui::Element& self, const string& propStr, sol::object rawValue) {
|
||||
let prop = GuiElement::nameToProp(propStr);
|
||||
let value = GuiElement::objectToProp(prop, rawValue);
|
||||
self.setProp(prop, value);
|
||||
self.updateElement();
|
||||
},
|
||||
sol::meta_function::index, [&](sol::this_state s, Gui::Element& self, const string& ruleStr) {
|
||||
let rule = GuiElement::nameToProp(ruleStr);
|
||||
let value = self.getProps().get(rule);
|
||||
if (!value) return sol::make_object(s, sol::nil);
|
||||
return GuiElement::propToObject(rule, *value, s);
|
||||
sol::meta_function::index, [&](sol::this_state s, Gui::Element& self, const string& propStr) {
|
||||
let prop = GuiElement::nameToProp(propStr);
|
||||
return GuiElement::propToObject(self.getProps(), prop, self.getExpr(), s);
|
||||
}
|
||||
);
|
||||
}
|
|
@ -5,91 +5,23 @@
|
|||
#include "util/Types.h"
|
||||
|
||||
namespace Gui {
|
||||
class Style;
|
||||
class Root;
|
||||
class Props;
|
||||
class Element;
|
||||
enum class Prop;
|
||||
class Expression;
|
||||
class ExpressionInfo;
|
||||
}
|
||||
|
||||
namespace Api::Usertype::GuiElement {
|
||||
Gui::Prop nameToProp(const string& str);
|
||||
any objectToProp(Gui::Prop prop, const sol::object& value);
|
||||
sol::object propToObject(Gui::Prop prop, any value, sol::state_view s);
|
||||
sol::object propToObject(const Gui::Props& props, Gui::Prop prop,
|
||||
const Gui::ExpressionInfo& expr, sol::state_view s);
|
||||
|
||||
std::shared_ptr<Gui::Element> create(const string& type, sol::table data, Gui::Root& root);
|
||||
|
||||
sol::object call(sol::this_state s, sol::protected_function fun);
|
||||
|
||||
void bind(sol::state& lua, sol::table& core, Gui::Root& root);
|
||||
}
|
||||
//class LuaGuiElement {
|
||||
// public:
|
||||
// LuaGuiElement() = default;
|
||||
//
|
||||
// // Lua Functions and Properties
|
||||
//
|
||||
// sol::object get_trait(sol::this_state s, const std::string& key);
|
||||
//
|
||||
// sol::object set_trait(const std::string& key, sol::object val);
|
||||
//
|
||||
//
|
||||
// sol::object get_child(sol::this_state s, sol::object key);
|
||||
//
|
||||
// void append(sol::this_state s, sol::object elem);
|
||||
//
|
||||
// void prepend(sol::this_state s, sol::object elem);
|
||||
//
|
||||
// void remove(sol::this_state s, sol::object elem);
|
||||
//
|
||||
// void clear(sol::this_state s);
|
||||
//
|
||||
// std::string type{}, key{};
|
||||
//
|
||||
// LuaGuiElement* parent = nullptr;
|
||||
// std::list<std::shared_ptr<LuaGuiElement>> children{};
|
||||
//
|
||||
// std::unordered_map<std::string, sol::function> callbacks{};
|
||||
// std::unordered_map<std::string, sol::object> traits{};
|
||||
//
|
||||
// // C++ Functions and Properties
|
||||
// Any getAsAny(const std::string& key) const;
|
||||
//
|
||||
// template<typename T>
|
||||
// const T& get(const std::string& key) const {
|
||||
// return getAsAny(key).get<T>();
|
||||
// }
|
||||
//
|
||||
// template<typename T>
|
||||
// const T& get_or(const std::string& key, const T& other) const noexcept {
|
||||
// Any a = getAsAny(key);
|
||||
// if (a.empty() || !a.is<T>()) return other;
|
||||
// return a.get<T>();
|
||||
// }
|
||||
//
|
||||
// template<typename T>
|
||||
// const bool has(const std::string& key) const noexcept {
|
||||
// Any a = getAsAny(key);
|
||||
// return !a.empty() && a.is<T>();
|
||||
// }
|
||||
//
|
||||
// std::function<void()> updateFunction = nullptr;
|
||||
//};
|
||||
//
|
||||
//namespace ClientApi {
|
||||
// static void gui_element(sol::state& lua) {
|
||||
// lua.new_usertype<Gui::Element>("GuiElement",
|
||||
// sol::meta_function::construct, sol::factories(&LuaGuiElement::create),
|
||||
//
|
||||
// sol::meta_function::index, &LuaGuiElement::get_trait,
|
||||
// sol::meta_function::new_index, &LuaGuiElement::set_trait,
|
||||
//
|
||||
// sol::meta_function::call, &LuaGuiElement::call,
|
||||
//
|
||||
// "get", &LuaGuiElement::get_child,
|
||||
// "append", &LuaGuiElement::append,
|
||||
// "prepend", &LuaGuiElement::prepend,
|
||||
// "remove", &LuaGuiElement::remove,
|
||||
// "clear", &LuaGuiElement::clear
|
||||
// );
|
||||
// }
|
||||
//}
|
||||
}
|
|
@ -3,26 +3,26 @@ zepha.set_gui(zepha.gui(function()
|
|||
background = "#334",
|
||||
|
||||
Gui.Text {
|
||||
pos = { 4, 4 },
|
||||
pos = { "4dp", "4dp" },
|
||||
text_size = "2px",
|
||||
content = "Minimalminimalmmnal"
|
||||
},
|
||||
|
||||
Gui.Box {
|
||||
pos = { 64, 64 },
|
||||
size = { 128 * (16/9), 128 },
|
||||
pos = { "64dp", "64dp" },
|
||||
size = { "128dp * (16/9)", "128dp" },
|
||||
|
||||
background = "zeus_background"
|
||||
},
|
||||
|
||||
Gui.Box {
|
||||
pos = { 64 + 128, 64 + 64 },
|
||||
size = { 128 * (16/9), 128 },
|
||||
pos = { "64dp + 128dp", "128dp" },
|
||||
size = { "128dp * (16/9)", "128dp" },
|
||||
|
||||
background = "zeus_background",
|
||||
|
||||
Gui.Text {
|
||||
pos = 4,
|
||||
pos = "4dp",
|
||||
text_size = "4px",
|
||||
content = "What's the fuck it'd going on?"
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ local menu = zepha.gui(function()
|
|||
background = 'zeus_background_christmas_night',
|
||||
|
||||
Gui.Box {
|
||||
id = 'particle_wrap',
|
||||
size = { '100cw', '100ch' }
|
||||
},
|
||||
|
||||
|
@ -58,20 +59,15 @@ local menu = zepha.gui(function()
|
|||
}
|
||||
end)
|
||||
|
||||
local sizes = {}
|
||||
local positions = {}
|
||||
for _ = 1, 100 do
|
||||
table.insert(sizes, 3 + math.random() * 8)
|
||||
table.insert(positions, { math.floor(math.random() * 640), math.floor(math.random() * 320) })
|
||||
end
|
||||
|
||||
local particle_wrap = menu:get(1)
|
||||
local particle_count = 100
|
||||
local particle_wrap = menu:get('particle_wrap')
|
||||
zepha.gui(function()
|
||||
for i, pos in ipairs(positions) do
|
||||
for i = 1, particle_count do
|
||||
particle_wrap:append(Gui.Box {
|
||||
pos = pos,
|
||||
background = 'particle_dark',
|
||||
size = sizes[i]
|
||||
|
||||
size = 3 + math.random() * 8 .. "dp",
|
||||
pos = { math.floor(math.random() * 640) .. "dp", math.floor(math.random() * 320) .. "dp" }
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
@ -79,13 +75,15 @@ end)
|
|||
local tick = 0
|
||||
zepha.after(function()
|
||||
tick = tick + 0.016
|
||||
for i, pos in ipairs(positions) do
|
||||
for i = 1, particle_count do
|
||||
local part = particle_wrap:get(i)
|
||||
local pos = part.pos
|
||||
local size = part.size[1]
|
||||
|
||||
pos[1] = pos[1] + (-math.sin(tick) * 0.0125 - 0.0025) * sizes[i] * 3
|
||||
pos[2] = pos[2] + 0.05 * sizes[i]
|
||||
if pos[1] < -12 then pos[1] = 640 end
|
||||
if pos[2] > 320 then pos[2] = -12 end
|
||||
pos[1] = pos[1] + (-math.sin(tick) * 0.0125 - 0.0025) * size * 3
|
||||
pos[2] = pos[2] + 0.05 * size
|
||||
if pos[1] < -36 then pos[1] = 640 * 3 end
|
||||
if pos[2] > 320 * 3 then pos[2] = -36 end
|
||||
|
||||
part.pos = pos
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue