From 3ddd64df2a69193c0b3a1d92c89a399cc8f63cf3 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 23 Feb 2021 13:57:51 +0100 Subject: [PATCH] Add support for drawing SpriteHandle in Sprite Render --- Content/Editor/SpriteMaterial.flax | 4 +-- Source/Engine/Render2D/SpriteAtlas.cpp | 3 +-- Source/Engine/Render2D/SpriteAtlas.h | 10 ++++--- Source/Engine/UI/SpriteRender.cpp | 37 +++++++++++++++++++++----- Source/Engine/UI/SpriteRender.h | 25 +++++++++++++---- 5 files changed, 60 insertions(+), 19 deletions(-) diff --git a/Content/Editor/SpriteMaterial.flax b/Content/Editor/SpriteMaterial.flax index 733249713..22f4f4ccd 100644 --- a/Content/Editor/SpriteMaterial.flax +++ b/Content/Editor/SpriteMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c6f3a619d8003855d59f24f3c74958c758a92e778a7e455193e10fc13ec3293b -size 30480 +oid sha256:cb44c362605be7e468e9e5eeedb14e5d0445bbb5d3f33dd0a2fc2f0ea298ee4e +size 31104 diff --git a/Source/Engine/Render2D/SpriteAtlas.cpp b/Source/Engine/Render2D/SpriteAtlas.cpp index b7a25f025..fba2b8a06 100644 --- a/Source/Engine/Render2D/SpriteAtlas.cpp +++ b/Source/Engine/Render2D/SpriteAtlas.cpp @@ -21,13 +21,12 @@ bool SpriteHandle::GetSprite(Sprite* result) const *result = Atlas->Sprites[Index]; return true; } - return false; } bool SpriteHandle::IsValid() const { - return Atlas && Index != INVALID_INDEX && Atlas->Sprites.Count() > Index; + return Atlas && Index >= 0 && Atlas->Sprites.Count() > Index; } GPUTexture* SpriteHandle::GetAtlasTexture() const diff --git a/Source/Engine/Render2D/SpriteAtlas.h b/Source/Engine/Render2D/SpriteAtlas.h index a0057a261..9631b9ac9 100644 --- a/Source/Engine/Render2D/SpriteAtlas.h +++ b/Source/Engine/Render2D/SpriteAtlas.h @@ -2,9 +2,11 @@ #pragma once +#include "Engine/Core/ISerializable.h" #include "Engine/Core/Types/String.h" #include "Engine/Core/Math/Rectangle.h" #include "Engine/Content/BinaryAsset.h" +#include "Engine/Content/AssetReference.h" #include "Engine/Graphics/Textures/TextureBase.h" class SpriteAtlas; @@ -31,8 +33,9 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(Sprite); /// /// Handle to sprite atlas slot with a single sprite texture. /// -API_STRUCT() struct FLAXENGINE_API SpriteHandle +API_STRUCT() struct FLAXENGINE_API SpriteHandle : ISerializable { +API_AUTO_SERIALIZATION(); DECLARE_SCRIPTING_TYPE_MINIMAL(SpriteHandle); /// @@ -43,7 +46,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(SpriteHandle); /// /// The parent atlas. /// - API_FIELD() SpriteAtlas* Atlas; + API_FIELD() AssetReference Atlas; /// /// The atlas sprites array index. @@ -55,7 +58,6 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(SpriteHandle); /// SpriteHandle() { - Atlas = nullptr; Index = -1; } @@ -65,8 +67,8 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(SpriteHandle); /// The sprite atlas. /// The sprite slot index. SpriteHandle(SpriteAtlas* atlas, int32 index) + : Atlas(atlas) { - Atlas = atlas; Index = index; } diff --git a/Source/Engine/UI/SpriteRender.cpp b/Source/Engine/UI/SpriteRender.cpp index 8929b8371..d2564fc84 100644 --- a/Source/Engine/UI/SpriteRender.cpp +++ b/Source/Engine/UI/SpriteRender.cpp @@ -17,7 +17,7 @@ SpriteRender::SpriteRender(const SpawnParams& params) { _quadModel = Content::LoadAsyncInternal(TEXT("Engine/Models/Quad")); Material.Loaded.Bind(this); - Image.Changed.Bind(this); + Image.Changed.Bind(this); } Vector2 SpriteRender::GetSize() const @@ -45,6 +45,17 @@ void SpriteRender::SetColor(const Color& value) _paramColor->SetValue(value); } +SpriteHandle SpriteRender::GetSprite() const +{ + return _sprite; +} + +void SpriteRender::SetSprite(const SpriteHandle& value) +{ + _sprite = value; + SetImage(); +} + void SpriteRender::OnMaterialLoaded() { // Setup material instance @@ -56,11 +67,14 @@ void SpriteRender::OnMaterialLoaded() _materialInstance->SetBaseMaterial(Material); // Cache parameters + _paramImageMAD = _materialInstance->GetParameter(TEXT("ImageMAD")); + if (_paramImageMAD && _paramImageMAD->GetParameterType() != MaterialParameterType::Vector4) + _paramImageMAD = nullptr; _paramImage = _materialInstance->GetParameter(TEXT("Image")); if (_paramImage && _paramImage->GetParameterType() != MaterialParameterType::Texture) _paramImage = nullptr; else if (_paramImage) - _paramImage->SetValue(Image.Get()); + SetImage(); _paramColor = _materialInstance->GetParameter(TEXT("Color")); if (_paramColor && _paramColor->GetParameterType() != MaterialParameterType::Color && _paramColor->GetParameterType() != MaterialParameterType::Vector4 && _paramColor->GetParameterType() != MaterialParameterType::Vector3) _paramColor = nullptr; @@ -68,10 +82,20 @@ void SpriteRender::OnMaterialLoaded() _paramColor->SetValue(_color); } -void SpriteRender::OnImageChanged() +void SpriteRender::SetImage() { + TextureBase* image = Image.Get(); + Vector4 imageMAD(Vector2::One, Vector2::Zero); + if (!image && _sprite.IsValid()) + { + image = _sprite.Atlas.Get(); + Sprite* sprite = &_sprite.Atlas->Sprites.At(_sprite.Index); + imageMAD = Vector4(sprite->Area.Size, sprite->Area.Location); + } if (_paramImage) - _paramImage->SetValue(Image.Get()); + _paramImage->SetValue(image); + if (_paramImageMAD) + _paramImageMAD->SetValue(imageMAD); } bool SpriteRender::HasContentLoaded() const @@ -120,6 +144,7 @@ void SpriteRender::Serialize(SerializeStream& stream, const void* otherObj) SERIALIZE_MEMBER(Size, _size); SERIALIZE_MEMBER(Color, _color); + SERIALIZE_MEMBER(Sprite, _sprite); SERIALIZE(Image); SERIALIZE(Material); SERIALIZE(FaceCamera); @@ -133,13 +158,13 @@ void SpriteRender::Deserialize(DeserializeStream& stream, ISerializeModifier* mo DESERIALIZE_MEMBER(Size, _size); DESERIALIZE_MEMBER(Color, _color); + DESERIALIZE_MEMBER(Sprite, _sprite); DESERIALIZE(Image); DESERIALIZE(Material); DESERIALIZE(FaceCamera); DESERIALIZE(DrawModes); - if (_paramImage) - _paramImage->SetValue(Image.Get()); + SetImage(); if (_paramColor) _paramColor->SetValue(_color); } diff --git a/Source/Engine/UI/SpriteRender.h b/Source/Engine/UI/SpriteRender.h index 6a994b188..9bd9eeaf0 100644 --- a/Source/Engine/UI/SpriteRender.h +++ b/Source/Engine/UI/SpriteRender.h @@ -5,6 +5,7 @@ #include "Engine/Level/Actor.h" #include "Engine/Content/Assets/MaterialBase.h" #include "Engine/Content/Assets/Texture.h" +#include "Engine/Render2D/SpriteAtlas.h" /// /// Sprite rendering object. @@ -16,8 +17,10 @@ private: Color _color; Vector2 _size; + SpriteHandle _sprite; MaterialInstance* _materialInstance = nullptr; MaterialParameter* _paramImage = nullptr; + MaterialParameter* _paramImageMAD = nullptr; MaterialParameter* _paramColor = nullptr; AssetReference _quadModel; @@ -52,27 +55,39 @@ public: AssetReference Image; /// - /// The material used for the sprite rendering. It should contain texture parameter named Image and color parameter named Color. + /// Gets the sprite to draw. Used only if Image is unset. /// - API_FIELD(Attributes="EditorOrder(20), DefaultValue(null), EditorDisplay(\"Sprite\")") + API_PROPERTY(Attributes="EditorOrder(25), EditorDisplay(\"Sprite\")") + SpriteHandle GetSprite() const; + + /// + /// Sets the sprite to draw. Used only if Image is unset. + /// + API_PROPERTY() + void SetSprite(const SpriteHandle& value); + + /// + /// The material used for the sprite rendering. It should contain texture parameter named Image and color parameter named Color. For showing sprites from sprite atlas ensure to add Vector4 param ImageMAD for UVs transformation. + /// + API_FIELD(Attributes="EditorOrder(30), DefaultValue(null), EditorDisplay(\"Sprite\")") AssetReference Material; /// /// If checked, the sprite will automatically face the view camera, otherwise it will be oriented as an actor. /// - API_FIELD(Attributes="EditorOrder(30), EditorDisplay(\"Sprite\")") + API_FIELD(Attributes="EditorOrder(40), EditorDisplay(\"Sprite\")") bool FaceCamera = true; /// /// The draw passes to use for rendering this object. Uncheck `Depth` to disable sprite casting shadows. /// - API_FIELD(Attributes="EditorOrder(40), DefaultValue(DrawPass.Default), EditorDisplay(\"Sprite\")") + API_FIELD(Attributes="EditorOrder(50), DefaultValue(DrawPass.Default), EditorDisplay(\"Sprite\")") DrawPass DrawModes = DrawPass::Default; private: void OnMaterialLoaded(); - void OnImageChanged(); + void SetImage(); public: