Browse Source

Add an additional event that executes scripts

Panagiotis Christopoulos Charitos 7 years ago
parent
commit
dbb04e2eae

+ 15 - 30
samples/physics_playground/Main.cpp

@@ -24,34 +24,6 @@ public:
 	}
 	}
 };
 };
 
 
-class DestroyBodyEvent : public Event
-{
-public:
-	DestroyBodyEvent(EventManager* events)
-		: Event(events)
-	{
-	}
-
-	Error init(Second duration, SceneNode* node)
-	{
-		Event::init(-1.0, duration);
-		m_associatedNodes.emplaceBack(getAllocator(), node);
-		return Error::NONE;
-	}
-
-	Error update(Second prevTime, Second crntTime) final
-	{
-		return Error::NONE;
-	}
-
-	Error onKilled(Second prevUpdateTime, Second crntTime, Bool& kill) final
-	{
-		m_associatedNodes[0]->setMarkedForDeletion();
-		kill = true;
-		return Error::NONE;
-	}
-};
-
 class MyApp : public SampleApp
 class MyApp : public SampleApp
 {
 {
 public:
 public:
@@ -203,8 +175,21 @@ Error MyApp::userMainLoop(Bool& quit)
 		body->addChild(monkey);
 		body->addChild(monkey);
 
 
 		// Create the destruction event
 		// Create the destruction event
-		DestroyBodyEvent* event;
-		ANKI_CHECK(getSceneGraph().getEventManager().newEvent(event, 10.0, body));
+		CString script = R"(
+function update(event, prevTime, crntTime)
+	-- Do nothing
+	return 1
+end
+
+function onKilled(event, prevTime, crntTime)
+	logi("onKilled")
+	event:getAssociatedSceneNodes():getAt(0):setMarkedForDeletion()
+	return 1
+end
+		)";
+		ScriptEvent* event;
+		ANKI_CHECK(getSceneGraph().getEventManager().newEvent(event, -1, 10.0, script));
+		event->addAssociatedSceneNode(body);
 	}
 	}
 
 
 	if(getInput().getMouseButton(MouseButton::RIGHT) == 1)
 	if(getInput().getMouseButton(MouseButton::RIGHT) == 1)

+ 2 - 1
src/anki/Scene.h

@@ -42,4 +42,5 @@
 #include <anki/scene/events/Event.h>
 #include <anki/scene/events/Event.h>
 #include <anki/scene/events/AnimationEvent.h>
 #include <anki/scene/events/AnimationEvent.h>
 #include <anki/scene/events/JitterMoveEvent.h>
 #include <anki/scene/events/JitterMoveEvent.h>
-#include <anki/scene/events/LightEvent.h>
+#include <anki/scene/events/LightEvent.h>
+#include <anki/scene/events/ScriptEvent.h>

+ 1 - 1
src/anki/gr/vulkan/GrManagerImpl.cpp

@@ -333,7 +333,7 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 		}
 		}
 	}
 	}
 
 
-#if ANKI_GR_MANAGER_DEBUG_MEMMORY
+#if 0 && ANKI_GR_MANAGER_DEBUG_MEMMORY
 	m_debugAllocCbs = {};
 	m_debugAllocCbs = {};
 	m_debugAllocCbs.pUserData = this;
 	m_debugAllocCbs.pUserData = this;
 	m_debugAllocCbs.pfnAllocation = allocateCallback;
 	m_debugAllocCbs.pfnAllocation = allocateCallback;

+ 15 - 3
src/anki/scene/events/Event.h

@@ -7,6 +7,7 @@
 
 
 #include <anki/scene/Common.h>
 #include <anki/scene/Common.h>
 #include <anki/util/List.h>
 #include <anki/util/List.h>
+#include <anki/util/WeakArray.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -74,6 +75,19 @@ public:
 		return m_reanimate;
 		return m_reanimate;
 	}
 	}
 
 
