Browse Source

Exceptions removed. Now testing

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
3a43da6cea
77 changed files with 751 additions and 1557 deletions
  1. 2 3
      CMakeLists.txt
  2. 0 1
      include/anki/Util.h
  3. 1 1
      include/anki/core/App.h
  4. 5 3
      include/anki/event/AnimationEvent.h
  5. 75 64
      include/anki/event/Event.h
  6. 51 28
      include/anki/event/EventManager.h
  7. 13 16
      include/anki/event/LightEvent.h
  8. 4 9
      include/anki/event/MoveEvent.h
  9. 7 6
      include/anki/event/SceneAmbientColorEvent.h
  10. 1 1
      include/anki/gl/GlQueue.h
  11. 4 3
      include/anki/misc/ConfigSet.h
  12. 0 1
      include/anki/misc/Xml.h
  13. 2 2
      include/anki/resource/DummyRsrc.h
  14. 2 0
      include/anki/resource/ResourceManager.h
  15. 20 4
      include/anki/resource/Script.h
  16. 0 401
      include/anki/scene/Property.h
  17. 0 1
      include/anki/scene/RenderComponent.h
  18. 13 0
      include/anki/script/ScriptManager.h
  19. 0 1
      include/anki/util/Allocator.h
  20. 0 79
      include/anki/util/Exception.h
  21. 1 1
      include/anki/util/String.h
  22. 5 1
      include/anki/util/String.inl.h
  23. 2 0
      include/anki/util/StringList.h
  24. 14 0
      include/anki/util/StringList.inl.h
  25. 0 350
      include/anki/util/Variant.h
  26. 5 5
      src/core/App.cpp
  27. 0 1
      src/core/NativeWindowAndroid.cpp
  28. 0 1
      src/core/NativeWindowEglFbdev.cpp
  29. 0 1
      src/core/NativeWindowSdl.cpp
  30. 5 1
      src/core/StdinListener.cpp
  31. 16 8
      src/event/AnimationEvent.cpp
  32. 20 33
      src/event/Event.cpp
  33. 60 59
      src/event/EventManager.cpp
  34. 16 9
      src/event/LightEvent.cpp
  35. 11 4
      src/event/MoveEvent.cpp
  36. 15 8
      src/event/SceneAmbientColorEvent.cpp
  37. 0 1
      src/gl/GlBuffer.cpp
  38. 14 3
      src/gl/GlProgram.cpp
  39. 5 4
      src/gl/GlQueue.cpp
  40. 2 2
      src/renderer/MainRenderer.cpp
  41. 0 1
      src/renderer/Renderer.cpp
  42. 4 2
      src/renderer/Sslr.cpp
  43. 0 1
      src/resource/Animation.cpp
  44. 0 1
      src/resource/Extension.cpp
  45. 0 1
      src/resource/Image.cpp
  46. 0 1
      src/resource/MaterialProgramCreator.cpp
  47. 0 1
      src/resource/ParticleEmitterResource.cpp
  48. 0 1
      src/resource/ProgramPrePreprocessor.cpp
  49. 0 1
      src/resource/ProgramResource.cpp
  50. 2 0
      src/resource/ResourceManager.cpp
  51. 19 6
      src/resource/Script.cpp
  52. 0 1
      src/resource/TextureResource.cpp
  53. 5 3
      src/scene/CMakeLists.txt
  54. 0 1
      src/scene/Octree.cpp
  55. 0 24
      src/scene/Property.cpp
  56. 15 7
      src/scene/SceneGraph.cpp
  57. 13 2
      src/script/LuaBinder.cpp
  58. 4 4
      src/script/ScriptManager.cpp
  59. 0 1
      src/ui/UiFont.cpp
  60. 0 1
      src/ui/UiFtFontLoader.cpp
  61. 1 1
      src/util/CMakeLists.txt
  62. 0 155
      src/util/Exception.cpp
  63. 25 18
      src/util/FilesystemWindows.cpp
  64. 12 6
      src/util/Memory.cpp
  65. 6 2
      src/util/Thread.cpp
  66. 0 1
      src/util/ThreadWindows.cpp
  67. 73 49
      testapp/Main.cpp
  68. 4 18
      tests/framework/Framework.cpp
  69. 8 3
      tests/framework/Framework.h
  70. 33 16
      tests/resource/AsyncLoader.cpp
  71. 14 17
      tests/resource/ResourceManager.cpp
  72. 10 4
      tests/script/LuaBinder.cpp
  73. 80 63
      tests/util/String.cpp
  74. 17 15
      tests/util/Thread.cpp
  75. 1 1
      thirdparty
  76. 6 4
      tools/scene/CMakeLists.txt
  77. 8 8
      tools/scene/Main.cpp

+ 2 - 3
CMakeLists.txt

@@ -104,6 +104,8 @@ if(NOT ANKI_CPU_ADDR_SPACE STREQUAL "0")
 	set(COMPILER_FLAGS "${COMPILER_FLAGS} -m${ANKI_CPU_ADDR_SPACE} ")
 	set(COMPILER_FLAGS "${COMPILER_FLAGS} -m${ANKI_CPU_ADDR_SPACE} ")
 endif()
 endif()
 
 
+add_definitions(-fno-exceptions)
+
 # static libstdc++
 # static libstdc++
 set(CXX_FLAGS "${CXX_FLAGS} -static-libstdc++ ")
 set(CXX_FLAGS "${CXX_FLAGS} -static-libstdc++ ")
 
 
@@ -244,9 +246,6 @@ endif()
 # AnKi specific compiler flags
 # AnKi specific compiler flags
 #
 #
 
 
-# thread local
-add_definitions("-Dthread_local=__thread")
-
 # AnKi compiler flags (Mainly warnings)
 # AnKi compiler flags (Mainly warnings)
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -W -Wextra -Wwrite-strings -Wunused -Wunused-variable -Wno-unused-parameter -Wundef -std=c++11 ")
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic -Wall -W -Wextra -Wwrite-strings -Wunused -Wunused-variable -Wno-unused-parameter -Wundef -std=c++11 ")
 
 

+ 0 - 1
include/anki/Util.h

@@ -45,7 +45,6 @@
 #include "anki/util/Thread.h"
 #include "anki/util/Thread.h"
 #include "anki/util/Bitset.h"
 #include "anki/util/Bitset.h"
 #include "anki/util/Dictionary.h"
 #include "anki/util/Dictionary.h"
-#include "anki/util/Exception.h"
 #include "anki/util/File.h"
 #include "anki/util/File.h"
 #include "anki/util/Filesystem.h"
 #include "anki/util/Filesystem.h"
 #include "anki/util/Functions.h"
 #include "anki/util/Functions.h"

+ 1 - 1
include/anki/core/App.h

