Browse Source

Removing exceptions

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
7ac24d42b0

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

@@ -8,6 +8,7 @@
 
 #include "anki/util/Exception.h"
 #include "anki/util/String.h"
+#include "anki/util/DArray.h"
 #include "anki/Math.h"
 #include <tinyxml2.h>
 #if !ANKI_TINYXML2
@@ -60,7 +61,8 @@ public:
 	ANKI_USE_RESULT Error getF64(F64& out) const;
 
 	/// Get a number of floats
-	Vector<F64, StackAllocator<F64>> getFloats() const;
+	ANKI_USE_RESULT Error getFloats(
+		DArray<F64, StackAllocator<F64>>& out) const;
 
 	/// Return the text inside as a Mat4
 	ANKI_USE_RESULT Error getMat4(Mat4& out) const;

+ 5 - 0
include/anki/scene/SceneObject.h

@@ -69,6 +69,11 @@ public:
 		return *m_scene;
 	}
 
+	ANKI_USE_RESULT Error addChild(SceneObject* obj)
+	{
+		return Base::addChild(getSceneAllocator(), obj);
+	}
+
 	const SceneGraph& getSceneGraph() const
 	{
 		return *m_scene;

+ 3 - 0
include/anki/util/List.h

@@ -288,6 +288,9 @@ public:
 	template<typename TFunc>
 	ANKI_USE_RESULT Error iterateBackward(TFunc func);
 
+	/// Find item.
+	Iterator find(const Value& a);
+
 	/// Quicksort.
 	template<typename TCompFunc = std::less<Value>>
 	void sort(TCompFunc compFunc = TCompFunc());

+ 19 - 0
include/anki/util/List.inl.h

@@ -281,5 +281,24 @@ void List<T, TAlloc>::erase(Allocator alloc, Iterator pos)
 	alloc.deleteInstance(node);
 }
 
+//==============================================================================
+template<typename T, typename TAlloc>
+typename List<T, TAlloc>::Iterator List<T, TAlloc>::find(const Value& a)
+{
+	Iterator it = getBegin();
+	Iterator end = getEnd();
+	while(it != end)
+	{
+		if(*it == a)
+		{
+			break;
+		}
+
+		++it;
+	}
+
+	return it;
+}
+
 } // end namespace anki
 

+ 27 - 120
include/anki/util/Object.h

@@ -7,7 +7,7 @@
 #define ANKI_UTIL_OBJECT_H
 
 #include "anki/util/Assert.h"
-#include "anki/util/Vector.h"
+#include "anki/util/List.h"
 #include "anki/util/StdTypes.h"
 #include "anki/util/Allocator.h"
 #include "anki/util/NonCopyable.h"
@@ -38,166 +38,72 @@ struct ObjectCallbackCollection
 };
 
 /// A hierarchical object