+	WeakArray<SceneNode*> getAssociatedSceneNodes()
+	{
+		return (m_associatedNodes.getSize() == 0)
+				   ? WeakArray<SceneNode*>()
+				   : WeakArray<SceneNode*>(&m_associatedNodes[0], m_associatedNodes.getSize());
+	}
+
+	void addAssociatedSceneNode(SceneNode* node)
+	{
+		ANKI_ASSERT(node);
+		m_associatedNodes.emplaceBack(getAllocator(), node);
+	}
+
 	/// This method should be implemented by the derived classes
 	/// This method should be implemented by the derived classes
 	/// @param prevUpdateTime The time of the previous update (sec)
 	/// @param prevUpdateTime The time of the previous update (sec)
 	/// @param crntTime The current time (sec)
 	/// @param crntTime The current time (sec)
@@ -82,12 +96,10 @@ public:
 	/// This is called when the event is killed
 	/// This is called when the event is killed
 	/// @param prevUpdateTime The time of the previous update (sec)
 	/// @param prevUpdateTime The time of the previous update (sec)
 	/// @param crntTime The current time (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(Second prevUpdateTime, Second crntTime, Bool& kill)
+	virtual ANKI_USE_RESULT Error onKilled(Second prevUpdateTime, Second crntTime)
 	{
 	{
 		(void)prevUpdateTime;
 		(void)prevUpdateTime;
 		(void)crntTime;
 		(void)crntTime;
-		kill = true;
 		return Error::NONE;
 		return Error::NONE;
 	}
 	}
 
 

+ 2 - 3
src/anki/scene/events/EventManager.cpp

@@ -99,9 +99,8 @@ Error EventManager::updateAllEvents(Second prevUpdateTime, Second crntTime)
 			}
 			}
 			else
 			else
 			{
 			{
-				Bool kill;
-				err = event.onKilled(prevUpdateTime, crntTime, kill);
-				if(!err && kill)
+				err = event.onKilled(prevUpdateTime, crntTime);
+				if(err || !event.getReanimate())
 				{
 				{
 					event.setMarkedForDeletion();
 					event.setMarkedForDeletion();
 				}
 				}

+ 1 - 1
src/anki/scene/events/LightEvent.h

@@ -11,7 +11,7 @@
 namespace anki
 namespace anki
 {
 {
 
 
-/// @addtogroup event
+/// @addtogroup scene
 /// @{
 /// @{
 
 
 /// An event for light animation
 /// An event for light animation

+ 136 - 0
src/anki/scene/events/ScriptEvent.cpp

@@ -0,0 +1,136 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/scene/events/ScriptEvent.h>
+#include <anki/util/Filesystem.h>
+#include <anki/resource/ScriptResource.h>
+#include <anki/script/ScriptEnvironment.h>
+#include <anki/script/ScriptManager.h>
+#include <anki/scene/SceneGraph.h>
+#include <anki/resource/ResourceManager.h>
+
+namespace anki
+{
+
+ScriptEvent::ScriptEvent(EventManager* manager)
+	: Event(manager)
+{
+}
+
+ScriptEvent::~ScriptEvent()
+{
+	m_script.destroy(getAllocator());
+}
+
+Error ScriptEvent::init(Second startTime, Second duration, CString script)
+{
+	Event::init(startTime, duration);
+
+	// Create the env
+	ANKI_CHECK(getSceneGraph().getScriptManager().newScriptEnvironment(m_env));
+
+	// Do the rest
+	String extension;
+	getFilepathExtension(script, getAllocator(), extension);
+
+	if(!extension.isEmpty() && extension == "lua")
+	{
+		// It's a file
+		ANKI_CHECK(getSceneGraph().getResourceManager().loadResource(script, m_scriptRsrc));
+
+		// Exec the script
+		ANKI_CHECK(m_env->evalString(m_scriptRsrc->getSource()));
+	}
+	else
+	{
+		// It's a string
+		m_script.create(getAllocator(), script);
+
+		// Exec the script
+		ANKI_CHECK(m_env->evalString(m_script.toCString()));
+	}
+
+	return Error::NONE;
+}
+
+Error ScriptEvent::update(Second prevUpdateTime, Second crntTime)
+{
+	lua_State* lua = &m_env->getLuaState();
+
+	// Push function name
+	lua_getglobal(lua, "update");
+
+	// Push args
+	LuaBinder::pushVariableToTheStack(lua, static_cast<Event*>(this));
+	lua_pushnumber(lua, prevUpdateTime);
+	lua_pushnumber(lua, crntTime);
+
+	// Do the call (3 arguments, 1 result)
+	if(lua_pcall(lua, 3, 1, 0) != 0)
+	{
+		ANKI_SCENE_LOGE("Error running ScriptEvent's \"update\": %s", lua_tostring(lua, -1));
+		return Error::USER_DATA;
+	}
+
+	if(!lua_isnumber(lua, -1))
+	{
+		ANKI_SCENE_LOGE("ScriptEvent's \"update\" should return a number");
+		lua_pop(lua, 1);
+		return Error::USER_DATA;
+	}
+
+	// Get the result
+	lua_Number result = lua_tonumber(lua, -1);
+	lua_pop(lua, 1);
+
+	if(result < 0)
+	{
+		ANKI_SCENE_LOGE("ScriptEvent's \"update\" return an error code");
+		return Error::USER_DATA;
+	}
+
+	return Error::NONE;
+}
+
+Error ScriptEvent::onKilled(Second prevUpdateTime, Second crntTime)
+{
+	lua_State* lua = &m_env->getLuaState();
+
+	// Push function name
+	lua_getglobal(lua, "onKilled");
+
+	// Push args
+	LuaBinder::pushVariableToTheStack(lua, static_cast<Event*>(this));
+	lua_pushnumber(lua, prevUpdateTime);
+	lua_pushnumber(lua, crntTime);
+
+	// Do the call (3 arguments, 1 result)
+	if(lua_pcall(lua, 3, 1, 0) != 0)
+	{
+		ANKI_SCENE_LOGE("Error running ScriptEvent's \"onKilled\": %s", lua_tostring(lua, -1));
+		return Error::USER_DATA;
+	}
+
+	if(!lua_isnumber(lua, -1))
+	{
+		ANKI_SCENE_LOGE("ScriptEvent's \"onKilled\" should return a number");
+		lua_pop(lua, 1);
+		return Error::USER_DATA;
+	}
+
+	// Get the result
+	lua_Number result = lua_tonumber(lua, -1);
+	lua_pop(lua, 1);
+
+	if(result < 0)
+	{
+		ANKI_SCENE_LOGE("ScriptEvent's \"onKilled\" return an error code");
+		return Error::USER_DATA;
+	}
+
+	return Error::NONE;
+}
+
+} // end namespace anki

+ 51 - 0
src/anki/scene/events/ScriptEvent.h

@@ -0,0 +1,51 @@
+// Copyright (C) 2009-2018, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/scene/events/Event.h>
+#include <anki/resource/Forward.h>
+#include <anki/script/Forward.h>
+
+namespace anki
+{
+
+/// @addtogroup scene
+/// @{
+
+/// A generic event that uses scripts. The script should contain something like this:
+/// @code
+/// function update(event, prevTime, crntTime)
+/// 	-- Do something
+/// 	return 1
+/// end
+///
+/// function onKilled(event, prevTime, crntTime)
+/// 	-- Do something
+/// 	return 1
+/// end
+/// @endcode
+class ScriptEvent : public Event
+{
+public:
+	ScriptEvent(EventManager* manager);
+
+	~ScriptEvent();
+
+	/// @param script It's a script or a filename to a script.
+	ANKI_USE_RESULT Error init(Second startTime, Second duration, CString script);
+
+	ANKI_USE_RESULT Error update(Second prevUpdateTime, Second crntTime) override;
+
+	ANKI_USE_RESULT Error onKilled(Second prevUpdateTime, Second crntTime) override;
+
+private:
+	ScriptResourcePtr m_scriptRsrc;
+	String m_script;
+	ScriptEnvironmentPtr m_env;
+};
+/// @}
+
+} // end namespace anki

+ 236 - 0
src/anki/script/Scene.cpp

@@ -59,6 +59,8 @@ static EventManager* getEventManager(lua_State* l)
 	return &getSceneGraph(l)->getEventManager();
 	return &getSceneGraph(l)->getEventManager();
 }
 }
 
 
+using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
+
 static const char* classnameMoveComponent = "MoveComponent";
 static const char* classnameMoveComponent = "MoveComponent";
 
 
 template<>
 template<>
@@ -1460,6 +1462,45 @@ static int wrapSceneNodeaddChild(lua_State* l)
 	return 0;
 	return 0;
 }
 }
 
 