@@ -34,7 +34,7 @@ class App
 {
 {
 public:
 public:
 	/// User callback of main loop
 	/// User callback of main loop
-	using UserMainLoopCallback = I32(*)(App& app, void* userData);
+	using UserMainLoopCallback = Error(*)(App& app, void* userData, Bool& quit);
 
 
 	App();
 	App();
 	~App();
 	~App();

+ 5 - 3
include/anki/event/AnimationEvent.h

@@ -8,18 +8,20 @@
 
 
 namespace anki {
 namespace anki {
 
 
-/// @addtogroup Events
+/// @addtogroup event
 /// @{
 /// @{
 
 
 /// Event controled by animation resource
 /// Event controled by animation resource
 class AnimationEvent: public Event
 class AnimationEvent: public Event
 {
 {
 public:
 public:
-	AnimationEvent(EventManager* manager, const AnimationResourcePointer& anim, 
+	ANKI_USE_RESULT Error create(
+		EventManager* manager, 
+		const AnimationResourcePointer& anim, 
 		SceneNode* movableSceneNode);
 		SceneNode* movableSceneNode);
 
 
 	/// Implements Event::update
 	/// Implements Event::update
-	void update(F32 prevUpdateTime, F32 crntTime) override;
+	ANKI_USE_RESULT Error update(F32 prevUpdateTime, F32 crntTime) override;
 
 
 private:
 private:
 	AnimationResourcePointer m_anim;
 	AnimationResourcePointer m_anim;

+ 75 - 64
include/anki/event/Event.h

@@ -7,121 +7,132 @@
 #define ANKI_EVENT_EVENT_H
 #define ANKI_EVENT_EVENT_H
 
 
 #include "anki/scene/Common.h"
 #include "anki/scene/Common.h"
-#include "anki/scene/SceneObject.h"
-#include "anki/util/Bitset.h"
 #include "anki/Math.h"
 #include "anki/Math.h"
+#include "anki/util/Enum.h"
 
 
 namespace anki {
 namespace anki {
 
 
 // Forward
 // Forward
 class EventManager;
 class EventManager;
 class SceneNode;
 class SceneNode;
+class SceneGraph;
 
 
-/// @addtogroup Events
+/// @addtogroup event
 /// @{
 /// @{
 
 
 /// The base class for all events
 /// The base class for all events
-class Event: public SceneObject, public Bitset<U8>
+class Event
 {
 {
 	friend class EventManager;
 	friend class EventManager;
 
 
 public:
 public:
 	/// Event flags
 	/// Event flags
-	enum EventFlags
+	enum class Flag: U8
 	{
 	{
-		EF_NONE = 0,
-		EF_REANIMATE = 1 << 0
+		NONE = 0,
+		REANIMATE = 1 << 0,
+		MARKED_FOR_DELETION = 1 << 1
 	};
 	};
-
-	/// @name Constructors/Destructor
-	/// @{
+	ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(Flag, friend);
 
 
 	/// Constructor
 	/// Constructor
-	Event(EventManager* manager, F32 startTime, F32 duration,  
-		SceneNode* snode = nullptr, U8 flags = EF_NONE);
+	Event();
 
 
 	virtual ~Event();
 	virtual ~Event();
-	/// @}
 
 
-	/// @name Accessors
-	/// @{
+	ANKI_USE_RESULT Error create(
+		EventManager* manager, F32 startTime, F32 duration,  
+		SceneNode* snode = nullptr, Flag flags = Flag::NONE);
+
 	F32 getStartTime() const
 	F32 getStartTime() const
 	{
 	{
-		return startTime;
+		return m_startTime;
 	}
 	}
 
 
 	F32 getDuration() const
 	F32 getDuration() const
 	{
 	{
-		return duration;
+		return m_duration;
 	}
 	}
 
 
 	Bool isDead(F32 crntTime) const
 	Bool isDead(F32 crntTime) const
 	{
 	{
-		return crntTime >= startTime + duration;
+		return crntTime >= m_startTime + m_duration;
 	}
 	}
 
 
-	EventManager& getEventManager();
-	const EventManager& getEventManager() const;
+	EventManager& getEventManager()
+	{
+		return *m_manager;
+	}
 
 
-	SceneNode* getSceneNode();
-	const SceneNode* getSceneNode() const;
-	/// @}
+	const EventManager& getEventManager() const
+	{
+		return *m_manager;
+	}
 
 
-	/// This method should be implemented by the derived classes
-	/// @param prevUpdateTime The time of the previous update (sec)
-	/// @param crntTime The current time (sec)
-	virtual void update(F32 prevUpdateTime, F32 crntTime) = 0;
+	SceneNode* getSceneNode()
+	{
+		return m_node;
+	}
 
 
-	/// This is called when the event is killed
-	/// @param prevUpdateTime The time of the previous update (sec)
-	/// @param crntTime The current time (sec)
-	/// @return Return false if you don't want to be killed
-	virtual Bool onKilled(F32 prevUpdateTime, F32 crntTime)
+	const SceneNode* getSceneNode() const
 	{
 	{
-		(void)prevUpdateTime;
-		(void)crntTime;
-		return true;
+		return m_node;
 	}
 	}
 
 
-protected:
-	/// The time the event will start. Eg 23:00. If it's < 0 then start the 
-	/// event now
-	F32 startTime;
-	F32 duration; ///< The duration of the event
-
-	/// Linear interpolation between values
-	/// @param[in] from Starting value
-	/// @param[in] to Ending value
-	/// @param[in] u The percentage from the from "from" value. Values
-	///              from [0.0, 1.0]
-	template<typename Type>
-	static Type interpolate(const Type& from, const Type& to, F32 u)
+	void markForDeletion()
 	{
 	{
-		//ANKI_ASSERT(u >= 0 && u <= 1.0);
-		return from * (1.0 - u) + to * u;
+		m_flags |= Flag::MARKED_FOR_DELETION;
 	}
 	}
 
 
-	template<typename Type>
-	static Type cosInterpolate(const Type& from, const Type& to, F32 u)
+	Bool getMarkedForDeletion() const
 	{
 	{
-		F32 u2 = (1.0 - cos(u * getPi<F32>())) / 2.0;
-		return from * (1.0 - u2) + to * u2;
+		return (m_flags & Flag::MARKED_FOR_DELETION) != Flag::NONE;
 	}
 	}
 
 
-	template<typename Type>
-	static Type cubicInterpolate(
-		const Type& a, const Type& b, const Type& c, 
-		const Type& d, F32 u)
+	void setReanimate(Bool reanimate)
 	{
 	{
-		F32 u2 = u * u;
-		Type a0 = d - c - a + b;
-		Type a1 = a - b - a0;
-		Type a2 = c - a;
-		Type a3 = b;
+		m_flags = (reanimate) 
+			? (m_flags | Flag::REANIMATE) 
+			: (m_flags & ~Flag::REANIMATE);
+	}
 
 
-		return(a0 * u * u2 + a1 * u2 + a2 * u + a3);
+	Bool getReanimate() const
+	{
+		return (m_flags & Flag::REANIMATE) != Flag::NONE;
 	}
 	}
 
 
+	SceneGraph& getSceneGraph();
+
+	const SceneGraph& getSceneGraph() const;
+
+	/// This method should be implemented by the derived classes
+	/// @param prevUpdateTime The time of the previous update (sec)
+	/// @param crntTime The current time (sec)
+	virtual ANKI_USE_RESULT Error update(F32 prevUpdateTime, F32 crntTime) = 0;
+
+	/// This is called when the event is killed
+	/// @param prevUpdateTime The time of the previous update (sec)
+	/// @param crntTime The current time (sec)
+	/// @param[out] Return false if you don't want to be killed
+	virtual ANKI_USE_RESULT Error onKilled(
+		F32 prevUpdateTime, F32 crntTime, Bool& kill)
+	{
+		(void)prevUpdateTime;
+		(void)crntTime;
+		kill = true;
+		return ErrorCode::NONE;
+	}
+
+protected:
+	Flag m_flags = Flag::NONE;
+	EventManager* m_manager = nullptr;
+	
+	F32 m_startTime; ///< The time the event will start. Eg 23:00. If it's < 0 
+	                 ///< then start the event now.
+	F32 m_duration; ///< The duration of the event
+
+	SceneNode* m_node = nullptr;
+
 	/// Return the u between current time and when the event started
 	/// Return the u between current time and when the event started
 	/// @return A number [0.0, 1.0]
 	/// @return A number [0.0, 1.0]
 	F32 getDelta(F32 crntTime) const;
 	F32 getDelta(F32 crntTime) const;

+ 51 - 28
include/anki/event/EventManager.h

@@ -17,53 +17,51 @@ namespace anki {
 // Forward
 // Forward
 class SceneGraph;
 class SceneGraph;
 
 
-/// @addtogroup Events
+/// @addtogroup event
 /// @{
 /// @{
 
 
-/// This manager creates the events ands keeps tracks of them
+/// This manager creates the events ands keeps track of them
 class EventManager
 class EventManager
 {
 {
 public:
 public:
-	typedef SceneVector<Event*> EventsContainer;
+	using EventsContainer = List<Event*, SceneAllocator<Event*>>;
 
 
-	EventManager(SceneGraph* scene);
+	EventManager();
 	~EventManager();
 	~EventManager();
 
 
-	/// @name Accessors
-	/// @{
+	ANKI_USE_RESULT Error create(SceneGraph* scene);
+
 	SceneGraph& getSceneGraph()
 	SceneGraph& getSceneGraph()
 	{
 	{
-		return *scene;
+		return *m_scene;
 	}
 	}
+
 	const SceneGraph& getSceneGraph() const
 	const SceneGraph& getSceneGraph() const
 	{
 	{
-		return *scene;
+		return *m_scene;
 	}
 	}
 
 
 	SceneAllocator<U8> getSceneAllocator() const;
 	SceneAllocator<U8> getSceneAllocator() const;
-	SceneAllocator<U8> getSceneFrameAllocator() const;
-	/// @}
+	SceneFrameAllocator<U8> getSceneFrameAllocator() const;
 
 
 	/// Iterate events
 	/// Iterate events
 	template<typename Func>
 	template<typename Func>
-	void iterateEvents(Func func)
+	ANKI_USE_RESULT Error iterateEvents(Func func)
 	{
 	{
-		for(Event* e : events)
+		Error err = ErrorCode::NONE;
+		auto it = m_events.getBegin();
+		auto end = m_events.getEnd();
+		for(; it != end && !err; ++it)
 		{
 		{
-			func(*e);
+			err = func(*(*it));
 		}
 		}
+
+		return err;
 	}
 	}
 
 
 	/// Create a new event
 	/// Create a new event
 	template<typename T, typename... Args>
 	template<typename T, typename... Args>
-	void newEvent(T*& event, Args&&... args)
-	{
-		SceneAllocator<T> al = getSceneAllocator();
-		event = al.allocate(1);
-		al.construct(event, this, std::forward<Args>(args)...);
-
-		registerEvent(event);
-	}
+	ANKI_USE_RESULT Error newEvent(T*& event, Args... args);
 
 
 	/// Delete an event. It actualy marks it for deletion
 	/// Delete an event. It actualy marks it for deletion
 	void deleteEvent(Event* event)
 	void deleteEvent(Event* event)
@@ -72,23 +70,48 @@ public:
 	}
 	}
 
 
 	/// Update
 	/// Update
-	void updateAllEvents(F32 prevUpdateTime, F32 crntTime);
+	ANKI_USE_RESULT Error updateAllEvents(F32 prevUpdateTime, F32 crntTime);
 
 
 	/// Delete events that pending deletion
 	/// Delete events that pending deletion
 	void deleteEventsMarkedForDeletion();
 	void deleteEventsMarkedForDeletion();
 
 
 private:
 private:
-	SceneGraph* scene = nullptr;
-	EventsContainer events;
-	F32 prevUpdateTime;
-	F32 crntTime;
+	SceneGraph* m_scene = nullptr;
+	EventsContainer m_events;
+	U32 m_markedForDeletionCount = 0;
+	F32 m_prevUpdateTime;
+	F32 m_crntTime;
 
 
 	/// Add an event to the local container
 	/// Add an event to the local container
-	void registerEvent(Event* event);
+	ANKI_USE_RESULT Error registerEvent(Event* event);
 
 
 	/// Remove an event from the container
 	/// Remove an event from the container
-	void unregisterEvent(Event* event);
+	void unregisterEvent(EventsContainer::Iterator it);
 };
 };
+
+//==============================================================================
+template<typename T, typename... Args>
+inline Error EventManager::newEvent(T*& event, Args... args)
+{
+	Error err = ErrorCode::NONE;
+	event = getSceneAllocator().template newInstance<T>();
+	if(event == nullptr)
+	{
+		err = ErrorCode::OUT_OF_MEMORY;
+	}
+	
+	if(!err)
+	{
+		err = event->create(this, args...);
+	}
+
+	if(!err)
+	{
+		err = registerEvent(event);
+	}
+
+	return err;
+}
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 13 - 16
include/anki/event/LightEvent.h

@@ -14,37 +14,34 @@ namespace anki {
 // Forward
 // Forward
 class Light;
 class Light;
 
 
-/// @addtogroup Events
+/// @addtogroup event
 /// @{
 /// @{
 
 
 /// Helper class
 /// Helper class
-struct LightEventData
+class LightEventData
 {
 {
-	F32 radiusMultiplier = 0.0;
-	Vec4 intensityMultiplier = Vec4(0.0);
-	Vec4 specularIntensityMultiplier = Vec4(0.0);
+public:
+	F32 m_radiusMultiplier = 0.0;
+	Vec4 m_intensityMultiplier = Vec4(0.0);
+	Vec4 m_specularIntensityMultiplier = Vec4(0.0);
 };
 };
 
 
 /// An event for light animation
 /// An event for light animation
 class LightEvent: public Event, private LightEventData
 class LightEvent: public Event, private LightEventData
 {
 {
 public:
 public:
-	/// @name Constructors/Destructor
-	/// @{
-
-	/// Constructor
-	LightEvent(EventManager* manager, F32 startTime, F32 duration,
+	/// Create
+	ANKI_USE_RESULT Error create(
+		EventManager* manager, F32 startTime, F32 duration,
 		Light* light, const LightEventData& data);
 		Light* light, const LightEventData& data);
-	/// @}
 
 
 	/// Implements Event::update
 	/// Implements Event::update
-	void update(F32 prevUpdateTime, F32 crntTime);
+	ANKI_USE_RESULT Error update(F32 prevUpdateTime, F32 crntTime);
 
 
 private:
 private:
-	Light* light;
-	F32 originalRadius;
-	Vec4 originalDiffColor;
-	Vec4 originalSpecColor;
+	F32 m_originalRadius;
+	Vec4 m_originalDiffColor;
+	Vec4 m_originalSpecColor;
 };
 };
 /// @}
 /// @}
 
 

+ 4 - 9
include/anki/event/MoveEvent.h

@@ -11,10 +11,7 @@
 
 
 namespace anki {
 namespace anki {
 
 
-// Forward
-class SceneNode;
-
-/// @addtogroup Events
+/// @addtogroup event
 /// @{
 /// @{
 
 
 /// Helper class
 /// Helper class
@@ -29,16 +26,14 @@ public:
 class MoveEvent: public Event, private MoveEventData
 class MoveEvent: public Event, private MoveEventData
 {
 {
 public:
 public:
-	/// @name Constructors/Destructor
-	/// @{
-
 	/// Constructor
 	/// Constructor
-	MoveEvent(EventManager* manager, F32 startTime, F32 duration,
+	ANKI_USE_RESULT Error create(
+		EventManager* manager, F32 startTime, F32 duration,
 		SceneNode* movableSceneNode, const MoveEventData& data);
 		SceneNode* movableSceneNode, const MoveEventData& data);
 	/// @}
 	/// @}
 
 
 	/// Implements Event::update
 	/// Implements Event::update
-	void update(F32 prevUpdateTime, F32 crntTime);
+	ANKI_USE_RESULT Error update(F32 prevUpdateTime, F32 crntTime);
 
 
 private:
 private:
 	Vec4 m_originalPos;
 	Vec4 m_originalPos;

+ 7 - 6
include/anki/event/SceneAmbientColorEvent.h

@@ -11,23 +11,24 @@
 
 
 namespace anki {
 namespace anki {
 
 
-/// @addtogroup Events
+/// @addtogroup event
 /// @{
 /// @{
 
 
 /// Change the scene color
 /// Change the scene color
 class SceneAmbientColorEvent: public Event
 class SceneAmbientColorEvent: public Event
 {
 {
 public:
 public:
-	/// Constructor
-	SceneAmbientColorEvent(EventManager* manager, F32 startTime, F32 duration,
+	/// Create
+	ANKI_USE_RESULT Error create(
+		EventManager* manager, F32 startTime, F32 duration,
 		const Vec4& finalColor);
 		const Vec4& finalColor);
 
 
 	/// Implements Event::update
 	/// Implements Event::update
-	void update(F32 prevUpdateTime, F32 crntTime);
+	ANKI_USE_RESULT Error update(F32 prevUpdateTime, F32 crntTime);
 
 
 private:
 private:
-	Vec4 originalColor; ///< Original scene color. The constructor sets it
-	Vec4 finalColor;
+	Vec4 m_originalColor; ///< Original scene color. The constructor sets it
+	Vec4 m_finalColor;
 };
 };
 /// @}
 /// @}
 
 

+ 1 - 1
include/anki/gl/GlQueue.h

@@ -124,7 +124,7 @@ private:
 	GlClientSyncHandle m_sync;
 	GlClientSyncHandle m_sync;
 
 
 	/// The function that the thread runs
 	/// The function that the thread runs
-	static I threadCallback(Thread::Info&);
+	static ANKI_USE_RESULT Error threadCallback(Thread::Info&);
 	void threadLoop();
 	void threadLoop();
 	void prepare();
 	void prepare();
 	void finish();
 	void finish();

+ 4 - 3
include/anki/misc/ConfigSet.h

@@ -7,7 +7,7 @@
 #define ANKI_MISC_CONFIG_SET_H
 #define ANKI_MISC_CONFIG_SET_H
 
 
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
-#include "anki/util/Exception.h"
+#include "anki/util/Logger.h"
 #include <unordered_map>
 #include <unordered_map>
 
 
 namespace anki {
 namespace anki {
@@ -27,7 +27,8 @@ public:
 		}
 		}
 		else
 		else
 		{
 		{
-			throw ANKI_EXCEPTION("Option not found");
+			ANKI_LOGE("Option not found");
+			return 0.0;
 		}
 		}
 	}
 	}
 
 
@@ -41,7 +42,7 @@ public:
 		}
 		}
 		else
 		else
 		{
 		{
-			throw ANKI_EXCEPTION("Option not found");
+			ANKI_LOGE("Option not found");
 		}
 		}
 	}
 	}
 
 

+ 0 - 1
include/anki/misc/Xml.h

@@ -6,7 +6,6 @@
 #ifndef ANKI_XML_H
 #ifndef ANKI_XML_H
 #define ANKI_XML_H
 #define ANKI_XML_H
 
 
-#include "anki/util/Exception.h"
 #include "anki/util/String.h"
 #include "anki/util/String.h"
 #include "anki/util/DArray.h"
 #include "anki/util/DArray.h"
 #include "anki/Math.h"
 #include "anki/Math.h"

+ 2 - 2
include/anki/resource/DummyRsrc.h

@@ -33,7 +33,7 @@ public:
 		const CString& filename, ResourceInitializer& init)
 		const CString& filename, ResourceInitializer& init)
 	{
 	{
 		Error err = ErrorCode::NONE;
 		Error err = ErrorCode::NONE;
-		if(filename != "exception")
+		if(filename != "error")
 		{
 		{
 			m_memory = m_alloc.allocate(128);
 			m_memory = m_alloc.allocate(128);
 			void* tempMem = init.m_tempAlloc.allocate(128);
 			void* tempMem = init.m_tempAlloc.allocate(128);
@@ -43,7 +43,7 @@ public:
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_LOGE("Dummy exception");
+			ANKI_LOGE("Dummy error");
 			err = ErrorCode::USER_DATA;
 			err = ErrorCode::USER_DATA;
 		}
 		}
 
 

+ 2 - 0
include/anki/resource/ResourceManager.h

@@ -34,6 +34,7 @@ ANKI_RESOURCE(BucketMesh, BucketMeshResourcePointer)
 ANKI_RESOURCE(Skeleton, SkeletonResourcePointer)
 ANKI_RESOURCE(Skeleton, SkeletonResourcePointer)
 ANKI_RESOURCE(ParticleEmitterResource, ParticleEmitterResourcePointer)
 ANKI_RESOURCE(ParticleEmitterResource, ParticleEmitterResourcePointer)
 ANKI_RESOURCE(Model, ModelResourcePointer)
 ANKI_RESOURCE(Model, ModelResourcePointer)
+ANKI_RESOURCE(Script, ScriptResourcePointer)
 ANKI_RESOURCE(DummyRsrc, DummyResourcePointer)
 ANKI_RESOURCE(DummyRsrc, DummyResourcePointer)
 
 
 #undef ANKI_RESOURCE
 #undef ANKI_RESOURCE
@@ -135,6 +136,7 @@ class ResourceManager:
 	ANKI_RESOURCE(Skeleton),
 	ANKI_RESOURCE(Skeleton),
 	ANKI_RESOURCE(ParticleEmitterResource),
 	ANKI_RESOURCE(ParticleEmitterResource),
 	ANKI_RESOURCE(Model),
 	ANKI_RESOURCE(Model),
+	ANKI_RESOURCE(Script),
 	ANKI_RESOURCE(DummyRsrc)
 	ANKI_RESOURCE(DummyRsrc)
 {
 {
 public:
 public:

+ 20 - 4
include/anki/resource/Script.h

@@ -6,19 +6,35 @@
 #ifndef ANKI_RESOURCE_SCRIPT_H
 #ifndef ANKI_RESOURCE_SCRIPT_H
 #define ANKI_RESOURCE_SCRIPT_H
 #define ANKI_RESOURCE_SCRIPT_H
 
 
-#include <string>
+#include "anki/resource/Common.h"
 
 
 namespace anki {
 namespace anki {
 
 
-/// Python script resource
+/// @addtogroup resource
+/// @{
+
+/// Script resource.
 class Script
 class Script
 {
 {
 public:
 public:
-	void load(const char* filename);
+	Script(ResourceAllocator<U8>&)
+	{}
+
+	~Script();
+
+	ANKI_USE_RESULT Error load(
+		const CString& filename, ResourceInitializer& init);
+
+	CString getSource() const
+	{
+		return m_source.toCString();
+	}
 
 
 private:
 private:
-	std::string source;
+	ResourceString m_source;
+	ResourceAllocator<char> m_alloc;
 };
 };
+/// @}
 
 
 } // end namespace
 } // end namespace
 
 

+ 0 - 401
include/anki/scene/Property.h

@@ -1,401 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#ifndef ANKI_SCENE_PROPERTY_H
-#define ANKI_SCENE_PROPERTY_H
-
-#if 0
-
-#include "anki/util/Observer.h"
-#include "anki/util/Exception.h"
-#include "anki/util/Assert.h"
-#include "anki/util/NonCopyable.h"
-#include "anki/util/Visitor.h"
-#include "anki/Math.h"
-#include "anki/resource/Resource.h"
-#include "anki/resource/TextureResource.h"
-#include "anki/Collision.h"
-#include "anki/util/Dictionary.h"
-
-namespace anki {
-
-// Forward
-class PropertyBase;
-
-template<typename T>
-class Property;
-
-typedef VisitableCommonBase<
-	PropertyBase, // Base
-	// Misc
-	Property<std::string>, Property<bool>, Property<float>,
-	Property<TextureResourcePointer>,
-	// Math
-	Property<Vec2>, Property<Vec3>, Property<Vec4>, Property<Mat3>,
-	Property<Mat4>, Property<Transform>,
-	// Collision
-	Property<OrthographicFrustum>, Property<PerspectiveFrustum>>
-	PropertyVisitable;
-
-/// Base class for property
-class PropertyBase: public NonCopyable, public PropertyVisitable
-{
-public:
-	/// @name Constructors/Destructor
-	/// @{
-	PropertyBase(const char* name_)
-		: name(name_)
-	{}
-
-	virtual ~PropertyBase()
-	{}
-	/// @}
-
-	/// @name Accessors
-	/// @{
-	const std::string& getName() const
-	{
-		return name;
-	}
-
-	/// Get the property value. Throws if the @a T is incorrect
-	template<typename TValue>
-	const TValue& getValue() const
-	{
-		checkType<TValue>();
-		return static_cast<const Property<TValue>*>(this)->getValue();
-	}
-
-	/// Set the property value. Throws if the @a T is incorrect
-	template<typename TValue>
-	void setValue(const TValue& x)
-	{
-		checkType<TValue>();
-		return static_cast<Property<TValue>*>(this)->setValue(x);
-	}
-	/// @}
-
-	/// Upcast to property. It makes a runtime check
-	template<typename TProp>
-	TProp& upCast()
-	{
-		checkType<TProp::Value>();
-		return static_cast<TProp&>(*this);
-	}
-
-private:
-	std::string name;
-
-	/// Runtime type checking
-	template<typename TValue>
-	void checkType() const
-	{
-		if(PropertyVisitable::getVariadicTypeId<Property<TValue>>() !=
-			getVisitableTypeId())
-		{
-			throw ANKI_EXCEPTION("Types do not match: %s", name.c_str());
-		}
-	}
-};
-
-/// Property interface
-template<typename T>
-class Property: public PropertyBase
-{
-public:
-	typedef T Value;
-	typedef Property<Value> Self;
-
-	/// @name Constructors/Destructor
-	/// @{
-
-	/// Read only property
-	Property(const char* name)
-		: PropertyBase(name)
-	{
-		setupVisitable(this);
-	}
-	/// @}
-
-	/// @name Accessors
-	/// @{
-	virtual const Value& getValue() const
-	{
-		throw ANKI_EXCEPTION("Property is not readable: %s", getName().c_str());
-	}
-
-	/// Set the value and emit the signal valueChanged
-	virtual void setValue(const Value& x)
-	{
-		(void)x;
-		throw ANKI_EXCEPTION("Property is not writable: %s", getName().c_str());
-	}
-	/// @}
-
-	/// Signal that it is emitted when the value gets changed
-	ANKI_SIGNAL(const Value&, valueChanged)
-};
-
-/// Read only property
-template<typename T>
-class ReadProperty: public Property<T>
-{
-public:
-	typedef T Value;
-	typedef Property<T> Base;
-
-	/// @name Constructors/Destructor
-	/// @{
-	ReadProperty(const char* name, const Value& initialValue)
-		: Base(name), x(initialValue)
-	{}
-	/// @}
-
-	/// @name Accessors
-	/// @{
-
-	/// Overrides Property::getValue()
-	const Value& getValue() const
-	{
-		return x;
-	}
-	/// @}
-
-private:
-	Value x;
-};
-
-/// Read write property
-template<typename T>
-class ReadWriteProperty: public Property<T>
-{
-public:
-	typedef T Value;
-	typedef Property<T> Base;
-
-	/// @name Constructors/Destructor
-	/// @{
-	ReadWriteProperty(const char* name, const Value& initialValue)
-		: Base(name), x(initialValue)
-	{}
-	/// @}
-
-	/// @name Accessors
-	/// @{
-
-	/// Overrides Property::getValue()
-	const Value& getValue() const
-	{
-		return x;
-	}
-
-	/// Overrides Property::setValue()
-	virtual void setValue(const Value& x_)
-	{
-		x = x_;
-		ANKI_EMIT valueChanged(x);
-	}
-	/// @}
-
-private:
-	Value x;
-};
-
-/// Read only property that holds a reference to a value
-template<typename T>
-class ReadPointerProperty: public Property<T>
-{
-public:
-	typedef T Value;
-	typedef Property<T> Base;
-
-	/// @name Constructors/Destructor
-	/// @{
-	ReadPointerProperty(const char* name, const Value* ptr_)
-		: Base(name), ptr(ptr_)
-	{}
-	/// @}
-
-	/// @name Accessors
-	/// @{
-
-	/// Overrides Property::getValue()
-	const Value& getValue() const
-	{
-		return *ptr;
-	}
-	/// @}
-
-private:
-	const Value* ptr;
-};
-
-/// Read write property that alters a reference to the value
-template<typename T>
-class ReadWritePointerProperty: public Property<T>
-{
-public:
-	typedef T Value;
-	typedef Property<T> Base;
-
-	/// @name Constructors/Destructor
-	/// @{
-	ReadWritePointerProperty(const char* name, Value* x)
-		: Base(name), ptr(x)
-	{}
-	/// @}
-
-	/// @name Accessors
-	/// @{
-
-	/// Overrides Property::getValue()
-	const Value& getValue() const
-	{
-		return *ptr;
-	}
-
-	/// Overrides Property::setValue()
-	virtual void setValue(const Value& x)
-	{
-		*ptr = x;
-		ANKI_EMIT valueChanged(x);
-	}
-	/// @}
-
-private:
-	Value* ptr;
-};
-
-/// Read and Copy on Write property
-template<typename T>
-class ReadCowPointerProperty: public Property<T>
-{
-public:
-	typedef T Value;
-	typedef Property<T> Base;
-
-	/// @name Constructors/Destructor
-	/// @{
-	ReadCowPointerProperty(const char* name, const Value* x)
-		: Base(name), ptr(x)
-	{}
-	/// @}
-
-	/// @name Accessors
-	/// @{
-	/// Overrides Property::getValue()
-	const Value& getValue() const
-	{
-		if(sptr.get())
-		{
-			return *sptr;
-		}
-		else
-		{
-			return *ptr;
-		}
-	}
-
-	/// Overrides Property::setValue()
-	virtual void setValue(const Value& x)
-	{
-		if(sptr.get())
-		{
-			*sptr = x;
-		}
-		else
-		{
-			sptr.reset(new Value(x));
-		}
-		ANKI_EMIT valueChanged(x);
-	}
-	/// @}
-
-private:
-	const Value* ptr;
-	std::unique_ptr<Value> sptr;
-};
-
-/// A set of properties
-class PropertyMap
-{
-public:
-	typedef Vector<PropertyBase*> Container;
-	typedef Dictionary<PropertyBase*> NameToPropertyMap;
-
-	/// Add new property to the map. The map gets the ownership of this
-	/// property
-	template<typename T>
-	Property<T>& addNewProperty(Property<T>* newp)
-	{
-		if(propertyExists(newp->getName().c_str()))
-		{
-			throw ANKI_EXCEPTION("Property already exists: %s", 
-				newp->getName().c_str());
-		}
-
-		props.push_back(newp);
-		map[newp->getName().c_str()] = newp;
-
-		return *newp;
-	}
-
-	/// Self explanatory
-	const PropertyBase& findPropertyBaseByName(const char* name) const
-	{
-		NameToPropertyMap::const_iterator it = map.find(name);
-		if(it == map.end())
-		{
-			throw ANKI_EXCEPTION("Property not found: %s", name);
-		}
-		return *(it->second);
-	}
-
-	/// Self explanatory
-	PropertyBase& findPropertyBaseByName(const char* name)
-	{
-		NameToPropertyMap::iterator it = map.find(name);
-		if(it == map.end())
-		{
-			throw ANKI_EXCEPTION("Property not found: %s", name);
-		}
-		return *(it->second);
-	}
-
-	/// Alias for findPropertyBaseByName
-	const PropertyBase& operator[](const char* name) const
-	{
-		return findPropertyBaseByName(name);
-	}
-
-	/// Alias for findPropertyBaseByName
-	PropertyBase& operator[](const char* name)
-	{
-		return findPropertyBaseByName(name);
-	}
-
-	/// Return true if the property named @a name exists
-	bool propertyExists(const char* name) const
-	{
-		return map.find(name) != map.end();
-	}
-
-	/// Set the value of a property. It may throw
-	template<typename T>
-	void setValue(const char* name, const T& v)
-	{
-		findPropertyBaseByName(name).setValue<T>(v);
-	}
-
-private:
-	Container props;
-	NameToPropertyMap map;
-};
-
-} // end namespace anki
-
-#endif
-
-#endif

+ 0 - 1
include/anki/scene/RenderComponent.h

@@ -6,7 +6,6 @@
 #ifndef ANKI_SCENE_RENDER_COMPONENT_H
 #ifndef ANKI_SCENE_RENDER_COMPONENT_H
 #define ANKI_SCENE_RENDER_COMPONENT_H
 #define ANKI_SCENE_RENDER_COMPONENT_H
 
 
-#include "anki/scene/Property.h"
 #include "anki/scene/Common.h"
 #include "anki/scene/Common.h"
 #include "anki/scene/SceneComponent.h"
 #include "anki/scene/SceneComponent.h"
 #include "anki/resource/Material.h"
 #include "anki/resource/Material.h"

+ 13 - 0
include/anki/script/ScriptManager.h

@@ -29,6 +29,19 @@ public:
 		void* allocCbData,
 		void* allocCbData,
 		SceneGraph* scene);
 		SceneGraph* scene);
 
 
+	/// Expose a variable to the scripting engine.
+	template<typename T>
+	void exposeVariable(const char* name, T* y)
+	{
+		m_lua.exposeVariable<T>(name, y);
+	}
+
+	/// Evaluate a string
+	ANKI_USE_RESULT Error evalString(const CString& str)
+	{
+		return m_lua.evalString(str);
+	}
+
 	/// @privatesection
 	/// @privatesection
 	/// @{
 	/// @{
 	SceneGraph& _getSceneGraph()
 	SceneGraph& _getSceneGraph()

+ 0 - 1
include/anki/util/Allocator.h

@@ -6,7 +6,6 @@
 #ifndef ANKI_UTIL_ALLOCATOR_H
 #ifndef ANKI_UTIL_ALLOCATOR_H
 #define ANKI_UTIL_ALLOCATOR_H
 #define ANKI_UTIL_ALLOCATOR_H
 
 
-#include "anki/util/Exception.h"
 #include "anki/util/Assert.h"
 #include "anki/util/Assert.h"
 #include "anki/util/Memory.h"
 #include "anki/util/Memory.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"

+ 0 - 79
include/anki/util/Exception.h

@@ -1,79 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#ifndef ANKI_UTIL_EXCEPTION_H
-#define ANKI_UTIL_EXCEPTION_H
-
-#include "anki/util/StdTypes.h"
-#include <exception>
-#include <utility>
-
-namespace anki {
-
-/// @addtogroup util_other
-/// @{
-
-/// Mother of all AnKi exceptions.
-///
-/// Custom exception that takes file, line and function that throw it. Throw 
-/// it using the ANKI_EXCEPTION macro
-class Exception: public std::exception
-{
-public:
-	/// Constructor
-	explicit Exception(const char* file, I line, const char* func, 
-		const char* errorFmt, ...) noexcept;
-
-	/// Copy constructor
-	Exception(const Exception& e) noexcept;
-
-	/// Move constructor
-	Exception(Exception&& e) noexcept
-	{
-		*this = std::move(e);
-	}
-
-	/// Destructor. Do nothing
-	~Exception() noexcept;
-
-	/// Move
-	Exception& operator=(Exception&& b) noexcept;
-
-	/// For re-throws.
-	/// Usage:
-	/// @code
-	/// catch(std::exception& e) {
-	/// 	throw Exception("message", ...) << e;
-	/// }
-	/// @endcode
-	Exception operator<<(const std::exception& e) const;
-
-	/// Implements std::exception::what()
-	const char* what() const noexcept
-	{
-		return m_err;
-	}
-
-private:
-	char* m_err;
-
-	Exception() noexcept
-	:	m_err(nullptr)
-	{}
-
-	/// Synthesize the error string
-	static char* synthErr(const char* error, const char* file,
-		I line, const char* func) noexcept;
-};
-
-/// Macro for easy throwing
-#define ANKI_EXCEPTION(...) \
-	Exception(ANKI_FILE, __LINE__, ANKI_FUNC, __VA_ARGS__)
-
-/// @}
-
-} // end namespace anki
-
-#endif

+ 1 - 1
include/anki/util/String.h

@@ -359,7 +359,7 @@ public:
 	Iterator end() 
 	Iterator end() 
 	{
 	{
 		checkInit();
 		checkInit();
-		return &m_data[m_data.size() - 1];
+		return &m_data[m_data.getSize() - 1];
 	}
 	}
 
 
 	ConstIterator end() const 
 	ConstIterator end() const 

+ 5 - 1
include/anki/util/String.inl.h

@@ -75,7 +75,11 @@ Error StringBase<TAlloc>::appendInternal(
 
 
 	if(!err)
 	if(!err)
 	{
 	{
-		std::memcpy(&newData[0], &m_data[0], sizeof(Char) * size);
+		if(!m_data.isEmpty())
+		{
+			std::memcpy(&newData[0], &m_data[0], sizeof(Char) * size);
+		}
+
 		std::memcpy(&newData[size - 1], str, sizeof(Char) * strSize);
 		std::memcpy(&newData[size - 1], str, sizeof(Char) * strSize);
 
 
 		m_data.destroy(alloc);
 		m_data.destroy(alloc);

+ 2 - 0
include/anki/util/StringList.h

@@ -51,6 +51,8 @@ public:
 	// Use the base constructors
 	// Use the base constructors
 	using Base::Base;
 	using Base::Base;
 
 
+	void destroy(Allocator alloc);
+
 	/// Join all the elements into a single big string using a the
 	/// Join all the elements into a single big string using a the
 	/// seperator @a separator
 	/// seperator @a separator
 	ANKI_USE_RESULT Error join(
 	ANKI_USE_RESULT Error join(

+ 14 - 0
include/anki/util/StringList.inl.h

@@ -8,6 +8,20 @@
 
 
 namespace anki {
 namespace anki {
 
 
+//==============================================================================
+template<typename TAlloc>
+void StringListBase<TAlloc>::destroy(Allocator alloc)
+{
+	auto it = Base::getBegin();
+	auto end = Base::getEnd();
+	for(; it != end; ++it)
+	{
+		(*it).destroy(alloc);
+	}
+
+	Base::destroy(alloc);
+}
+
 //==============================================================================
 //==============================================================================
 template<typename TAlloc>
 template<typename TAlloc>
 Error StringListBase<TAlloc>::join(
 Error StringListBase<TAlloc>::join(

+ 0 - 350
include/anki/util/Variant.h

@@ -1,350 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#ifndef ANKI_UTIL_VARIANT_H
-#define ANKI_UTIL_VARIANT_H
-
-#include "anki/util/Visitor.h"
-#include "anki/util/Exception.h"
-#include <iosfwd>
-#include <memory>
-
-namespace anki {
-
-/// @addtogroup util_patterns
-/// @{
-
-// Forwards
-template<typename Data, typename VariantBase>
-class VariantDerived;
-
-template<typename... Types>
-class VariantBase;
-
-/// The variant base class
-template<typename... Types>
-class VariantBase:
-	public Visitable<VariantDerived<Types, VariantBase<Types...>>...>
-{
-public:
-	typedef Visitable<VariantDerived<Types, VariantBase<Types...>>...> Base;
-	typedef VariantBase<Types...> Self;
-	typedef typename BaseType::ConstVisitor ConstVisitor;
-	typedef typename BaseType::MutableVisitor MutableVisitor;
-
-	static const int TEMPLATE_PARAMETERS_NUM = sizeof...(Types);
-
-	/// Default constructor
-	VariantBase(int typeId_)
-		: typeId(typeId_)
-	{}
-
-	virtual ~VariantBase()
-	{}
-
-	uint getTypeId() const
-	{
-		return typeId;
-	}
-
-	/// Get the parameter's value. It throws if the @a Data is incompatible
-	template<typename Data>
-	const Data& get() const
-	{
-		checkValue<Data>();
-		return static_cast<const VariantDerived<Data, SelfType>&>(*this).get();
-	}
-
-	/// Generic setter. It throws if the @a Data is incompatible
-	template<typename Data>
-	void set(const Data& x)
-	{
-		checkValue<Data>();
-		static_cast<VariantDerived<Data, SelfType>&>(*this).set(x);
-	}
-
-	/// Compare the derived classes
-	virtual bool equal(const SelfType& b) const = 0;
-
-	/// Copy the derived classes
-	virtual void copy(const SelfType& b) = 0;
-
-	/// Check if two derived are the same type
-	bool areSameType(const SelfType& b) const
-	{
-		return typeId == b.typeId;
-	}
-
-	/// Print
-	friend std::ostream& operator<<(std::ostream& s, const SelfType& x)
-	{
-		PrintVisitor v(s);
-		x.accept(v);
-		return s;
-	}
-
-protected:
-	static constexpr char* INCOMPATIBLES_ERR = "Incompatible parameter types";
-
-private:
-	template<typename... Types_>
-	struct PrintVisitor;
-
-	template<typename First, typename... Types_>
-	struct PrintVisitor<First, Types_...>: PrintVisitor<Types_...>
-	{
-		PrintVisitor(std::ostream& stream)
-			: PrintVisitor<Types_...>(stream)
-		{}
-
-		void visit(const First& x)
-		{
-			PrintVisitor<Types_...>::stream << x;
-		}
-	};
-
-	template<typename First>
-	struct PrintVisitor<First>: ConstVisitorType
-	{
-		std::ostream& stream;
-
-		PrintVisitor(std::ostream& stream_)
-			: stream(stream_)
-		{}
-
-		void visit(const First& x)
-		{
-			stream << x;
-		}
-	};
-
-	using PrintVisitor = PrintVisitor<VariantDerived<Types, SelfType>...>;
-
-	uint typeId; ///< type ID
-
-	/// Use const struff to check if @a Data is compatible with this
-	template<typename Data>
-	void checkValue() const
-	{
-		typedef VariantDerived<Data, SelfType> Vd;
-		const int id = BaseType::template getTypeId<Vd>();
-		if(id != typeId)
-		{
-			throw ANKI_EXCEPTION(INCOMPATIBLES_ERR);
-		}
-	}
-};
-
-/// VariantDerived template class. Using the @a TData and the @a TVariantBase 
-/// it constructs a variant class
-template<typename TData, typename TVariantBase>
-class VariantDerived: public TVariantBase
-{
-public:
-	typedef TData Data;
-	typedef TVariantBase Base;
-	typedef VariantDerived<DataType, BaseType> Self;
-	typedef typename BaseType::ConstVisitor ConstVisitor;
-	typedef typename BaseType::MutableVisitor MutableVisitor;
-
-	static const int TYPE_ID =
-		BaseType::BaseType::template getTypeId<SelfType>();
-
-	/// Constructor
-	VariantDerived()
-		: BaseType(TYPE_ID), data(DataType())
-	{}
-
-	/// Constructor
-	VariantDerived(const DataType& x)
-		: BaseType(TYPE_ID), data(x)
-	{}
-
-	/// Copy constructor
-	VariantDerived(const SelfType& b)
-		: BaseType(TYPE_ID), data(b.data)
-	{}
-
-	/// @name Accessors
-	/// @{
-	void set(const DataType& x)
-	{
-		data = x;
-	}
-	const DataType& get() const
-	{
-		return data;
-	}
-	/// @}
-
-	/// Compare
-	bool operator==(const SelfType& b) const
-	{
-		return data == b.data;
-	}
-
-	/// Implements the VariantBase::equal
-	bool equal(const BaseType& b) const
-	{
-		if(!BaseType::areSameType(b))
-		{
-			throw ANKI_EXCEPTION(BaseType::INCOMPATIBLES_ERR);
-		}
-
-		return *this == static_cast<const SelfType&>(b);
-	}
-
-	/// Implements the VariantBase::copy
-	void copy(const BaseType& b)
-	{
-		if(!BaseType::areSameType(b))
-		{
-			throw ANKI_EXCEPTION(BaseType::INCOMPATIBLES_ERR);
-		}
-
-		data = static_cast<const SelfType&>(b).data;
-	}
-
-	/// Implements VariantBase::accept
-	void accept(ConstVisitorType& v) const
-	{
-		v.visit(*this);
-	}
-	/// Implements VariantBase::accept
-	void accept(MutableVisitorType& v)
-	{
-		v.visit(*this);
-	}
-
-	/// Print
-	friend std::ostream& operator<<(std::ostream& s, const SelfType& x)
-	{
-		s << x.data;
-		return s;
-	}
-
-private:
-	DataType data; ///< The data
-};
-
-/// XXX
-/// @note It is no possible to have default constructor because we cannot have
-/// template default constructor
-template<typename... Types>
-class Variant
-{
-public:
-	typedef Variant<Types...> SelfType;
-	typedef VariantBase<Types...> VariantBaseType;
-
-	/// Default constructor
-	Variant()
-	{}
-
-	/// Constructor with data
-	template<typename Data>
-	explicit Variant(const Data& x)
-		: ptr(new VariantDerived<Data, VariantBaseType>(x))
-	{}
-
-	/// Copy constructor
-	Variant(const SelfType& x)
-	{
-		CopyVisitorType v(*this);
-		x.ptr->accept(v);
-	}
-
-	~Variant()
-	{}
-
-	/// Get the parameter's value. It throws if the @a Data is incompatible
-	template<typename Data>
-	const Data& get() const
-	{
-		return ptr->get<Data>();
-	}
-
-	/// Generic setter. It throws if the @a Data is incompatible
-	template<typename Data>
-	void set(const Data& x)
-	{
-		ptr->set<Data>(x);
-	}
-
-	/// Copy
-	SelfType& operator=(const SelfType& b)
-	{
-		ptr->copy(*b.ptr);
-		return *this;
-	}
-
-	/// Compare
-	bool operator==(const SelfType& b) const
-	{
-		return ptr->equal(*b.ptr);
-	}
-
-	/// set value
-	template<typename Data>
-	SelfType& operator=(const Data& b)
-	{
-		set<Data>(b);
-		return *this;
-	}
-
-	friend std::ostream& operator<<(std::ostream& s, const SelfType& x)
-	{
-		s << *x.ptr;
-		return s;
-	}
-
-private:
-	// Forward
-	template<typename... Types_>
-	struct CopyVisitor;
-
-	/// Visitor used to copy the data of a VariantBase to a Variant
-	template<typename First, typename... Types_>
-	struct CopyVisitor<First, Types_...>: CopyVisitor<Types_...>
-	{
-		using CopyVisitor<Types_...>::visit;
-
-		CopyVisitor(SelfType& a)
-			: CopyVisitor<Types_...>(a)
-		{}
-
-		void visit(const First& b)
-		{
-			CopyVisitor<Types_...>::a.ptr.reset(new First(b.get()));
-		}
-	};
-
-	// Specialized for one
-	template<typename First>
-	struct CopyVisitor<First>: VariantBaseType::ConstVisitorType
-	{
-		SelfType& a;
-
-		CopyVisitor(SelfType& a_)
-			: a(a_)
-		{}
-
-		void visit(const First& b)
-		{
-			a.ptr.reset(new First(b.get()));
-		}
-	};
-
-	typedef CopyVisitor<VariantDerived<Types, VariantBaseType>...>
-		CopyVisitorType;
-
-	/// The only data member, a pointer to a VariantBase class
-	std::unique_ptr<VariantBaseType> ptr;
-};
-/// @}
-
-} // end namespace anki
-
-#endif

+ 5 - 5
src/core/App.cpp

@@ -6,7 +6,6 @@
 #include "anki/core/App.h"
 #include "anki/core/App.h"
 #include "anki/misc/ConfigSet.h"
 #include "anki/misc/ConfigSet.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
-#include "anki/util/Exception.h"
 #include "anki/util/File.h"
 #include "anki/util/File.h"
 #include "anki/util/Filesystem.h"
 #include "anki/util/Filesystem.h"
 #include "anki/util/System.h"
 #include "anki/util/System.h"
@@ -98,7 +97,7 @@ void App::cleanup()
 Error App::create(const ConfigSet& config, 
 Error App::create(const ConfigSet& config, 
 	AllocAlignedCallback allocCb, void* allocCbUserData)
 	AllocAlignedCallback allocCb, void* allocCbUserData)
 {
 {
-	Error err = create(config, allocCb, allocCbUserData);
+	Error err = createInternal(config, allocCb, allocCbUserData);
 	if(err)
 	if(err)
 	{
 	{
 		cleanup();
 		cleanup();
@@ -328,13 +327,13 @@ Error App::mainLoop(UserMainLoopCallback callback, void* userData)
 {
 {
 	Error err = ErrorCode::NONE;
 	Error err = ErrorCode::NONE;
 	ANKI_LOGI("Entering main loop");
 	ANKI_LOGI("Entering main loop");
-	I32 userRetCode = 0;
+	Bool quit = false;
 
 
 	HighRezTimer::Scalar prevUpdateTime = HighRezTimer::getCurrentTime();
 	HighRezTimer::Scalar prevUpdateTime = HighRezTimer::getCurrentTime();
 	HighRezTimer::Scalar crntTime = prevUpdateTime;
 	HighRezTimer::Scalar crntTime = prevUpdateTime;
 
 
 	ANKI_COUNTER_START_TIMER(FPS);
 	ANKI_COUNTER_START_TIMER(FPS);
-	while(userRetCode == 0)
+	while(!quit)
 	{
 	{
 		HighRezTimer timer;
 		HighRezTimer timer;
 		timer.start();
 		timer.start();
@@ -347,7 +346,8 @@ Error App::mainLoop(UserMainLoopCallback callback, void* userData)
 		if(err)	break;
 		if(err)	break;
 
 
 		// User update
 		// User update
-		userRetCode = callback(*this, userData);
+		err = callback(*this, userData, quit);
+		if(err)	break;
 
 
 		err = m_scene->update(prevUpdateTime, crntTime, *m_renderer);
 		err = m_scene->update(prevUpdateTime, crntTime, *m_renderer);
 		if(err)	break;
 		if(err)	break;

+ 0 - 1
src/core/NativeWindowAndroid.cpp

@@ -6,7 +6,6 @@
 #include "anki/core/NativeWindowAndroid.h"
 #include "anki/core/NativeWindowAndroid.h"
 #include "anki/core/App.h"
 #include "anki/core/App.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Array.h"
 #include "anki/util/Array.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Counters.h"

+ 0 - 1
src/core/NativeWindowEglFbdev.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/core/NativeWindowEglFbdev.h"
 #include "anki/core/NativeWindowEglFbdev.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Vector.h"
 #include "anki/util/Vector.h"
 #include "anki/util/Array.h"
 #include "anki/util/Array.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/StdTypes.h"

+ 0 - 1
src/core/NativeWindowSdl.cpp

@@ -6,7 +6,6 @@
 #include "anki/core/NativeWindowSdl.h"
 #include "anki/core/NativeWindowSdl.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Counters.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
-#include "anki/util/Exception.h"
 #include <GL/glew.h>
 #include <GL/glew.h>
 
 
 namespace anki {
 namespace anki {

+ 5 - 1
src/core/StdinListener.cpp

@@ -14,7 +14,11 @@ namespace anki {
 StdinListener::~StdinListener()
 StdinListener::~StdinListener()
 {
 {
 	m_quit = true;
 	m_quit = true;
-	m_thrd.join();
+	Error err = m_thrd.join();
+	if(err)
+	{
+		ANKI_LOGE("Error when joining StdinListener");
+	}
 	
 	
 	for(String& s : m_q)
 	for(String& s : m_q)
 	{
 	{

+ 16 - 8
src/event/AnimationEvent.cpp

@@ -11,21 +11,27 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-AnimationEvent::AnimationEvent(EventManager* manager, 
-	const AnimationResourcePointer& anim, SceneNode* movableSceneNode)
-	:	Event(manager, 0.0, 0.0, movableSceneNode),
-		m_anim(anim)
+Error AnimationEvent::create(EventManager* manager, 
+	const AnimationResourcePointer& anim, 
+	SceneNode* movableSceneNode)
 {
 {
 	ANKI_ASSERT(movableSceneNode);
 	ANKI_ASSERT(movableSceneNode);
+	m_anim = anim;
 
 
-	startTime = m_anim->getStartingTime();
-	duration = m_anim->getDuration();
+	Flag f = Flag::NONE;
+	if(m_anim->getRepeat())
+	{
+		f = Flag::REANIMATE;
+	}
 
 
-	enableBits(EF_REANIMATE, m_anim->getRepeat());
+	Error err = Event::create(manager, m_anim->getStartingTime(), 
+		m_anim->getDuration(), movableSceneNode, f);
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void AnimationEvent::update(F32 prevUpdateTime, F32 crntTime)
+Error AnimationEvent::update(F32 prevUpdateTime, F32 crntTime)
 {
 {
 	ANKI_ASSERT(getSceneNode());
 	ANKI_ASSERT(getSceneNode());
 	MoveComponent& move = getSceneNode()->getComponent<MoveComponent>();
 	MoveComponent& move = getSceneNode()->getComponent<MoveComponent>();
@@ -40,6 +46,8 @@ void AnimationEvent::update(F32 prevUpdateTime, F32 crntTime)
 	trf.setRotation(Mat3x4(rot));
 	trf.setRotation(Mat3x4(rot));
 	trf.setScale(scale);
 	trf.setScale(scale);
 	move.setLocalTransform(trf);
 	move.setLocalTransform(trf);
+
+	return ErrorCode::NONE;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 20 - 33
src/event/Event.cpp

@@ -11,12 +11,7 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-Event::Event(EventManager* manager, F32 startTime_, F32 duration_, 
-	SceneNode* node, U8 flags)
-:	SceneObject(Type::EVENT, node, &manager->getSceneGraph()),
-	Bitset<U8>(flags), 
-	startTime(startTime_),
-	duration(duration_)
+Event::Event()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
@@ -24,47 +19,39 @@ Event::~Event()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-EventManager& Event::getEventManager()
+Error Event::create(
+	EventManager* manager, F32 startTime, F32 duration, 
+	SceneNode* node, Flag flags)
 {
 {
-	return getSceneGraph().getEventManager();
-}
+	ANKI_ASSERT(manager);
 
 
-//==============================================================================
-const EventManager& Event::getEventManager() const
-{
-	return getSceneGraph().getEventManager();
+	m_flags = flags;
+	m_manager = manager;
+	m_startTime = startTime;
+	m_duration = duration;
+	m_node = node;
+
+	return ErrorCode::NONE;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-SceneNode* Event::getSceneNode()
+F32 Event::getDelta(F32 crntTime) const
 {
 {
-	SceneObject* parent = getParent();
-	if(parent)
-	{
-		return &parent->downCast<SceneNode>();
-	}
-
-	return nullptr;
+	F32 d = crntTime - m_startTime; // delta
+	F32 dp = d / m_duration; // delta as persentage
+	return dp;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-const SceneNode* Event::getSceneNode() const
+SceneGraph& Event::getSceneGraph()
 {
 {
-	const SceneObject* parent = getParent();
-	if(parent)
-	{
-		return &parent->downCast<SceneNode>();
-	}
-
-	return nullptr;
+	return m_manager->getSceneGraph();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-F32 Event::getDelta(F32 crntTime) const
+const SceneGraph& Event::getSceneGraph() const
 {
 {
-	F32 d = crntTime - startTime; // delta
-	F32 dp = d / duration; // delta as persentage
-	return dp;
+	return m_manager->getSceneGraph();
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 60 - 59
src/event/EventManager.cpp

@@ -9,8 +9,7 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-EventManager::EventManager(SceneGraph* scene_)
-	: scene(scene_), events(getSceneAllocator())
+EventManager::EventManager()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
@@ -18,126 +17,128 @@ EventManager::~EventManager()
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
-SceneAllocator<U8> EventManager::getSceneAllocator() const
+Error EventManager::create(SceneGraph* scene)
 {
 {
-	return scene->getAllocator();
+	ANKI_ASSERT(scene);
+	m_scene = scene;
+	return ErrorCode::NONE;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-SceneAllocator<U8> EventManager::getSceneFrameAllocator() const
+SceneAllocator<U8> EventManager::getSceneAllocator() const
 {
 {
-	return scene->getFrameAllocator();
+	return m_scene->getAllocator();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void EventManager::registerEvent(Event* event)
+SceneFrameAllocator<U8> EventManager::getSceneFrameAllocator() const
 {
 {
-	ANKI_ASSERT(event);
-	ANKI_ASSERT(std::find(events.begin(), events.end(), event) == events.end());
-	events.push_back(event);
+	return m_scene->getFrameAllocator();
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void EventManager::unregisterEvent(Event* event)
+Error EventManager::registerEvent(Event* event)
 {
 {
 	ANKI_ASSERT(event);
 	ANKI_ASSERT(event);
-	
-	EventsContainer::iterator it = events.begin();
-	for(; it != events.end(); it++)
-	{
-		if((*it) == event)
-		{
-			break;
-		}
-	}
+	return m_events.pushBack(getSceneAllocator(), event);
+}
 
 
-	ANKI_ASSERT(it == events.end() && "Trying to unreg non-existing event");
-	events.erase(it);
+//==============================================================================
+void EventManager::unregisterEvent(EventsContainer::Iterator it)
+{	
+	ANKI_ASSERT(it != m_events.getEnd());
+	m_events.erase(getSceneAllocator(), it);
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void EventManager::updateAllEvents(F32 prevUpdateTime_, F32 crntTime_)
+Error EventManager::updateAllEvents(F32 prevUpdateTime, F32 crntTime)
 {
 {
-	prevUpdateTime = prevUpdateTime_;
-	crntTime = crntTime_;
+	Error err = ErrorCode::NONE;
+	m_prevUpdateTime = prevUpdateTime;
+	m_crntTime = crntTime;
 
 
-	EventsContainer::iterator it = events.begin();
-	for(; it != events.end(); it++)
+	auto it = m_events.getBegin();
+	auto end = m_events.getEnd();
+	for(; it != end && !err; ++it)
 	{
 	{
-		Event* pevent = *it;
+		Event* event = *it;
 
 
 		// If event or the node's event is marked for deletion then dont 
 		// If event or the node's event is marked for deletion then dont 
 		// do anything else for that event
 		// do anything else for that event
-		if(pevent->isMarkedForDeletion() 
-			|| (pevent->getSceneNode() != nullptr 
-				&& pevent->getSceneNode()->isMarkedForDeletion()))
+		if(event->getMarkedForDeletion())
+		{
+			continue;
+		}
+
+		if(event->getSceneNode() != nullptr 
+			&& event->getSceneNode()->isMarkedForDeletion())
 		{
 		{
-			pevent->markForDeletion();
+			event->markForDeletion();
 			continue;
 			continue;
 		}
 		}
 
 
 		// Audjust starting time
 		// Audjust starting time
-		if(pevent->startTime < 0.0)
+		if(event->m_startTime < 0.0)
 		{
 		{
-			pevent->startTime = crntTime;
+			event->m_startTime = crntTime;
 		}
 		}
 
 
 		// Check if dead
 		// Check if dead
-		if(!pevent->isDead(crntTime))
+		if(!event->isDead(crntTime))
 		{
 		{
 			// If not dead update it
 			// If not dead update it
 
 
-			if(pevent->getStartTime() <= crntTime)
+			if(event->getStartTime() <= crntTime)
 			{
 			{
-				pevent->update(prevUpdateTime, crntTime);
+				err = event->update(prevUpdateTime, crntTime);
 			}
 			}
 		}
 		}
 		else
 		else
 		{
 		{
 			// Dead
 			// Dead
 
 
-			if(pevent->bitsEnabled(Event::EF_REANIMATE))
+			if(event->getReanimate())
 			{
 			{
-				pevent->startTime = prevUpdateTime;
-				pevent->update(prevUpdateTime, crntTime);
+				event->m_startTime = prevUpdateTime;
+				err = event->update(prevUpdateTime, crntTime);
 			}
 			}
 			else
 			else
 			{
 			{
-				if(pevent->onKilled(prevUpdateTime, crntTime))
+				Bool kill;
+				err = event->onKilled(prevUpdateTime, crntTime, kill);
+				if(!err && kill)
 				{
 				{
-					pevent->markForDeletion();
+					event->markForDeletion();
 				}
 				}
 			}
 			}
 		}
 		}
 	}
 	}
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 void EventManager::deleteEventsMarkedForDeletion()
 void EventManager::deleteEventsMarkedForDeletion()
 {
 {
-	SceneAllocator<Event> al = getSceneAllocator();
+	SceneAllocator<U8> alloc = getSceneAllocator();
 
 
 	// Gather events for deletion
 	// Gather events for deletion
-	SceneFrameVector<EventsContainer::iterator> 
-		forDeletion(getSceneFrameAllocator());
-
-	for(EventsContainer::iterator it = events.begin(); it != events.end(); ++it)
+	while(m_markedForDeletionCount != 0)
 	{
 	{
-		Event* event = *it;
-		if(event->isMarkedForDeletion())
+		auto it = m_events.getBegin();
+		auto end = m_events.getEnd();
+		for(; it != end; ++it)
 		{
 		{
-			forDeletion.push_back(it);
+			Event* event = *it;
+			if(event->getMarkedForDeletion())
+			{
+				unregisterEvent(it);
+				alloc.deleteInstance<Event>(event);
+				--m_markedForDeletionCount;
+				break;
+			}
 		}
 		}
 	}
 	}
-
-	// Delete events
-	for(auto it : forDeletion)
-	{
-		Event* event = *it;
-
-		unregisterEvent(event);
-		al.deleteInstance(event);
-	}
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 16 - 9
src/event/LightEvent.cpp

@@ -9,10 +9,12 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-LightEvent::LightEvent(EventManager* manager, F32 startTime, F32 duration,
+Error LightEvent::create(EventManager* manager, F32 startTime, F32 duration,
 	Light* light, const LightEventData& data)
 	Light* light, const LightEventData& data)
-:	Event(manager, startTime, duration, light, EF_NONE)
 {
 {
+	Error err = Event::create(manager, startTime, duration, light);
+	if(err) return err;
+
 	*static_cast<LightEventData*>(this) = data;
 	*static_cast<LightEventData*>(this) = data;
 
 
 	switch(light->getLightType())
 	switch(light->getLightType())
@@ -20,7 +22,7 @@ LightEvent::LightEvent(EventManager* manager, F32 startTime, F32 duration,
 	case Light::Type::POINT:
 	case Light::Type::POINT:
 		{
 		{
 			PointLight* plight = static_cast<PointLight*>(light);
 			PointLight* plight = static_cast<PointLight*>(light);
-			originalRadius = plight->getRadius();
+			m_originalRadius = plight->getRadius();
 		}
 		}
 		break;
 		break;
 	case Light::Type::SPOT:
 	case Light::Type::SPOT:
@@ -31,12 +33,14 @@ LightEvent::LightEvent(EventManager* manager, F32 startTime, F32 duration,
 		break;
 		break;
 	}
 	}
 
 
-	originalDiffColor = light->getDiffuseColor();
-	originalSpecColor = light->getSpecularColor();
+	m_originalDiffColor = light->getDiffuseColor();
+	m_originalSpecColor = light->getSpecularColor();
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void LightEvent::update(F32 prevUpdateTime, F32 crntTime)
+Error LightEvent::update(F32 prevUpdateTime, F32 crntTime)
 {
 {
 	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
 	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
 	Light* light = static_cast<Light*>(getSceneNode());
 	Light* light = static_cast<Light*>(getSceneNode());
@@ -47,7 +51,7 @@ void LightEvent::update(F32 prevUpdateTime, F32 crntTime)
 		{
 		{
 			PointLight* plight = static_cast<PointLight*>(light);
 			PointLight* plight = static_cast<PointLight*>(light);
 			plight->setRadius(
 			plight->setRadius(
-				factor * radiusMultiplier + originalRadius);
+				factor * m_radiusMultiplier + m_originalRadius);
 		}
 		}
 		break;
 		break;
 	case Light::Type::SPOT:
 	case Light::Type::SPOT:
@@ -58,9 +62,12 @@ void LightEvent::update(F32 prevUpdateTime, F32 crntTime)
 		break;
 		break;
 	}
 	}
 
 
-	light->setDiffuseColor(originalDiffColor + factor * intensityMultiplier);
+	light->setDiffuseColor(
+		m_originalDiffColor + factor * m_intensityMultiplier);
 	light->setSpecularColor(
 	light->setSpecularColor(
-		originalSpecColor + factor * specularIntensityMultiplier);
+		m_originalSpecColor + factor * m_specularIntensityMultiplier);
+
+	return ErrorCode::NONE;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 11 - 4
src/event/MoveEvent.cpp

@@ -11,11 +11,13 @@
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-MoveEvent::MoveEvent(EventManager* manager, F32 startTime, F32 duration,
+Error MoveEvent::create(EventManager* manager, F32 startTime, F32 duration,
 	SceneNode* node, const MoveEventData& data)
 	SceneNode* node, const MoveEventData& data)
-	: Event(manager, startTime, duration, node, EF_NONE)
 {
 {
 	ANKI_ASSERT(node);
 	ANKI_ASSERT(node);
+	Error err = Event::create(manager, startTime, duration, node);
+	if(err) return err;
+
 	*static_cast<MoveEventData*>(this) = data;
 	*static_cast<MoveEventData*>(this) = data;
 
 
 	const MoveComponent& move = node->getComponent<MoveComponent>();
 	const MoveComponent& move = node->getComponent<MoveComponent>();
@@ -26,12 +28,15 @@ MoveEvent::MoveEvent(EventManager* manager, F32 startTime, F32 duration,
 	{
 	{
 		m_newPos[i] = randRange(m_posMin[i], m_posMax[i]);
 		m_newPos[i] = randRange(m_posMin[i], m_posMax[i]);
 	}
 	}
+
 	m_newPos[3] = 0.0;
 	m_newPos[3] = 0.0;
 	m_newPos += move.getLocalTransform().getOrigin();
 	m_newPos += move.getLocalTransform().getOrigin();
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void MoveEvent::update(F32 prevUpdateTime, F32 crntTime)
+Error MoveEvent::update(F32 prevUpdateTime, F32 crntTime)
 {
 {
 	SceneNode* node = getSceneNode();
 	SceneNode* node = getSceneNode();
 	ANKI_ASSERT(node);
 	ANKI_ASSERT(node);
@@ -42,9 +47,11 @@ void MoveEvent::update(F32 prevUpdateTime, F32 crntTime)
 
 
 	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
 	F32 factor = sin(getDelta(crntTime) * getPi<F32>());
 
 
-	trf.getOrigin() = interpolate(m_originalPos, m_newPos, factor);
+	trf.getOrigin() = linearInterpolate(m_originalPos, m_newPos, factor);
 
 
 	move.setLocalTransform(trf);
 	move.setLocalTransform(trf);
+
+	return ErrorCode::NONE;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 15 - 8
src/event/SceneAmbientColorEvent.cpp

@@ -5,24 +5,31 @@
 
 
 #include "anki/event/SceneAmbientColorEvent.h"
 #include "anki/event/SceneAmbientColorEvent.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/scene/SceneGraph.h"
-#include "anki/util/Logger.h"
 
 
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-SceneAmbientColorEvent::SceneAmbientColorEvent(EventManager* manager,
-	F32 startTime, F32 duration, const Vec4& finalColor_)
-	:	Event(manager, startTime, duration), 
-		finalColor(finalColor_)
+Error SceneAmbientColorEvent::create(EventManager* manager,
+	F32 startTime, F32 duration, const Vec4& finalColor)
 {
 {
-	originalColor = getSceneGraph().getAmbientColor();
+	Error err = Event::create(manager, startTime, duration);
+
+	if(!err)
+	{
+		m_finalColor = finalColor;
+		m_originalColor = getSceneGraph().getAmbientColor();
+	}
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void SceneAmbientColorEvent::update(F32 /*prevUpdateTime*/, F32 crntTime)
+Error SceneAmbientColorEvent::update(F32 /*prevUpdateTime*/, F32 crntTime)
 {
 {
 	getSceneGraph().setAmbientColor(
 	getSceneGraph().setAmbientColor(
-		interpolate(originalColor, finalColor, getDelta(crntTime)));
+		linearInterpolate(m_originalColor, m_finalColor, getDelta(crntTime)));
+
+	return ErrorCode::NONE;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 0 - 1
src/gl/GlBuffer.cpp

@@ -6,7 +6,6 @@
 #include <cstring>
 #include <cstring>
 #include "anki/gl/GlBuffer.h"
 #include "anki/gl/GlBuffer.h"
 #include "anki/gl/GlError.h"
 #include "anki/gl/GlError.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
 #include <cmath>
 #include <cmath>
 
 

+ 14 - 3
src/gl/GlProgram.cpp

@@ -362,6 +362,12 @@ Error GlProgram::create(GLenum type, const CString& source,
 		if(status == GL_FALSE)
 		if(status == GL_FALSE)
 		{
 		{
 			err = handleError(alloc, fullSrc);
 			err = handleError(alloc, fullSrc);
+
+			if(!err)
+			{
+				// Compilation failed, set error anyway
+				err = ErrorCode::USER_DATA;
+			}
 		}
 		}
 	}
 	}
 
 
@@ -386,6 +392,7 @@ Error GlProgram::handleError(GlAllocator<U8>& alloc, String& src)
 	GLint charsWritten = 0;
 	GLint charsWritten = 0;
 	String compilerLog;
 	String compilerLog;
 	String prettySrc;
 	String prettySrc;
+	StringList lines;
 
 
 	static const char* padding = 
 	static const char* padding = 
 		"======================================="
 		"======================================="
@@ -393,15 +400,14 @@ Error GlProgram::handleError(GlAllocator<U8>& alloc, String& src)
 
 
 	glGetProgramiv(m_glName, GL_INFO_LOG_LENGTH, &compilerLogLen);
 	glGetProgramiv(m_glName, GL_INFO_LOG_LENGTH, &compilerLogLen);
 
 
-	err = compilerLog.create(alloc, '?', compilerLogLen + 1);
+	err = compilerLog.create(alloc, ' ', compilerLogLen + 1);
 
 
-	StringList lines;
 	if(!err)
 	if(!err)
 	{
 	{
 		glGetProgramInfoLog(
 		glGetProgramInfoLog(
 			m_glName, compilerLogLen, &charsWritten, &compilerLog[0]);
 			m_glName, compilerLogLen, &charsWritten, &compilerLog[0]);
 		
 		
-		err = StringList::splitString(alloc, src.toCString(), '\n', lines);
+		err = lines.splitString(alloc, src.toCString(), '\n');
 	}
 	}
 
 
 	I lineno = 0;
 	I lineno = 0;
@@ -415,6 +421,8 @@ Error GlProgram::handleError(GlAllocator<U8>& alloc, String& src)
 		{
 		{
 			err = prettySrc.append(alloc, tmp);
 			err = prettySrc.append(alloc, tmp);
 		}
 		}
+
+		tmp.destroy(alloc);
 	}
 	}
 
 
 	if(!err)
 	if(!err)
@@ -423,6 +431,9 @@ Error GlProgram::handleError(GlAllocator<U8>& alloc, String& src)
 			m_type, padding, &compilerLog[0], padding, &prettySrc[0]);
 			m_type, padding, &compilerLog[0], padding, &prettySrc[0]);
 	}
 	}
 
 
+	lines.destroy(alloc);
+	prettySrc.destroy(alloc);
+	compilerLog.destroy(alloc);
 	return err;
 	return err;
 }
 }
 
 

+ 5 - 4
src/gl/GlQueue.cpp

@@ -125,7 +125,7 @@ Error GlQueue::start(
 
 
 	if(err && threadStarted)
 	if(err && threadStarted)
 	{
 	{
-		m_thread.join();
+		err = m_thread.join();
 	}
 	}
 #else
 #else
 	prepare();
 	prepare();
@@ -146,7 +146,8 @@ void GlQueue::stop()
 		m_tail = m_queue.size() + 1;
 		m_tail = m_queue.size() + 1;
 		m_head = m_tail + 1;
 		m_head = m_tail + 1;
 	}
 	}
-	m_thread.join();
+	Error err = m_thread.join();
+	(void)err;
 #else
 #else
 	finish();
 	finish();
 #endif
 #endif
@@ -202,11 +203,11 @@ void GlQueue::finish()
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-I GlQueue::threadCallback(Thread::Info& info)
+Error GlQueue::threadCallback(Thread::Info& info)
 {
 {
 	GlQueue* queue = reinterpret_cast<GlQueue*>(info.m_userData);
 	GlQueue* queue = reinterpret_cast<GlQueue*>(info.m_userData);
 	queue->threadLoop();
 	queue->threadLoop();
-	return 0;
+	return ErrorCode::NONE;
 }
 }
 
 
 //==============================================================================
 //==============================================================================

+ 2 - 2
src/renderer/MainRenderer.cpp

@@ -40,10 +40,10 @@ Error MainRenderer::create(
 	config.set("height", 
 	config.set("height", 
 		config.get("height") * config.get("renderingQuality"));
 		config.get("height") * config.get("renderingQuality"));
 
 
-	err = initGl();
+	err = Renderer::init(threadpool, resources, gl, alloc, config);
 	if(err) return err;
 	if(err) return err;
 
 
-	err = Renderer::init(threadpool, resources, gl, alloc, config);
+	err = initGl();
 	if(err) return err;
 	if(err) return err;
 
 
 	err = m_blitFrag.load("shaders/Final.frag.glsl", &_getResourceManager());
 	err = m_blitFrag.load("shaders/Final.frag.glsl", &_getResourceManager());

+ 0 - 1
src/renderer/Renderer.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/renderer/Renderer.h"
 #include "anki/renderer/Renderer.h"
-#include "anki/util/Exception.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Counters.h"

+ 4 - 2
src/renderer/Sslr.cpp

@@ -67,7 +67,8 @@ Error Sslr::init(const ConfigSet& config)
 	// Init FBOs and RTs and blurring
 	// Init FBOs and RTs and blurring
 	if(m_blurringIterationsCount > 0)
 	if(m_blurringIterationsCount > 0)
 	{
 	{
-		initBlurring(*m_r, m_width, m_height, 9, 0.0);
+		err = initBlurring(*m_r, m_width, m_height, 9, 0.0);
+		if(err) return err;
 	}
 	}
 	else
 	else
 	{
 	{
@@ -121,7 +122,8 @@ Error Sslr::run(GlCommandBufferHandle& cmdBuff)
 	//
 	//
 	if(m_blurringIterationsCount > 0)
 	if(m_blurringIterationsCount > 0)
 	{
 	{
-		runBlurring(*m_r, cmdBuff);
+		err = runBlurring(*m_r, cmdBuff);
+		if(err) return err;
 	}
 	}
 
 
 	// Write the reflection back to IS RT
 	// Write the reflection back to IS RT

+ 0 - 1
src/resource/Animation.cpp

@@ -5,7 +5,6 @@
 
 
 #include "anki/resource/Animation.h"
 #include "anki/resource/Animation.h"
 #include "anki/misc/Xml.h"
 #include "anki/misc/Xml.h"
-#include "anki/util/Exception.h"
 
 
 namespace anki {
 namespace anki {
 
 

+ 0 - 1
src/resource/Extension.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/resource/Extension.h"
 #include "anki/resource/Extension.h"
-#include "anki/util/Exception.h"
 //#include <dlfcn.h>
 //#include <dlfcn.h>
 
 
 namespace anki {
 namespace anki {

+ 0 - 1
src/resource/Image.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/resource/Image.h"
 #include "anki/resource/Image.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
 #include "anki/util/File.h"
 #include "anki/util/File.h"
 #include "anki/util/Filesystem.h"
 #include "anki/util/Filesystem.h"

+ 0 - 1
src/resource/MaterialProgramCreator.cpp

@@ -5,7 +5,6 @@
 
 
 #include "anki/resource/MaterialProgramCreator.h"
 #include "anki/resource/MaterialProgramCreator.h"
 #include "anki/util/Assert.h"
 #include "anki/util/Assert.h"
-#include "anki/util/Exception.h"
 #include "anki/misc/Xml.h"
 #include "anki/misc/Xml.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
 
 

+ 0 - 1
src/resource/ParticleEmitterResource.cpp

@@ -5,7 +5,6 @@
 
 
 #include "anki/resource/ParticleEmitterResource.h"
 #include "anki/resource/ParticleEmitterResource.h"
 #include "anki/resource/Model.h"
 #include "anki/resource/Model.h"
-#include "anki/util/Exception.h"
 #include "anki/util/StringList.h"
 #include "anki/util/StringList.h"
 #include "anki/misc/Xml.h"
 #include "anki/misc/Xml.h"
 #include <cstring>
 #include <cstring>

+ 0 - 1
src/resource/ProgramPrePreprocessor.cpp

@@ -5,7 +5,6 @@
 
 
 #include "anki/resource/ProgramPrePreprocessor.h"
 #include "anki/resource/ProgramPrePreprocessor.h"
 #include "anki/resource/ResourceManager.h"
 #include "anki/resource/ResourceManager.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Functions.h"
 #include "anki/util/Functions.h"
 #include "anki/util/File.h"
 #include "anki/util/File.h"
 #include "anki/util/Array.h"
 #include "anki/util/Array.h"

+ 0 - 1
src/resource/ProgramResource.cpp

@@ -10,7 +10,6 @@
 #include "anki/util/File.h"
 #include "anki/util/File.h"
 #include "anki/util/Filesystem.h"
 #include "anki/util/Filesystem.h"
 #include "anki/util/Hash.h"
 #include "anki/util/Hash.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Assert.h"
 #include "anki/util/Assert.h"
 
 
 namespace anki {
 namespace anki {

+ 2 - 0
src/resource/ResourceManager.cpp

@@ -9,6 +9,7 @@
 #include "anki/resource/Material.h"
 #include "anki/resource/Material.h"
 #include "anki/resource/Mesh.h"
 #include "anki/resource/Mesh.h"
 #include "anki/resource/Model.h"
 #include "anki/resource/Model.h"
+#include "anki/resource/Script.h"
 #include "anki/resource/DummyRsrc.h"
 #include "anki/resource/DummyRsrc.h"
 #include "anki/resource/ProgramResource.h"
 #include "anki/resource/ProgramResource.h"
 #include "anki/resource/ParticleEmitterResource.h"
 #include "anki/resource/ParticleEmitterResource.h"
@@ -81,6 +82,7 @@ Error ResourceManager::create(Initializer& init)
 	ANKI_RESOURCE(Skeleton)
 	ANKI_RESOURCE(Skeleton)
 	ANKI_RESOURCE(ParticleEmitterResource)
 	ANKI_RESOURCE(ParticleEmitterResource)
 	ANKI_RESOURCE(Model)
 	ANKI_RESOURCE(Model)
+	ANKI_RESOURCE(Script)
 	ANKI_RESOURCE(DummyRsrc)
 	ANKI_RESOURCE(DummyRsrc)
 
 
 #undef ANKI_RESOURCE
 #undef ANKI_RESOURCE

+ 19 - 6
src/resource/Script.cpp

@@ -4,18 +4,31 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/resource/Script.h"
 #include "anki/resource/Script.h"
-#include "anki/util/Exception.h"
+#include "anki/util/File.h"
 
 
 namespace anki {
 namespace anki {
 
 
 //==============================================================================
 //==============================================================================
-void Script::load(const char* filename)
+Script::~Script()
 {
 {
-	/*source = readFile(filename);
-	if(source.length() < 1)
+	m_source.destroy(m_alloc);
+}
+
+//==============================================================================
+Error Script::load(const CString& filename, ResourceInitializer& init)
+{
+	Error err = ErrorCode::NONE;
+	File file;
+
+	err = file.open(filename, File::OpenFlag::READ);
+
+	if(!err)
 	{
 	{
-		throw ANKI_EXCEPTION("Cannot load script: " + filename);
-	}*/
+		m_alloc = init.m_alloc;
+		err = file.readAllText(m_alloc, m_source);
+	}
+
+	return err;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 0 - 1
src/resource/TextureResource.cpp

@@ -6,7 +6,6 @@
 #include "anki/resource/TextureResource.h"
 #include "anki/resource/TextureResource.h"
 #include "anki/resource/Image.h"
 #include "anki/resource/Image.h"
 #include "anki/resource/ResourceManager.h"
 #include "anki/resource/ResourceManager.h"
-#include "anki/util/Exception.h"
 
 
 namespace anki {
 namespace anki {
 
 

+ 5 - 3
src/scene/CMakeLists.txt

@@ -1,4 +1,6 @@
-FILE(GLOB_RECURSE ANKI_SCENE_SOURCES *.cpp)
-FILE(GLOB_RECURSE ANKI_SCENE_HEADERS *.h)
+file(GLOB_RECURSE ANKI_SCENE_SOURCES *.cpp)
+file(GLOB_RECURSE ANKI_SCENE_HEADERS *.h)
 
 
-ADD_LIBRARY(ankiscene ${ANKI_SCENE_SOURCES} ${ANKI_SCENE_HEADERS})
+add_library(ankiscene ${ANKI_SCENE_SOURCES} ${ANKI_SCENE_HEADERS})
+
+target_link_libraries(ankiscene ankicore)

+ 0 - 1
src/scene/Octree.cpp

@@ -9,7 +9,6 @@
 #include "anki/scene/Light.h"
 #include "anki/scene/Light.h"
 #include "anki/scene/Sector.h"
 #include "anki/scene/Sector.h"
 #include "anki/scene/SceneGraph.h"
 #include "anki/scene/SceneGraph.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
 #include "anki/scene/RenderComponent.h"
 #include "anki/scene/RenderComponent.h"
 
 

+ 0 - 24
src/scene/Property.cpp

@@ -1,24 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include "anki/scene/Property.h"
-
-#if 0
-namespace anki {
-
-/// To avoid idiotic mistakes
-#define ANKI_DEFINE_PROPERTY_TYPE(SubType_) \
-	class SubType_; \
-	template<> const uint Property<SubType_>::TYPE_ID = __LINE__;
-
-template<> const uint Property<float>::TYPE_ID = __LINE__;
-template<> const uint Property<bool>::TYPE_ID = __LINE__;
-ANKI_DEFINE_PROPERTY_TYPE(Vec2)
-ANKI_DEFINE_PROPERTY_TYPE(Vec3)
-ANKI_DEFINE_PROPERTY_TYPE(OrthographicFrustum)
-ANKI_DEFINE_PROPERTY_TYPE(PerspectiveFrustum)
-
-}  // namespace anki
-#endif

+ 15 - 7
src/scene/SceneGraph.cpp

@@ -7,7 +7,6 @@
 #include "anki/scene/Camera.h"
 #include "anki/scene/Camera.h"
 #include "anki/scene/ModelNode.h"
 #include "anki/scene/ModelNode.h"
 #include "anki/scene/InstanceNode.h"
 #include "anki/scene/InstanceNode.h"
-#include "anki/util/Exception.h"
 #include "anki/core/Counters.h"
 #include "anki/core/Counters.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/renderer/Renderer.h"
 #include "anki/misc/Xml.h"
 #include "anki/misc/Xml.h"
@@ -100,8 +99,7 @@ public:
 //==============================================================================
 //==============================================================================
 SceneGraph::SceneGraph()
 SceneGraph::SceneGraph()
 :	m_physics(),
 :	m_physics(),
-	m_sectorGroup(this),
-	m_events(this)
+	m_sectorGroup(this)
 {}
 {}
 
 
 //==============================================================================
 //==============================================================================
@@ -115,6 +113,8 @@ Error SceneGraph::create(
 	Threadpool* threadpool, 
 	Threadpool* threadpool, 
 	ResourceManager* resources)
 	ResourceManager* resources)
 {
 {
+	Error err = ErrorCode::NONE;
+
 	m_threadpool = threadpool;
 	m_threadpool = threadpool;
 	m_resources = resources;
 	m_resources = resources;
 	m_objectsMarkedForDeletionCount.store(0);
 	m_objectsMarkedForDeletionCount.store(0);
@@ -126,7 +126,14 @@ Error SceneGraph::create(
 	m_frameAlloc = SceneFrameAllocator<U8>(
 	m_frameAlloc = SceneFrameAllocator<U8>(
 		allocCb, allocCbData, ANKI_SCENE_FRAME_ALLOCATOR_SIZE);
 		allocCb, allocCbData, ANKI_SCENE_FRAME_ALLOCATOR_SIZE);
 
 
-	return ErrorCode::NONE;
+	err = m_events.create(this);
+
+	if(err)
+	{
+		ANKI_LOGE("Scene creation failed");
+	}
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
@@ -249,16 +256,17 @@ Error SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 	// Reset the framepool
 	// Reset the framepool
 	m_frameAlloc.getMemoryPool().reset();
 	m_frameAlloc.getMemoryPool().reset();
 
 
-	// Delete nodes
+	// Delete stuff
+	m_events.deleteEventsMarkedForDeletion();
 	deleteNodesMarkedForDeletion();
 	deleteNodesMarkedForDeletion();
 
 
 	Threadpool& threadPool = *m_threadpool;
 	Threadpool& threadPool = *m_threadpool;
 	(void)threadPool;
 	(void)threadPool;
 
 
-	// XXX Do that in parallel
 	//m_physics.update(prevUpdateTime, crntTime);
 	//m_physics.update(prevUpdateTime, crntTime);
 	renderer.getTiler().updateTiles(*m_mainCam);
 	renderer.getTiler().updateTiles(*m_mainCam);
-	m_events.updateAllEvents(prevUpdateTime, crntTime);
+	err = m_events.updateAllEvents(prevUpdateTime, crntTime);
+	if(err) return err;
 
 
 	// Then the rest
 	// Then the rest
 	Array<UpdateSceneNodesTask, Threadpool::MAX_THREADS> jobs2;
 	Array<UpdateSceneNodesTask, Threadpool::MAX_THREADS> jobs2;

+ 13 - 2
src/script/LuaBinder.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/script/LuaBinder.h"
 #include "anki/script/LuaBinder.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
 #include <iostream>
 #include <iostream>
 #include <cstring>
 #include <cstring>
@@ -51,7 +50,8 @@ void* LuaBinder::luaAllocCallback(
 {
 {
 	ANKI_ASSERT(userData);
 	ANKI_ASSERT(userData);
 	
 	
-	LuaBinder& binder = *(LuaBinder*)userData;
+#if 1
+	LuaBinder& binder = *reinterpret_cast<LuaBinder*>(userData);
 	void* out = nullptr;
 	void* out = nullptr;
 
 
 	if(nsize == 0) 
 	if(nsize == 0) 
@@ -82,6 +82,17 @@ void* LuaBinder::luaAllocCallback(
 			binder.m_alloc.getMemoryPool().free(ptr);
 			binder.m_alloc.getMemoryPool().free(ptr);
 		}
 		}
 	}
 	}
+#else
+	void* out = nullptr;
+	if (nsize == 0) 
+	{
+		free(ptr);
+	}
+	else
+	{
+		out = realloc(ptr, nsize);
+	}
+#endif
 
 
 	return out;
 	return out;
 }
 }

+ 4 - 4
src/script/ScriptManager.cpp

@@ -6,9 +6,9 @@
 #include "anki/script/ScriptManager.h"
 #include "anki/script/ScriptManager.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
 
 
-#define ANKI_SCRIPT_CALL_WRAP(type_) \
-	extern void wrap##x(lua_State*); \
-	wrap##x(l);
+#define ANKI_SCRIPT_CALL_WRAP(x_) \
+	extern void wrapModule##x_(lua_State*); \
+	wrapModule##x_(l);
 
 
 namespace anki {
 namespace anki {
 
 
@@ -30,7 +30,7 @@ Error ScriptManager::create(
 	ANKI_LOGI("Initializing scripting engine...");
 	ANKI_LOGI("Initializing scripting engine...");
 
 
 	m_scene = scene;
 	m_scene = scene;
-	m_alloc = ChainAllocator<U8>(allocCb, allocCbData, 1024, 1024);
+	m_alloc = ChainAllocator<U8>(allocCb, allocCbData, 1024, 1024 * 1024);
 
 
 	Error err = m_lua.create(m_alloc, this);
 	Error err = m_lua.create(m_alloc, this);
 	if(err) return err;
 	if(err) return err;

+ 0 - 1
src/ui/UiFont.cpp

@@ -5,7 +5,6 @@
 
 
 #include "anki/ui/UiFont.h"
 #include "anki/ui/UiFont.h"
 #include "anki/resource/TextureResource.h"
 #include "anki/resource/TextureResource.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Assert.h"
 #include "anki/util/Assert.h"
 #include "anki/ui/UiFtFontLoader.h"
 #include "anki/ui/UiFtFontLoader.h"
 
 

+ 0 - 1
src/ui/UiFtFontLoader.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/ui/UiFtFontLoader.h"
 #include "anki/ui/UiFtFontLoader.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
 
 
 namespace anki {
 namespace anki {

+ 1 - 1
src/util/CMakeLists.txt

@@ -1,4 +1,4 @@
-set(ANKI_UTIL_SOURCES Assert.cpp Exception.cpp Functions.cpp File.cpp Filesystem.cpp Memory.cpp System.cpp HighRezTimer.cpp Thread.cpp Hash.cpp Logger.cpp)
+set(ANKI_UTIL_SOURCES Assert.cpp Functions.cpp File.cpp Filesystem.cpp Memory.cpp System.cpp HighRezTimer.cpp Thread.cpp Hash.cpp Logger.cpp)
 
 
 if(LINUX OR ANDROID OR MACOS)
 if(LINUX OR ANDROID OR MACOS)
 	set(ANKI_UTIL_SOURCES ${ANKI_UTIL_SOURCES} HighRezTimerPosix.cpp FilesystemPosix.cpp ThreadPosix.cpp)
 	set(ANKI_UTIL_SOURCES ${ANKI_UTIL_SOURCES} HighRezTimerPosix.cpp FilesystemPosix.cpp ThreadPosix.cpp)

+ 0 - 155
src/util/Exception.cpp

@@ -1,155 +0,0 @@
-// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include "anki/util/Exception.h"
-#include "anki/util/Array.h"
-#include "anki/util/Memory.h"
-#include <cstring>
-#include <cstdarg>
-#include <cstdio> // For vsnprintf
-#if ANKI_DEBUG == 1
-#	include "anki/util/Thread.h"
-#endif
-
-// Instead of throwing abort. Its easier to debug
-#define ANKI_ABORT_ON_THROW 0
-
-namespace anki {
-
-//==============================================================================
-Exception::Exception(const char* file, I line, const char* func, 
-	const char* fmt, ...) noexcept
-{
-	Array<char, 1024> buffer; 
-	char* out = &buffer[0];
-	va_list args;
-
-	va_start(args, fmt);
-	I len = std::vsnprintf(&buffer[0], sizeof(buffer), fmt, args);
-	va_end(args);
-
-	if(len < 0)
-	{
-		// Error in vsnprintf()
-		std::strcpy(
-			&buffer[0], "Error when throwing exception. vsnprintf() failed");
-	}
-	else if((PtrSize)len >= sizeof(buffer))
-	{
-		// The buffer is not big enough
-
-		// Create a huge string
-		I size = len + 1;
-		out = reinterpret_cast<char*>(mallocAligned(size, 1));
-
-		va_start(args, fmt);
-		len = std::vsnprintf(out, size, fmt, args);
-		(void)len;
-		va_end(args);
-
-		ANKI_ASSERT(len < size);
-	}
-
-	m_err = synthErr(out, file, line, func);
-
-	// Delete the allocated memory
-	if(out != &buffer[0])
-	{
-		freeAligned(out);
-	}
-
-#if ANKI_DEBUG == 1
-	fprintf(stderr, "Exception thrown\n");
-#endif
-
-#if ANKI_ABORT_ON_THROW == 1
-	abort();
-#endif
-}
-
-//==============================================================================
-Exception::Exception(const Exception& e) noexcept
-{
-	ANKI_ASSERT(e.m_err);
-
-	m_err = reinterpret_cast<char*>(mallocAligned(std::strlen(e.m_err) + 1, 1));
-	std::strcpy(m_err, e.m_err);
-
-#if ANKI_DEBUG == 1
-	fprintf(stderr, "Exception copied\n");
-#endif
-
-#if ANKI_ABORT_ON_THROW == 1
-	abort();
-#endif
-}
-
-//==============================================================================
-Exception::~Exception() noexcept
-{
-	if(m_err)
-	{
-		freeAligned(m_err);
-		m_err = nullptr;
-	}
-}
-
-//==============================================================================
-Exception& Exception::operator=(Exception&& b) noexcept
-{
-	if(m_err)
-	{
-		freeAligned(m_err);
-	}
-
-	m_err = b.m_err;
-	b.m_err = nullptr;
-	return *this;
-}
-
-//==============================================================================
-char* Exception::synthErr(const char* error, const char* file,
-	I line, const char* func) noexcept
-{
-	// The length of all strings plus some extra chars for the formating 
-	// plus 10 to be safe
-	U len = 
-		std::strlen(error) + std::strlen(file) + 5 + std::strlen(func) + 5 + 10;
-
-	char* out = reinterpret_cast<char*>(mallocAligned(len + 1, 1));
-	
-	I olen = std::snprintf(out, len + 1, "(%s:%d %s) %s", file, 
-		static_cast<int>(line), func, error);
-	
-	ANKI_ASSERT(olen >= 0 && (U)olen <= len);
-	(void)olen;
-
-	return out;
-}
-
-//==============================================================================
-Exception Exception::operator<<(const std::exception& e) const
-{
-	ANKI_ASSERT(m_err);
-	ANKI_ASSERT(e.what());
-
-	static const char* filling = "\nFrom: ";
-	Exception out;
-
-	U len = std::strlen(filling);
-	len += std::strlen(m_err);
-	len += std::strlen(e.what());
-
-	out.m_err = reinterpret_cast<char*>(mallocAligned(len + 1, 1));
-	I olen = std::snprintf(
-		out.m_err, len + 1, "%s%s%s", m_err, filling, e.what());
-
-	ANKI_ASSERT(olen >= 0 && (U)olen <= len);
-	(void)olen;
-
-	return out;
-}
-
-} // end namespace anki

+ 25 - 18
src/util/FilesystemWindows.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/util/Filesystem.h"
 #include "anki/util/Filesystem.h"
-#include "anki/util/Exception.h"
 #include "anki/util/Assert.h"
 #include "anki/util/Assert.h"
 #include <windows.h>
 #include <windows.h>
 
 
@@ -29,8 +28,9 @@ Bool directoryExists(const CString& filename)
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void removeDirectory(const CString& dirname)
+Error removeDirectory(const CString& dirname)
 {
 {
+	Error err = ErrorCode::NONE;
 	SHFILEOPSTRUCTA fileOperation;
 	SHFILEOPSTRUCTA fileOperation;
 	fileOperation.wFunc = FO_DELETE;
 	fileOperation.wFunc = FO_DELETE;
 	fileOperation.pFrom = dirname.get();
 	fileOperation.pFrom = dirname.get();
@@ -39,46 +39,53 @@ void removeDirectory(const CString& dirname)
 	I result = SHFileOperationA(&fileOperation);
 	I result = SHFileOperationA(&fileOperation);
 	if(result != 0) 
 	if(result != 0) 
 	{
 	{
-		throw ANKI_EXCEPTION("Could not delete directory %s", dirname.get());
+		ANKI_LOGE("Could not delete directory %s", dirname.get());
+		err = ErrorCode::FUNCTION_FAILED;
 	}
 	}
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void createDirectory(const CString& dir)
+Error createDirectory(const CString& dir)
 {
 {
+	Error err = ErrorCode::NONE;
 	if(CreateDirectory(dir.get(), NULL) == 0)
 	if(CreateDirectory(dir.get(), NULL) == 0)
 	{
 	{
-		throw ANKI_EXCEPTION("Failed to create directory %s", dir.get());
+		ANKI_LOGE("Failed to create directory %s", dir.get());
+		err = ErrorCode::FUNCTION_FAILED;
 	}
 	}
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-String getHomeDirectory(HeapAllocator<U8>& alloc)
+Error getHomeDirectory(HeapAllocator<U8>& alloc, String& out);
 {
 {
 	const char* homed = getenv("HOMEDRIVE");
 	const char* homed = getenv("HOMEDRIVE");
 	const char* homep = getenv("HOMEPATH");
 	const char* homep = getenv("HOMEPATH");
 
 
 	if(homed == nullptr || homep == nullptr)
 	if(homed == nullptr || homep == nullptr)
 	{
 	{
-		throw ANKI_EXCEPTION("HOME environment variables not set");
+		ANKI_LOGE("HOME environment variables not set");
+		return ErrorCode::FUNCTION_FAILED;
 	}
 	}
 
 
-	String out(alloc);
-	out.reserve(std::strlen(homed) + std::strlen(homep));
-
-	out += CString(homed);
-	out += CString(homep);
-
-	// Convert to Unix path
-	for(char& c : out)
+	String out;
+	Error err = out.sprintf("%s/%s", homed, homep);
+	if(!err)
 	{
 	{
-		if(c == '\\')
+		// Convert to Unix path
+		for(char& c : out)
 		{
 		{
-			c = '/';
+			if(c == '\\')
+			{
+				c = '/';
+			}
 		}
 		}
 	}
 	}
 
 
-	return out;
+	return err;
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 12 - 6
src/util/Memory.cpp

@@ -709,7 +709,7 @@ public:
 	ChainMemoryPool::ChunkGrowMethod m_method;
 	ChainMemoryPool::ChunkGrowMethod m_method;
 
 
 	/// Allocations number.
 	/// Allocations number.
-	AtomicU32 m_allocationsCount;
+	AtomicU32 m_allocationsCount = {0};
 
 
 	/// Construct
 	/// Construct
 	Implementation(
 	Implementation(
@@ -731,25 +731,25 @@ public:
 		ANKI_ASSERT(m_allocCb);
 		ANKI_ASSERT(m_allocCb);
 
 
 		// Initial size should be > 0
 		// Initial size should be > 0
-		ANKI_ASSERT(m_initSize > 0);
+		ANKI_ASSERT(m_initSize > 0 && "Wrong arg");
 
 
 		// On fixed step should be 0
 		// On fixed step should be 0
 		if(m_method == ChainMemoryPool::ChunkGrowMethod::FIXED)
 		if(m_method == ChainMemoryPool::ChunkGrowMethod::FIXED)
 		{
 		{
-			ANKI_ASSERT(m_step == 0);
+			ANKI_ASSERT(m_step == 0 && "Wrong arg");
 		}
 		}
 
 
 		// On fixed initial size is the same as the max
 		// On fixed initial size is the same as the max
 		if(m_method == ChainMemoryPool::ChunkGrowMethod::FIXED)
 		if(m_method == ChainMemoryPool::ChunkGrowMethod::FIXED)
 		{
 		{
-			ANKI_ASSERT(m_initSize == m_maxSize);
+			ANKI_ASSERT(m_initSize == m_maxSize && "Wrong arg");
 		}
 		}
 
 
 		// On add and mul the max size should be greater than initial
 		// On add and mul the max size should be greater than initial
 		if(m_method == ChainMemoryPool::ChunkGrowMethod::ADD 
 		if(m_method == ChainMemoryPool::ChunkGrowMethod::ADD 
 			|| m_method == ChainMemoryPool::ChunkGrowMethod::MULTIPLY)
 			|| m_method == ChainMemoryPool::ChunkGrowMethod::MULTIPLY)
 		{
 		{
-			ANKI_ASSERT(m_initSize < m_maxSize);
+			ANKI_ASSERT(m_initSize < m_maxSize && "Wrong arg");
 		}
 		}
 	}
 	}
 
 
@@ -957,16 +957,22 @@ public:
 		{
 		{
 			mem = allocateFromChunk(ch, size, alignment);
 			mem = allocateFromChunk(ch, size, alignment);
 			ANKI_ASSERT(mem != nullptr && "The chunk should have space");
 			ANKI_ASSERT(mem != nullptr && "The chunk should have space");
-			++m_allocationsCount;
 		}
 		}
 
 
 		m_lock.unlock();
 		m_lock.unlock();
+		++m_allocationsCount;
+
 		return mem;
 		return mem;
 	}
 	}
 
 
 	/// Free memory
 	/// Free memory
 	Bool free(void* ptr) noexcept
 	Bool free(void* ptr) noexcept
 	{
 	{
+		if(ptr == nullptr)
+		{
+			return true;
+		}
+
 		m_lock.lock();
 		m_lock.lock();
 
 
 		// Get the chunk that ptr belongs to
 		// Get the chunk that ptr belongs to

+ 6 - 2
src/util/Thread.cpp

@@ -9,6 +9,7 @@
 #include "anki/util/Functions.h"
 #include "anki/util/Functions.h"
 #include <cstdlib>
 #include <cstdlib>
 #include <new>
 #include <new>
+#include <cstdio>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -90,8 +91,9 @@ private:
 		Barrier& barrier = self.m_threadpool->m_barrier;
 		Barrier& barrier = self.m_threadpool->m_barrier;
 		Mutex& mtx = self.m_mutex; 
 		Mutex& mtx = self.m_mutex; 
 		const PtrSize threadCount = self.m_threadpool->getThreadsCount();
 		const PtrSize threadCount = self.m_threadpool->getThreadsCount();
+		Bool quit = false;
 
 
-		while(!self.m_quit)
+		while(!quit)
 		{
 		{
 			Threadpool::Task* task;
 			Threadpool::Task* task;
 
 
@@ -104,6 +106,8 @@ private:
 				}
 				}
 				task = self.m_task;
 				task = self.m_task;
 				self.m_task = nullptr;
 				self.m_task = nullptr;
+
+				quit = self.m_quit;
 			}
 			}
 
 
 			// Exec
 			// Exec
@@ -172,7 +176,7 @@ Threadpool::~Threadpool()
 		thread.m_quit = true;
 		thread.m_quit = true;
 		thread.assignNewTask(&m_dummyTask); // Wake it
 		thread.assignNewTask(&m_dummyTask); // Wake it
 	}
 	}
-
+	
 	Error err = waitForAllThreadsToFinish();
 	Error err = waitForAllThreadsToFinish();
 	(void)err;
 	(void)err;
 
 

+ 0 - 1
src/util/ThreadWindows.cpp

@@ -4,7 +4,6 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include "anki/util/Thread.h"
 #include "anki/util/Thread.h"
-#include "anki/util/Exception.h"
 #include <windows.h>
 #include <windows.h>
 
 
 namespace anki {
 namespace anki {

+ 73 - 49
testapp/Main.cpp

@@ -14,6 +14,7 @@
 #include "anki/script/ScriptManager.h"
 #include "anki/script/ScriptManager.h"
 #include "anki/core/StdinListener.h"
 #include "anki/core/StdinListener.h"
 #include "anki/resource/Model.h"
 #include "anki/resource/Model.h"
+#include "anki/resource/Script.h"
 #include "anki/util/Logger.h"
 #include "anki/util/Logger.h"
 #include "anki/Util.h"
 #include "anki/Util.h"
 #include "anki/resource/Skin.h"
 #include "anki/resource/Skin.h"
@@ -38,8 +39,9 @@ PerspectiveCamera* cam;
 
 
 
 
 //==============================================================================
 //==============================================================================
-void init()
+Error init()
 {
 {
+	Error err = ErrorCode::NONE;
 	ANKI_LOGI("Other init...");
 	ANKI_LOGI("Other init...");
 
 
 	SceneGraph& scene = app->getSceneGraph();
 	SceneGraph& scene = app->getSceneGraph();
@@ -60,7 +62,8 @@ void init()
 #endif
 #endif
 
 
 	// camera
 	// camera
-	cam = scene.newSceneNode<PerspectiveCamera>("main-camera");
+	err = scene.newSceneNode<PerspectiveCamera>("main-camera", cam);
+	if(err) return err;
 	const F32 ang = 45.0;
 	const F32 ang = 45.0;
 	cam->setAll(
 	cam->setAll(
 		renderer.getAspectRatio() * toRad(ang),
 		renderer.getAspectRatio() * toRad(ang),
@@ -79,7 +82,9 @@ void init()
 		{
 		{
 			std::string name = "plight" + std::to_string(i) + std::to_string(j);
 			std::string name = "plight" + std::to_string(i) + std::to_string(j);
 
 
-			PointLight* point = scene.newSceneNode<PointLight>(name.c_str());
+			PointLight* point;
+			err = scene.newSceneNode<PointLight>(name.c_str(), point);
+			if(err) return err;
 			point->setRadius(0.5);
 			point->setRadius(0.5);
 			point->setDiffuseColor(Vec4(randFloat(6.0) - 2.0, 
 			point->setDiffuseColor(Vec4(randFloat(6.0) - 2.0, 
 				randFloat(6.0) - 2.0, randFloat(6.0) - 2.0, 0.0));
 				randFloat(6.0) - 2.0, randFloat(6.0) - 2.0, 0.0));
@@ -96,7 +101,9 @@ void init()
 #endif
 #endif
 
 
 #if 1
 #if 1
-	SpotLight* spot = scene.newSceneNode<SpotLight>("spot0");
+	SpotLight* spot;
+	err = scene.newSceneNode<SpotLight>("spot0", spot);
+	if(err) return err;
 	spot->setOuterAngle(toRad(45.0));
 	spot->setOuterAngle(toRad(45.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setLocalTransform(Transform(Vec4(8.27936, 5.86285, 1.85526, 0.0),
 	spot->setLocalTransform(Transform(Vec4(8.27936, 5.86285, 1.85526, 0.0),
@@ -109,7 +116,8 @@ void init()
 #endif
 #endif
 
 
 #if 1
 #if 1
-	spot = scene.newSceneNode<SpotLight>("spot1");
+	err = scene.newSceneNode<SpotLight>("spot1", spot);
+	if(err) return err;
 	spot->setOuterAngle(toRad(45.0));
 	spot->setOuterAngle(toRad(45.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setInnerAngle(toRad(15.0));
 	spot->setLocalTransform(Transform(Vec4(5.3, 4.3, 3.0, 0.0),
 	spot->setLocalTransform(Transform(Vec4(5.3, 4.3, 3.0, 0.0),
@@ -131,8 +139,10 @@ void init()
 	{
 	{
 		Vec4 lightPos = vaseLightPos[i].xyz0();
 		Vec4 lightPos = vaseLightPos[i].xyz0();
 
 
-		PointLight* point = scene.newSceneNode<PointLight>(
-			("vase_plight" + std::to_string(i)).c_str());
+		PointLight* point;
+		err = scene.newSceneNode<PointLight>(
+			("vase_plight" + std::to_string(i)).c_str(), point);
+		if(err) return err;
 
 
 		point->loadLensFlare("textures/lens_flare/flares0.ankitex");
 		point->loadLensFlare("textures/lens_flare/flares0.ankitex");
 
 
@@ -144,46 +154,51 @@ void init()
 		point->setLensFlaresAlpha(1.0);
 		point->setLensFlaresAlpha(1.0);
 
 
 		LightEventData eventData;
 		LightEventData eventData;
-		eventData.radiusMultiplier = 0.2;
-		eventData.intensityMultiplier = Vec4(-1.2, 0.0, 0.0, 0.0);
-		eventData.specularIntensityMultiplier = Vec4(0.1, 0.1, 0.0, 0.0);
+		eventData.m_radiusMultiplier = 0.2;
+		eventData.m_intensityMultiplier = Vec4(-1.2, 0.0, 0.0, 0.0);
+		eventData.m_specularIntensityMultiplier = Vec4(0.1, 0.1, 0.0, 0.0);
 		LightEvent* event;
 		LightEvent* event;
-		scene.getEventManager().newEvent(event, 0.0, 0.8, point, eventData);
-		event->enableBits(Event::EF_REANIMATE);
+		err = scene.getEventManager().newEvent(event, 0.0, 0.8, point, eventData);
+		if(err) return err;
+		event->setReanimate(true);
 
 
 		MoveEventData moveData;
 		MoveEventData moveData;
 		moveData.m_posMin = Vec4(-0.5, 0.0, -0.5, 0);
 		moveData.m_posMin = Vec4(-0.5, 0.0, -0.5, 0);
 		moveData.m_posMax = Vec4(0.5, 0.0, 0.5, 0);
 		moveData.m_posMax = Vec4(0.5, 0.0, 0.5, 0);
 		MoveEvent* mevent;
 		MoveEvent* mevent;
 		scene.getEventManager().newEvent(mevent, 0.0, 2.0, point, moveData);
 		scene.getEventManager().newEvent(mevent, 0.0, 2.0, point, moveData);
-		mevent->enableBits(Event::EF_REANIMATE);
+		mevent->setReanimate(true);
 
 
 		ParticleEmitter* pe;
 		ParticleEmitter* pe;
 		/**/
 		/**/
 
 
 		if(i == 0)
 		if(i == 0)
 		{
 		{
-			pe = scene.newSceneNode<ParticleEmitter>(
-				"pefire", "particles/fire.ankipart");
+			err = scene.newSceneNode<ParticleEmitter>(
+				"pefire", pe, "particles/fire.ankipart");
+			if(err) return err;
 			pe->setLocalOrigin(lightPos);
 			pe->setLocalOrigin(lightPos);
 
 
-			pe = scene.newSceneNode<ParticleEmitter>(
-				"pesmoke", "particles/smoke.ankipart");
+			err = scene.newSceneNode<ParticleEmitter>(
+				"pesmoke", pe, "particles/smoke.ankipart");
+			if(err) return err;
 			pe->setLocalOrigin(lightPos);
 			pe->setLocalOrigin(lightPos);
 		}
 		}
 		else
 		else
 		{
 		{
 			InstanceNode* instance;
 			InstanceNode* instance;
-			instance = scene.newSceneNode<InstanceNode>( 
-				("pefire_inst" + std::to_string(i)).c_str());
+			err = scene.newSceneNode<InstanceNode>( 
+				("pefire_inst" + std::to_string(i)).c_str(), instance);
+			if(err) return err;
 
 
 			instance->setLocalOrigin(lightPos);
 			instance->setLocalOrigin(lightPos);
 
 
 			SceneNode& sn = scene.findSceneNode("pefire");
 			SceneNode& sn = scene.findSceneNode("pefire");
 			sn.addChild(instance);
 			sn.addChild(instance);
 
 
-			instance = scene.newSceneNode<InstanceNode>(
-				("pesmoke_inst" + std::to_string(i)).c_str());
+			err = scene.newSceneNode<InstanceNode>(
+				("pesmoke_inst" + std::to_string(i)).c_str(), instance);
+			if(err) return err;
 
 
 			instance->setLocalOrigin(lightPos);
 			instance->setLocalOrigin(lightPos);
 
 
@@ -200,7 +215,9 @@ void init()
 
 
 #if 1
 #if 1
 	// horse
 	// horse
-	horse = scene.newSceneNode<ModelNode>("horse", "models/horse/horse.ankimdl");
+	err = scene.newSceneNode<ModelNode>("horse", horse, 
+		"models/horse/horse.ankimdl");
+	if(err) return err;
 	horse->setLocalTransform(
 	horse->setLocalTransform(
 		Transform(Vec4(-2, 0, 0, 0.0), Mat3x4::getIdentity(), 0.7));
 		Transform(Vec4(-2, 0, 0, 0.0), Mat3x4::getIdentity(), 0.7));
 
 
@@ -218,13 +235,13 @@ void init()
 
 
 #if 1
 #if 1
 	{
 	{
-		String str(app->getAllocator());
-		File file;
-		file.open(
-			resources.fixResourceFilename("maps/sponza/scene.lua").toCString(), 
-			File::OpenFlag::READ);
-		file.readAllText(str);
-		app->getScriptManager().evalString(str.toCString());
+		ScriptResourcePointer script;
+
+		err = script.load("maps/sponza/scene.lua", &resources);
+		if(err) return err;
+
+		err = app->getScriptManager().evalString(script->getSource());
+		if(err) return err;
 	}
 	}
 #endif
 #endif
 
 
@@ -307,12 +324,14 @@ void execStdinScpripts()
 #endif
 #endif
 
 
 //==============================================================================
 //==============================================================================
-I32 mainLoopExtra(App& app, void*)
+Error mainLoopExtra(App& app, void*, Bool& quit)
 {
 {
+	Error err = ErrorCode::NONE;
 	F32 dist = 0.1;
 	F32 dist = 0.1;
 	F32 ang = toRad(2.5);
 	F32 ang = toRad(2.5);
 	F32 scale = 0.01;
 	F32 scale = 0.01;
 	F32 mouseSensivity = 9.0;
 	F32 mouseSensivity = 9.0;
+	quit = false;
 
 
 	SceneGraph& scene = app.getSceneGraph();
 	SceneGraph& scene = app.getSceneGraph();
 	Input& in = app.getInput();
 	Input& in = app.getInput();
@@ -320,7 +339,8 @@ I32 mainLoopExtra(App& app, void*)
 
 
 	if(in.getKey(KeyCode::ESCAPE))
 	if(in.getKey(KeyCode::ESCAPE))
 	{
 	{
-		return 1;
+		quit = true;
+		return err;
 	}
 	}
 
 
 	// move the camera
 	// move the camera
@@ -465,15 +485,18 @@ end)");
 
 
 	if(getenv("PROFILE") && getGlobTimestamp() == 2000)
 	if(getenv("PROFILE") && getGlobTimestamp() == 2000)
 	{
 	{
-		return 1;
+		quit = true;
+		return err;
 	}
 	}
 
 
-	return 0;
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
-void initSubsystems(int argc, char* argv[])
+Error initSubsystems(int argc, char* argv[])
 {
 {
+	Error err = ErrorCode::NONE;
+
 	// Config
 	// Config
 	Config config;
 	Config config;
 	config.set("ms.ez.enabled", false);
 	config.set("ms.ez.enabled", false);
@@ -514,34 +537,35 @@ void initSubsystems(int argc, char* argv[])
 	config.set("fullscreenDesktopResolution", true);
 	config.set("fullscreenDesktopResolution", true);
 	config.set("debugContext", false);
 	config.set("debugContext", false);
 
 
-	app = new App(config, allocAligned, nullptr);
+	app = new App;
+	err = app->create(config, allocAligned, nullptr);
+	if(err) return err;
 
 
 	// Input
 	// Input
 	app->getInput().lockCursor(true);
 	app->getInput().lockCursor(true);
 	app->getInput().hideCursor(true);
 	app->getInput().hideCursor(true);
 	app->getInput().moveCursor(Vec2(0.0));
 	app->getInput().moveCursor(Vec2(0.0));
+
+	return err;
 }
 }
 
 
 //==============================================================================
 //==============================================================================
 int main(int argc, char* argv[])
 int main(int argc, char* argv[])
 {
 {
-	int exitCode;
+	Error err = ErrorCode::NONE;
 
 
-	try
-	{
-		initSubsystems(argc, argv);
-		init();
-
-		app->mainLoop(mainLoopExtra, nullptr);
+	initSubsystems(argc, argv);
+	init();
 
 
-		ANKI_LOGI("Exiting...");
-		exitCode = 0;
+	err = app->mainLoop(mainLoopExtra, nullptr);
+	if(err)
+	{
+		ANKI_LOGE("Error reported. See previous messages");
 	}
 	}
-	catch(std::exception& e)
+	else
 	{
 	{
-		ANKI_LOGE("Aborting: %s", e.what());
-		exitCode = 1;
+		ANKI_LOGI("Bye!!");
 	}
 	}
-	ANKI_LOGI("Bye!!");
-	return exitCode;
+
+	return 0;
 }
 }

+ 4 - 18
tests/framework/Framework.cpp

@@ -154,15 +154,8 @@ Options:
 			for(Test* test : suite->tests)
 			for(Test* test : suite->tests)
 			{
 			{
 				++run;
 				++run;
-				try
-				{
-					test->run();
-					++passed;
-				}
-				catch(const std::exception& e)
-				{
-					std::cerr << e.what() << std::endl;
-				}
+				test->run();
+				++passed;
 			}
 			}
 		}
 		}
 	}
 	}
@@ -177,15 +170,8 @@ Options:
 					if(test->name == testName || testName.length() == 0)
 					if(test->name == testName || testName.length() == 0)
 					{
 					{
 						++run;
 						++run;
-						try
-						{
-							test->run();
-							++passed;
-						}
-						catch(const std::exception& e)
-						{
-							std::cerr << e.what() << std::endl;
-						}
+						test->run();
+						++passed;
 					}
 					}
 				}
 				}
 			}
 			}

+ 8 - 3
tests/framework/Framework.h

@@ -97,7 +97,7 @@ extern void deleteTesterSingleton();
 			ss << "FAILURE: " << #x << " != " << #y << " (" \
 			ss << "FAILURE: " << #x << " != " << #y << " (" \
 				<< file_ << ":" << line_ << ")"; \
 				<< file_ << ":" << line_ << ")"; \
 			fprintf(stderr, "%s\n", ss.str().c_str()); \
 			fprintf(stderr, "%s\n", ss.str().c_str()); \
-			throw std::runtime_error("Test faled"); \
+			abort(); \
 		} \
 		} \
 	} while(0);
 	} while(0);
 
 
@@ -109,7 +109,7 @@ extern void deleteTesterSingleton();
 			ss << "FAILURE: " << #x << " == " << #y << " (" \
 			ss << "FAILURE: " << #x << " == " << #y << " (" \
 				<< file_ << ":" << line_ << ")"; \
 				<< file_ << ":" << line_ << ")"; \
 			fprintf(stderr, "%s\n", ss.str().c_str()); \
 			fprintf(stderr, "%s\n", ss.str().c_str()); \
-			throw std::runtime_error("Test faled"); \
+			abort(); \
 		} \
 		} \
 	} while(0);
 	} while(0);
 
 
@@ -121,7 +121,7 @@ extern void deleteTesterSingleton();
 			ss << "FAILURE: " << #x << " != " << #y << " (" \
 			ss << "FAILURE: " << #x << " != " << #y << " (" \
 				<< file_ << ":" << line_ << ")"; \
 				<< file_ << ":" << line_ << ")"; \
 			fprintf(stderr, "%s\n", ss.str().c_str()); \
 			fprintf(stderr, "%s\n", ss.str().c_str()); \
-			throw std::runtime_error("Test faled"); \
+			abort(); \
 		} \
 		} \
 	} while(0);
 	} while(0);
 
 
@@ -137,6 +137,11 @@ extern void deleteTesterSingleton();
 #define ANKI_TEST_EXPECT_NEAR(x_, y_, e_) \
 #define ANKI_TEST_EXPECT_NEAR(x_, y_, e_) \
 	ANKI_TEST_EXPECT_NEAR_IMPL(__FILE__, __LINE__, __func__, x_, y_, e_)
 	ANKI_TEST_EXPECT_NEAR_IMPL(__FILE__, __LINE__, __func__, x_, y_, e_)
 
 
+/// Check error code.
+#define ANKI_TEST_EXPECT_NO_ERR(x_) \
+	ANKI_TEST_EXPECT_EQ_IMPL(__FILE__, __LINE__, __func__, x_, ErrorCode::NONE)
+
+
 } // end namespace anki
 } // end namespace anki
 
 
 #endif
 #endif

+ 33 - 16
tests/resource/AsyncLoader.cpp

@@ -27,7 +27,7 @@ public:
 		m_id(id)
 		m_id(id)
 	{}
 	{}
 
 
-	void operator()()
+	Error operator()()
 	{
 	{
 		if(m_count)
 		if(m_count)
 		{
 		{
@@ -37,9 +37,12 @@ public:
 			{
 			{
 				if(m_id != static_cast<I32>(x))
 				if(m_id != static_cast<I32>(x))
 				{
 				{
-					throw ANKI_EXCEPTION("Wrong excecution order");
+					ANKI_LOGE("Wrong excecution order");
+					return ErrorCode::FUNCTION_FAILED;
 				}
 				}
 			}
 			}
+
+			return ErrorCode::NONE;
 		}
 		}
 
 
 		if(m_sleepTime != 0.0)
 		if(m_sleepTime != 0.0)
@@ -51,6 +54,8 @@ public:
 		{
 		{
 			m_barrier->wait();
 			m_barrier->wait();
 		}
 		}
+
+		return ErrorCode::NONE;
 	}
 	}
 };
 };
 
 
@@ -66,9 +71,11 @@ public:
 		m_barrier(barrier)
 		m_barrier(barrier)
 	{}
 	{}
 
 
-	void operator()()
+	Error operator()()
 	{
 	{
 		void* mem = m_alloc.allocate(10);
 		void* mem = m_alloc.allocate(10);
+		if(!mem) return ErrorCode::FUNCTION_FAILED;
+
 		HighRezTimer::sleep(0.1);
 		HighRezTimer::sleep(0.1);
 
 
 		m_alloc.deallocate(mem, 10);
 		m_alloc.deallocate(mem, 10);
@@ -77,6 +84,8 @@ public:
 		{
 		{
 			m_barrier->wait();
 			m_barrier->wait();
 		}
 		}
+
+		return ErrorCode::NONE;
 	}
 	}
 };
 };
 
 
@@ -87,21 +96,24 @@ ANKI_TEST(Resource, AsyncLoader)
 
 
 	// Simple create destroy
 	// Simple create destroy
 	{
 	{
-		AsyncLoader a(alloc);
+		AsyncLoader a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc));
 	}
 	}
 
 
 	// Simple task that will finish
 	// Simple task that will finish
 	{
 	{
-		AsyncLoader a(alloc);
+		AsyncLoader a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc));
 		Barrier barrier(2);
 		Barrier barrier(2);
 
 
-		a.newTask<Task>(0.0, &barrier, nullptr);
+		ANKI_TEST_EXPECT_NO_ERR(a.newTask<Task>(0.0, &barrier, nullptr));
 		barrier.wait();
 		barrier.wait();
 	}
 	}
 
 
 	// Many tasks that will finish
 	// Many tasks that will finish
 	{
 	{
-		AsyncLoader a(alloc);
+		AsyncLoader a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc));
 		Barrier barrier(2);
 		Barrier barrier(2);
 		AtomicU32 counter = {0};
 		AtomicU32 counter = {0};
 
 
@@ -114,7 +126,7 @@ ANKI_TEST(Resource, AsyncLoader)
 				pbarrier = &barrier;
 				pbarrier = &barrier;
 			}
 			}
 
 
-			a.newTask<Task>(0.0, pbarrier, &counter);
+			ANKI_TEST_EXPECT_NO_ERR(a.newTask<Task>(0.0, pbarrier, &counter));
 		}
 		}
 
 
 		barrier.wait();
 		barrier.wait();
@@ -124,17 +136,19 @@ ANKI_TEST(Resource, AsyncLoader)
 
 
 	// Many tasks that will _not_ finish
 	// Many tasks that will _not_ finish
 	{
 	{
-		AsyncLoader a(alloc);
+		AsyncLoader a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc));
 
 
 		for(U i = 0; i < 100; i++)
 		for(U i = 0; i < 100; i++)
 		{
 		{
-			a.newTask<Task>(0.0, nullptr, nullptr);
+			ANKI_TEST_EXPECT_NO_ERR(a.newTask<Task>(0.0, nullptr, nullptr));
 		}
 		}
 	}
 	}
 
 
 	// Tasks that allocate
 	// Tasks that allocate
 	{
 	{
-		AsyncLoader a(alloc);
+		AsyncLoader a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc));
 		Barrier barrier(2);
 		Barrier barrier(2);
 
 
 		for(U i = 0; i < 10; i++)
 		for(U i = 0; i < 10; i++)
@@ -146,7 +160,7 @@ ANKI_TEST(Resource, AsyncLoader)
 				pbarrier = &barrier;
 				pbarrier = &barrier;
 			}
 			}
 
 
-			a.newTask<MemTask>(alloc, pbarrier);
+			ANKI_TEST_EXPECT_NO_ERR(a.newTask<MemTask>(alloc, pbarrier));
 		}
 		}
 
 
 		barrier.wait();
 		barrier.wait();
@@ -154,17 +168,19 @@ ANKI_TEST(Resource, AsyncLoader)
 
 
 	// Tasks that allocate and never finished
 	// Tasks that allocate and never finished
 	{
 	{
-		AsyncLoader a(alloc);
+		AsyncLoader a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc));
 
 
 		for(U i = 0; i < 10; i++)
 		for(U i = 0; i < 10; i++)
 		{
 		{
-			a.newTask<MemTask>(alloc, nullptr);
+			ANKI_TEST_EXPECT_NO_ERR(a.newTask<MemTask>(alloc, nullptr));
 		}
 		}
 	}
 	}
 
 
 	// Random struf
 	// Random struf
 	{
 	{
-		AsyncLoader a(alloc);
+		AsyncLoader a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc));
 		Barrier barrier(2);
 		Barrier barrier(2);
 		AtomicU32 counter = {0};
 		AtomicU32 counter = {0};
 
 
@@ -177,7 +193,8 @@ ANKI_TEST(Resource, AsyncLoader)
 				pbarrier = &barrier;
 				pbarrier = &barrier;
 			}
 			}
 
 
-			a.newTask<Task>(randRange(0.0, 0.5), pbarrier, &counter, i);
+			ANKI_TEST_EXPECT_NO_ERR(
+				a.newTask<Task>(randRange(0.0, 0.5), pbarrier, &counter, i));
 		}
 		}
 
 
 		barrier.wait();
 		barrier.wait();

+ 14 - 17
tests/resource/ResourceManager.cpp

@@ -20,8 +20,7 @@ ANKI_TEST(Resource, ResourceManager)
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 
 	GlDevice* gl = alloc.newInstance<GlDevice>();
 	GlDevice* gl = alloc.newInstance<GlDevice>();
-	Error err = gl->create(allocAligned, nullptr, "/tmp/");
-	ANKI_TEST_EXPECT_EQ(err, ErrorCode::NONE);
+	ANKI_TEST_EXPECT_NO_ERR(gl->create(allocAligned, nullptr, "/tmp/"));
 
 
 	ResourceManager::Initializer rinit;
 	ResourceManager::Initializer rinit;
 	rinit.m_gl = gl;
 	rinit.m_gl = gl;
@@ -29,13 +28,15 @@ ANKI_TEST(Resource, ResourceManager)
 	rinit.m_cacheDir = "/tmp/";
 	rinit.m_cacheDir = "/tmp/";
 	rinit.m_allocCallback = allocAligned;
 	rinit.m_allocCallback = allocAligned;
 	rinit.m_allocCallbackData = nullptr;
 	rinit.m_allocCallbackData = nullptr;
-	ResourceManager* resources = alloc.newInstance<ResourceManager>(rinit);
+	ResourceManager* resources = alloc.newInstance<ResourceManager>();
+	ANKI_TEST_EXPECT_NEQ(resources, nullptr);
+	ANKI_TEST_EXPECT_NO_ERR(resources->create(rinit));
 
 
 	// Load a resource
 	// Load a resource
 	{
 	{
 		DummyResourcePointer a;
 		DummyResourcePointer a;
 
 
-		a.load("blah", resources);
+		ANKI_TEST_EXPECT_NO_ERR(a.load("blah", resources));
 
 
 		{
 		{
 			DummyResourcePointer b = a;
 			DummyResourcePointer b = a;
@@ -47,11 +48,11 @@ ANKI_TEST(Resource, ResourceManager)
 	// Load and load again
 	// Load and load again
 	{
 	{
 		DummyResourcePointer a;
 		DummyResourcePointer a;
-		a.load("blah", resources);
+		ANKI_TEST_EXPECT_NO_ERR(a.load("blah", resources));
 		auto refcount = a.getReferenceCount();
 		auto refcount = a.getReferenceCount();
 
 
 		DummyResourcePointer b;
 		DummyResourcePointer b;
-		b.load("blah", resources);
+		ANKI_TEST_EXPECT_NO_ERR(b.load("blah", resources));
 		ANKI_TEST_EXPECT_EQ(b.getReferenceCount(), a.getReferenceCount());
 		ANKI_TEST_EXPECT_EQ(b.getReferenceCount(), a.getReferenceCount());
 		ANKI_TEST_EXPECT_EQ(a.getReferenceCount(), refcount + 1);
 		ANKI_TEST_EXPECT_EQ(a.getReferenceCount(), refcount + 1);
 
 
@@ -59,32 +60,28 @@ ANKI_TEST(Resource, ResourceManager)
 
 
 		// Again
 		// Again
 		DummyResourcePointer c;
 		DummyResourcePointer c;
-		c.load("blah", resources);
+		ANKI_TEST_EXPECT_NO_ERR(c.load("blah", resources));
 		ANKI_TEST_EXPECT_EQ(a.getReferenceCount(), refcount + 2);
 		ANKI_TEST_EXPECT_EQ(a.getReferenceCount(), refcount + 2);
 
 
 		// Load something else
 		// Load something else
 		DummyResourcePointer d;
 		DummyResourcePointer d;
-		d.load("blih", resources);
+		ANKI_TEST_EXPECT_NO_ERR(d.load("blih", resources));
 		ANKI_TEST_EXPECT_EQ(a.getReferenceCount(), refcount + 2);
 		ANKI_TEST_EXPECT_EQ(a.getReferenceCount(), refcount + 2);
 	}
 	}
 
 
 	// Exception
 	// Exception
 	{
 	{
-		try
 		{
 		{
 			DummyResourcePointer a;
 			DummyResourcePointer a;
-			a.load("exception", resources);
+			ANKI_TEST_EXPECT_EQ(
+				a.load("error", resources), ErrorCode::USER_DATA);
 		}
 		}
-		catch(...)
-		{}
 
 
-		DummyResourcePointer a;
-		try
 		{
 		{
-			a.load("exception", resources);
+			DummyResourcePointer a;
+			ANKI_TEST_EXPECT_EQ(
+				a.load("error", resources), ErrorCode::USER_DATA);
 		}
 		}
-		catch(...)
-		{}
 	}
 	}
 
 
 	// Delete
 	// Delete

+ 10 - 4
tests/script/LuaBinder.cpp

@@ -8,7 +8,10 @@
 #include "anki/Math.h"
 #include "anki/Math.h"
 
 
 static const char* script = R"(
 static const char* script = R"(
-b = Vec2.new(3.0, 4.0)
+b = Vec2.new()
+b:setX(3.0)
+b:setY(4.0)
+
 v2:copy(v2 * b)
 v2:copy(v2 * b)
 
 
 v3:setZ(0.1)
 v3:setZ(0.1)
@@ -16,16 +19,19 @@ v3:setZ(0.1)
 
 
 ANKI_TEST(Script, LuaBinder)
 ANKI_TEST(Script, LuaBinder)
 {
 {
-	HeapAllocator<U8> alloc(allocAligned, nullptr);
-	ScriptManager sm(alloc, nullptr);
+	ScriptManager sm;
+
+	ANKI_TEST_EXPECT_NO_ERR(sm.create(allocAligned, nullptr, nullptr));
 	Vec2 v2(2.0, 3.0);
 	Vec2 v2(2.0, 3.0);
 	Vec3 v3(1.1, 2.2, 3.3);
 	Vec3 v3(1.1, 2.2, 3.3);
 
 
+#if 0
 	sm.exposeVariable("v2", &v2);
 	sm.exposeVariable("v2", &v2);
 	sm.exposeVariable("v3", &v3);
 	sm.exposeVariable("v3", &v3);
 
 
-	sm.evalString(script);
+	ANKI_TEST_EXPECT_NO_ERR(sm.evalString(script));
 
 
 	ANKI_TEST_EXPECT_EQ(v2, Vec2(6, 12));
 	ANKI_TEST_EXPECT_EQ(v2, Vec2(6, 12));
 	ANKI_TEST_EXPECT_EQ(v3, Vec3(1.1, 2.2, 0.1));
 	ANKI_TEST_EXPECT_EQ(v3, Vec3(1.1, 2.2, 0.1));
+#endif
 }
 }

+ 80 - 63
tests/util/String.cpp

@@ -16,33 +16,46 @@ ANKI_TEST(Util, String)
 
 
 	// Copy
 	// Copy
 	{
 	{
-		String a("123", alloc);
-		String b(a);
+		String a, b;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc, "123"));
+		ANKI_TEST_EXPECT_NO_ERR(b.create(alloc, a));
+
 		ANKI_TEST_EXPECT_EQ(a, b);
 		ANKI_TEST_EXPECT_EQ(a, b);
 		ANKI_TEST_EXPECT_EQ(b, "123");
 		ANKI_TEST_EXPECT_EQ(b, "123");
 
 
-		b = "321";
-		a = b;
+		b.destroy(alloc);
+		a.destroy(alloc);
+		ANKI_TEST_EXPECT_NO_ERR(b.create(alloc, "321"));
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc, b));
+		ANKI_TEST_EXPECT_EQ(a, b);
 		ANKI_TEST_EXPECT_EQ(a, "321");
 		ANKI_TEST_EXPECT_EQ(a, "321");
+
+		b.destroy(alloc);
+		a.destroy(alloc);
 	}
 	}
 
 
+
 	// Move
 	// Move
 	{
 	{
-		String a("123", alloc);
+		String a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc, "123"));
 		String b(std::move(a));
 		String b(std::move(a));
 		ANKI_TEST_EXPECT_EQ(a.isEmpty(), true);
 		ANKI_TEST_EXPECT_EQ(a.isEmpty(), true);
 		ANKI_TEST_EXPECT_EQ(b, "123");
 		ANKI_TEST_EXPECT_EQ(b, "123");
 
 
-		b = "321";
+		b.destroy(alloc);
+		ANKI_TEST_EXPECT_NO_ERR(b.create(alloc, "321"));
 		a = std::move(b);
 		a = std::move(b);
 		ANKI_TEST_EXPECT_EQ(a, "321");
 		ANKI_TEST_EXPECT_EQ(a, "321");
 		ANKI_TEST_EXPECT_EQ(b.isEmpty(), true);
 		ANKI_TEST_EXPECT_EQ(b.isEmpty(), true);
+		a.destroy(alloc);
 	}
 	}
 
 
 	// Accessors
 	// Accessors
 	{
 	{
 		const char* s = "123";
 		const char* s = "123";
-		String a(s, alloc);
+		String a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc, s));
 		ANKI_TEST_EXPECT_EQ(a[0], '1');
 		ANKI_TEST_EXPECT_EQ(a[0], '1');
 		ANKI_TEST_EXPECT_EQ(a[1], '2');
 		ANKI_TEST_EXPECT_EQ(a[1], '2');
 		ANKI_TEST_EXPECT_EQ(a[2], '3');
 		ANKI_TEST_EXPECT_EQ(a[2], '3');
@@ -59,44 +72,39 @@ ANKI_TEST(Util, String)
 
 
 		ANKI_TEST_EXPECT_EQ(a.begin(), &a[0]);
 		ANKI_TEST_EXPECT_EQ(a.begin(), &a[0]);
 		ANKI_TEST_EXPECT_EQ(a.end(), &a[0] + 3);
 		ANKI_TEST_EXPECT_EQ(a.end(), &a[0] + 3);
+		a.destroy(alloc);
 	}
 	}
 
 
-	// Addition
-	{
-		String a(alloc);
-		String b(alloc);
-
-		a = "123";
-		b = String("456", alloc);
-
-		String c;
-		c = a + b;
-
-		ANKI_TEST_EXPECT_EQ(c, "123456");
-	}
 
 
 	// Append
 	// Append
 	{
 	{
-		String a(alloc);
-		String b("123", alloc);
+		String a, b;
 
 
-		a += b;
+		ANKI_TEST_EXPECT_NO_ERR(b.create(alloc, "123"));
+
+		ANKI_TEST_EXPECT_NO_ERR(a.append(alloc, b));
 		ANKI_TEST_EXPECT_EQ(a, "123");
 		ANKI_TEST_EXPECT_EQ(a, "123");
 
 
-		a += "456";
-		a += String("789", alloc);
-		a += String(alloc);
-		a += "";
-		a += "0";
+		ANKI_TEST_EXPECT_NO_ERR(a.append(alloc, "456789"));
+		ANKI_TEST_EXPECT_NO_ERR(a.append(alloc, String()));
+		ANKI_TEST_EXPECT_NO_ERR(a.append(alloc, ""));
+		ANKI_TEST_EXPECT_NO_ERR(a.append(alloc, "0"));
 		ANKI_TEST_EXPECT_EQ(a, "1234567890");
 		ANKI_TEST_EXPECT_EQ(a, "1234567890");
+		a.destroy(alloc);
+		b.destroy(alloc);
 	}
 	}
 
 
 	// Compare
 	// Compare
 	{
 	{
 #define COMPARE(x_, y_, op_) \
 #define COMPARE(x_, y_, op_) \
-	ANKI_TEST_EXPECT_EQ(String(x_, alloc) op_ String(y_, alloc), \
-	std::string(x_) op_ std::string(y_) )
-
+	ANKI_TEST_EXPECT_NO_ERR(a.append(alloc, x_)); \
+	ANKI_TEST_EXPECT_NO_ERR(b.append(alloc, y_)); \
+	ANKI_TEST_EXPECT_EQ(a op_ b, \
+	std::string(x_) op_ std::string(y_)) \
+	a.destroy(alloc); \
+	b.destroy(alloc); 
+	
+		String a, b;
 		COMPARE("123", "1233", <);
 		COMPARE("123", "1233", <);
 		COMPARE("0123", "1233", <=);
 		COMPARE("0123", "1233", <=);
 		COMPARE("ASDFA", "asdf90f", >);
 		COMPARE("ASDFA", "asdf90f", >);
@@ -107,92 +115,101 @@ ANKI_TEST(Util, String)
 
 
 	// sprintf
 	// sprintf
 	{
 	{
-		String a(alloc);
+		String a;
 
 
 		// Simple
 		// Simple
-		a.sprintf("12%c  %d", '3', 123);
+		ANKI_TEST_EXPECT_NO_ERR(a.sprintf(alloc, "12%c  %d", '3', 123));
 		ANKI_TEST_EXPECT_EQ(a, "123  123");
 		ANKI_TEST_EXPECT_EQ(a, "123  123");
+		a.destroy(alloc);
 
 
 		// Extreme
 		// Extreme
 		const char* s = "1234567890ABCDEF!@#$%^&*()_+asfghjkl:,.;ljk\"><{}[]/";
 		const char* s = "1234567890ABCDEF!@#$%^&*()_+asfghjkl:,.;ljk\"><{}[]/";
-		a.sprintf("%s%s%s%s%s%s%s%s%s%s%s %d", 
-			s, s, s, s, s, s, s, s, s, s, s, 88);
+		ANKI_TEST_EXPECT_NO_ERR(a.sprintf(alloc, "%s%s%s%s%s%s%s%s%s%s%s %d", 
+			s, s, s, s, s, s, s, s, s, s, s, 88));
 
 
-		String b(alloc);
+		String b;
 		for(U i = 0; i < 11; i++)
 		for(U i = 0; i < 11; i++)
 		{
 		{
-			b += s;
+			ANKI_TEST_EXPECT_NO_ERR(b.append(alloc, s));
 		}
 		}
-		b += " 88";
+		ANKI_TEST_EXPECT_NO_ERR(b.append(alloc, " 88"));
 
 
 		ANKI_TEST_EXPECT_EQ(a, b);
 		ANKI_TEST_EXPECT_EQ(a, b);
 		ANKI_TEST_EXPECT_EQ(a.getLength(), b.getLength());
 		ANKI_TEST_EXPECT_EQ(a.getLength(), b.getLength());
+
+		a.destroy(alloc);
+		b.destroy(alloc);
 	}
 	}
 
 
 	// sprintf #2: Smaller result (will trigger another path)
 	// sprintf #2: Smaller result (will trigger another path)
 	{
 	{
-		String a(alloc);
+		String a;
 
 
 		// Simple
 		// Simple
-		a.sprintf("12%c  %d", '3', 123);
+		ANKI_TEST_EXPECT_NO_ERR(a.sprintf(alloc, "12%c  %d", '3', 123));
 		ANKI_TEST_EXPECT_EQ(a, "123  123");
 		ANKI_TEST_EXPECT_EQ(a, "123  123");
+		a.destroy(alloc);
 
 
 		// Extreme
 		// Extreme
 		const char* s = "12345";
 		const char* s = "12345";
-		a.sprintf("%s%s %d", s, s, 88);
+		ANKI_TEST_EXPECT_NO_ERR(a.sprintf(alloc, "%s%s %d", s, s, 88));
 
 
-		String b(alloc);
+		String b;
 		for(U i = 0; i < 2; i++)
 		for(U i = 0; i < 2; i++)
 		{
 		{
-			b += s;
+			ANKI_TEST_EXPECT_NO_ERR(b.append(alloc, s));
 		}
 		}
-		b += " 88";
+		ANKI_TEST_EXPECT_NO_ERR(b.append(alloc, " 88"));
 
 
 		ANKI_TEST_EXPECT_EQ(a, b);
 		ANKI_TEST_EXPECT_EQ(a, b);
 		ANKI_TEST_EXPECT_EQ(a.getLength(), b.getLength());
 		ANKI_TEST_EXPECT_EQ(a.getLength(), b.getLength());
+
+		a.destroy(alloc);
+		b.destroy(alloc);
 	}
 	}
 
 
-	// Resize
+	// Other create
 	{
 	{
-		String a(alloc);
+		String a;
 
 
-		a.resize(3, '1');
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc, '1', 3));
 		ANKI_TEST_EXPECT_EQ(a, "111");
 		ANKI_TEST_EXPECT_EQ(a, "111");
+		ANKI_TEST_EXPECT_EQ(a.getLength(), 3);
 
 
-		a.resize(2, '2');
-		ANKI_TEST_EXPECT_EQ(a, "11");
-
-		a.resize(3, '3');
-		ANKI_TEST_EXPECT_EQ(a, "113");
-
-		a.resize(3, '?');
-		ANKI_TEST_EXPECT_EQ(a, "113");
-
-		a.resize(4, '4');
-		ANKI_TEST_EXPECT_EQ(a, "1134");
+		a.destroy(alloc);
 	}
 	}
 
 
 	// toString
 	// toString
 	{
 	{
-		String a(String::toString(123, alloc));
+		String a;
+		ANKI_TEST_EXPECT_NO_ERR(a.toString(alloc, 123));
 		ANKI_TEST_EXPECT_EQ(a, "123");
 		ANKI_TEST_EXPECT_EQ(a, "123");
+		a.destroy(alloc);
 
 
-		a = String::toString(123.123, alloc);
+		ANKI_TEST_EXPECT_NO_ERR(a.toString(alloc, 123.123));
 		ANKI_TEST_EXPECT_EQ(a, "123.123000");
 		ANKI_TEST_EXPECT_EQ(a, "123.123000");
+		a.destroy(alloc);
 	}
 	}
 
 
 	// To number
 	// To number
 	{
 	{
 		I64 i;
 		I64 i;
-		String("123456789", alloc).toI64(i);
+		String a;
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc, "123456789"));
+		ANKI_TEST_EXPECT_NO_ERR(a.toI64(i));
 		ANKI_TEST_EXPECT_EQ(i, 123456789);
 		ANKI_TEST_EXPECT_EQ(i, 123456789);
+		a.destroy(alloc);
 
 
-		String("-9223372036854775807", alloc).toI64(i);
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc, "-9223372036854775807"));
+		ANKI_TEST_EXPECT_NO_ERR(a.toI64(i));
 		ANKI_TEST_EXPECT_EQ(i, -9223372036854775807);
 		ANKI_TEST_EXPECT_EQ(i, -9223372036854775807);
+		a.destroy(alloc);
 
 
 		F64 f;
 		F64 f;
-		String("123456789.145", alloc).toF64(f);
+		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc, "123456789.145"));
+		ANKI_TEST_EXPECT_NO_ERR(a.toF64(f));
 		ANKI_TEST_EXPECT_EQ(f, 123456789.145);
 		ANKI_TEST_EXPECT_EQ(f, 123456789.145);
+		a.destroy(alloc);
 	}
 	}
 }
 }
 
 

+ 17 - 15
tests/util/Thread.cpp

@@ -20,7 +20,7 @@ ANKI_TEST(Util, Thread)
 	static const U64 NUMBER = 0xFAFAFAFABABABA;
 	static const U64 NUMBER = 0xFAFAFAFABABABA;
 	U64 u = NUMBER;
 	U64 u = NUMBER;
 
 
-	t.start(&u, [](Thread::Info& info) -> I
+	t.start(&u, [](Thread::Info& info) -> Error
 	{
 	{
 		Bool check = true; 
 		Bool check = true; 
 		
 		
@@ -36,11 +36,11 @@ ANKI_TEST(Util, Thread)
 
 
 		HighRezTimer::sleep(1.0);
 		HighRezTimer::sleep(1.0);
 
 
-		return check != true;
+		return (check != true) ? ErrorCode::FUNCTION_FAILED : ErrorCode::NONE;
 	});
 	});
 
 
 
 
-	I err = t.join();
+	Error err = t.join();
 	ANKI_TEST_EXPECT_EQ(err, 0);
 	ANKI_TEST_EXPECT_EQ(err, 0);
 	ANKI_TEST_EXPECT_EQ(u, 0xF00);
 	ANKI_TEST_EXPECT_EQ(u, 0xF00);
 }
 }
@@ -63,7 +63,7 @@ ANKI_TEST(Util, Mutex)
 	In in;
 	In in;
 	in.m_mtx = &mtx;
 	in.m_mtx = &mtx;
 
 
-	t0.start(&in, [](Thread::Info& info) -> I
+	t0.start(&in, [](Thread::Info& info) -> Error
 	{
 	{
 		In& in = *reinterpret_cast<In*>(info.m_userData);
 		In& in = *reinterpret_cast<In*>(info.m_userData);
 		I64& num = in.m_num;
 		I64& num = in.m_num;
@@ -76,10 +76,10 @@ ANKI_TEST(Util, Mutex)
 			mtx.unlock();
 			mtx.unlock();
 		}
 		}
 
 
-		return 0;
+		return ErrorCode::NONE;
 	});
 	});
 
 
-	t1.start(&in, [](Thread::Info& info) -> I
+	t1.start(&in, [](Thread::Info& info) -> Error
 	{
 	{
 		In& in = *reinterpret_cast<In*>(info.m_userData);
 		In& in = *reinterpret_cast<In*>(info.m_userData);
 		I64& num = in.m_num;
 		I64& num = in.m_num;
@@ -92,12 +92,12 @@ ANKI_TEST(Util, Mutex)
 			mtx.unlock();
 			mtx.unlock();
 		}
 		}
 
 
-		return 0;
+		return ErrorCode::NONE;
 	});
 	});
 
 
 
 
-	t0.join();
-	t1.join();
+	ANKI_TEST_EXPECT_NO_ERR(t0.join());
+	ANKI_TEST_EXPECT_NO_ERR(t1.join());
 
 
 	ANKI_TEST_EXPECT_EQ(in.m_num, ITERATIONS * 2);
 	ANKI_TEST_EXPECT_EQ(in.m_num, ITERATIONS * 2);
 }
 }
@@ -110,12 +110,14 @@ struct TestJobTP: Threadpool::Task
 	U32 in = 0;
 	U32 in = 0;
 	U32 iterations = 0;
 	U32 iterations = 0;
 
 
-	void operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
+	Error operator()(U32 /*threadId*/, PtrSize /*threadsCount*/)
 	{
 	{
 		for(U32 i = 0; i < iterations; i++)	
 		for(U32 i = 0; i < iterations; i++)	
 		{
 		{
 			++in;
 			++in;
 		}
 		}
+
+		return ErrorCode::NONE;
 	}
 	}
 };
 };
 
 
@@ -124,7 +126,7 @@ struct TestJobTP: Threadpool::Task
 ANKI_TEST(Util, Threadpool)
 ANKI_TEST(Util, Threadpool)
 {
 {
 	const U32 threadsCount = 4;
 	const U32 threadsCount = 4;
-	const U32 repeat = 500;
+	const U32 repeat = 5;
 	Threadpool* tp = new Threadpool(threadsCount);
 	Threadpool* tp = new Threadpool(threadsCount);
 
 
 	TestJobTP jobs[threadsCount];
 	TestJobTP jobs[threadsCount];
@@ -141,7 +143,7 @@ ANKI_TEST(Util, Threadpool)
 			tp->assignNewTask(j, &jobs[j]);
 			tp->assignNewTask(j, &jobs[j]);
 		}
 		}
 
 
-		tp->waitForAllThreadsToFinish();
+		ANKI_TEST_EXPECT_NO_ERR(tp->waitForAllThreadsToFinish());
 
 
 		for(U32 j = 0; j < threadsCount; j++)
 		for(U32 j = 0; j < threadsCount; j++)
 		{
 		{
@@ -160,15 +162,15 @@ ANKI_TEST(Util, Barrier)
 		Barrier b(2);
 		Barrier b(2);
 		Thread t(nullptr);
 		Thread t(nullptr);
 
 
-		t.start(&b, [](Thread::Info& info) -> I
+		t.start(&b, [](Thread::Info& info) -> Error
 		{
 		{
 			Barrier& b = *reinterpret_cast<Barrier*>(info.m_userData);
 			Barrier& b = *reinterpret_cast<Barrier*>(info.m_userData);
 			b.wait();
 			b.wait();
-			return 0;
+			return ErrorCode::NONE;
 		});
 		});
 
 
 		b.wait();
 		b.wait();
-		t.join();
+		ANKI_TEST_EXPECT_NO_ERR(t.join());
 	}
 	}
 }
 }
 
 

+ 1 - 1
thirdparty

@@ -1 +1 @@
-Subproject commit 00c2e2af187b5f2ead3c6c829a495d72d65acce5
+Subproject commit 5dead0e94f164d59066837a0eb89ec3685981ae7

+ 6 - 4
tools/scene/CMakeLists.txt

@@ -1,5 +1,7 @@
-INCLUDE_DIRECTORIES("../../thirdparty/assimp/include")
-	
-ADD_EXECUTABLE(ankisceneimp Main.cpp Model.cpp Animation.cpp Light.cpp 
+include_directories("../../thirdparty/assimp/include")
+
+add_definitions("-fexceptions")
+
+add_executable(ankisceneimp Main.cpp Model.cpp Animation.cpp Light.cpp 
 	Common.cpp)
 	Common.cpp)
-TARGET_LINK_LIBRARIES(ankisceneimp ankiassimp) 
+target_link_libraries(ankisceneimp ankiassimp) 

+ 8 - 8
tools/scene/Main.cpp

@@ -189,7 +189,7 @@ static void writeNodeTransform(const Exporter& exporter, std::ofstream& file,
 	pos[1] = m[1][3];
 	pos[1] = m[1][3];
 	pos[2] = m[2][3];
 	pos[2] = m[2][3];
 
 
-	file << "pos = Vec4.new()\n";
+	file << "local pos = Vec4.new()\n";
 	file << "pos:setX(" << pos[0] << ")\n";
 	file << "pos:setX(" << pos[0] << ")\n";
 	file << "pos:setY(" << pos[1] << ")\n";
 	file << "pos:setY(" << pos[1] << ")\n";
 	file << "pos:setZ(" << pos[2] << ")\n";
 	file << "pos:setZ(" << pos[2] << ")\n";
@@ -197,7 +197,7 @@ static void writeNodeTransform(const Exporter& exporter, std::ofstream& file,
 	file << node 
 	file << node 
 		<< ":getSceneNodeBase():getMoveComponent():setLocalOrigin(pos)\n";
 		<< ":getSceneNodeBase():getMoveComponent():setLocalOrigin(pos)\n";
 
 
-	file << "rot = Mat3x4.new()\n";
+	file << "local rot = Mat3x4.new()\n";
 	for(unsigned j = 0; j < 3; j++)
 	for(unsigned j = 0; j < 3; j++)
 	{
 	{
 		for(unsigned i = 0; i < 3; i++)
 		for(unsigned i = 0; i < 3; i++)
@@ -225,7 +225,7 @@ static void exportScene(Exporter& exporter)
 	std::ofstream file;
 	std::ofstream file;
 	file.open(exporter.outDir + "scene.lua");
 	file.open(exporter.outDir + "scene.lua");
 
 
-	file << "scene = Anki.getSceneGraph()\n";
+	file << "local scene = getSceneGraph()\n";
 
 
 	//
 	//
 	// Get all the data
 	// Get all the data
@@ -254,16 +254,16 @@ static void exportScene(Exporter& exporter)
 		std::string name = getModelName(exporter, model);
 		std::string name = getModelName(exporter, model);
 
 
 		// Write the main node
 		// Write the main node
-		file << "\nnode = scene:newModelNode(CString.new(\"" 
-			<< name << "\"), CString.new(\"" 
-			<< exporter.rpath << name << ".ankimdl" << "\"))\n"; 
+		file << "\nlocal node = scene:newModelNode(\"" 
+			<< name << "\", \"" 
+			<< exporter.rpath << name << ".ankimdl" << "\")\n"; 
 		writeNodeTransform(exporter, file, "node", node.transforms[0]);
 		writeNodeTransform(exporter, file, "node", node.transforms[0]);
 
 
 		// Write instance nodes
 		// Write instance nodes
 		for(unsigned j = 1; j < node.transforms.size(); j++)
 		for(unsigned j = 1; j < node.transforms.size(); j++)
 		{
 		{
-			file << "inst = scene:newInstanceNode(CString.new(\"" 
-				<< name << "_inst" << (j - 1) << "\"))\n"
+			file << "local inst = scene:newInstanceNode(\"" 
+				<< name << "_inst" << (j - 1) << "\")\n"
 				<< "node:getSceneNodeBase():addChild("
 				<< "node:getSceneNodeBase():addChild("
 				<< "inst:getSceneNodeBase())\n";
 				<< "inst:getSceneNodeBase())\n";