瀏覽代碼

Editor: Add the decal component UI

Panagiotis Christopoulos Charitos 1 周之前
父節點
當前提交
680db00c73

+ 0 - 3
AnKi/Core/App.cpp

@@ -367,21 +367,18 @@ Error App::mainLoop()
 	if((err = userPreInit()))
 	{
 		ANKI_CORE_LOGE("User initialization failed. Shutting down");
-		cleanup();
 		return err;
 	}
 
 	if((err = init()))
 	{
 		ANKI_CORE_LOGE("App initialization failed. Shutting down");
-		cleanup();
 		return err;
 	}
 
 	if((err = userPostInit()))
 	{
 		ANKI_CORE_LOGE("User initialization failed. Shutting down");
-		cleanup();
 		return err;
 	}
 

+ 77 - 0
AnKi/Editor/EditorUi.cpp

@@ -780,6 +780,9 @@ void EditorUi::sceneNodePropertiesWindow()
 					case SceneComponentType::kJoint:
 						jointComponent(static_cast<JointComponent&>(comp));
 						break;
+					case SceneComponentType::kDecal:
+						decalComponent(static_cast<DecalComponent&>(comp));
+						break;
 					default:
 						ImGui::Text("TODO");
 					}
@@ -1246,6 +1249,80 @@ void EditorUi::bodyComponent(BodyComponent& comp)
 	}
 }
 
+void EditorUi::decalComponent(DecalComponent& comp)
+{
+	if(!comp.isValid())
+	{
+		ImGui::SameLine();
+		ImGui::TextUnformatted(ICON_MDI_ALERT);
+		ImGui::SetItemTooltip("Component not valid");
+	}
+
+	ImGui::SeparatorText("Diffuse");
+
+	// Diffuse filename
+	{
+		ImGui::SetNextItemWidth(-1.0f);
+
+		Char buff[kMaxTextInputLen] = "";
+		if(comp.hasDiffuseImageResource())
+		{
+			std::strncpy(buff, comp.getDiffuseImageFilename().cstr(), sizeof(buff));
+		}
+
+		if(ImGui::InputTextWithHint("##DiffImgFname", ".ankitex Filename", buff, sizeof(buff)))
+		{
+			comp.setDiffuseImageFilename(buff);
+		}
+
+		if(comp.hasDiffuseImageResource())
+		{
+			ImGui::SetItemTooltip("%s", comp.getDiffuseImageFilename().cstr());
+		}
+	}
+
+	// Diffuse factor
+	ImGui::SetNextItemWidth(-1.0f);
+	F32 diffFactor = comp.getDiffuseBlendFactor();
+	if(ImGui::SliderFloat("##Factor0", &diffFactor, 0.0f, 1.0f))
+	{
+		comp.setDiffuseBlendFactor(diffFactor);
+	}
+	ImGui::SetItemTooltip("Blend Factor");
+
+	ImGui::SeparatorText("Roughness and Metallic");
+
+	// Roughness/metallic filename
+	{
+		ImGui::SetNextItemWidth(-1.0f);
+
+		Char buff[kMaxTextInputLen] = "";
+		if(comp.hasRoughnessMetalnessImageResource())
+		{
+			std::strncpy(buff, comp.getRoughnessMetalnessImageFilename().cstr(), sizeof(buff));
+		}
+
+		if(ImGui::InputTextWithHint("##RoughMetImgFname", ".ankitex Filename", buff, sizeof(buff)))
+		{
+			comp.setRoughnessMetalnessImageFilename(buff);
+		}
+
+		if(comp.hasRoughnessMetalnessImageResource())
+		{
+			ImGui::SetItemTooltip("%s", comp.getRoughnessMetalnessImageFilename().cstr());
+		}
+	}
+
+	// Roughness/metallic factor
+	ImGui::SetNextItemWidth(-1.0f);
+	F32 rmFactor = comp.getRoughnessMetalnessBlendFactor();
+	if(ImGui::SliderFloat("##Factor1", &rmFactor, 0.0f, 1.0f))
+	{
+		comp.setRoughnessMetalnessBlendFactor(rmFactor);
+	}
+	ImGui::SetItemTooltip("Blend Factor");
+}
+
 void EditorUi::cVarsWindow()
 {
 	if(!m_showCVarEditorWindow)

+ 1 - 0
AnKi/Editor/EditorUi.h

@@ -179,6 +179,7 @@ private:
 	void lightComponent(LightComponent& comp);
 	void jointComponent(JointComponent& comp);
 	void bodyComponent(BodyComponent& comp);
+	void decalComponent(DecalComponent& comp);
 	void dirTree(const AssetPath& path);
 
 	// Widget/UI utils

+ 2 - 2
AnKi/Importer/GltfImporter.cpp

@@ -809,7 +809,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 				ANKI_CHECK(getExtra(extras, "decal_diffuse_factor", extraValuef, extraFound));
 
 				ANKI_CHECK(
-					m_sceneFile.writeTextf("comp:loadDiffuseImageResource(\"%s\", %f)\n", extraValueStr.cstr(), (extraFound) ? extraValuef : 1.0f));
+					m_sceneFile.writeTextf("comp:setDiffuseImageFilename(\"%s\", %f)\n", extraValueStr.cstr(), (extraFound) ? extraValuef : 1.0f));
 			}
 
 			ANKI_CHECK(getExtra(extras, "decal_metal_roughness", extraValueStr, extraFound));
@@ -817,7 +817,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 			{
 				ANKI_CHECK(getExtra(extras, "decal_metal_roughness_factor", extraValuef, extraFound));
 
-				ANKI_CHECK(m_sceneFile.writeTextf("comp:loadMetalRoughnessImageResource(\"%s\", %f)\n", extraValueStr.cstr(),
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setMetalRoughnessImageFilename(\"%s\", %f)\n", extraValueStr.cstr(),
 												  (extraFound) ? extraValuef : 1.0f));
 			}
 

+ 25 - 12
AnKi/Scene/Components/DecalComponent.cpp

@@ -15,7 +15,8 @@ DecalComponent::DecalComponent(SceneNode* node)
 	: SceneComponent(node, kClassType)
 {
 	m_gpuSceneDecal.allocate();
-	loadDiffuseImageResource("EngineAssets/DefaultDecal.png", 0.9f);
+	setDiffuseImageFilename("EngineAssets/DefaultDecal.png");
+	setDiffuseBlendFactor(0.9f);
 
 	m_defaultDecalImage = m_layers[LayerType::kDiffuse].m_image;
 }
@@ -24,22 +25,34 @@ DecalComponent::~DecalComponent()
 {
 }
 
-void DecalComponent::setLayer(CString fname, F32 blendFactor, LayerType type)
+void DecalComponent::setImage(LayerType type, CString fname)
 {
-	Layer& l = m_layers[type];
-
 	ImageResourcePtr rsrc;
-	if(ResourceManager::getSingleton().loadResource(fname, rsrc))
+	if(ANKI_EXPECT(type < LayerType::kCount && !ResourceManager::getSingleton().loadResource(fname, rsrc)))
 	{
-		ANKI_SCENE_LOGE("Failed to load image");
-		return;
+		Layer& l = m_layers[type];
+		if(!l.m_image || rsrc->getUuid() != l.m_image->getUuid())
+		{
+			m_dirty = true;
+
+			l.m_image = std::move(rsrc);
+			l.m_bindlessTextureIndex = l.m_image->getTexture().getOrCreateBindlessTextureIndex(TextureSubresourceDesc::all());
+		}
 	}
+}
 
-	m_dirty = true;
-
-	l.m_image = std::move(rsrc);
-	l.m_bindlessTextureIndex = l.m_image->getTexture().getOrCreateBindlessTextureIndex(TextureSubresourceDesc::all());
-	l.m_blendFactor = clamp(blendFactor, 0.0f, 1.0f);
+void DecalComponent::setBlendFactor(LayerType type, F32 blendFactor)
+{
+	if(ANKI_EXPECT(type < LayerType::kCount))
+	{
+		Layer& l = m_layers[type];
+		blendFactor = saturate(blendFactor);
+		if(l.m_blendFactor != blendFactor)
+		{
+			l.m_blendFactor = blendFactor;
+			m_dirty = true;
+		}
+	}
 }
 
 void DecalComponent::update(SceneComponentUpdateInfo& info, Bool& updated)

+ 54 - 14
AnKi/Scene/Components/DecalComponent.h

@@ -12,35 +12,74 @@
 
 namespace anki {
 
-/// @addtogroup scene
-/// @{
-
-/// Decal component. Contains all the relevant info for a deferred decal.
+// Decal component. Contains all the relevant info for a deferred decal.
 class DecalComponent : public SceneComponent
 {
 	ANKI_SCENE_COMPONENT(DecalComponent)
 
 public:
-	static constexpr U32 kAtlasSubImageMargin = 16;
-
 	DecalComponent(SceneNode* node);
 
 	~DecalComponent();
 
-	Bool isEnabled() const
+	Bool isValid() const
 	{
 		return m_layers[LayerType::kDiffuse].m_bindlessTextureIndex != kMaxU32
 			   || m_layers[LayerType::kRoughnessMetalness].m_bindlessTextureIndex != kMaxU32;
 	}
 
-	void loadDiffuseImageResource(CString fname, F32 blendFactor)
+	DecalComponent& setDiffuseImageFilename(CString fname)
+	{
+		setImage(LayerType::kDiffuse, fname);
+		return *this;
+	}
+
+	CString getDiffuseImageFilename() const
+	{
+		return (m_layers[LayerType::kDiffuse].m_image) ? m_layers[LayerType::kDiffuse].m_image->getFilename() : "*Error*";
+	}
+
+	Bool hasDiffuseImageResource() const
+	{
+		return m_layers[LayerType::kDiffuse].m_bindlessTextureIndex != kMaxU32;
+	}
+
+	DecalComponent& setDiffuseBlendFactor(F32 f)
+	{
+		setBlendFactor(LayerType::kDiffuse, f);
+		return *this;
+	}
+
+	F32 getDiffuseBlendFactor() const
 	{
-		setLayer(fname, blendFactor, LayerType::kDiffuse);
+		return m_layers[LayerType::kDiffuse].m_blendFactor;
 	}
 
-	void loadMetalRoughnessImageResource(CString fname, F32 blendFactor)
+	DecalComponent& setRoughnessMetalnessImageFilename(CString fname)
 	{
-		setLayer(fname, blendFactor, LayerType::kRoughnessMetalness);
+		setImage(LayerType::kRoughnessMetalness, fname);
+		return *this;
+	}
+
+	CString getRoughnessMetalnessImageFilename() const
+	{
+		return (m_layers[LayerType::kRoughnessMetalness].m_image) ? m_layers[LayerType::kRoughnessMetalness].m_image->getFilename() : "*Error*";
+	}
+
+	Bool hasRoughnessMetalnessImageResource() const
+	{
+		return m_layers[LayerType::kRoughnessMetalness].m_bindlessTextureIndex != kMaxU32;
+	}
+
+	DecalComponent& setRoughnessMetalnessBlendFactor(F32 f)
+	{
+		setBlendFactor(LayerType::kRoughnessMetalness, f);
+		return *this;
+	}
+
+	F32 getRoughnessMetalnessBlendFactor() const
+	{
+		return m_layers[LayerType::kRoughnessMetalness].m_blendFactor;
 	}
 
 private:
@@ -59,7 +98,7 @@ private:
 		U32 m_bindlessTextureIndex = kMaxU32;
 	};
 
-	ImageResourcePtr m_defaultDecalImage; ///< Keep that loaded to avoid loading it all the time when a new decal is constructed.
+	ImageResourcePtr m_defaultDecalImage; // Keep that loaded to avoid loading it all the time when a new decal is constructed
 
 	Array<Layer, U(LayerType::kCount)> m_layers;
 
@@ -67,10 +106,11 @@ private:
 
 	Bool m_dirty = true;
 
-	void setLayer(CString fname, F32 blendFactor, LayerType type);
+	void setImage(LayerType type, CString fname);
+
+	void setBlendFactor(LayerType type, F32 blendFactor);
 
 	void update(SceneComponentUpdateInfo& info, Bool& updated) override;
 };
-/// @}
 
 } // end namespace anki

+ 247 - 43
AnKi/Script/Scene.cpp

@@ -40,7 +40,7 @@ static EventManager* getEventManager(lua_State* l)
 
 using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoLightComponentType = {500059253544827468, "LightComponentType", 0, nullptr, nullptr};
+LuaUserDataTypeInfo g_luaUserDataTypeInfoLightComponentType = {-5594775432067847771, "LightComponentType", 0, nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<LightComponentType>()
@@ -75,7 +75,7 @@ static inline void wrapLightComponentType(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoBodyComponentCollisionShapeType = {-6258057474314043911, "BodyComponentCollisionShapeType", 0, nullptr,
+LuaUserDataTypeInfo g_luaUserDataTypeInfoBodyComponentCollisionShapeType = {5886730633021150151, "BodyComponentCollisionShapeType", 0, nullptr,
 																			nullptr};
 
 template<>
@@ -119,7 +119,7 @@ static inline void wrapBodyComponentCollisionShapeType(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoParticleGeometryType = {2653659908218658077, "ParticleGeometryType", 0, nullptr, nullptr};
+LuaUserDataTypeInfo g_luaUserDataTypeInfoParticleGeometryType = {-1970280843451934837, "ParticleGeometryType", 0, nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ParticleGeometryType>()
@@ -150,7 +150,7 @@ static inline void wrapParticleGeometryType(lua_State* l)
 }
 
 LuaUserDataTypeInfo g_luaUserDataTypeInfoWeakArraySceneNodePtr = {
-	2562544859972501538, "WeakArraySceneNodePtr", LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>(), nullptr, nullptr};
+	3153302682457725628, "WeakArraySceneNodePtr", LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<WeakArraySceneNodePtr>()
@@ -241,7 +241,7 @@ static inline void wrapWeakArraySceneNodePtr(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoLightComponent = {-5754315097982438042, "LightComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoLightComponent = {-6661654181898649904, "LightComponent",
 														   LuaUserData::computeSizeForGarbageCollected<LightComponent>(), nullptr, nullptr};
 
 template<>
@@ -683,7 +683,7 @@ static inline void wrapLightComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoDecalComponent = {-8980488684929453085, "DecalComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoDecalComponent = {-5520034723432182506, "DecalComponent",
 														   LuaUserData::computeSizeForGarbageCollected<DecalComponent>(), nullptr, nullptr};
 
 template<>
@@ -692,14 +692,14 @@ const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<DecalComponent>()
 	return g_luaUserDataTypeInfoDecalComponent;
 }
 
-// Wrap method DecalComponent::loadDiffuseImageResource.
-static inline int wrapDecalComponentloadDiffuseImageResource(lua_State* l)
+// Wrap method DecalComponent::setDiffuseImageFilename.
+static inline int wrapDecalComponentsetDiffuseImageFilename(lua_State* l)
 {
 	[[maybe_unused]] LuaUserData* ud;
 	[[maybe_unused]] void* voidp;
 	[[maybe_unused]] PtrSize size;
 
-	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 3)) [[unlikely]]
+	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 2)) [[unlikely]]
 	{
 		return lua_error(l);
 	}
@@ -719,26 +719,125 @@ static inline int wrapDecalComponentloadDiffuseImageResource(lua_State* l)
 		return lua_error(l);
 	}
 