-template<typename T, typename Alloc = HeapAllocator<T>,
+template<typename T, typename TAlloc = HeapAllocator<T>,
 	typename TCallbackCollection = ObjectCallbackCollection<T>>
 class Object: public NonCopyable
 {
 public:
 	using Value = T;
-	using Container = Vector<Value*, Alloc>;
+	using Allocator = TAlloc;
+	using Container = List<Value*, Allocator>;
 	using CallbackCollection = TCallbackCollection;
 
-	/// Calls addChild if parent is not nullptr
-	///
-	/// @param parent The parent. Can be nullptr
-	/// @param alloc The allocator to use on internal allocations
 	/// @param callbacks A set of callbacks
-	Object(
-		Value* parent, 
-		const Alloc& alloc = Alloc(),
-		const CallbackCollection& callbacks = CallbackCollection())
-	:	m_parent(nullptr), // Set to nullptr or prepare for an assertion
-		m_children(alloc), 
+	Object(const CallbackCollection& callbacks = CallbackCollection())
+	:	m_parent(nullptr),
 		m_callbacks(callbacks)
-	{
-		if(parent != nullptr)
-		{
-			parent->addChild(getSelf());
-		}
-	}
+	{}
 
 	/// Delete children from the last entered to the first and update parent
 	virtual ~Object()
 	{
-		if(m_parent != nullptr)
-		{
-			m_parent->removeChild(getSelf());
-		}
-
-		// Remove all children (fast version)
-		for(Value* child : m_children)
-		{
-			child->m_parent = nullptr;
-
-			// Pass the parent as nullptr because at this point there is 
-			// nothing you should do with a deleteding parent
-			m_callbacks.onChildRemoved(child, nullptr);
-		}
+		ANKI_ASSERT(m_parent == nullptr && m_children.isEmpty()
+			&& "Requires manual desruction");
 	}
 
+	void destroy(Allocator alloc);
+
 	const Value* getParent() const
 	{
 		return m_parent;
 	}
+
 	Value* getParent()
 	{
 		return m_parent;
 	}
 
-	PtrSize getChildrenSize() const
-	{
-		return m_children.size();
-	}
-
 	Value& getChild(PtrSize i)
 	{
-		ANKI_ASSERT(i < m_children.size());
-		return *m_children[i];
-	}
-	const Value& getChild(PtrSize i) const
-	{
-		ANKI_ASSERT(i < m_children.size());
-		return *m_children[i];
+		return *(*(m_children.getBegin() + i));
 	}
 
-	Alloc getAllocator() const
+	const Value& getChild(PtrSize i) const
 	{
-		return m_children.get_allocator();
+		return *(*(m_children.getBegin() + i));
 	}
 
-	/// Add a new child
-	void addChild(Value* child)
-	{
-		ANKI_ASSERT(child != nullptr && "Null arg");
-		ANKI_ASSERT(child != getSelf() && "Cannot put itself");
-		ANKI_ASSERT(child->m_parent == nullptr && "Child already has parent");
-		ANKI_ASSERT(child->findChild(getSelf()) == child->m_children.end()
-			&& "Cyclic add");
-		ANKI_ASSERT(findChild(child) == m_children.end() && "Already a child");
-
-		child->m_parent = getSelf();
-		m_children.push_back(child);
-
-		m_callbacks.onChildAdded(child, getSelf());
-	}
+	/// Add a new child.
+	ANKI_USE_RESULT Error addChild(Allocator alloc, Value* child);
 
-	/// Remove a child
-	void removeChild(Value* child)
-	{
-		ANKI_ASSERT(child != nullptr && "Null arg");
-		ANKI_ASSERT(child->m_parent == getSelf() && "Child has other parent");
-
-		typename Container::iterator it = findChild(child);
-
-		ANKI_ASSERT(it != m_children.end() && "Child not found");
-
-		m_children.erase(it);
-		child->m_parent = nullptr;
-
-		m_callbacks.onChildRemoved(child, getSelf());
-	}
+	/// Remove a child.
+	void removeChild(Allocator alloc, Value* child);
 
 	/// Visit the children and the children's children. Use it with lambda
 	template<typename VisitorFunc>
-	void visitChildren(VisitorFunc vis)
-	{
-		for(Value* c : m_children)
-		{
-			vis(*c);
-			c->visitChildren(vis);
-		}
-	}
+	ANKI_USE_RESULT Error visitChildren(VisitorFunc vis);
 
 	/// Visit this object and move to the children. Use it with lambda
 	template<typename VisitorFunc>
-	void visitThisAndChildren(VisitorFunc vis)
-	{
-		vis(*getSelf());
-
-		visitChildren(vis);
-	}
+	ANKI_USE_RESULT Error visitThisAndChildren(VisitorFunc vis);
 
 	/// Visit the whole tree. Use it with lambda
 	template<typename VisitorFunc>
-	void visitTree(VisitorFunc vis)
-	{
-		// Move to root
-		Value* root = getSelf();
-		while(root->m_parent != nullptr)
-		{
-			root = root->m_parent;
-		}
-
-		root->visitThisAndChildren(vis);
-	}
+	ANKI_USE_RESULT Error visitTree(VisitorFunc vis);
 
 	/// Visit the children and limit the depth. Use it with lambda.
 	template<typename VisitorFunc>
-	void visitChildrenMaxDepth(I maxDepth, VisitorFunc vis)
-	{
-		ANKI_ASSERT(maxDepth >= 0);
-		--maxDepth;
-
-		for(Value* c : m_children)
-		{
-			vis(*c);
-
-			if(maxDepth >= 0)
-			{
-				c->visitChildrenMaxDepth(maxDepth, vis);
-			}
-		}
-	}
+	ANKI_USE_RESULT Error visitChildrenMaxDepth(I maxDepth, VisitorFunc vis);
 
 private:
 	Value* m_parent; ///< May be nullptr
@@ -211,10 +117,9 @@ private:
 	}
 
 	/// Find the child
