diff --git a/Content/Content.vcxitems b/Content/Content.vcxitems
index 877e71ce6..a19676dab 100644
--- a/Content/Content.vcxitems
+++ b/Content/Content.vcxitems
@@ -34,6 +34,10 @@
true
true
+
+ true
+ true
+
true
true
@@ -358,6 +362,10 @@
true
true
+
+ true
+ true
+
true
true
@@ -378,6 +386,14 @@
true
true
+
+ true
+ true
+
+
+ true
+ true
+
true
true
diff --git a/Content/Content.vcxitems.filters b/Content/Content.vcxitems.filters
index e870423c8..4cdf2d159 100644
--- a/Content/Content.vcxitems.filters
+++ b/Content/Content.vcxitems.filters
@@ -216,6 +216,18 @@
scripts\subscript_demo
+
+ models
+
+
+ models
+
+
+ models
+
+
+ models
+
diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md
index ffcd1b3c8..55e1696e5 100644
--- a/Content/Documentation/ScriptingAPI-Documentation.md
+++ b/Content/Documentation/ScriptingAPI-Documentation.md
@@ -456,7 +456,8 @@ The scene holds components. Entity handles can be used to retrieve associated co
- Component_CreateLight(Entity entity) : LightComponent result -- attach a light component to an entity. The returned LightComponent is associated with the entity and can be manipulated
- Component_CreateObject(Entity entity) : ObjectComponent result -- attach an object component to an entity. The returned ObjectComponent is associated with the entity and can be manipulated
- Component_CreateInverseKinematics(Entity entity) : InverseKinematicsComponent result -- attach an IK component to an entity. The returned InverseKinematicsComponent is associated with the entity and can be manipulated
-- Component_CreateSpring(Entity entity) : SpringComponent result -- attach a spring component to an entity. The returned InverseKinematicsComponent is associated with the entity and can be manipulated
+- Component_CreateSpring(Entity entity) : SpringComponent result -- attach a spring component to an entity. The returned SpringKinematicsComponent is associated with the entity and can be manipulated
+- Component_CreateSpring(Entity entity) : ScriptComponent result -- attach a script component to an entity. The returned ScriptKinematicsComponent is associated with the entity and can be manipulated
- Component_GetName(Entity entity) : NameComponent? result -- query the name component of the entity (if exists)
- Component_GetLayer(Entity entity) : LayerComponent? result -- query the layer component of the entity (if exists)
@@ -469,6 +470,7 @@ The scene holds components. Entity handles can be used to retrieve associated co
- Component_GetObject(Entity entity) : ObjectComponent? result -- query the object component of the entity (if exists)
- Component_GetInverseKinematics(Entity entity) : InverseKinematicsComponent? result -- query the IK component of the entity (if exists)
- Component_GetSpring(Entity entity) : SpringComponent? result -- query the spring component of the entity (if exists)
+- Component_GetSpring(Entity entity) : ScriptComponent? result -- query the script component of the entity (if exists)
- Component_GetNameArray() : NameComponent[] result -- returns the array of all components of this type
- Component_GetLayerArray() : LayerComponent[] result -- returns the array of all components of this type
@@ -480,7 +482,8 @@ The scene holds components. Entity handles can be used to retrieve associated co
- Component_GetLightArray() : LightComponent[] result -- returns the array of all components of this type
- Component_GetObjectArray() : ObjectComponent[] result -- returns the array of all components of this type
- Component_GetInverseKinematicsArray() : InverseKinematicsComponent[] result -- returns the array of all components of this type
-- Component_GetSpringArray() : InverseKinematicsComponent[] result -- returns the array of all components of this type
+- Component_GetSpringArray() : SpringComponent[] result -- returns the array of all components of this type
+- Component_GetScriptArray() : ScriptComponent[] result -- returns the array of all components of this type
- Entity_GetNameArray() : Entity[] result -- returns the array of all entities that have this component type
- Entity_GetLayerArray() : Entity[] result -- returns the array of all entities that have this component type
@@ -493,6 +496,7 @@ The scene holds components. Entity handles can be used to retrieve associated co
- Entity_GetObjectArray() : Entity[] result -- returns the array of all entities that have this component type
- Entity_GetInverseKinematicsArray() : Entity[] result -- returns the array of all entities that have this component type
- Entity_GetSpringArray() : Entity[] result -- returns the array of all entities that have this component type
+- Entity_GetScriptArray() : Entity[] result -- returns the array of all entities that have this component type
- Component_Attach(Entity entity,parent) -- attaches entity to parent (adds a hierarchy component to entity). From now on, entity will inherit certain properties from parent, such as transform (entity will move with parent) or layer (entity's layer will be a sublayer of parent's layer)
- Component_Detach(Entity entity) -- detaches entity from parent (if hierarchycomponent exists for it). Restores entity's original layer, and applies current transformation to entity
@@ -624,6 +628,14 @@ Enables jiggle effect on transforms such as bones for example.
- SetDamping(float value)
- SetWindAffection(float value)
+#### ScriptComponent
+A lua script bound to an entity
+- CreateFromFile(string filename)
+- Play()
+- IsPlaying() : bool result
+- SetPlayOnce(bool once = true)
+- Stop()
+
## Canvas
This is used to describe a drawable area
- GetDPI() : float -- pixels per inch
diff --git a/Content/models/script_component_test.lua b/Content/models/script_component_test.lua
new file mode 100644
index 000000000..b1f3cf59e
--- /dev/null
+++ b/Content/models/script_component_test.lua
@@ -0,0 +1,14 @@
+local scene = GetScene() -- GetScene() is from global scope
+local entity = GetEntity() -- GetEntity() is local to this script (only available if this is running from a ScriptComponent)
+local transform = scene.Component_GetTransform(entity)
+if transform ~= nil then
+ transform.Rotate(Vector(0, math.pi * getDeltaTime(), 0))
+
+ local text = "This sample shows usage of a ScriptComponent, which is attached to a scene entity.\n"
+ text = text .. "Each ScriptComponent will get these functions that can be used to reference data:\n"
+ text = text .. "script_file() : " .. script_file() .. "\n"
+ text = text .. "script_dir() : " .. script_dir() .. "\n"
+ text = text .. "script_pid() : " .. script_pid() .. "\n"
+ text = text .. "GetEntity() : " .. GetEntity() .. "\n"
+ DrawDebugText(text, vector.Add(transform.GetPosition(), Vector(0,3,0)), Vector(1,1,1,1), 0.25)
+end
diff --git a/Content/models/script_component_test.wiscene b/Content/models/script_component_test.wiscene
new file mode 100644
index 000000000..f2e3f50d6
Binary files /dev/null and b/Content/models/script_component_test.wiscene differ
diff --git a/Editor/CMakeLists.txt b/Editor/CMakeLists.txt
index bbfb65d22..c61040352 100644
--- a/Editor/CMakeLists.txt
+++ b/Editor/CMakeLists.txt
@@ -24,6 +24,7 @@ set (SOURCE_FILES
GraphicsWindow.cpp
SoundWindow.cpp
SpringWindow.cpp
+ ScriptWindow.cpp
stdafx.cpp
TransformWindow.cpp
Translator.cpp
diff --git a/Editor/ComponentsWindow.cpp b/Editor/ComponentsWindow.cpp
index a6f9b5c4e..31b713014 100644
--- a/Editor/ComponentsWindow.cpp
+++ b/Editor/ComponentsWindow.cpp
@@ -32,6 +32,7 @@ void ComponentsWindow::Create(EditorComponent* _editor)
transformWnd.Create(editor);
layerWnd.Create(editor);
nameWnd.Create(editor);
+ scriptWnd.Create(editor);
newComponentCombo.Create("Add: ");
@@ -55,6 +56,7 @@ void ComponentsWindow::Create(EditorComponent* _editor)
newComponentCombo.AddItem("Weather " ICON_WEATHER, 12);
newComponentCombo.AddItem("Force Field " ICON_FORCE, 13);
newComponentCombo.AddItem("Animation " ICON_ANIMATION, 14);
+ newComponentCombo.AddItem("Script " ICON_SCRIPT, 15);
newComponentCombo.OnSelect([=](wi::gui::EventArgs args) {
newComponentCombo.SetSelectedWithoutCallback(-1);
if (editor->translator.selected.empty())
@@ -130,6 +132,10 @@ void ComponentsWindow::Create(EditorComponent* _editor)
if (scene.animations.Contains(entity))
return;
break;
+ case 15:
+ if (scene.scripts.Contains(entity))
+ return;
+ break;
default:
return;
}
@@ -208,6 +214,9 @@ void ComponentsWindow::Create(EditorComponent* _editor)
case 14:
scene.animations.Create(entity);
break;
+ case 15:
+ scene.scripts.Create(entity);
+ break;
default:
break;
}
@@ -237,6 +246,7 @@ void ComponentsWindow::Create(EditorComponent* _editor)
AddWidget(&transformWnd);
AddWidget(&layerWnd);
AddWidget(&nameWnd);
+ AddWidget(&scriptWnd);
materialWnd.SetVisible(false);
weatherWnd.SetVisible(false);
@@ -255,6 +265,7 @@ void ComponentsWindow::Create(EditorComponent* _editor)
transformWnd.SetVisible(false);
layerWnd.SetVisible(false);
nameWnd.SetVisible(false);
+ scriptWnd.SetVisible(false);
SetSize(editor->optionsWnd.GetSize());
@@ -520,4 +531,17 @@ void ComponentsWindow::ResizeLayout()
{
weatherWnd.SetVisible(false);
}
+
+ if (scene.scripts.Contains(scriptWnd.entity))
+ {
+ scriptWnd.SetVisible(true);
+ scriptWnd.SetPos(pos);
+ scriptWnd.SetSize(XMFLOAT2(width, scriptWnd.GetScale().y));
+ pos.y += scriptWnd.GetSize().y;
+ pos.y += padding;
+ }
+ else
+ {
+ scriptWnd.SetVisible(false);
+ }
}
diff --git a/Editor/ComponentsWindow.h b/Editor/ComponentsWindow.h
index f212e1e07..97d121b33 100644
--- a/Editor/ComponentsWindow.h
+++ b/Editor/ComponentsWindow.h
@@ -17,6 +17,7 @@
#include "TransformWindow.h"
#include "LayerWindow.h"
#include "NameWindow.h"
+#include "ScriptWindow.h"
class EditorComponent;
@@ -47,4 +48,5 @@ public:
TransformWindow transformWnd;
LayerWindow layerWnd;
NameWindow nameWnd;
+ ScriptWindow scriptWnd;
};
diff --git a/Editor/Editor.cpp b/Editor/Editor.cpp
index 4bb98daeb..dae5e9e89 100644
--- a/Editor/Editor.cpp
+++ b/Editor/Editor.cpp
@@ -362,6 +362,7 @@ void EditorComponent::Load()
componentsWnd.layerWnd.SetEntity(INVALID_ENTITY);
componentsWnd.nameWnd.SetEntity(INVALID_ENTITY);
componentsWnd.animWnd.SetEntity(INVALID_ENTITY);
+ componentsWnd.scriptWnd.SetEntity(INVALID_ENTITY);
optionsWnd.RefreshEntityTree();
ResetHistory();
@@ -1309,6 +1310,7 @@ void EditorComponent::Update(float dt)
componentsWnd.nameWnd.SetEntity(INVALID_ENTITY);
componentsWnd.weatherWnd.SetEntity(INVALID_ENTITY);
componentsWnd.animWnd.SetEntity(INVALID_ENTITY);
+ componentsWnd.scriptWnd.SetEntity(INVALID_ENTITY);
}
else
{
@@ -1341,6 +1343,7 @@ void EditorComponent::Update(float dt)
componentsWnd.nameWnd.SetEntity(picked.entity);
componentsWnd.weatherWnd.SetEntity(picked.entity);
componentsWnd.animWnd.SetEntity(picked.entity);
+ componentsWnd.scriptWnd.SetEntity(picked.entity);
if (picked.subsetIndex >= 0)
{
diff --git a/Editor/Editor_SOURCE.vcxitems b/Editor/Editor_SOURCE.vcxitems
index d7f154681..854f4a245 100644
--- a/Editor/Editor_SOURCE.vcxitems
+++ b/Editor/Editor_SOURCE.vcxitems
@@ -96,6 +96,7 @@
+
@@ -150,6 +151,7 @@
+
diff --git a/Editor/Editor_SOURCE.vcxitems.filters b/Editor/Editor_SOURCE.vcxitems.filters
index fc3bd904b..bdcd9efb7 100644
--- a/Editor/Editor_SOURCE.vcxitems.filters
+++ b/Editor/Editor_SOURCE.vcxitems.filters
@@ -76,6 +76,7 @@
+
@@ -116,6 +117,7 @@
+
diff --git a/Editor/IconDefinitions.h b/Editor/IconDefinitions.h
index 854228ca2..6c9cdb6fa 100644
--- a/Editor/IconDefinitions.h
+++ b/Editor/IconDefinitions.h
@@ -27,6 +27,7 @@
#define ICON_IK ICON_FA_HAND_FIST
#define ICON_NAME ICON_FA_COMMENT_DOTS
#define ICON_COLLIDER ICON_FA_CAPSULES
+#define ICON_SCRIPT ICON_FA_SCROLL
#define ICON_TERRAIN ICON_FA_MOUNTAIN_SUN
diff --git a/Editor/NameWindow.cpp b/Editor/NameWindow.cpp
index 51c6991f5..69b4cfcdc 100644
--- a/Editor/NameWindow.cpp
+++ b/Editor/NameWindow.cpp
@@ -77,6 +77,6 @@ void NameWindow::SetEntity(Entity entity)
void NameWindow::Update()
{
- nameInput.SetPos(XMFLOAT2(60, 0));
+ nameInput.SetPos(XMFLOAT2(60, 4));
nameInput.SetSize(XMFLOAT2(GetSize().x - 65, nameInput.GetSize().y));
}
diff --git a/Editor/OptionsWindow.cpp b/Editor/OptionsWindow.cpp
index 633dbbc76..324391e69 100644
--- a/Editor/OptionsWindow.cpp
+++ b/Editor/OptionsWindow.cpp
@@ -135,8 +135,6 @@ void OptionsWindow::Create(EditorComponent* _editor)
newCombo.selected_font.anim.typewriter.time = 2;
newCombo.selected_font.anim.typewriter.character_start = 1;
newCombo.SetInvalidSelectionText("...");
- newCombo.AddItem("Cube " ICON_CUBE, 13);
- newCombo.AddItem("Plane " ICON_SQUARE, 14);
newCombo.AddItem("Transform " ICON_TRANSFORM, 0);
newCombo.AddItem("Material " ICON_MATERIAL, 1);
newCombo.AddItem("Point Light " ICON_POINTLIGHT, 2);
@@ -150,7 +148,10 @@ void OptionsWindow::Create(EditorComponent* _editor)
newCombo.AddItem("Emitter " ICON_EMITTER, 10);
newCombo.AddItem("HairParticle " ICON_HAIR, 11);
newCombo.AddItem("Camera " ICON_CAMERA, 12);
+ newCombo.AddItem("Cube " ICON_CUBE, 13);
+ newCombo.AddItem("Plane " ICON_SQUARE, 14);
newCombo.AddItem("Animation " ICON_ANIMATION, 15);
+ newCombo.AddItem("Script " ICON_SCRIPT, 16);
newCombo.OnSelect([&](wi::gui::EventArgs args) {
newCombo.SetSelectedWithoutCallback(-1);
const EditorComponent::EditorScene& editorscene = editor->GetCurrentEditorScene();
@@ -250,6 +251,11 @@ void OptionsWindow::Create(EditorComponent* _editor)
scene.animations.Create(pick.entity);
scene.names.Create(pick.entity) = "animation";
break;
+ case 16:
+ pick.entity = CreateEntity();
+ scene.scripts.Create(pick.entity);
+ scene.names.Create(pick.entity) = "script";
+ break;
default:
break;
}
@@ -293,6 +299,7 @@ void OptionsWindow::Create(EditorComponent* _editor)
filterCombo.AddItem("Inverse Kinematics " ICON_IK, (uint64_t)Filter::IK);
filterCombo.AddItem("Camera " ICON_CAMERA, (uint64_t)Filter::Camera);
filterCombo.AddItem("Armature " ICON_ARMATURE, (uint64_t)Filter::Armature);
+ filterCombo.AddItem("Script " ICON_SCRIPT, (uint64_t)Filter::Script);
filterCombo.SetTooltip("Apply filtering to the Entities");
filterCombo.OnSelect([&](wi::gui::EventArgs args) {
filter = (Filter)args.userdata;
@@ -861,6 +868,10 @@ void OptionsWindow::PushToEntityTree(wi::ecs::Entity entity, int level)
{
item.name += ICON_COLLIDER " ";
}
+ if (scene.scripts.Contains(entity))
+ {
+ item.name += ICON_SCRIPT " ";
+ }
if (entity == terragen.terrainEntity)
{
item.name += ICON_TERRAIN " ";
@@ -1077,7 +1088,7 @@ void OptionsWindow::RefreshEntityTree()
}
}
- if (has_flag(filter, Filter::All))
+ if (has_flag(filter, Filter::Collider))
{
for (size_t i = 0; i < scene.colliders.GetCount(); ++i)
{
@@ -1101,6 +1112,14 @@ void OptionsWindow::RefreshEntityTree()
}
}
+ if (has_flag(filter, Filter::Script))
+ {
+ for (size_t i = 0; i < scene.scripts.GetCount(); ++i)
+ {
+ PushToEntityTree(scene.scripts.GetEntity(i), 0);
+ }
+ }
+
entitytree_added_items.clear();
entitytree_opened_items.clear();
}
diff --git a/Editor/OptionsWindow.h b/Editor/OptionsWindow.h
index 830f3877c..437054c50 100644
--- a/Editor/OptionsWindow.h
+++ b/Editor/OptionsWindow.h
@@ -53,6 +53,8 @@ public:
IK = 1 << 13,
Camera = 1 << 14,
Armature = 1 << 15,
+ Collider = 1 << 16,
+ Script = 1 << 17,
All = ~0ull,
} filter = Filter::All;
diff --git a/Editor/ScriptWindow.cpp b/Editor/ScriptWindow.cpp
new file mode 100644
index 000000000..ac7717638
--- /dev/null
+++ b/Editor/ScriptWindow.cpp
@@ -0,0 +1,161 @@
+#include "stdafx.h"
+#include "ScriptWindow.h"
+#include "Editor.h"
+
+void ScriptWindow::Create(EditorComponent* _editor)
+{
+ editor = _editor;
+ wi::gui::Window::Create(ICON_SCRIPT " Script", wi::gui::Window::WindowControls::COLLAPSE | wi::gui::Window::WindowControls::CLOSE);
+ SetSize(XMFLOAT2(520, 80));
+
+ closeButton.SetTooltip("Delete Script");
+ OnClose([=](wi::gui::EventArgs args) {
+
+ wi::Archive& archive = editor->AdvanceHistory();
+ archive << EditorComponent::HISTORYOP_COMPONENT_DATA;
+ editor->RecordEntity(archive, entity);
+
+ editor->GetCurrentScene().scripts.Remove(entity);
+
+ editor->RecordEntity(archive, entity);
+
+ editor->optionsWnd.RefreshEntityTree();
+ });
+
+ float hei = 20;
+ float wid = 100;
+
+ fileButton.Create("Open File...");
+ fileButton.SetDescription("File: ");
+ fileButton.SetSize(XMFLOAT2(wid, hei));
+ fileButton.OnClick([=](wi::gui::EventArgs args) {
+ wi::scene::Scene& scene = editor->GetCurrentScene();
+ wi::scene::ScriptComponent* script = scene.scripts.GetComponent(entity);
+ if (script == nullptr)
+ return;
+
+ if (script->resource.IsValid())
+ {
+ script->resource = {};
+ script->filename = {};
+ script->script = {};
+ fileButton.SetText("Open File...");
+ }
+ else
+ {
+ wi::helper::FileDialogParams params;
+ params.type = wi::helper::FileDialogParams::OPEN;
+ params.description = "Lua Script (*.lua)";
+ params.extensions = wi::resourcemanager::GetSupportedScriptExtensions();
+ wi::helper::FileDialog(params, [=](std::string fileName) {
+ wi::eventhandler::Subscribe_Once(wi::eventhandler::EVENT_THREAD_SAFE_POINT, [=](uint64_t userdata) {
+ script->CreateFromFile(fileName);
+ fileButton.SetText(wi::helper::GetFileNameFromPath(fileName));
+ });
+ });
+ }
+ });
+ AddWidget(&fileButton);
+
+ playonceCheckBox.Create("Once: ");
+ playonceCheckBox.SetTooltip("Play the script only one time, and stop immediately.\nUseful for having custom update frequency logic in the script.");
+ playonceCheckBox.SetSize(XMFLOAT2(hei, hei));
+ playonceCheckBox.OnClick([=](wi::gui::EventArgs args) {
+ wi::scene::Scene& scene = editor->GetCurrentScene();
+ wi::scene::ScriptComponent* script = scene.scripts.GetComponent(entity);
+ if (script == nullptr)
+ return;
+
+ script->SetPlayOnce(args.bValue);
+ });
+ AddWidget(&playonceCheckBox);
+
+ playstopButton.Create("");
+ playstopButton.SetTooltip("Play / Stop script");
+ playstopButton.SetSize(XMFLOAT2(wid, hei));
+ playstopButton.OnClick([=](wi::gui::EventArgs args) {
+ wi::scene::Scene& scene = editor->GetCurrentScene();
+ wi::scene::ScriptComponent* script = scene.scripts.GetComponent(entity);
+ if (script == nullptr)
+ return;
+
+ if (script->IsPlaying())
+ {
+ script->Stop();
+ }
+ else
+ {
+ script->Play();
+ }
+ });
+ AddWidget(&playstopButton);
+
+ SetMinimized(true);
+ SetVisible(false);
+}
+
+void ScriptWindow::SetEntity(wi::ecs::Entity entity)
+{
+ if (this->entity == entity)
+ return;
+
+ this->entity = entity;
+
+ wi::scene::Scene& scene = editor->GetCurrentScene();
+ wi::scene::ScriptComponent* script = scene.scripts.GetComponent(entity);
+
+ if (script != nullptr)
+ {
+ if (script->resource.IsValid())
+ {
+ fileButton.SetText(wi::helper::GetFileNameFromPath(script->filename));
+ }
+ else
+ {
+ fileButton.SetText("Open File...");
+ }
+ }
+}
+
+void ScriptWindow::Update(const wi::Canvas& canvas, float dt)
+{
+ wi::scene::Scene& scene = editor->GetCurrentScene();
+ wi::scene::ScriptComponent* script = scene.scripts.GetComponent(entity);
+ if (script != nullptr)
+ {
+ if (script->IsPlaying())
+ {
+ playstopButton.SetText(ICON_STOP);
+ }
+ else
+ {
+ playstopButton.SetText(ICON_PLAY);
+ }
+ }
+
+ wi::gui::Window::Update(canvas, dt);
+}
+void ScriptWindow::ResizeLayout()
+{
+ wi::gui::Window::ResizeLayout();
+
+ fileButton.SetPos(XMFLOAT2(60, 4));
+ fileButton.SetSize(XMFLOAT2(GetSize().x - 65, fileButton.GetSize().y));
+
+ wi::scene::Scene& scene = editor->GetCurrentScene();
+ wi::scene::ScriptComponent* script = scene.scripts.GetComponent(entity);
+ if (script != nullptr && script->resource.IsValid())
+ {
+ playstopButton.SetVisible(true);
+ playstopButton.SetPos(XMFLOAT2(84, fileButton.GetPos().y + fileButton.GetSize().y + 4));
+ playstopButton.SetSize(XMFLOAT2(GetSize().x - 90, playstopButton.GetSize().y));
+
+ playonceCheckBox.SetVisible(true);
+ playonceCheckBox.SetPos(XMFLOAT2(playstopButton.GetPos().x - playonceCheckBox.GetSize().x - 4, playstopButton.GetPos().y));
+ }
+ else
+ {
+ playstopButton.SetVisible(false);
+ playonceCheckBox.SetVisible(false);
+ }
+}
diff --git a/Editor/ScriptWindow.h b/Editor/ScriptWindow.h
new file mode 100644
index 000000000..d3f93f4f0
--- /dev/null
+++ b/Editor/ScriptWindow.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "WickedEngine.h"
+
+class EditorComponent;
+
+class ScriptWindow : public wi::gui::Window
+{
+public:
+ void Create(EditorComponent* editor);
+
+ EditorComponent* editor = nullptr;
+ wi::ecs::Entity entity = wi::ecs::INVALID_ENTITY;
+ void SetEntity(wi::ecs::Entity entity);
+
+ wi::gui::Button fileButton;
+ wi::gui::CheckBox playonceCheckBox;
+ wi::gui::Button playstopButton;
+
+ void Update(const wi::Canvas& canvas, float dt) override;
+ void ResizeLayout() override;
+};
+
diff --git a/WickedEngine/wiImageParams_BindLua.cpp b/WickedEngine/wiImageParams_BindLua.cpp
index 68e95d6c5..8ad3aaf27 100644
--- a/WickedEngine/wiImageParams_BindLua.cpp
+++ b/WickedEngine/wiImageParams_BindLua.cpp
@@ -47,10 +47,10 @@ namespace wi::lua
lunamethod(ImageParams_BindLua, DisableBackgroundBlur),
lunamethod(ImageParams_BindLua, EnableBackground),
lunamethod(ImageParams_BindLua, DisableBackground),
- { NULL, NULL }
+ { nullptr, nullptr }
};
Luna::PropertyType ImageParams_BindLua::properties[] = {
- { NULL, NULL }
+ { nullptr, nullptr }
};
diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp
index 76d367a14..1bc2d0d94 100644
--- a/WickedEngine/wiLua.cpp
+++ b/WickedEngine/wiLua.cpp
@@ -43,12 +43,14 @@ namespace wi::lua
};
LuaInternal luainternal;
- uint32_t Internal_GenScriptPID(){
+ uint32_t GeneratePID()
+ {
static std::atomic scriptpid_next{ 0 + 1 };
return scriptpid_next.fetch_add(1);
}
- uint32_t Internal_EncapsulateScript(std::string& script, const std::string& filename = "", uint32_t PID = 0){
+ uint32_t AttachScriptParameters(std::string& script, const std::string& filename, uint32_t PID)
+ {
static const std::string persistent_inject = R"(
local runProcess = function(func)
success, co = Internal_runProcess(script_file(), script_pid(), func)
@@ -62,19 +64,15 @@ namespace wi::lua
end
)";
- if(PID == 0){
- PID = Internal_GenScriptPID();
- }
-
// Make sure the file path doesn't contain backslash characters, replace them with forward slash.
// - backslash would be recognized by lua as escape character
// - the path string could be coming from unknown location (content, programmer, filepicker), so always do this
std::string filepath = filename;
std::replace(filepath.begin(), filepath.end(), '\\', '/');
- std::string dynamic_inject = "local function script_file() return \""+ filepath +"\" end\n";
- dynamic_inject += "local function script_pid() return \""+std::to_string(PID)+"\" end\n";
- dynamic_inject += "local function script_dir() return \""+wi::helper::GetDirectoryFromPath(filepath)+"\" end\n";
+ std::string dynamic_inject = "local function script_file() return \"" + filepath + "\" end\n";
+ dynamic_inject += "local function script_pid() return \"" + std::to_string(PID) + "\" end\n";
+ dynamic_inject += "local function script_dir() return \"" + wi::helper::GetDirectoryFromPath(filepath) + "\" end\n";
dynamic_inject += persistent_inject;
script = dynamic_inject + script;
@@ -98,7 +96,7 @@ namespace wi::lua
if (wi::helper::FileRead(filename, filedata))
{
std::string command = std::string(filedata.begin(), filedata.end());
- PID = Internal_EncapsulateScript(command, filename, PID);
+ PID = AttachScriptParameters(command, filename, PID);
int status = luaL_loadstring(L, command.c_str());
if (status == 0)
@@ -210,7 +208,7 @@ namespace wi::lua
if (wi::helper::FileRead(filename, filedata))
{
auto script = std::string(filedata.begin(), filedata.end());
- Internal_EncapsulateScript(script, filename);
+ AttachScriptParameters(script, filename);
return RunText(script);
}
return false;
diff --git a/WickedEngine/wiLua.h b/WickedEngine/wiLua.h
index ba8172638..c14c8ceff 100644
--- a/WickedEngine/wiLua.h
+++ b/WickedEngine/wiLua.h
@@ -61,6 +61,13 @@ namespace wi::lua
//kill every running background task (coroutine)
void KillProcesses();
+ // Generates a unique identifier for a script instance:
+ uint32_t GeneratePID();
+
+ // Adds some local management functions to the script
+ // returns the PID
+ uint32_t AttachScriptParameters(std::string& script, const std::string& filename = "", uint32_t PID = GeneratePID());
+
//Following functions are "static", operating on specified lua state:
//get string from lua on stack position
diff --git a/WickedEngine/wiPrimitive.h b/WickedEngine/wiPrimitive.h
index d74f7eacc..82ee215f6 100644
--- a/WickedEngine/wiPrimitive.h
+++ b/WickedEngine/wiPrimitive.h
@@ -123,11 +123,14 @@ namespace wi::primitive
float TMax = std::numeric_limits::max();
XMFLOAT3 direction_inverse;
- Ray(const XMFLOAT3& newOrigin = XMFLOAT3(0, 0, 0), const XMFLOAT3& newDirection = XMFLOAT3(0, 0, 1), float newTMin = 0, float newTMax = std::numeric_limits::max()) : Ray(XMLoadFloat3(&newOrigin), XMLoadFloat3(&newDirection), TMin, TMax) {}
- Ray(const XMVECTOR& newOrigin, const XMVECTOR& newDirection, float newTMin = 0, float newTMax = std::numeric_limits::max()) {
+ Ray(const XMFLOAT3& newOrigin = XMFLOAT3(0, 0, 0), const XMFLOAT3& newDirection = XMFLOAT3(0, 0, 1), float newTMin = 0, float newTMax = std::numeric_limits::max()) :
+ Ray(XMLoadFloat3(&newOrigin), XMLoadFloat3(&newDirection), newTMin, newTMax)
+ {}
+ Ray(const XMVECTOR& newOrigin, const XMVECTOR& newDirection, float newTMin = 0, float newTMax = std::numeric_limits::max())
+ {
XMStoreFloat3(&origin, newOrigin);
XMStoreFloat3(&direction, newDirection);
- XMStoreFloat3(&direction_inverse, XMVectorDivide(XMVectorReplicate(1.0f), newDirection));
+ XMStoreFloat3(&direction_inverse, XMVectorReciprocal(newDirection));
TMin = newTMin;
TMax = newTMax;
}
diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp
index ad97205d7..24e38ca6a 100644
--- a/WickedEngine/wiResourceManager.cpp
+++ b/WickedEngine/wiResourceManager.cpp
@@ -23,6 +23,7 @@ namespace wi
resourcemanager::Flags flags = resourcemanager::Flags::NONE;
wi::graphics::Texture texture;
wi::audio::Sound sound;
+ std::string script;
wi::vector filedata;
};
@@ -41,6 +42,11 @@ namespace wi
const ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
return resourceinternal->sound;
}
+ const std::string& Resource::GetScript() const
+ {
+ const ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
+ return resourceinternal->script;
+ }
void Resource::SetFileData(const wi::vector& data)
{
@@ -78,6 +84,15 @@ namespace wi
ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
resourceinternal->sound = sound;
}
+ void Resource::SetScript(const std::string& script)
+ {
+ if (internal_state == nullptr)
+ {
+ internal_state = std::make_shared();
+ }
+ ResourceInternal* resourceinternal = (ResourceInternal*)internal_state.get();
+ resourceinternal->script = script;
+ }
namespace resourcemanager
{
@@ -98,6 +113,7 @@ namespace wi
{
IMAGE,
SOUND,
+ SCRIPT,
};
static const wi::unordered_map types = {
{"BASIS", DataType::IMAGE},
@@ -111,6 +127,7 @@ namespace wi
{"QOI", DataType::IMAGE},
{"WAV", DataType::SOUND},
{"OGG", DataType::SOUND},
+ {"LUA", DataType::SCRIPT},
};
wi::vector GetSupportedImageExtensions()
{
@@ -136,6 +153,18 @@ namespace wi
}
return ret;
}
+ wi::vector GetSupportedScriptExtensions()
+ {
+ wi::vector ret;
+ for (auto& x : types)
+ {
+ if (x.second == DataType::SCRIPT)
+ {
+ ret.push_back(x.first);
+ }
+ }
+ return ret;
+ }
Resource Load(const std::string& name, Flags flags, const uint8_t* filedata, size_t filesize)
{
@@ -641,11 +670,21 @@ namespace wi
}
}
break;
+
case DataType::SOUND:
{
success = wi::audio::CreateSound(filedata, filesize, &resource->sound);
}
break;
+
+ case DataType::SCRIPT:
+ {
+ resource->script.resize(filesize);
+ std::memcpy(resource->script.data(), filedata, filesize);
+ success = true;
+ }
+ break;
+
};
if (success)
diff --git a/WickedEngine/wiResourceManager.h b/WickedEngine/wiResourceManager.h
index d3aeee497..579078404 100644
--- a/WickedEngine/wiResourceManager.h
+++ b/WickedEngine/wiResourceManager.h
@@ -20,11 +20,13 @@ namespace wi
const wi::vector& GetFileData() const;
const wi::graphics::Texture& GetTexture() const;
const wi::audio::Sound& GetSound() const;
+ const std::string& GetScript() const;
void SetFileData(const wi::vector& data);
void SetFileData(wi::vector&& data);
void SetTexture(const wi::graphics::Texture& texture);
void SetSound(const wi::audio::Sound& sound);
+ void SetScript(const std::string& script);
};
namespace resourcemanager
@@ -39,6 +41,7 @@ namespace wi
Mode GetMode();
wi::vector GetSupportedImageExtensions();
wi::vector GetSupportedSoundExtensions();
+ wi::vector GetSupportedScriptExtensions();
// Order of these must not change as the flags can be serialized!
enum class Flags
diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp
index 52e861d64..c78ecfcf8 100644
--- a/WickedEngine/wiScene.cpp
+++ b/WickedEngine/wiScene.cpp
@@ -11,6 +11,7 @@
#include "wiBacklog.h"
#include "wiTimer.h"
#include "wiUnorderedMap.h"
+#include "wiLua.h"
#include "shaders/ShaderInterop_SurfelGI.h"
#include "shaders/ShaderInterop_DDGI.h"
@@ -1466,6 +1467,13 @@ namespace wi::scene
UpdateCamera();
}
+ void ScriptComponent::CreateFromFile(const std::string& filename)
+ {
+ this->filename = filename;
+ resource = wi::resourcemanager::Load(filename, wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA);
+ script.clear(); // will be created on first Update()
+ }
+
const uint32_t small_subtask_groupsize = 64u;
@@ -1612,6 +1620,8 @@ namespace wi::scene
}
});
+ RunScriptUpdateSystem(ctx);
+
wi::physics::RunPhysicsUpdateSystem(ctx, *this, dt);
RunAnimationUpdateSystem(ctx);
@@ -4808,6 +4818,30 @@ namespace wi::scene
wi::audio::SetVolume(sound.volume, &sound.soundinstance);
}
}
+ void Scene::RunScriptUpdateSystem(wi::jobsystem::context& ctx)
+ {
+ for (size_t i = 0; i < scripts.GetCount(); ++i)
+ {
+ ScriptComponent& script = scripts[i];
+ Entity entity = scripts.GetEntity(i);
+
+ if (script.IsPlaying())
+ {
+ if (script.script.empty() && script.resource.IsValid())
+ {
+ script.script += "local function GetEntity() return " + std::to_string(entity) + "; end\n";
+ script.script += script.resource.GetScript();
+ wi::lua::AttachScriptParameters(script.script, script.filename);
+ }
+ wi::lua::RunText(script.script);
+
+ if (script.IsPlayingOnlyOnce())
+ {
+ script.Stop();
+ }
+ }
+ }
+ }
void Scene::PutWaterRipple(const std::string& image, const XMFLOAT3& pos)
{
diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h
index 9a026cdaa..dcc3e2452 100644
--- a/WickedEngine/wiScene.h
+++ b/WickedEngine/wiScene.h
@@ -1342,6 +1342,34 @@ namespace wi::scene
void Serialize(wi::Archive& archive, wi::ecs::EntitySerializer& seri);
};
+ struct ScriptComponent
+ {
+ enum FLAGS
+ {
+ EMPTY = 0,
+ PLAYING = 1 << 0,
+ PLAY_ONCE = 1 << 1,
+ };
+ uint32_t _flags = EMPTY;
+
+ std::string filename;
+
+ // Non-serialized attributes:
+ std::string script;
+ wi::Resource resource;
+
+ inline void Play() { _flags |= PLAYING; }
+ inline void SetPlayOnce(bool once = true) { if (once) { _flags |= PLAY_ONCE; } else { _flags &= ~PLAY_ONCE; } }
+ inline void Stop() { _flags &= ~PLAYING; }
+
+ inline bool IsPlaying() const { return _flags & PLAYING; }
+ inline bool IsPlayingOnlyOnce() const { return _flags & PLAY_ONCE; }
+
+ void CreateFromFile(const std::string& filename);
+
+ void Serialize(wi::Archive& archive, wi::ecs::EntitySerializer& seri);
+ };
+
struct Scene
{
wi::ecs::ComponentLibrary componentLibrary;
@@ -1375,6 +1403,7 @@ namespace wi::scene
wi::ecs::ComponentManager& inverse_kinematics = componentLibrary.Register("wi::scene::Scene::inverse_kinematics");
wi::ecs::ComponentManager& springs = componentLibrary.Register("wi::scene::Scene::springs", 1); // version = 1
wi::ecs::ComponentManager& colliders = componentLibrary.Register("wi::scene::Scene::colliders");
+ wi::ecs::ComponentManager& scripts = componentLibrary.Register("wi::scene::Scene::scripts");
// Non-serialized attributes:
float dt = 0;
@@ -1631,6 +1660,7 @@ namespace wi::scene
void RunParticleUpdateSystem(wi::jobsystem::context& ctx);
void RunWeatherUpdateSystem(wi::jobsystem::context& ctx);
void RunSoundUpdateSystem(wi::jobsystem::context& ctx);
+ void RunScriptUpdateSystem(wi::jobsystem::context& ctx);
};
// Returns skinned vertex position in armature local space
diff --git a/WickedEngine/wiScene_BindLua.cpp b/WickedEngine/wiScene_BindLua.cpp
index 9a1d4e47a..100248569 100644
--- a/WickedEngine/wiScene_BindLua.cpp
+++ b/WickedEngine/wiScene_BindLua.cpp
@@ -314,6 +314,7 @@ void Bind()
Luna::Register(L);
Luna::Register(L);
Luna::Register(L);
+ Luna::Register(L);
}
}
@@ -335,6 +336,7 @@ Luna::FunctionType Scene_BindLua::methods[] = {
lunamethod(Scene_BindLua, Component_CreateObject),
lunamethod(Scene_BindLua, Component_CreateInverseKinematics),
lunamethod(Scene_BindLua, Component_CreateSpring),
+ lunamethod(Scene_BindLua, Component_CreateScript),
lunamethod(Scene_BindLua, Component_GetName),
lunamethod(Scene_BindLua, Component_GetLayer),
@@ -347,6 +349,7 @@ Luna::FunctionType Scene_BindLua::methods[] = {
lunamethod(Scene_BindLua, Component_GetObject),
lunamethod(Scene_BindLua, Component_GetInverseKinematics),
lunamethod(Scene_BindLua, Component_GetSpring),
+ lunamethod(Scene_BindLua, Component_GetScript),
lunamethod(Scene_BindLua, Component_GetNameArray),
lunamethod(Scene_BindLua, Component_GetLayerArray),
@@ -359,6 +362,7 @@ Luna::FunctionType Scene_BindLua::methods[] = {
lunamethod(Scene_BindLua, Component_GetObjectArray),
lunamethod(Scene_BindLua, Component_GetInverseKinematicsArray),
lunamethod(Scene_BindLua, Component_GetSpringArray),
+ lunamethod(Scene_BindLua, Component_GetScriptArray),
lunamethod(Scene_BindLua, Entity_GetNameArray),
lunamethod(Scene_BindLua, Entity_GetLayerArray),
@@ -371,6 +375,7 @@ Luna::FunctionType Scene_BindLua::methods[] = {
lunamethod(Scene_BindLua, Entity_GetObjectArray),
lunamethod(Scene_BindLua, Entity_GetInverseKinematicsArray),
lunamethod(Scene_BindLua, Entity_GetSpringArray),
+ lunamethod(Scene_BindLua, Entity_GetScriptArray),
lunamethod(Scene_BindLua, Component_Attach),
lunamethod(Scene_BindLua, Component_Detach),
@@ -599,6 +604,23 @@ int Scene_BindLua::Component_CreateSpring(lua_State* L)
}
return 0;
}
+int Scene_BindLua::Component_CreateScript(lua_State* L)
+{
+ int argc = wi::lua::SGetArgCount(L);
+ if (argc > 0)
+ {
+ Entity entity = (Entity)wi::lua::SGetLongLong(L, 1);
+
+ ScriptComponent& component = scene->scripts.Create(entity);
+ Luna::push(L, new ScriptComponent_BindLua(&component));
+ return 1;
+ }
+ else
+ {
+ wi::lua::SError(L, "Scene::Component_CreateScript(Entity entity) not enough arguments!");
+ }
+ return 0;
+}
int Scene_BindLua::Component_GetName(lua_State* L)
{
@@ -842,6 +864,28 @@ int Scene_BindLua::Component_GetSpring(lua_State* L)
}
return 0;
}
+int Scene_BindLua::Component_GetScript(lua_State* L)
+{
+ int argc = wi::lua::SGetArgCount(L);
+ if (argc > 0)
+ {
+ Entity entity = (Entity)wi::lua::SGetLongLong(L, 1);
+
+ ScriptComponent* component = scene->scripts.GetComponent(entity);
+ if (component == nullptr)
+ {
+ return 0;
+ }
+
+ Luna::push(L, new ScriptComponent_BindLua(component));
+ return 1;
+ }
+ else
+ {
+ wi::lua::SError(L, "Scene::Component_GetScript(Entity entity) not enough arguments!");
+ }
+ return 0;
+}
int Scene_BindLua::Component_GetNameArray(lua_State* L)
{
@@ -964,6 +1008,17 @@ int Scene_BindLua::Component_GetSpringArray(lua_State* L)
}
return 1;
}
+int Scene_BindLua::Component_GetScriptArray(lua_State* L)
+{
+ lua_createtable(L, (int)scene->scripts.GetCount(), 0);
+ int newTable = lua_gettop(L);
+ for (size_t i = 0; i < scene->scripts.GetCount(); ++i)
+ {
+ Luna::push(L, new ScriptComponent_BindLua(&scene->scripts[i]));
+ lua_rawseti(L, newTable, lua_Integer(i + 1));
+ }
+ return 1;
+}
int Scene_BindLua::Entity_GetNameArray(lua_State* L)
{
@@ -1086,6 +1141,17 @@ int Scene_BindLua::Entity_GetSpringArray(lua_State* L)
}
return 1;
}
+int Scene_BindLua::Entity_GetScriptArray(lua_State* L)
+{
+ lua_createtable(L, (int)scene->scripts.GetCount(), 0);
+ int newTable = lua_gettop(L);
+ for (size_t i = 0; i < scene->scripts.GetCount(); ++i)
+ {
+ wi::lua::SSetLongLong(L, scene->scripts.GetEntity(i));
+ lua_rawseti(L, newTable, lua_Integer(i + 1));
+ }
+ return 1;
+}
int Scene_BindLua::Component_Attach(lua_State* L)
{
@@ -2665,4 +2731,77 @@ int SpringComponent_BindLua::SetWindAffection(lua_State* L)
}
+
+
+
+
+
+const char ScriptComponent_BindLua::className[] = "ScriptComponent";
+
+Luna::FunctionType ScriptComponent_BindLua::methods[] = {
+ lunamethod(ScriptComponent_BindLua, CreateFromFile),
+ lunamethod(ScriptComponent_BindLua, Play),
+ lunamethod(ScriptComponent_BindLua, IsPlaying),
+ lunamethod(ScriptComponent_BindLua, SetPlayOnce),
+ lunamethod(ScriptComponent_BindLua, Stop),
+ { NULL, NULL }
+};
+Luna::PropertyType ScriptComponent_BindLua::properties[] = {
+ { NULL, NULL }
+};
+
+ScriptComponent_BindLua::ScriptComponent_BindLua(lua_State* L)
+{
+ owning = true;
+ component = new ScriptComponent;
+}
+ScriptComponent_BindLua::~ScriptComponent_BindLua()
+{
+ if (owning)
+ {
+ delete component;
+ }
+}
+
+int ScriptComponent_BindLua::CreateFromFile(lua_State* L)
+{
+ int argc = wi::lua::SGetArgCount(L);
+ if (argc > 0)
+ {
+ component->CreateFromFile(wi::lua::SGetString(L, 1));
+ }
+ else
+ {
+ wi::lua::SError(L, "CreateFromFile(string filename) not enough arguments!");
+ }
+ return 0;
+}
+int ScriptComponent_BindLua::Play(lua_State* L)
+{
+ component->Play();
+ return 0;
+}
+int ScriptComponent_BindLua::IsPlaying(lua_State* L)
+{
+ wi::lua::SSetBool(L, component->IsPlaying());
+ return 1;
+}
+int ScriptComponent_BindLua::SetPlayOnce(lua_State* L)
+{
+ int argc = wi::lua::SGetArgCount(L);
+ bool once = true;
+ if (argc > 0)
+ {
+ once = wi::lua::SGetBool(L, 1);
+ }
+ component->SetPlayOnce(once);
+ return 0;
+}
+int ScriptComponent_BindLua::Stop(lua_State* L)
+{
+ component->Stop();
+ return 0;
+}
+
+
}
diff --git a/WickedEngine/wiScene_BindLua.h b/WickedEngine/wiScene_BindLua.h
index 12b2a4472..08e895c4f 100644
--- a/WickedEngine/wiScene_BindLua.h
+++ b/WickedEngine/wiScene_BindLua.h
@@ -48,6 +48,7 @@ namespace wi::lua::scene
int Component_CreateObject(lua_State* L);
int Component_CreateInverseKinematics(lua_State* L);
int Component_CreateSpring(lua_State* L);
+ int Component_CreateScript(lua_State* L);
int Component_GetName(lua_State* L);
int Component_GetLayer(lua_State* L);
@@ -60,6 +61,7 @@ namespace wi::lua::scene
int Component_GetObject(lua_State* L);
int Component_GetInverseKinematics(lua_State* L);
int Component_GetSpring(lua_State* L);
+ int Component_GetScript(lua_State* L);
int Component_GetNameArray(lua_State* L);
int Component_GetLayerArray(lua_State* L);
@@ -72,6 +74,7 @@ namespace wi::lua::scene
int Component_GetObjectArray(lua_State* L);
int Component_GetInverseKinematicsArray(lua_State* L);
int Component_GetSpringArray(lua_State* L);
+ int Component_GetScriptArray(lua_State* L);
int Entity_GetNameArray(lua_State* L);
int Entity_GetLayerArray(lua_State* L);
@@ -84,6 +87,7 @@ namespace wi::lua::scene
int Entity_GetObjectArray(lua_State* L);
int Entity_GetInverseKinematicsArray(lua_State* L);
int Entity_GetSpringArray(lua_State* L);
+ int Entity_GetScriptArray(lua_State* L);
int Component_Attach(lua_State* L);
int Component_Detach(lua_State* L);
@@ -366,5 +370,26 @@ namespace wi::lua::scene
int SetWindAffection(lua_State* L);
};
+ class ScriptComponent_BindLua
+ {
+ public:
+ bool owning = false;
+ wi::scene::ScriptComponent* component = nullptr;
+
+ static const char className[];
+ static Luna::FunctionType methods[];
+ static Luna::PropertyType properties[];
+
+ ScriptComponent_BindLua(wi::scene::ScriptComponent* component) :component(component) {}
+ ScriptComponent_BindLua(lua_State* L);
+ ~ScriptComponent_BindLua();
+
+ int CreateFromFile(lua_State* L);
+ int Play(lua_State* L);
+ int IsPlaying(lua_State* L);
+ int SetPlayOnce(lua_State* L);
+ int Stop(lua_State* L);
+ };
+
}
diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp
index b6d281357..b02eedef7 100644
--- a/WickedEngine/wiScene_Serializers.cpp
+++ b/WickedEngine/wiScene_Serializers.cpp
@@ -1428,6 +1428,36 @@ namespace wi::scene
archive << tail;
}
}
+ void ScriptComponent::Serialize(wi::Archive& archive, EntitySerializer& seri)
+ {
+ const std::string& dir = archive.GetSourceDirectory();
+
+ if (archive.IsReadMode())
+ {
+ archive >> _flags;
+ archive >> filename;
+
+ if (IsPlayingOnlyOnce())
+ {
+ Play();
+ }
+
+ wi::jobsystem::Execute(seri.ctx, [&](wi::jobsystem::JobArgs args) {
+ CreateFromFile(dir + filename);
+ });
+ }
+ else
+ {
+ std::string relative_filename = filename; // don't modify actual filename, because script_file() and script_dir() can rely on it
+ if (!dir.empty())
+ {
+ wi::helper::MakePathRelative(dir, relative_filename);
+ }
+
+ archive << _flags;
+ archive << relative_filename;
+ }
+ }
void Scene::Serialize(wi::Archive& archive)
{
diff --git a/WickedEngine/wiSpriteAnim_BindLua.cpp b/WickedEngine/wiSpriteAnim_BindLua.cpp
index 1ed20be72..92b9a3502 100644
--- a/WickedEngine/wiSpriteAnim_BindLua.cpp
+++ b/WickedEngine/wiSpriteAnim_BindLua.cpp
@@ -28,10 +28,10 @@ namespace wi::lua
lunamethod(SpriteAnim_BindLua, GetScaleY),
lunamethod(SpriteAnim_BindLua, GetMovingTexAnim),
lunamethod(SpriteAnim_BindLua, GetDrawRecAnim),
- { NULL, NULL }
+ { nullptr, nullptr }
};
Luna::PropertyType SpriteAnim_BindLua::properties[] = {
- { NULL, NULL }
+ { nullptr, nullptr }
};
SpriteAnim_BindLua::SpriteAnim_BindLua(const wi::Sprite::Anim& anim) :anim(anim)
@@ -264,10 +264,10 @@ namespace wi::lua
lunamethod(MovingTexAnim_BindLua, GetSpeedX),
lunamethod(MovingTexAnim_BindLua, GetSpeedY),
- { NULL, NULL }
+ { nullptr, nullptr }
};
Luna::PropertyType MovingTexAnim_BindLua::properties[] = {
- { NULL, NULL }
+ { nullptr, nullptr }
};
MovingTexAnim_BindLua::MovingTexAnim_BindLua(const wi::Sprite::Anim::MovingTexAnim& anim) :anim(anim)
@@ -348,7 +348,7 @@ namespace wi::lua
{ NULL, NULL }
};
- DrawRectAnim_BindLua::DrawRectAnim_BindLua(const wi::Sprite::Anim::DrawRectAnim& data) :anim(anim)
+ DrawRectAnim_BindLua::DrawRectAnim_BindLua(const wi::Sprite::Anim::DrawRectAnim& anim) :anim(anim)
{
}
diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp
index f522e957b..9b1298afc 100644
--- a/WickedEngine/wiVersion.cpp
+++ b/WickedEngine/wiVersion.cpp
@@ -9,7 +9,7 @@ namespace wi::version
// minor features, major updates, breaking compatibility changes
const int minor = 71;
// minor bug fixes, alterations, refactors, updates
- const int revision = 20;
+ const int revision = 21;
const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);