Browse Source

Add the ScriptComponent

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
16bd80ba35

+ 10 - 6
src/anki/core/App.cpp

@@ -497,6 +497,12 @@ Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb,
 	ANKI_CHECK(m_renderer->init(
 	ANKI_CHECK(m_renderer->init(
 		m_threadpool, m_resources, m_gr, m_stagingMem, m_ui, m_allocCb, m_allocCbData, config, &m_globalTimestamp));
 		m_threadpool, m_resources, m_gr, m_stagingMem, m_ui, m_allocCb, m_allocCbData, config, &m_globalTimestamp));
 
 
+	//
+	// Script
+	//
+	m_script = m_heapAlloc.newInstance<ScriptManager>();
+	ANKI_CHECK(m_script->init(m_allocCb, m_allocCbData));
+
 	//
 	//
 	// Scene
 	// Scene
 	//
 	//
@@ -509,15 +515,13 @@ Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb,
 		m_resources,
 		m_resources,
 		m_stagingMem,
 		m_stagingMem,
 		m_input,
 		m_input,
+		m_script,
 		&m_globalTimestamp,
 		&m_globalTimestamp,
 		config));
 		config));
 
 
-	//
-	// Script
-	//
-	m_script = m_heapAlloc.newInstance<ScriptManager>();
-
-	ANKI_CHECK(m_script->init(m_allocCb, m_allocCbData, m_scene, m_renderer));
+	// Inform the script engine about some subsystems
+	m_script->setRenderer(m_renderer);
+	m_script->setSceneGraph(m_scene);
 
 
 	ANKI_CORE_LOGI("Application initialized");
 	ANKI_CORE_LOGI("Application initialized");
 	return Error::NONE;
 	return Error::NONE;

+ 2 - 0
src/anki/scene/SceneGraph.cpp

@@ -70,6 +70,7 @@ Error SceneGraph::init(AllocAlignedCallback allocCb,
 	ResourceManager* resources,
 	ResourceManager* resources,
 	StagingGpuMemoryManager* stagingMem,
 	StagingGpuMemoryManager* stagingMem,
 	Input* input,
 	Input* input,
+	ScriptManager* scriptManager,
 	const Timestamp* globalTimestamp,
 	const Timestamp* globalTimestamp,
 	const ConfigSet& config)
 	const ConfigSet& config)
 {
 {
@@ -82,6 +83,7 @@ Error SceneGraph::init(AllocAlignedCallback allocCb,
 	m_gr = &m_resources->getGrManager();
 	m_gr = &m_resources->getGrManager();
 	m_physics = &m_resources->getPhysicsWorld();
 	m_physics = &m_resources->getPhysicsWorld();
 	m_input = input;
 	m_input = input;
+	m_scriptManager = scriptManager;
 
 
 	m_alloc = SceneAllocator<U8>(allocCb, allocCbData, 1024 * 10, 1.0, 0);
 	m_alloc = SceneAllocator<U8>(allocCb, allocCbData, 1024 * 10, 1.0, 0);
 	m_frameAlloc = SceneFrameAllocator<U8>(allocCb, allocCbData, 1 * 1024 * 1024);
 	m_frameAlloc = SceneFrameAllocator<U8>(allocCb, allocCbData, 1 * 1024 * 1024);

+ 8 - 0
src/anki/scene/SceneGraph.h

@@ -57,6 +57,7 @@ public:
 		ResourceManager* resources,
 		ResourceManager* resources,
 		StagingGpuMemoryManager* stagingAlloc,
 		StagingGpuMemoryManager* stagingAlloc,
 		Input* input,
 		Input* input,
+		ScriptManager* scriptManager,
 		const Timestamp* globalTimestamp,
 		const Timestamp* globalTimestamp,
 		const ConfigSet& config);
 		const ConfigSet& config);
 
 
@@ -190,6 +191,12 @@ anki_internal:
 		return *m_physics;
 		return *m_physics;
 	}
 	}
 
 