-	typename Container::iterator findChild(Value* child)
+	typename Container::Iterator findChild(Value* child)
 	{
-		typename Container::iterator it =
-			std::find(m_children.begin(), m_children.end(), child);
+		typename Container::Iterator it = m_children.find(child);
 		return it;
 	}
 };
@@ -222,4 +127,6 @@ private:
 
 } // end namespace anki
 
+#include "anki/util/Object.inl.h"
+
 #endif

+ 150 - 0
include/anki/util/Object.inl.h

@@ -0,0 +1,150 @@
+// Copyright (C) 2014, Panagiotis Christopoulos Charitos.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+namespace anki {
+
+//==============================================================================
+template<typename T, typename TAlloc, typename TCallbackCollection>
+void Object<T, TAlloc, TCallbackCollection>::destroy(Allocator alloc)
+{
+	if(m_parent != nullptr)
+	{
+		m_parent->removeChild(alloc, getSelf());
+		m_parent = nullptr;
+	}
+
+	// Remove all children (fast version)
+	for(typename Container::Iterator it : m_children)
+	{
+		Value* child = *it;
+		child->m_parent = nullptr;
+
+		// Pass the parent as nullptr because at this point there is 
+		// nothing you should do with a deleteding parent
+		m_callbacks.onChildRemoved(child, nullptr);
+	}
+
+	m_children.destroy(alloc);
+}
+
+//==============================================================================
+template<typename T, typename TAlloc, typename TCallbackCollection>
+Error Object<T, TAlloc, TCallbackCollection>::addChild(
+	Allocator alloc, Value* child)
+{
+	ANKI_ASSERT(child != nullptr && "Null arg");
+	ANKI_ASSERT(child != getSelf() && "Cannot put itself");
+	ANKI_ASSERT(child->m_parent == nullptr && "Child already has parent");
+	ANKI_ASSERT(child->findChild(getSelf()) == child->m_children.getEnd()
+		&& "Cyclic add");
+	ANKI_ASSERT(findChild(child) == m_children.getEnd() 
+		&& "Already has that child");
+
+	child->m_parent = getSelf();
+	Error err = m_children.emplaceBack(alloc, child);
+
+	if(!err)
+	{
+		m_callbacks.onChildAdded(child, getSelf());
+	}
+
+	return err;
+}
+
+//==============================================================================
+template<typename T, typename TAlloc, typename TCallbackCollection>
+void Object<T, TAlloc, TCallbackCollection>::removeChild(
+	Allocator alloc, Value* child)
+{
+	ANKI_ASSERT(child != nullptr && "Null arg");
+	ANKI_ASSERT(child->m_parent == getSelf() && "Child has other parent");
+
+	typename Container::Iterator it = findChild(child);
+
+	ANKI_ASSERT(it != m_children.getEnd() && "Child not found");
+
+	m_children.erase(it);
+	child->m_parent = nullptr;
+
+	m_callbacks.onChildRemoved(child, getSelf());
+}
+
+//==============================================================================
+template<typename T, typename TAlloc, typename TCallbackCollection>
+template<typename VisitorFunc>
+Error Object<T, TAlloc, TCallbackCollection>::visitChildren(VisitorFunc vis)
+{
+	Error err = ErrorCode::NONE;
+	typename Container::Iterator it = m_children.getBegin();
+	for(; it != m_children.getEnd() && !err; it++)
+	{
+		err = vis(*(*it));
+
+		if(!err)
+		{
+			err = (*it)->visitChildren(vis);
+		}
+	}
+
+	return err;
+}
+
+//==============================================================================
+template<typename T, typename TAlloc, typename TCallbackCollection>
+template<typename VisitorFunc>
+Error Object<T, TAlloc, TCallbackCollection>::visitThisAndChildren(
+	VisitorFunc vis)
+{
+	Error err = vis(*getSelf());
+
+	if(!err)
+	{
+		err = visitChildren(vis);
+	}
+
+	return err;
+}
+
+//==============================================================================
+template<typename T, typename TAlloc, typename TCallbackCollection>
+template<typename VisitorFunc>
+Error Object<T, TAlloc, TCallbackCollection>::visitTree(VisitorFunc vis)
+{
+	// Move to root
+	Value* root = getSelf();
+	while(root->m_parent != nullptr)
+	{
+		root = root->m_parent;
+	}
+
+	return root->visitThisAndChildren(vis);
+}
+
+//==============================================================================
+template<typename T, typename TAlloc, typename TCallbackCollection>
+template<typename VisitorFunc>
+Error Object<T, TAlloc, TCallbackCollection>::visitChildrenMaxDepth(
+	I maxDepth, VisitorFunc vis)
+{
+	ANKI_ASSERT(maxDepth >= 0);
+	Error err = ErrorCode::NONE;
+	--maxDepth;
+
+	typename Container::Iterator it = m_children.getBegin();
+	for(; it != m_children.getEnd() && !err; ++it)
+	{
+		err = vis(*(*it));
+
+		if(!err && maxDepth >= 0)
+		{
+			err = (*it)->visitChildrenMaxDepth(maxDepth, vis);
+		}
+	}
+
+	return err;
+}
+
+} // end namespace anki
+