-	F32 arg1;
-	if(LuaBinder::checkNumber(l, ANKI_FILE, __LINE__, ANKI_FUNC, 3, arg1)) [[unlikely]]
+	// Call the method
+	DecalComponent& ret = self->setDiffuseImageFilename(arg0);
+
+	// Push return value
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "DecalComponent");
+	extern LuaUserDataTypeInfo g_luaUserDataTypeInfoDecalComponent;
+	ud->initPointed(&g_luaUserDataTypeInfoDecalComponent, &ret);
+
+	return 1;
+}
+
+// Wrap method DecalComponent::getDiffuseImageFilename.
+static inline int wrapDecalComponentgetDiffuseImageFilename(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1)) [[unlikely]]
 	{
 		return lua_error(l);
 	}
 
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1, g_luaUserDataTypeInfoDecalComponent, ud)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	DecalComponent* self = ud->getData<DecalComponent>();
+
 	// Call the method
-	self->loadDiffuseImageResource(arg0, arg1);
+	CString ret = self->getDiffuseImageFilename();
 
-	return 0;
+	// Push return value
+	lua_pushstring(l, &ret[0]);
+
+	return 1;
 }
 
-// Wrap method DecalComponent::loadMetalRoughnessImageResource.
-static inline int wrapDecalComponentloadMetalRoughnessImageResource(lua_State* l)
+// Wrap method DecalComponent::setDiffuseBlendFactor.
+static inline int wrapDecalComponentsetDiffuseBlendFactor(lua_State* l)
 {
 	[[maybe_unused]] LuaUserData* ud;
 	[[maybe_unused]] void* voidp;
 	[[maybe_unused]] PtrSize size;
 
-	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 3)) [[unlikely]]
+	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 2)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1, g_luaUserDataTypeInfoDecalComponent, ud)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	DecalComponent* self = ud->getData<DecalComponent>();
+
+	// Pop arguments
+	F32 arg0;
+	if(LuaBinder::checkNumber(l, ANKI_FILE, __LINE__, ANKI_FUNC, 2, arg0)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	// Call the method
+	DecalComponent& ret = self->setDiffuseBlendFactor(arg0);
+
+	// Push return value
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "DecalComponent");
+	extern LuaUserDataTypeInfo g_luaUserDataTypeInfoDecalComponent;
+	ud->initPointed(&g_luaUserDataTypeInfoDecalComponent, &ret);
+
+	return 1;
+}
+
+// Wrap method DecalComponent::getDiffuseBlendFactor.
+static inline int wrapDecalComponentgetDiffuseBlendFactor(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1, g_luaUserDataTypeInfoDecalComponent, ud)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	DecalComponent* self = ud->getData<DecalComponent>();
+
+	// Call the method
+	F32 ret = self->getDiffuseBlendFactor();
+
+	// Push return value
+	lua_pushnumber(l, lua_Number(ret));
+
+	return 1;
+}
+
+// Wrap method DecalComponent::setRoughnessMetalnessImageFilename.
+static inline int wrapDecalComponentsetRoughnessMetalnessImageFilename(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 2)) [[unlikely]]
 	{
 		return lua_error(l);
 	}