+	ScriptManager& getScriptManager()
+	{
+		ANKI_ASSERT(m_scriptManager);
+		return *m_scriptManager;
+	}
+
 	const PhysicsWorld& getPhysicsWorld() const
 	const PhysicsWorld& getPhysicsWorld() const
 	{
 	{
 		return *m_physics;
 		return *m_physics;
@@ -239,6 +246,7 @@ private:
 	GrManager* m_gr = nullptr;
 	GrManager* m_gr = nullptr;
 	PhysicsWorld* m_physics = nullptr;
 	PhysicsWorld* m_physics = nullptr;
 	Input* m_input = nullptr;
 	Input* m_input = nullptr;
+	ScriptManager* m_scriptManager = nullptr;
 	StagingGpuMemoryManager* m_stagingAlloc = nullptr;
 	StagingGpuMemoryManager* m_stagingAlloc = nullptr;
 
 
 	SceneAllocator<U8> m_alloc;
 	SceneAllocator<U8> m_alloc;

+ 1 - 0
src/anki/scene/components/SceneComponent.h

@@ -34,6 +34,7 @@ enum class SceneComponentType : U16
 	OCCLUDER,
 	OCCLUDER,
 	DECAL,
 	DECAL,
 	SKIN,
 	SKIN,
+	SCRIPT,
 	PLAYER_CONTROLLER,
 	PLAYER_CONTROLLER,
 
 
 	COUNT,
 	COUNT,

+ 81 - 0
src/anki/scene/components/ScriptComponent.cpp

@@ -0,0 +1,81 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/scene/components/ScriptComponent.h>
+#include <anki/scene/SceneGraph.h>
+#include <anki/resource/ResourceManager.h>
+#include <anki/resource/Script.h>
+#include <anki/script/ScriptManager.h>
+#include <anki/script/ScriptEnvironment.h>
+
+namespace anki
+{
+
+ScriptComponent::ScriptComponent(SceneNode* node)
+	: SceneComponent(CLASS_TYPE, node)
+{
+}
+
+ScriptComponent::~ScriptComponent()
+{
+}
+
+Error ScriptComponent::load(CString fname)
+{
+	// Load
+	ANKI_CHECK(getSceneGraph().getResourceManager().loadResource(fname, m_script));
+
+	// Create the env
+	ANKI_CHECK(getSceneGraph().getScriptManager().newScriptEnvironment(m_env));
+
+	// Exec the script
+	ANKI_CHECK(m_env->evalString(m_script->getSource()));
+
+	return Error::NONE;
+}
+
+Error ScriptComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
+{
+	updated = false;
+	lua_State* lua = &m_env->getLuaState();
+
+	// Push function name
+	lua_getglobal(lua, "update");
+
+	// Push args
+	LuaBinder::pushVariableToTheStack(lua, &node);
+	lua_pushnumber(lua, prevTime);
+	lua_pushnumber(lua, crntTime);
+
+	// Do the call (3 arguments, 1 result)
+	if(lua_pcall(lua, 3, 1, 0) != 0)
+	{
+		ANKI_SCENE_LOGE("Error running ScriptComponent's \"update\": %s", lua_tostring(lua, -1));
+		return Error::USER_DATA;
+	}
+
+	if(!lua_isnumber(lua, -1))
+	{
+		ANKI_SCENE_LOGE("ScriptComponent's \"update\" should return a number");
+		lua_pop(lua, 1);
+		return Error::USER_DATA;
+	}
+
+	// Get the result
+	lua_Number result = lua_tonumber(lua, -1);
+	lua_pop(lua, 1);
+
+	if(result < 0)
+	{
+		ANKI_SCENE_LOGE("ScriptComponent's \"update\" return an error code");
+		return Error::USER_DATA;
+	}
+
+	updated = (result != 0);
+
+	return Error::NONE;
+}
+
+} // end namespace anki

+ 38 - 0
src/anki/scene/components/ScriptComponent.h

@@ -0,0 +1,38 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/scene/components/SceneComponent.h>
+#include <anki/resource/Forward.h>
+#include <anki/script/Forward.h>
+
+namespace anki
+{
+
+/// @addtogroup scene
+/// @{
+
+/// Component of scripts.
+class ScriptComponent : public SceneComponent
+{
+public:
+	static const SceneComponentType CLASS_TYPE = SceneComponentType::SCRIPT;
+
+	ScriptComponent(SceneNode* node);
+
+	~ScriptComponent();
+
+	ANKI_USE_RESULT Error load(CString fname);
+
+	ANKI_USE_RESULT Error update(SceneNode&, Second prevTime, Second crntTime, Bool& updated) override;
+
+private:
+	ScriptResourcePtr m_script;
+	ScriptEnvironmentPtr m_env;
+};
+/// @}
+
+} // end namespace anki

+ 8 - 0
src/anki/script/Forward.h

@@ -0,0 +1,8 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/script/Common.h>

+ 9 - 0
src/anki/script/LuaBinder.h

@@ -162,6 +162,15 @@ public:
 		lua_setglobal(state, name.cstr());
 		lua_setglobal(state, name.cstr());
 	}
 	}
 
 