+ 30 - 13
include/anki/util/String.h

@@ -198,31 +198,48 @@ public:
 	}
 
 	/// Convert to F64.
-	F64 toF64() const
+	ANKI_USE_RESULT Error toF64(F64& out) const
 	{
 		checkInit();
-		F64 out = std::strtod(m_ptr, nullptr);
+		Error err = ErrorCode::NONE;
+		out = std::strtod(m_ptr, nullptr);
 
 		if(out == HUGE_VAL)
 		{
-			throw ANKI_EXCEPTION("Conversion failed");
+			ANKI_LOGE("Conversion failed");
+			err = ErrorCode::USER_DATA;
 		}
 
-		return out;
+		return err;
+	}
+
+	/// Convert to F32.
+	ANKI_USE_RESULT Error toF32(F32& out) const
+	{
+		F64 d;
+		Error err = toF64(d);
+		if(!err)
+		{
+			out = d;
+		}
+
+		return err;
 	}
 
 	/// Convert to I64.
-	I64 toI64() const
+	ANKI_USE_RESULT Error toI64(I64& out) const
 	{
 		checkInit();
-		I64 out = std::strtoll(m_ptr, nullptr, 10);
+		Error err = ErrorCode::NONE;
+		out = std::strtoll(m_ptr, nullptr, 10);
 
-		if(out == LLONG_MAX)
+		if(out == LLONG_MAX || out == LLONG_MIN)
 		{
-			throw ANKI_EXCEPTION("Conversion failed");
+			ANKI_LOGE("Conversion failed");
+			err = ErrorCode::USER_DATA;
 		}
 
-		return out;
+		return err;
 	}
 
 private:
@@ -639,15 +656,15 @@ public:
 	}
 
 	/// Convert to F64.
-	F64 toF64() const
+	ANKI_USE_RESULT Error toF64(F64& out) const
 	{
-		return toCString().toF64();
+		return toCString().toF64(out);
 	}
 
 	/// Convert to I64.
-	I64 toI64() const
+	ANKI_USE_RESULT Error toI64(I64& out) const
 	{
-		return toCString().toI64();
+		return toCString().toI64(out);
 	}
 
 private:

+ 72 - 75
src/misc/Xml.cpp