+/// Pre-wrap method SceneNode::setMarkedForDeletion.
+static inline int pwrapSceneNodesetMarkedForDeletion(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	LuaBinder::checkArgsCount(l, 1);
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, classnameSceneNode, -2220074417980276571, ud))
+	{
+		return -1;
+	}
+
+	SceneNode* self = ud->getData<SceneNode>();
+
+	// Call the method
+	self->setMarkedForDeletion();
+
+	return 0;
+}
+
+/// Wrap method SceneNode::setMarkedForDeletion.
+static int wrapSceneNodesetMarkedForDeletion(lua_State* l)
+{
+	int res = pwrapSceneNodesetMarkedForDeletion(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
 /// Pre-wrap method SceneNode::tryGetComponent<MoveComponent>.
 /// Pre-wrap method SceneNode::tryGetComponent<MoveComponent>.
 static inline int pwrapSceneNodegetMoveComponent(lua_State* l)
 static inline int pwrapSceneNodegetMoveComponent(lua_State* l)
 {
 {
@@ -1670,6 +1711,7 @@ static inline void wrapSceneNode(lua_State* l)
 	LuaBinder::createClass(l, classnameSceneNode);
 	LuaBinder::createClass(l, classnameSceneNode);
 	LuaBinder::pushLuaCFuncMethod(l, "getName", wrapSceneNodegetName);
 	LuaBinder::pushLuaCFuncMethod(l, "getName", wrapSceneNodegetName);
 	LuaBinder::pushLuaCFuncMethod(l, "addChild", wrapSceneNodeaddChild);
 	LuaBinder::pushLuaCFuncMethod(l, "addChild", wrapSceneNodeaddChild);
+	LuaBinder::pushLuaCFuncMethod(l, "setMarkedForDeletion", wrapSceneNodesetMarkedForDeletion);
 	LuaBinder::pushLuaCFuncMethod(l, "getMoveComponent", wrapSceneNodegetMoveComponent);
 	LuaBinder::pushLuaCFuncMethod(l, "getMoveComponent", wrapSceneNodegetMoveComponent);
 	LuaBinder::pushLuaCFuncMethod(l, "getLightComponent", wrapSceneNodegetLightComponent);
 	LuaBinder::pushLuaCFuncMethod(l, "getLightComponent", wrapSceneNodegetLightComponent);
 	LuaBinder::pushLuaCFuncMethod(l, "getLensFlareComponent", wrapSceneNodegetLensFlareComponent);
 	LuaBinder::pushLuaCFuncMethod(l, "getLensFlareComponent", wrapSceneNodegetLensFlareComponent);
@@ -3446,6 +3488,198 @@ static inline void wrapSceneGraph(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
+static const char* classnameWeakArraySceneNodePtr = "WeakArraySceneNodePtr";
+
+template<>
+I64 LuaBinder::getWrappedTypeSignature<WeakArraySceneNodePtr>()
+{
+	return 4158963409681942864;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<WeakArraySceneNodePtr>()
+{
+	return classnameWeakArraySceneNodePtr;
+}
+
+/// Pre-wrap method WeakArraySceneNodePtr::getSize.
+static inline int pwrapWeakArraySceneNodePtrgetSize(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	LuaBinder::checkArgsCount(l, 1);
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, classnameWeakArraySceneNodePtr, 4158963409681942864, ud))
+	{
+		return -1;
+	}
+
+	WeakArraySceneNodePtr* self = ud->getData<WeakArraySceneNodePtr>();
+
+	// Call the method
+	PtrSize ret = self->getSize();
+
+	// Push return value
+	lua_pushnumber(l, ret);
+
+	return 1;
+}
+
+/// Wrap method WeakArraySceneNodePtr::getSize.
+static int wrapWeakArraySceneNodePtrgetSize(lua_State* l)
+{
+	int res = pwrapWeakArraySceneNodePtrgetSize(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method WeakArraySceneNodePtr::getAt.
+static inline int pwrapWeakArraySceneNodePtrgetAt(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	LuaBinder::checkArgsCount(l, 2);
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, classnameWeakArraySceneNodePtr, 4158963409681942864, ud))
+	{
+		return -1;
+	}
+
+	WeakArraySceneNodePtr* self = ud->getData<WeakArraySceneNodePtr>();
+
+	// Pop arguments
+	U arg0;
+	if(LuaBinder::checkNumber(l, 2, arg0))
+	{
+		return -1;
+	}
+
+	// Call the method
+	SceneNode* ret = (*self)[arg0];
+
+	// Push return value
+	if(ANKI_UNLIKELY(ret == nullptr))
+	{
+		lua_pushstring(l, "Glue code returned nullptr");
+		return -1;
+	}
+
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "SceneNode");
+	ud->initPointed(-2220074417980276571, const_cast<SceneNode*>(ret));
+
+	return 1;
+}
+
+/// Wrap method WeakArraySceneNodePtr::getAt.
+static int wrapWeakArraySceneNodePtrgetAt(lua_State* l)
+{
+	int res = pwrapWeakArraySceneNodePtrgetAt(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Wrap class WeakArraySceneNodePtr.
+static inline void wrapWeakArraySceneNodePtr(lua_State* l)
+{
+	LuaBinder::createClass(l, classnameWeakArraySceneNodePtr);
+	LuaBinder::pushLuaCFuncMethod(l, "getSize", wrapWeakArraySceneNodePtrgetSize);
+	LuaBinder::pushLuaCFuncMethod(l, "getAt", wrapWeakArraySceneNodePtrgetAt);
+	lua_settop(l, 0);
+}
+
+static const char* classnameEvent = "Event";
+
+template<>
+I64 LuaBinder::getWrappedTypeSignature<Event>()
+{
+	return 1660689530604735101;
+}
+
+template<>
+const char* LuaBinder::getWrappedTypeName<Event>()
+{
+	return classnameEvent;
+}
+
+/// Pre-wrap method Event::getAssociatedSceneNodes.
+static inline int pwrapEventgetAssociatedSceneNodes(lua_State* l)
+{
+	LuaUserData* ud;
+	(void)ud;
+	void* voidp;
+	(void)voidp;
+	PtrSize size;
+	(void)size;
+
+	LuaBinder::checkArgsCount(l, 1);
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, classnameEvent, 1660689530604735101, ud))
+	{
+		return -1;
+	}
+
+	Event* self = ud->getData<Event>();
+
+	// Call the method
+	WeakArraySceneNodePtr ret = self->getAssociatedSceneNodes();
+
+	// Push return value
+	size = LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>();
+	voidp = lua_newuserdata(l, size);
+	luaL_setmetatable(l, "WeakArraySceneNodePtr");
+	ud = static_cast<LuaUserData*>(voidp);
+	ud->initGarbageCollected(4158963409681942864);
+	::new(ud->getData<WeakArraySceneNodePtr>()) WeakArraySceneNodePtr(std::move(ret));
+
+	return 1;
+}
+
+/// Wrap method Event::getAssociatedSceneNodes.
+static int wrapEventgetAssociatedSceneNodes(lua_State* l)
+{
+	int res = pwrapEventgetAssociatedSceneNodes(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Wrap class Event.
+static inline void wrapEvent(lua_State* l)
+{
+	LuaBinder::createClass(l, classnameEvent);
+	LuaBinder::pushLuaCFuncMethod(l, "getAssociatedSceneNodes", wrapEventgetAssociatedSceneNodes);
+	lua_settop(l, 0);
+}
+
 static const char* classnameLightEvent = "LightEvent";
 static const char* classnameLightEvent = "LightEvent";
 
 
 template<>
 template<>
@@ -3770,6 +4004,8 @@ void wrapModuleScene(lua_State* l)
 	wrapOccluderNode(l);
 	wrapOccluderNode(l);
 	wrapDecalNode(l);
 	wrapDecalNode(l);
 	wrapSceneGraph(l);
 	wrapSceneGraph(l);
+	wrapWeakArraySceneNodePtr(l);
+	wrapEvent(l);
 	wrapLightEvent(l);
 	wrapLightEvent(l);
 	wrapEventManager(l);
 	wrapEventManager(l);
 	LuaBinder::pushLuaCFunc(l, "getSceneGraph", wrapgetSceneGraph);
 	LuaBinder::pushLuaCFunc(l, "getSceneGraph", wrapgetSceneGraph);

+ 26 - 1
src/anki/script/Scene.xml

@@ -59,6 +59,8 @@ static EventManager* getEventManager(lua_State* l)
 {
 {
 	return &getSceneGraph(l)->getEventManager();
 	return &getSceneGraph(l)->getEventManager();
 }
 }
+
+using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 ]]></head>
 ]]></head>
 
 
 	<classes>
 	<classes>
@@ -201,6 +203,7 @@ static EventManager* getEventManager(lua_State* l)
 						<arg>SceneNode*</arg>
 						<arg>SceneNode*</arg>
 					</args>
 					</args>
 				</method>
 				</method>
+				<method name="setMarkedForDeletion"></method>
 				<method name="tryGetComponent&lt;MoveComponent&gt;" alias="getMoveComponent">
 				<method name="tryGetComponent&lt;MoveComponent&gt;" alias="getMoveComponent">
 					<return>MoveComponent*</return>
 					<return>MoveComponent*</return>
 				</method>
 				</method>
@@ -430,13 +433,35 @@ static EventManager* getEventManager(lua_State* l)
 		</class>
 		</class>
 
 
 		<!-- Events -->
 		<!-- Events -->
+		<class name="WeakArraySceneNodePtr">
+			<methods>
+				<method name="getSize">
+					<return>PtrSize</return>
+				</method>
+				<method name="getAt">
+					<overrideCall><![CDATA[SceneNode* ret = (*self)[arg0];]]></overrideCall>
+					<args><arg>U</arg></args>
+					<return>SceneNode*</return>
+				</method>
+			</methods>
+		</class>
+		<class name="Event">
+			<methods>
+				<method name="getAssociatedSceneNodes">
+					<return>WeakArraySceneNodePtr</return>
+				</method>
+			</methods>
+		</class>
 		<class name="LightEvent">
 		<class name="LightEvent">
 			<methods>
 			<methods>
 				<method name="setIntensityMultiplier">
 				<method name="setIntensityMultiplier">
 					<args><arg>const Vec4&amp;</arg></args>
 					<args><arg>const Vec4&amp;</arg></args>
 				</method>
 				</method>
 				<method name="setFrequency">
 				<method name="setFrequency">
-					<args><arg>F32</arg><arg>F32</arg></args>
+					<args>
+						<arg>F32</arg>
+						<arg>F32</arg>
+					</args>
 				</method>
 				</method>
 			</methods>
 			</methods>
 		</class>
 		</class>