+	template<typename T>
+	static void pushVariableToTheStack(lua_State* state, T* y)
+	{
+		void* ptr = lua_newuserdata(state, sizeof(LuaUserData));
+		LuaUserData* ud = static_cast<LuaUserData*>(ptr);
+		ud->initPointed(getWrappedTypeSignature<T>(), y);
+		luaL_setmetatable(state, getWrappedTypeName<T>());
+	}
+
 	/// Evaluate a string
 	/// Evaluate a string
 	static Error evalString(lua_State* state, const CString& str);
 	static Error evalString(lua_State* state, const CString& str);
 
 

+ 6 - 0
src/anki/script/ScriptEnvironment.h

@@ -40,6 +40,12 @@ public:
 		return LuaBinder::evalString(m_thread.m_luaState, str);
 		return LuaBinder::evalString(m_thread.m_luaState, str);
 	}
 	}
 
 
+	lua_State& getLuaState()
+	{
+		ANKI_ASSERT(m_thread.m_luaState);
+		return *m_thread.m_luaState;
+	}
+
 private:
 private:
 	LuaThread m_thread;
 	LuaThread m_thread;
 };
 };

+ 1 - 3
src/anki/script/ScriptManager.cpp

@@ -28,12 +28,10 @@ ScriptManager::~ScriptManager()
 	ANKI_SCRIPT_LOGI("Destroying scripting engine...");
 	ANKI_SCRIPT_LOGI("Destroying scripting engine...");
 }
 }
 
 
-Error ScriptManager::init(AllocAlignedCallback allocCb, void* allocCbData, SceneGraph* scene, MainRenderer* renderer)
+Error ScriptManager::init(AllocAlignedCallback allocCb, void* allocCbData)
 {
 {
 	ANKI_SCRIPT_LOGI("Initializing scripting engine...");
 	ANKI_SCRIPT_LOGI("Initializing scripting engine...");
 
 
-	m_scene = scene;
-	m_r = renderer;
 	m_alloc = ScriptAllocator(allocCb, allocCbData);
 	m_alloc = ScriptAllocator(allocCb, allocCbData);
 
 
 	ANKI_CHECK(m_lua.create(m_alloc, this));
 	ANKI_CHECK(m_lua.create(m_alloc, this));

+ 13 - 2
src/anki/script/ScriptManager.h

@@ -25,8 +25,17 @@ public:
 	~ScriptManager();
 	~ScriptManager();
 
 
 	/// Create the script manager.
 	/// Create the script manager.
-	ANKI_USE_RESULT Error init(
-		AllocAlignedCallback allocCb, void* allocCbData, SceneGraph* scene, MainRenderer* renderer);
+	ANKI_USE_RESULT Error init(AllocAlignedCallback allocCb, void* allocCbData);
+
+	void setRenderer(MainRenderer* renderer)
+	{
+		m_r = renderer;
+	}
+
+	void setSceneGraph(SceneGraph* scene)
+	{
+		m_scene = scene;
+	}
 
 
 	/// Expose a variable to the scripting engine.
 	/// Expose a variable to the scripting engine.
 	template<typename T>
 	template<typename T>
@@ -48,11 +57,13 @@ public:
 anki_internal:
 anki_internal:
 	SceneGraph& getSceneGraph()
 	SceneGraph& getSceneGraph()
 	{
 	{
+		ANKI_ASSERT(m_scene);
 		return *m_scene;
 		return *m_scene;
 	}
 	}
 
 
 	MainRenderer& getMainRenderer()
 	MainRenderer& getMainRenderer()
 	{
 	{
+		ANKI_ASSERT(m_r);
 		return *m_r;
 		return *m_r;
 	}
 	}
 
 

+ 2 - 2
tests/script/LuaBinder.cpp

@@ -26,7 +26,7 @@ ANKI_TEST(Script, LuaBinder)
 {
 {
 	ScriptManager sm;
 	ScriptManager sm;
 
 
-	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr, nullptr, nullptr));
+	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr));
 	Vec4 v4(2.0, 3.0, 4.0, 5.0);
 	Vec4 v4(2.0, 3.0, 4.0, 5.0);
 	Vec3 v3(1.1, 2.2, 3.3);
 	Vec3 v3(1.1, 2.2, 3.3);
 
 
@@ -42,7 +42,7 @@ ANKI_TEST(Script, LuaBinder)
 ANKI_TEST(Script, LuaBinderThreads)
 ANKI_TEST(Script, LuaBinderThreads)
 {
 {
 	ScriptManager sm;
 	ScriptManager sm;
-	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr, nullptr, nullptr));
+	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr));
 
 
 	ScriptEnvironmentPtr env;
 	ScriptEnvironmentPtr env;
 	ANKI_TEST_EXPECT_NO_ERR(sm.newScriptEnvironment(env));
 	ANKI_TEST_EXPECT_NO_ERR(sm.newScriptEnvironment(env));