Skip to content

Commit

Permalink
Use resource pointers all the way for GUI textures (#8945)
Browse files Browse the repository at this point in the history
* Use resource pointers all the way

* Test wip

* Add test
  • Loading branch information
Jhonnyg committed May 19, 2024
1 parent 881a387 commit baf9a31
Show file tree
Hide file tree
Showing 8 changed files with 298 additions and 23 deletions.
63 changes: 42 additions & 21 deletions engine/gamesys/src/gamesys/components/comp_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -587,24 +587,27 @@ namespace dmGameSystem

for (uint32_t i = 0; i < scene_resource->m_GuiTextureSets.Size(); ++i)
{
const char* name = scene_desc->m_Textures[i].m_Name;
const char* name = scene_desc->m_Textures[i].m_Name;
TextureResource* texture_res = scene_resource->m_GuiTextureSets[i].m_Texture;
TextureSetResource* texture_set_res = scene_resource->m_GuiTextureSets[i].m_TextureSet;
dmGraphics::HTexture texture = texture_res->m_Texture;

dmGui::HTextureSource texture_source;
dmGraphics::HTexture texture = scene_resource->m_GuiTextureSets[i].m_Texture->m_Texture;
dmGui::NodeTextureType texture_source_type;

if (scene_resource->m_GuiTextureSets[i].m_TextureSet)
if (texture_set_res)
{
texture_source_type = dmGui::NODE_TEXTURE_TYPE_TEXTURE_SET;
texture_source = (dmGui::HTextureSource) scene_resource->m_GuiTextureSets[i].m_TextureSet;
texture_source = (dmGui::HTextureSource) texture_set_res;
}
else
{
texture_source_type = dmGui::NODE_TEXTURE_TYPE_TEXTURE;
texture_source = (dmGui::HTextureSource) texture;
texture_source = (dmGui::HTextureSource) texture_res;
}

dmGui::Result r = dmGui::AddTexture(scene, dmHashString64(name), texture_source, texture_source_type, dmGraphics::GetOriginalTextureWidth(texture), dmGraphics::GetOriginalTextureHeight(texture));

if (r != dmGui::RESULT_OK) {
dmLogError("Unable to add texture '%s' to scene (%d)", name, r);
return false;
Expand Down Expand Up @@ -948,19 +951,38 @@ namespace dmGameSystem
ApplyStencilClipping(gui_context, state, params.m_StencilTestParams);
}

static dmGraphics::HTexture GetNodeTexture(dmGui::HScene scene, dmGui::HNode node)
static inline dmGraphics::HTexture GetNodeTexture(dmGui::HScene scene, dmGui::HNode node)
{
dmGui::NodeTextureType texture_type;
dmGui::HTextureSource texture_source = dmGui::GetNodeTexture(scene, node, &texture_type);

if (texture_type == dmGui::NODE_TEXTURE_TYPE_TEXTURE_SET)
{
TextureSetResource* texture_set_res = (TextureSetResource*) texture_source;
assert(texture_set_res);
assert(texture_set_res->m_Texture);
return texture_set_res->m_Texture->m_Texture;
}
else if (texture_type == dmGui::NODE_TEXTURE_TYPE_TEXTURE)
{
TextureResource* texture_res = (TextureResource*) texture_source;
return texture_res->m_Texture;
}
else if (texture_type == dmGui::NODE_TEXTURE_TYPE_DYNAMIC)
{
return (dmGraphics::HTexture) texture_source;
}
return 0;
}

return (dmGraphics::HTexture) texture_source;
static inline dmGameSystemDDF::TextureSet* GetNodeTextureSetDDF(dmGui::HScene scene, dmGui::HNode node)
{
dmGui::TextureSetAnimDesc* anim_desc = dmGui::GetNodeTextureSet(scene, node);
if (anim_desc)
{
TextureSetResource* texture_set_res = (TextureSetResource*) anim_desc->m_TextureSet;
return texture_set_res->m_TextureSet;
}
return 0;
}

static inline dmRender::HMaterial GetNodeMaterial(void* material_res)
Expand Down Expand Up @@ -1430,11 +1452,10 @@ namespace dmGameSystem

uint32_t frame_index = 0;
uint32_t page_index = 0;
dmGui::TextureSetAnimDesc* anim_desc = dmGui::GetNodeTextureSet(scene, node);
dmGameSystemDDF::TextureSet* texture_set_ddf = 0;
if (anim_desc)

dmGameSystemDDF::TextureSet* texture_set_ddf = GetNodeTextureSetDDF(scene, node);
if (texture_set_ddf)
{
texture_set_ddf = (dmGameSystemDDF::TextureSet*) anim_desc->m_TextureSet;
frame_index = dmGui::GetNodeAnimationFrame(scene, node);
frame_index = texture_set_ddf->m_FrameIndices[frame_index];
uint32_t* page_indices = texture_set_ddf->m_PageIndices.m_Data;
Expand Down Expand Up @@ -1694,15 +1715,15 @@ namespace dmGameSystem
if (dmMath::Abs(size.getX()) < 0.001f)
continue;

uint32_t page_index = 0;
dmGui::TextureSetAnimDesc* anim_desc = dmGui::GetNodeTextureSet(scene, node);
if (anim_desc)
uint32_t page_index = 0;
dmGameSystemDDF::TextureSet* texture_set_ddf = GetNodeTextureSetDDF(scene, node);

if (texture_set_ddf)
{
dmGameSystemDDF::TextureSet* texture_set_ddf = (dmGameSystemDDF::TextureSet*) anim_desc->m_TextureSet;
uint32_t frame_index = dmGui::GetNodeAnimationFrame(scene, node);
frame_index = texture_set_ddf->m_FrameIndices[frame_index];
uint32_t* page_indices = texture_set_ddf->m_PageIndices.m_Data;
page_index = page_indices[frame_index];
uint32_t frame_index = dmGui::GetNodeAnimationFrame(scene, node);
frame_index = texture_set_ddf->m_FrameIndices[frame_index];
uint32_t* page_indices = texture_set_ddf->m_PageIndices.m_Data;
page_index = page_indices[frame_index];
}

const Vector4& color = dmGui::GetNodeProperty(scene, node, dmGui::PROPERTY_COLOR);
Expand Down Expand Up @@ -2112,7 +2133,7 @@ namespace dmGameSystem
out_data->m_State.m_FPS = animation->m_Fps;
out_data->m_FlipHorizontal = animation->m_FlipHorizontal;
out_data->m_FlipVertical = animation->m_FlipVertical;
out_data->m_TextureSet = (void*)texture_set;
out_data->m_TextureSet = (void*) texture_set_res;
return dmGui::FETCH_ANIMATION_OK;
}
else
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
components {
id: "gui"
component: "/gui/texture_resources/texture_resources.gui"
}
components {
id: "script"
component: "/gui/texture_resources/texture_resources.script"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
script: "/gui/texture_resources/texture_resources.gui_script"
textures {
name: "atlas"
texture: "/atlas/valid.atlas"
}
textures {
name: "texture"
texture: "/texture/valid_png.png"
}
background_color {
x: 0.0
y: 0.0
z: 0.0
w: 0.0
}
material: "/gui/gui.material"
adjust_reference: ADJUST_REFERENCE_PARENT
max_nodes: 512

nodes {
position {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
rotation {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
scale {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
size {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
color {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
id: "box1"
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "texture"
}

nodes {
position {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
rotation {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
scale {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
size {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
color {
x: 1.0
y: 0.0
z: 0.0
w: 0.0
}
id: "box2"
type: TYPE_BOX
blend_mode: BLEND_MODE_ALPHA
texture: "atlas/valid_png_128"
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-- Copyright 2020-2024 The Defold Foundation
-- Copyright 2014-2020 King
-- Copyright 2009-2014 Ragnar Svensson, Christian Murray
-- Licensed under the Defold License version 1.0 (the "License"); you may not use
-- this file except in compliance with the License.
--
-- You may obtain a copy of the License, together with FAQs at
-- https://www.defold.com/license
--
-- Unless required by applicable law or agreed to in writing, software distributed
-- under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-- CONDITIONS OF ANY KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations under the License.

function init(self)
local w = 32
local h = 32
local orange = string.char(0xff) .. string.char(0x80) .. string.char(0x10)
gui.new_texture("dynamic_texture", w, h, "rgb", string.rep(orange, w * h))

local n = gui.new_box_node(vmath.vector3(200, 200, 0), vmath.vector3(w, h, 0))
gui.set_texture(n, "dynamic_texture")
gui.set_id(n, "box3")
end

function final(self)
gui.delete_texture("dynamic_texture")
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- Copyright 2020-2024 The Defold Foundation
-- Copyright 2014-2020 King
-- Copyright 2009-2014 Ragnar Svensson, Christian Murray
-- Licensed under the Defold License version 1.0 (the "License"); you may not use
-- this file except in compliance with the License.
--
-- You may obtain a copy of the License, together with FAQs at
-- https://www.defold.com/license
--
-- Unless required by applicable law or agreed to in writing, software distributed
-- under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-- CONDITIONS OF ANY KIND, either express or implied. See the License for the
-- specific language governing permissions and limitations under the License.

function init(self)

local tbuffer = buffer.create(32 * 32, { {name=hash("rgba"), type=buffer.VALUE_TYPE_FLOAT32, count=4} } )
local tstream = buffer.get_stream(tbuffer, hash("rgba"))
local tparams = {
width = 32,
height = 32,
type = resource.TEXTURE_TYPE_2D,
format = resource.TEXTURE_FORMAT_RGBA,
}

resource.set_texture("/atlas/valid.texturec", tparams, tbuffer)
resource.set_texture("/texture/valid_png.texturec", tparams, tbuffer)

-- create a new texture and assign the the atlas
local tnew = resource.create_texture("/texture/custom.texturec", tparams, tbuffer)
local atlas_info = resource.get_atlas("/atlas/valid.t.texturesetc")
atlas_info.texture = tnew
resource.set_atlas("/atlas/valid.t.texturesetc", atlas_info)
end
91 changes: 91 additions & 0 deletions engine/gamesys/src/gamesys/test/test_gamesys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1284,6 +1284,97 @@ TEST_P(CursorTest, Cursor)
ASSERT_TRUE(dmGameObject::Final(m_Collection));
}

// Tests the different types of textures (atlas, texture, dynamic)
// This test makes sure that we can use the correct resource pointers.
TEST_F(GuiTest, TextureResources)
{
dmhash_t go_id = dmHashString64("/go");
dmhash_t gui_comp_id = dmHashString64("gui");

dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

dmGameSystem::TextureSetResource* valid_atlas = 0;
dmGameSystem::TextureResource* valid_texture = 0;

ASSERT_EQ(dmResource::RESULT_OK, dmResource::Get(m_Factory, "/atlas/valid.t.texturesetc", (void**) &valid_atlas));
ASSERT_TRUE(valid_atlas != 0x0);

ASSERT_EQ(dmResource::RESULT_OK, dmResource::Get(m_Factory, "/texture/valid_png.texturec", (void**) &valid_texture));
ASSERT_TRUE(valid_atlas != 0x0);

dmGraphics::HTexture valid_atlas_th = valid_atlas->m_Texture->m_Texture;
dmGraphics::HTexture valid_texture_th = valid_texture->m_Texture;

dmGameObject::HInstance go = Spawn(m_Factory, m_Collection, "/gui/texture_resources/texture_resources.goc", go_id, 0, 0, Point3(0, 0, 0), Quat(0, 0, 0, 1), Vector3(1, 1, 1));
ASSERT_NE((void*)0x0, go);

dmResource::Release(m_Factory, valid_atlas);
dmResource::Release(m_Factory, valid_texture);

// Update + render the GO - this is needed to trigger the creation of the dynamic texture
ASSERT_TRUE(dmGameObject::Update(m_Collection, &m_UpdateContext));

dmRender::RenderListBegin(m_RenderContext);
dmGameObject::Render(m_Collection);

dmRender::RenderListEnd(m_RenderContext);
dmRender::DrawRenderList(m_RenderContext, 0x0, 0x0, 0x0);

uint32_t component_type_index = dmGameObject::GetComponentTypeIndex(m_Collection, dmHashString64("guic"));
dmGameSystem::GuiWorld* gui_world = (dmGameSystem::GuiWorld*) dmGameObject::GetWorld(m_Collection, component_type_index);
dmGameSystem::GuiComponent* gui_comp = gui_world->m_Components[0];

{
// Box1 is using the "texture" entry, which should equate to a texture resource
dmGui::HNode box1 = dmGui::GetNodeById(gui_comp->m_Scene, "box1");
ASSERT_NE(0, box1);

dmGui::NodeTextureType texture_type;
dmGui::HTextureSource texture_source = dmGui::GetNodeTexture(gui_comp->m_Scene, box1, &texture_type);
ASSERT_EQ(dmGui::NODE_TEXTURE_TYPE_TEXTURE, texture_type);

dmGameSystem::TextureResource* texture_res = (dmGameSystem::TextureResource*) texture_source;
ASSERT_EQ(texture_res, valid_texture);
ASSERT_EQ(valid_texture_th, texture_res->m_Texture); // same texture

ASSERT_TRUE(dmGraphics::IsAssetHandleValid(m_GraphicsContext, texture_res->m_Texture));
}

{
// Box2 is using the "texture set" entry, which should equate to a texture set resource
dmGui::HNode box2 = dmGui::GetNodeById(gui_comp->m_Scene, "box2");
ASSERT_NE(0, box2);

dmGui::NodeTextureType texture_type;
dmGui::HTextureSource texture_source = dmGui::GetNodeTexture(gui_comp->m_Scene, box2, &texture_type);
ASSERT_EQ(dmGui::NODE_TEXTURE_TYPE_TEXTURE_SET, texture_type);

dmGameSystem::TextureSetResource* texture_set_res = (dmGameSystem::TextureSetResource*) texture_source;
ASSERT_EQ(valid_atlas, texture_set_res);
ASSERT_NE(valid_texture_th, texture_set_res->m_Texture->m_Texture); // NOT the same texture, we swap it out in the script

ASSERT_TRUE(dmGraphics::IsAssetHandleValid(m_GraphicsContext, texture_set_res->m_Texture->m_Texture));
ASSERT_FALSE(dmGraphics::IsAssetHandleValid(m_GraphicsContext, valid_atlas_th)); // Old texture has been removed
}

{
// Box2 is using the "texture set" entry, which should equate to a texture set resource
dmGui::HNode box3 = dmGui::GetNodeById(gui_comp->m_Scene, "box3");
ASSERT_NE(0, box3);

dmGui::NodeTextureType texture_type;
dmGui::HTextureSource texture_source = dmGui::GetNodeTexture(gui_comp->m_Scene, box3, &texture_type);
ASSERT_EQ(dmGui::NODE_TEXTURE_TYPE_DYNAMIC, texture_type);

dmGraphics::HTexture texture_h = (dmGraphics::HTexture) texture_source;
ASSERT_TRUE(dmGraphics::IsAssetHandleValid(m_GraphicsContext, texture_h));
}

dmGameSystem::FinalizeScriptLibs(m_Scriptlibcontext);

ASSERT_TRUE(dmGameObject::Final(m_Collection));
}

TEST_F(FontTest, GlyphBankTest)
{
const char path_font_1[] = "/font/glyph_bank_test_1.fontc";
Expand Down
2 changes: 1 addition & 1 deletion engine/gamesys/src/gamesys/test/test_gamesys.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ class FontTest : public GamesysTest<const char*>
virtual ~FontTest() {}
};

class GuiTest : public GamesysTest<const char*>
class GuiTest : public ScriptBaseTest
{
public:
virtual ~GuiTest() {}
Expand Down

0 comments on commit baf9a31

Please sign in to comment.