@@ -52,7 +52,7 @@ Error XmlElement::getI64(I64& out) const
 		const char* txt = m_el->GetText();
 		if(txt != nullptr)
 		{
-			out = CString(txt).toI64();
+			err = CString(txt).toI64(out);
 		}
 		else
 		{
@@ -74,7 +74,7 @@ Error XmlElement::getF64(F64& out) const
 		const char* txt = m_el->GetText();
 		if(txt != nullptr)
 		{
-			out = CString(txt).toF64();
+			err = CString(txt).toF64(out);
 		}
 		else
 		{
@@ -87,133 +87,130 @@ Error XmlElement::getF64(F64& out) const
 }
 
 //==============================================================================V
-Vector<F64, StackAllocator<F64>> XmlElement::getFloats() const
+Error XmlElement::getFloats(DArray<F64, StackAllocator<F64>>& out) const
 {
-	check();
-	const char* txt = m_el->GetText();
-	if(txt == nullptr)
+	Error err = check();
+	
+	const char* txt;
+	if(!err)
 	{
-		throw ANKI_EXCEPTION("Failed to return floats. Element: %s",
-			m_el->Value());
+		txt = m_el->GetText();
+		if(txt == nullptr)
+		{
+			err = ErrorCode::USER_DATA;
+		}
 	}
 
-	StringListBase<StackAllocator<char>> list(
-		StringListBase<StackAllocator<char>>::splitString(
-		CString(txt), ' ', m_alloc));
+	StringListBase<StackAllocator<char>> list;
+	if(!err)
+	{
+		 list = StringListBase<StackAllocator<char>>(
+			StringListBase<StackAllocator<char>>::splitString(
+			CString(txt), ' ', m_alloc));
 
-	Vector<F64, StackAllocator<F64>> out;
-	out.resize(list.size());
+		err = out.create(m_alloc, list.size());
+	}
 
-	try
+	for(U i = 0; i < out.getSize() && !err; i++)
 	{
-		for(U i = 0; i < out.size(); i++)
-		{
-			out[i] = list[i].toF64();
-		}
+		err = list[i].toF64(out[i]);
 	}
-	catch(const std::exception& e)
+
+	if(err)
 	{
-		throw ANKI_EXCEPTION("Found non-float element for vec of floats");
+		ANKI_LOGE("Failed to return floats. Element: %s", m_el->Value());
 	}
 
-	return out;
+	return err;
 }
 
 //==============================================================================
 Error XmlElement::getMat4(Mat4& out) const
 {
-	check();
+	DArray<F64, StackAllocator<F64>> arr;
+	Error err = getFloats(arr);	
 
-	const char* txt = m_el->GetText();
-	if(txt == nullptr)
+	if(!err && arr.getSize() != 16)
 	{
-		ANKI_LOGE("Failed to return Mat4");
-		return ErrorCode::USER_DATA;
+		ANKI_LOGE("Expecting 16 elements for Mat4");
+		err = ErrorCode::USER_DATA;
 	}
 
-	StringListBase<StackAllocator<char>> list = 
-		StringListBase<StackAllocator<char>>::splitString(
-		CString(txt), ' ', m_alloc);
-
-	if(list.size() != 16)
+	if(!err)
 	{
-		ANKI_LOGE("Expecting 16 elements for Mat4");
-		return ErrorCode::USER_DATA;
+		for(U i = 0; i < 16 && !err; i++)
+		{
+			out[i] = arr[i];
+		}
 	}
 
-	for(U i = 0; i < 16; i++)
+	arr.destroy(m_alloc);
+
+	if(err)
 	{
-		out[i] = list[i].toF64();
+		ANKI_LOGE("Failed to return Mat4. Element: %s", m_el->Value());
 	}
 
-	return ErrorCode::NONE;
+	return err;
 }
 
 //==============================================================================
 Error XmlElement::getVec3(Vec3& out) const
 {
-	Error err = check();
-	if(err)
+	DArray<F64, StackAllocator<F64>> arr;
+	Error err = getFloats(arr);
+	
+	if(!err && arr.getSize() != 3)
 	{
-		return err;
+		ANKI_LOGE("Expecting 3 elements for Vec3");
+		err = ErrorCode::USER_DATA;
 	}
 
-	const char* txt = m_el->GetText();
-	if(txt == nullptr)
+	if(!err)
 	{
-		ANKI_LOGE("Failed to return Vec3");
-		return ErrorCode::USER_DATA;
+		for(U i = 0; i < 3; i++)
+		{
+			out[i] = arr[i];
+		}
 	}
 
-	StringListBase<StackAllocator<char>> list = 
-		StringListBase<StackAllocator<char>>::splitString(
-		CString(txt), ' ', m_alloc);
-
-	if(list.size() != 3)
-	{
-		ANKI_LOGE("Expecting 3 elements for Vec3");
-		return ErrorCode::USER_DATA;
-	}
+	arr.destroy(m_alloc);
 
-	for(U i = 0; i < 3; i++)
+	if(err)
 	{
-		out[i] = list[i].toF64();
+		ANKI_LOGE("Failed to return Vec3. Element: %s", m_el->Value());
 	}
 	
-	return ErrorCode::NONE;
+	return err;
 }
 //==============================================================================
 Error XmlElement::getVec4(Vec4& out) const
 {
-	Error err = check();
-	if(err)
+	DArray<F64, StackAllocator<F64>> arr;
+	Error err = getFloats(arr);
+	
+	if(!err && arr.getSize() != 4)
 	{
-		return err;
+		ANKI_LOGE("Expecting 4 elements for Vec3");
+		err = ErrorCode::USER_DATA;
 	}
 
-	const char* txt = m_el->GetText();
-	if(txt == nullptr)
+	if(!err)
 	{
-		ANKI_LOGE("Failed to return Vec4");
-		return ErrorCode::USER_DATA;
+		for(U i = 0; i < 4; i++)
+		{
+			out[i] = arr[i];
+		}
 	}
 
-	StringListBase<StackAllocator<char>> list = 
-		StringListBase<StackAllocator<char>>::splitString(
-		CString(txt), ' ', m_alloc);
+	arr.destroy(m_alloc);
 
-	if(list.size() != 4)
-	{
-		ANKI_LOGE("Expecting 3 elements for Vec4");
-		return ErrorCode::USER_DATA;
-	}
-
-	for(U i = 0; i < 4; i++)
+	if(err)
 	{
-		out[i] = list[i].toF64();
+		ANKI_LOGE("Failed to return Vec4. Element: %s", m_el->Value());
 	}
-
-	return ErrorCode::NONE;
+	
+	return err;
 }
 
 //==============================================================================

+ 8 - 1
src/resource/Material.cpp

@@ -50,7 +50,14 @@ static MaterialVariable* newMaterialVariable(
 		floatvec.resize(floatsNeeded);
 		for(U i = 0; i < floatsNeeded; ++i)
 		{
-			floatvec[i] = in.m_value[i].toF64();
+			F64 d;
+			Error err = in.m_value[i].toF64(d);
+			if(err)
+			{
+				return nullptr;
+			}
+
+			floatvec[i] = d;
 		}
 
 		out = alloc.newInstance<MaterialVariableTemplate<T>>(

+ 1 - 1
src/scene/Light.cpp

@@ -107,7 +107,7 @@ void PointLight::frameUpdate(F32 prevUpdateTime, F32 crntTime)
 {
 	if(getShadowEnabled() && m_shadowData == nullptr)
 	{
-		m_shadowData = getAllocator().newInstance<ShadowData>(this);
+		m_shadowData = getSceneAllocator().newInstance<ShadowData>(this);
 
 		const F32 ang = toRad(90.0);
 		F32 dist = m_sphereW.getRadius();

+ 3 - 1
src/scene/ModelNode.cpp

@@ -216,7 +216,7 @@ void ModelNode::frameUpdate(F32, F32)
 	// Gather the move components of the instances
 	SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
 	Timestamp instancesTimestamp = 0;
-	SceneObject::visitChildren([&](SceneObject& obj)
+	SceneObject::visitChildren([&](SceneObject& obj) -> Error
 	{
 		if(obj.getType() == SceneNode::getClassType())
 		{
@@ -231,6 +231,8 @@ void ModelNode::frameUpdate(F32, F32)
 					std::max(instancesTimestamp, move.getTimestamp());
 			}
 		}
+
+		return ErrorCode::NONE;
 	});
 
 	// If having instances

+ 3 - 1
src/scene/MoveComponent.cpp

@@ -79,7 +79,7 @@ Bool MoveComponent::updateWorldTransform(SceneNode& node)
 	// whole tree because you will re-walk it later
 	if(dirty)
 	{
-		node.visitChildrenMaxDepth(1, [](SceneObject& obj)
+		node.visitChildrenMaxDepth(1, [](SceneObject& obj) -> Error
 		{
 			if(obj.getType() == SceneNode::getClassType())
 			{
@@ -91,6 +91,8 @@ Bool MoveComponent::updateWorldTransform(SceneNode& node)
 					mov.markForUpdate();
 				});
 			}
+
+			return ErrorCode::NONE;
 		});
 	}
 

+ 3 - 1
src/scene/ParticleEmitter.cpp

@@ -498,7 +498,7 @@ void ParticleEmitter::doInstancingCalcs()
 	// Gather the move components of the instances
 	SceneFrameVector<MoveComponent*> instanceMoves(getSceneFrameAllocator());
 	Timestamp instancesTimestamp = 0;
-	SceneObject::visitChildren([&](SceneObject& obj)
+	SceneObject::visitChildren([&](SceneObject& obj) -> Error
 	{	
 		if(obj.getType() == SceneObject::Type::SCENE_NODE)
 		{
@@ -513,6 +513,8 @@ void ParticleEmitter::doInstancingCalcs()
 					std::max(instancesTimestamp, move.getTimestamp());
 			}
 		}
+
+		return ErrorCode::NONE;
 	});
 
 	// If instancing

+ 3 - 1
src/scene/SceneGraph.cpp

@@ -53,13 +53,15 @@ public:
 		});
 
 		// Update children
-		node.visitChildren([&](SceneObject& obj)
+		node.visitChildren([&](SceneObject& obj) -> Error
 		{
 			if(obj.getType() == SceneObject::Type::SCENE_NODE)
 			{
 				SceneNode& child = obj.downCast<SceneNode>();
 				updateInternal(child, prevTime, crntTime);
 			}
+
+			return ErrorCode::NONE;
 		});
 
 		// Frame update

+ 9 - 2
src/scene/SceneObject.cpp

@@ -10,11 +10,17 @@ namespace anki {
 
 //==============================================================================
 SceneObject::SceneObject(Type type, SceneObject* parent, SceneGraph* scene)
-:	Base(parent, scene->getAllocator()),
+:	Base(),
 	m_scene(scene),
 	m_bits(static_cast<U8>(type))
 {
 	ANKI_ASSERT(m_scene);
+
+	// TODO Remove that
+	if(parent)
+	{
+		parent->addChild(this);
+	}
 }
 
 //==============================================================================
@@ -48,9 +54,10 @@ void SceneObject::markForDeletion()
 		m_scene->increaseObjectsMarkedForDeletion();
 	}
 
-	visitChildren([](SceneObject& obj)
+	visitChildren([](SceneObject& obj) -> Error
 	{
 		obj.markForDeletion();
+		return ErrorCode::NONE;
 	});
 }
 

+ 5 - 3
tests/util/String.cpp

@@ -183,13 +183,15 @@ ANKI_TEST(Util, String)
 
 	// To number
 	{
-		I64 i = String("123456789", alloc).toI64();
+		I64 i;
+		String("123456789", alloc).toI64(i);
 		ANKI_TEST_EXPECT_EQ(i, 123456789);
 
-		i = String("-9223372036854775807", alloc).toI64();
+		String("-9223372036854775807", alloc).toI64(i);
 		ANKI_TEST_EXPECT_EQ(i, -9223372036854775807);
 
-		F64 f = String("123456789.145", alloc).toF64();
+		F64 f;
+		String("123456789.145", alloc).toF64(f);
 		ANKI_TEST_EXPECT_EQ(f, 123456789.145);
 	}
 }