@@ -758,28 +857,133 @@ static inline int wrapDecalComponentloadMetalRoughnessImageResource(lua_State* l
 		return lua_error(l);
 	}
 
-	F32 arg1;
-	if(LuaBinder::checkNumber(l, ANKI_FILE, __LINE__, ANKI_FUNC, 3, arg1)) [[unlikely]]
+	// Call the method
+	DecalComponent& ret = self->setRoughnessMetalnessImageFilename(arg0);
+
+	// Push return value
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "DecalComponent");
+	extern LuaUserDataTypeInfo g_luaUserDataTypeInfoDecalComponent;
+	ud->initPointed(&g_luaUserDataTypeInfoDecalComponent, &ret);
+
+	return 1;
+}
+
+// Wrap method DecalComponent::getRoughnessMetalnessImageFilename.
+static inline int wrapDecalComponentgetRoughnessMetalnessImageFilename(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1)) [[unlikely]]
 	{
 		return lua_error(l);
 	}
 
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1, g_luaUserDataTypeInfoDecalComponent, ud)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	DecalComponent* self = ud->getData<DecalComponent>();
+
 	// Call the method
-	self->loadMetalRoughnessImageResource(arg0, arg1);
+	CString ret = self->getRoughnessMetalnessImageFilename();
 
-	return 0;
+	// Push return value
+	lua_pushstring(l, &ret[0]);
+
+	return 1;
+}
+
+// Wrap method DecalComponent::setRoughnessMetalnessBlendFactor.
+static inline int wrapDecalComponentsetRoughnessMetalnessBlendFactor(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 2)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1, g_luaUserDataTypeInfoDecalComponent, ud)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	DecalComponent* self = ud->getData<DecalComponent>();
+
+	// Pop arguments
+	F32 arg0;
+	if(LuaBinder::checkNumber(l, ANKI_FILE, __LINE__, ANKI_FUNC, 2, arg0)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	// Call the method
+	DecalComponent& ret = self->setRoughnessMetalnessBlendFactor(arg0);
+
+	// Push return value
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "DecalComponent");
+	extern LuaUserDataTypeInfo g_luaUserDataTypeInfoDecalComponent;
+	ud->initPointed(&g_luaUserDataTypeInfoDecalComponent, &ret);
+
+	return 1;
+}
+
+// Wrap method DecalComponent::getRoughnessMetalnessBlendFactor.
+static inline int wrapDecalComponentgetRoughnessMetalnessBlendFactor(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(LuaBinder::checkArgsCount(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, ANKI_FILE, __LINE__, ANKI_FUNC, 1, g_luaUserDataTypeInfoDecalComponent, ud)) [[unlikely]]
+	{
+		return lua_error(l);
+	}
+
+	DecalComponent* self = ud->getData<DecalComponent>();
+
+	// Call the method
+	F32 ret = self->getRoughnessMetalnessBlendFactor();
+
+	// Push return value
+	lua_pushnumber(l, lua_Number(ret));
+
+	return 1;
 }
 
 // Wrap class DecalComponent.
 static inline void wrapDecalComponent(lua_State* l)
 {
 	LuaBinder::createClass(l, &g_luaUserDataTypeInfoDecalComponent);
-	LuaBinder::pushLuaCFuncMethod(l, "loadDiffuseImageResource", wrapDecalComponentloadDiffuseImageResource);
-	LuaBinder::pushLuaCFuncMethod(l, "loadMetalRoughnessImageResource", wrapDecalComponentloadMetalRoughnessImageResource);
+	LuaBinder::pushLuaCFuncMethod(l, "setDiffuseImageFilename", wrapDecalComponentsetDiffuseImageFilename);
+	LuaBinder::pushLuaCFuncMethod(l, "getDiffuseImageFilename", wrapDecalComponentgetDiffuseImageFilename);
+	LuaBinder::pushLuaCFuncMethod(l, "setDiffuseBlendFactor", wrapDecalComponentsetDiffuseBlendFactor);
+	LuaBinder::pushLuaCFuncMethod(l, "getDiffuseBlendFactor", wrapDecalComponentgetDiffuseBlendFactor);
+	LuaBinder::pushLuaCFuncMethod(l, "setRoughnessMetalnessImageFilename", wrapDecalComponentsetRoughnessMetalnessImageFilename);
+	LuaBinder::pushLuaCFuncMethod(l, "getRoughnessMetalnessImageFilename", wrapDecalComponentgetRoughnessMetalnessImageFilename);
+	LuaBinder::pushLuaCFuncMethod(l, "setRoughnessMetalnessBlendFactor", wrapDecalComponentsetRoughnessMetalnessBlendFactor);
+	LuaBinder::pushLuaCFuncMethod(l, "getRoughnessMetalnessBlendFactor", wrapDecalComponentgetRoughnessMetalnessBlendFactor);
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoLensFlareComponent = {-9010711042401244097, "LensFlareComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoLensFlareComponent = {1436135364773864160, "LensFlareComponent",
 															   LuaUserData::computeSizeForGarbageCollected<LensFlareComponent>(), nullptr, nullptr};
 
 template<>
@@ -903,7 +1107,7 @@ static inline void wrapLensFlareComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoBodyComponent = {-1808713994974392597, "BodyComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoBodyComponent = {4859266942639207558, "BodyComponent",
 														  LuaUserData::computeSizeForGarbageCollected<BodyComponent>(), nullptr, nullptr};
 
 template<>
@@ -1089,7 +1293,7 @@ static inline void wrapBodyComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoTriggerComponent = {8480637138822006110, "TriggerComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoTriggerComponent = {-8532250760246815794, "TriggerComponent",
 															 LuaUserData::computeSizeForGarbageCollected<TriggerComponent>(), nullptr, nullptr};
 
 template<>
@@ -1177,7 +1381,7 @@ static inline void wrapTriggerComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoFogDensityComponent = {442223863329677979, "FogDensityComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoFogDensityComponent = {-6273562933061222924, "FogDensityComponent",
 																LuaUserData::computeSizeForGarbageCollected<FogDensityComponent>(), nullptr, nullptr};
 
 template<>
@@ -1257,7 +1461,7 @@ static inline void wrapFogDensityComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoCameraComponent = {-8246053165735489426, "CameraComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoCameraComponent = {5614357661140762094, "CameraComponent",
 															LuaUserData::computeSizeForGarbageCollected<CameraComponent>(), nullptr, nullptr};
 
 template<>
@@ -1326,7 +1530,7 @@ static inline void wrapCameraComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo g_luaUserDataTypeInfoGlobalIlluminationProbeComponent = {
-	-8370548681073261698, "GlobalIlluminationProbeComponent", LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeComponent>(),
+	-3401910529701313771, "GlobalIlluminationProbeComponent", LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeComponent>(),
 	nullptr, nullptr};
 
 template<>
@@ -1471,7 +1675,7 @@ static inline void wrapGlobalIlluminationProbeComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo g_luaUserDataTypeInfoReflectionProbeComponent = {
-	-749342065311431559, "ReflectionProbeComponent", LuaUserData::computeSizeForGarbageCollected<ReflectionProbeComponent>(), nullptr, nullptr};
+	1875218110388114974, "ReflectionProbeComponent", LuaUserData::computeSizeForGarbageCollected<ReflectionProbeComponent>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ReflectionProbeComponent>()
@@ -1487,7 +1691,7 @@ static inline void wrapReflectionProbeComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo g_luaUserDataTypeInfoParticleEmitterComponent = {
-	-6324147425669031594, "ParticleEmitterComponent", LuaUserData::computeSizeForGarbageCollected<ParticleEmitterComponent>(), nullptr, nullptr};
+	2925717460779801052, "ParticleEmitterComponent", LuaUserData::computeSizeForGarbageCollected<ParticleEmitterComponent>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ParticleEmitterComponent>()
@@ -1537,7 +1741,7 @@ static inline void wrapParticleEmitterComponent(lua_State* l)
 }
 
 LuaUserDataTypeInfo g_luaUserDataTypeInfoParticleEmitter2Component = {
-	-6428473293581697754, "ParticleEmitter2Component", LuaUserData::computeSizeForGarbageCollected<ParticleEmitter2Component>(), nullptr, nullptr};
+	5715853988873556419, "ParticleEmitter2Component", LuaUserData::computeSizeForGarbageCollected<ParticleEmitter2Component>(), nullptr, nullptr};
 
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ParticleEmitter2Component>()
@@ -1701,7 +1905,7 @@ static inline void wrapParticleEmitter2Component(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoMeshComponent = {-5886906078203910994, "MeshComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoMeshComponent = {7129233230963760247, "MeshComponent",
 														  LuaUserData::computeSizeForGarbageCollected<MeshComponent>(), nullptr, nullptr};
 
 template<>
@@ -1758,7 +1962,7 @@ static inline void wrapMeshComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoMaterialComponent = {4307950519165030427, "MaterialComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoMaterialComponent = {-5240416883337639304, "MaterialComponent",
 															  LuaUserData::computeSizeForGarbageCollected<MaterialComponent>(), nullptr, nullptr};
 
 template<>
@@ -1856,7 +2060,7 @@ static inline void wrapMaterialComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoSkinComponent = {-8305467920182704546, "SkinComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoSkinComponent = {3016724804384428667, "SkinComponent",
 														  LuaUserData::computeSizeForGarbageCollected<SkinComponent>(), nullptr, nullptr};
 
 template<>
@@ -1913,7 +2117,7 @@ static inline void wrapSkinComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoSkyboxComponent = {810469901655694713, "SkyboxComponent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoSkyboxComponent = {-3538427196989067145, "SkyboxComponent",
 															LuaUserData::computeSizeForGarbageCollected<SkyboxComponent>(), nullptr, nullptr};
 
 template<>
@@ -2274,7 +2478,7 @@ static inline void wrapSkyboxComponent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoSceneNode = {-7577845182840444439, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(),
+LuaUserDataTypeInfo g_luaUserDataTypeInfoSceneNode = {-1325538657283171084, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(),
 													  nullptr, nullptr};
 
 template<>
@@ -3750,7 +3954,7 @@ static inline void wrapSceneNode(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoSceneGraph = {-81513401149441617, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(),
+LuaUserDataTypeInfo g_luaUserDataTypeInfoSceneGraph = {8901208207670225695, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(),
 													   nullptr, nullptr};
 
 template<>
@@ -3896,7 +4100,7 @@ static inline void wrapSceneGraph(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoEvent = {-4301901788827764407, "Event", LuaUserData::computeSizeForGarbageCollected<Event>(), nullptr,
+LuaUserDataTypeInfo g_luaUserDataTypeInfoEvent = {-7252054505959214788, "Event", LuaUserData::computeSizeForGarbageCollected<Event>(), nullptr,
 												  nullptr};
 
 template<>
@@ -3948,7 +4152,7 @@ static inline void wrapEvent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoLightEvent = {-4171269143232873120, "LightEvent", LuaUserData::computeSizeForGarbageCollected<LightEvent>(),
+LuaUserDataTypeInfo g_luaUserDataTypeInfoLightEvent = {-8586733957439759552, "LightEvent", LuaUserData::computeSizeForGarbageCollected<LightEvent>(),
 													   nullptr, nullptr};
 
 template<>
@@ -4041,7 +4245,7 @@ static inline void wrapLightEvent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoScriptEvent = {-1360916742028316670, "ScriptEvent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoScriptEvent = {3521092713286297735, "ScriptEvent",
 														LuaUserData::computeSizeForGarbageCollected<ScriptEvent>(), nullptr, nullptr};
 
 template<>
@@ -4057,7 +4261,7 @@ static inline void wrapScriptEvent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoJitterMoveEvent = {5365643697589966891, "JitterMoveEvent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoJitterMoveEvent = {-8794680355368287829, "JitterMoveEvent",
 															LuaUserData::computeSizeForGarbageCollected<JitterMoveEvent>(), nullptr, nullptr};
 
 template<>
@@ -4119,7 +4323,7 @@ static inline void wrapJitterMoveEvent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoAnimationEvent = {-6541151698016447688, "AnimationEvent",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoAnimationEvent = {-8172624010586710412, "AnimationEvent",
 														   LuaUserData::computeSizeForGarbageCollected<AnimationEvent>(), nullptr, nullptr};
 
 template<>
@@ -4135,7 +4339,7 @@ static inline void wrapAnimationEvent(lua_State* l)
 	lua_settop(l, 0);
 }
 
-LuaUserDataTypeInfo g_luaUserDataTypeInfoEventManager = {-6168092957409596379, "EventManager",
+LuaUserDataTypeInfo g_luaUserDataTypeInfoEventManager = {1713399154262730355, "EventManager",
 														 LuaUserData::computeSizeForGarbageCollected<EventManager>(), nullptr, nullptr};
 
 template<>

+ 26 - 2
AnKi/Script/Scene.xml

@@ -138,17 +138,41 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 
 		<class name="DecalComponent">
 			<methods>
-				<method name="loadDiffuseImageResource">
+				<method name="setDiffuseImageFilename">
 					<args>
 						<arg>CString</arg>
+					</args>
+					<return>DecalComponent&amp;</return>
+				</method>
+				<method name="getDiffuseImageFilename">
+					<return>CString</return>
+				</method>
+				<method name="setDiffuseBlendFactor">
+					<args>
 						<arg>F32</arg>
 					</args>
+					<return>DecalComponent&amp;</return>
+				</method>
+				<method name="getDiffuseBlendFactor">
+					<return>F32</return>
 				</method>
-				<method name="loadMetalRoughnessImageResource">
+				<method name="setRoughnessMetalnessImageFilename">
 					<args>
 						<arg>CString</arg>
+					</args>
+					<return>DecalComponent&amp;</return>
+				</method>
+				<method name="getRoughnessMetalnessImageFilename">
+					<return>CString</return>
+				</method>
+				<method name="setRoughnessMetalnessBlendFactor">
+					<args>
 						<arg>F32</arg>
 					</args>
+					<return>DecalComponent&amp;</return>
+				</method>
+				<method name="getRoughnessMetalnessBlendFactor">
+					<return>F32</return>
 				</method>
 			</methods>
 		</class>

+ 1 - 1
Samples/PhysicsPlayground/FpsCharacterNode.cpp

@@ -237,7 +237,7 @@ void FpsCharacter::fireShotgun()
 				bulletDecal->setLocalTransform(trf);
 				bulletDecal->setLocalScale(Vec3(0.1f, 0.1f, 0.3f));
 				DecalComponent* decalc = bulletDecal->newComponent<DecalComponent>();
-				decalc->loadDiffuseImageResource("Assets/bullet_hole_decal.ankitex", 1.0f);
+				decalc->setDiffuseImageFilename("Assets/bullet_hole_decal.ankitex");
 
 				createDestructionEvent(bulletDecal, 10.0_sec);
 			}

+ 8 - 8
Samples/Sponza/Assets/Scene.lua

@@ -18,8 +18,8 @@ node:setLocalTransform(trf)
 
 node = scene:newSceneNode("Cube.017")
 comp = node:newDecalComponent()
-comp:loadDiffuseImageResource("Assets/blood_decal_albedo.ankitex", 1.000000)
-comp:loadMetalRoughnessImageResource("Assets/blood_decal_metal_roughness.ankitex", 1.000000)
+comp:setDiffuseImageFilename("Assets/blood_decal_albedo.ankitex")
+comp:setRoughnessMetalnessImageFilename("Assets/blood_decal_metal_roughness.ankitex")
 trf = Transform.new()
 trf:setOrigin(Vec3.new(-7.248238, -0.031180, 2.810158))
 rot = Mat3.new()
@@ -30,8 +30,8 @@ node:setLocalTransform(trf)
 
 node = scene:newSceneNode("Cube.018")
 comp = node:newDecalComponent()
-comp:loadDiffuseImageResource("Assets/blood_decal_albedo.ankitex", 1.000000)
-comp:loadMetalRoughnessImageResource("Assets/blood_decal_metal_roughness.ankitex", 1.000000)
+comp:setDiffuseImageFilename("Assets/blood_decal_albedo.ankitex")
+comp:setRoughnessMetalnessImageFilename("Assets/blood_decal_metal_roughness.ankitex")
 trf = Transform.new()
 trf:setOrigin(Vec3.new(-7.248238, 1.820668, 3.320379))
 rot = Mat3.new()
@@ -3223,7 +3223,7 @@ node:setLocalTransform(trf)
 
 node = scene:newSceneNode("decal")
 comp = node:newDecalComponent()
-comp:loadDiffuseImageResource("Assets/torch_burn_decal.ankitex", 1.000000)
+comp:setDiffuseImageFilename("Assets/torch_burn_decal.ankitex")
 trf = Transform.new()
 trf:setOrigin(Vec3.new(8.551484, 3.596614, -4.380483))
 rot = Mat3.new()
@@ -3234,7 +3234,7 @@ node:setLocalTransform(trf)
 
 node = scene:newSceneNode("decal.001")
 comp = node:newDecalComponent()
-comp:loadDiffuseImageResource("Assets/torch_burn_decal.ankitex", 1.000000)
+comp:setDiffuseImageFilename("Assets/torch_burn_decal.ankitex")
 trf = Transform.new()
 trf:setOrigin(Vec3.new(-10.791684, 3.596614, -4.380483))
 rot = Mat3.new()
@@ -3245,7 +3245,7 @@ node:setLocalTransform(trf)
 
 node = scene:newSceneNode("decal.002")
 comp = node:newDecalComponent()
-comp:loadDiffuseImageResource("Assets/torch_burn_decal.ankitex", 1.000000)
+comp:setDiffuseImageFilename("Assets/torch_burn_decal.ankitex")
 trf = Transform.new()
 trf:setOrigin(Vec3.new(-10.791684, 3.596614, 3.085766))
 rot = Mat3.new()
@@ -3256,7 +3256,7 @@ node:setLocalTransform(trf)
 
 node = scene:newSceneNode("decal.003")
 comp = node:newDecalComponent()
-comp:loadDiffuseImageResource("Assets/torch_burn_decal.ankitex", 1.000000)
+comp:setDiffuseImageFilename("Assets/torch_burn_decal.ankitex")
 trf = Transform.new()
 trf:setOrigin(Vec3.new(8.552687, 3.596614, 3.085766))
 rot = Mat3.new()