Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 'slice' as a property to get and set slice9 values #8758

Merged
merged 2 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
20 changes: 17 additions & 3 deletions engine/gamesys/src/gamesys/components/comp_sprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ namespace dmGameSystem
Quat m_Rotation;
Vector3 m_Scale;
Vector3 m_Size; // The current size of the animation frame (in texels)
Vector4 m_Slice9;
Matrix4 m_World;
dmMessage::URL m_Listener;
int m_FunctionRef; // Animation callback function
Expand Down Expand Up @@ -149,6 +150,7 @@ namespace dmGameSystem

DM_GAMESYS_PROP_VECTOR3(SPRITE_PROP_SCALE, scale, false);
DM_GAMESYS_PROP_VECTOR3(SPRITE_PROP_SIZE, size, false);
DM_GAMESYS_PROP_VECTOR4(SPRITE_PROP_SLICE, slice, false);

static const dmhash_t SPRITE_PROP_CURSOR = dmHashString64("cursor");
static const dmhash_t SPRITE_PROP_PLAYBACK_RATE = dmHashString64("playback_rate");
Expand Down Expand Up @@ -579,7 +581,8 @@ namespace dmGameSystem
component->m_Enabled = 1;
component->m_FunctionRef = 0;
component->m_ReHash = 1;
component->m_UseSlice9 = sum(component->m_Resource->m_DDF->m_Slice9) != 0 &&
component->m_Slice9 = component->m_Resource->m_DDF->m_Slice9;
component->m_UseSlice9 = sum(component->m_Slice9) != 0 &&
component->m_Resource->m_DDF->m_SizeMode == dmGameSystemDDF::SpriteDesc::SIZE_MODE_MANUAL;

component->m_DynamicVertexAttributeIndex = INVALID_DYNAMIC_ATTRIBUTE_INDEX;
Expand Down Expand Up @@ -1182,7 +1185,7 @@ namespace dmGameSystem
int flipx = component->m_FlipHorizontal;
int flipy = component->m_FlipVertical;
CreateVertexDataSlice9(vertices, indices, sprite_world->m_Is16BitIndex, has_local_position_attribute,
w, component->m_Size, component->m_Resource->m_DDF->m_Slice9, vertex_offset, vertex_stride,
w, component->m_Size, component->m_Slice9, vertex_offset, vertex_stride,
&textures, scratch_uvs, flipx, flipy, sprite_attribute_info_ptr);

indices += index_type_size * SPRITE_INDEX_COUNT_SLICE9;
Expand Down Expand Up @@ -1962,6 +1965,10 @@ namespace dmGameSystem
{
return GetProperty(out_value, get_property, component->m_Size, SPRITE_PROP_SIZE);
}
else if (IsReferencingProperty(SPRITE_PROP_SLICE, get_property))
{
return GetProperty(out_value, get_property, component->m_Slice9, SPRITE_PROP_SLICE);
}
else if (get_property == SPRITE_PROP_CURSOR)
{
out_value.m_Variant = dmGameObject::PropertyVar(GetCursor(component));
Expand Down Expand Up @@ -2026,9 +2033,16 @@ namespace dmGameSystem
{
return dmGameObject::PROPERTY_RESULT_UNSUPPORTED_OPERATION;
}

return SetProperty(set_property, params.m_Value, component->m_Size, SPRITE_PROP_SIZE);
}
else if (IsReferencingProperty(SPRITE_PROP_SLICE, set_property))
{
if (component->m_Resource->m_DDF->m_SizeMode == dmGameSystemDDF::SpriteDesc::SIZE_MODE_AUTO)
{
return dmGameObject::PROPERTY_RESULT_UNSUPPORTED_OPERATION;
}
return SetProperty(set_property, params.m_Value, component->m_Slice9, SPRITE_PROP_SLICE);
}
else if (params.m_PropertyId == SPRITE_PROP_CURSOR)
{
if (params.m_Value.m_Type != dmGameObject::PROPERTY_TYPE_NUMBER)
Expand Down
33 changes: 33 additions & 0 deletions engine/gamesys/src/gamesys/scripts/script_sprite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,39 @@ namespace dmGameSystem
* ```
*/

/*# [type:vector3] sprite slice
*
* The slice values of the sprite. The type of the property is a vector4 that corresponds to
* the left, top, right, bottom values of the sprite in the editor.
* It is not possible to set the slice property if the size mode of the sprite is set to auto.
*
* @name slice
* @property
*
* @examples
*
* How to query a sprite's slice values, either as a vector or selecting a specific dimension:
*
* ```lua
* function init(self)
* local slice = go.get("#sprite", "slice")
* local slicex = go.get("#sprite", "slice.x")
* assert(slice.x == slicex)
* end
* ```
*
* Animate the slice property with go.animate:
*
* ```lua
* function init(self)
* -- animate the entire slice vector at once
* go.animate("#sprite", "slice", go.PLAYBACK_LOOP_PINGPONG, vmath.vector4(96, 96, 96, 96), go.EASING_INCUBIC, 2)
* -- or animate a single component
* go.animate("#sprite", "slice.y", go.PLAYBACK_LOOP_PINGPONG, 32, go.EASING_INCUBIC, 8)
* end
* ```
*/

/*# [type:vector3] sprite scale
*
* The non-uniform scale of the sprite. The type of the property is vector3.
Expand Down
10 changes: 10 additions & 0 deletions engine/gamesys/src/gamesys/test/atlas/valid.atlas
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
images {
image: "/texture/valid_png_128.png"
sprite_trim_mode: SPRITE_TRIM_MODE_OFF
}
margin: 0
extrude_borders: 0
inner_padding: 0
max_page_width: 0
max_page_height: 0
rename_patterns: ""
9 changes: 9 additions & 0 deletions engine/gamesys/src/gamesys/test/sprite/sprite_slice9.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
components {
id: "sprite"
component: "/sprite/sprite_slice9.sprite"
}
components {
id: "script"
component: "/sprite/sprite_slice9.script"
}

56 changes: 56 additions & 0 deletions engine/gamesys/src/gamesys/test/sprite/sprite_slice9.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
-- 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.

local function assert_exit(assert_that, error_string)
if not assert_that then
if error_string then
print(error_string)
end
msg.post("@system:", "exit", { code = 1 })
assert(assert_that)
end
end

local function assert_vec4(v_test,v_correct)
local v = v_test.x == v_correct.x and
v_test.y == v_correct.y and
v_test.z == v_correct.z and
v_test.w == v_correct.w
local e = v and nil or tostring(v_test) .. " and " .. tostring(v_correct) .. " are not the same!"
assert_exit(v, e)
end

local function assert_number(v_test,v_correct)
local v = v_test == v_correct
local e = v and nil or tostring(v_test) .. " and " .. tostring(v_correct) .. " are not the same!"
assert_exit(v, e)
end

function test_get(self, v_correct)
assert_vec4(go.get("#sprite", "slice"), v_correct)
assert_number(go.get("#sprite", "slice.x"), v_correct.x)
assert_number(go.get("#sprite", "slice.y"), v_correct.y)
assert_number(go.get("#sprite", "slice.z"), v_correct.z)
assert_number(go.get("#sprite", "slice.w"), v_correct.w)
end

function test_set(self, v_correct)
go.set("#sprite", "slice", v_correct)
test_get(self, v_correct)
end

function init(self)
test_get(self, vmath.vector4(32,32,32,32))
test_set(self, vmath.vector4(1,2,3,4))
end
20 changes: 20 additions & 0 deletions engine/gamesys/src/gamesys/test/sprite/sprite_slice9.sprite
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
material: "/sprite/sprite.material"
default_animation: "valid_png_128"
blend_mode: BLEND_MODE_ALPHA
slice9 {
x: 32.0
y: 32.0
z: 32.0
w: 32.0
}
size {
x: 256.0
y: 256.0
z: 0.0
w: 0.0
}
size_mode: SIZE_MODE_MANUAL
textures {
sampler: "texture_sampler"
texture: "/atlas/valid.atlas"
}
88 changes: 26 additions & 62 deletions engine/gamesys/src/gamesys/test/test_gamesys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1056,20 +1056,13 @@ TEST_F(SpriteTest, GoDeletion)
// Test that animation done event reaches either callback or onmessage
TEST_F(SpriteTest, FlipbookAnim)
{
dmGameSystem::ScriptLibContext scriptlibcontext;
scriptlibcontext.m_Factory = m_Factory;
scriptlibcontext.m_Register = m_Register;
scriptlibcontext.m_LuaState = dmScript::GetLuaState(m_ScriptContext);
scriptlibcontext.m_GraphicsContext = m_GraphicsContext;
scriptlibcontext.m_ScriptContext = m_ScriptContext;

dmGameSystem::InitializeScriptLibs(scriptlibcontext);
dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

// Spawn one go with a script that will initiate animations on the above sprites
dmGameObject::HInstance go = Spawn(m_Factory, m_Collection, "/sprite/sprite_flipbook_anim.goc", dmHashString64("/go"), 0, 0, Point3(0, 0, 0), Quat(0, 0, 0, 1), Vector3(1, 1, 1));
ASSERT_NE((void*)0, go);

lua_State* L = scriptlibcontext.m_LuaState;
lua_State* L = m_Scriptlibcontext.m_LuaState;

WaitForTestsDone(10000, true, 0);

Expand All @@ -1089,14 +1082,7 @@ TEST_F(SpriteTest, FlipbookAnim)

TEST_F(SpriteTest, FrameCount)
{
dmGameSystem::ScriptLibContext scriptlibcontext;
scriptlibcontext.m_Factory = m_Factory;
scriptlibcontext.m_Register = m_Register;
scriptlibcontext.m_LuaState = dmScript::GetLuaState(m_ScriptContext);
scriptlibcontext.m_GraphicsContext = m_GraphicsContext;
scriptlibcontext.m_ScriptContext = m_ScriptContext;

dmGameSystem::InitializeScriptLibs(scriptlibcontext);
dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

dmGameObject::HInstance go = Spawn(m_Factory, m_Collection, "/sprite/frame_count/sprite_frame_count.goc", dmHashString64("/go"), 0, 0, Point3(0, 0, 0), Quat(0, 0, 0, 1), Vector3(1, 1, 1));
ASSERT_NE((void*)0, go);
Expand All @@ -1106,6 +1092,19 @@ TEST_F(SpriteTest, FrameCount)
ASSERT_TRUE(dmGameObject::Final(m_Collection));
}

TEST_F(SpriteTest, GetSetSliceProperty)
{
dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

dmGameObject::HInstance go = Spawn(m_Factory, m_Collection, "/sprite/sprite_slice9.goc", dmHashString64("/go"), 0, 0, Point3(0, 0, 0), Quat(0, 0, 0, 1), Vector3(1, 1, 1));
ASSERT_NE((void*)0, go);

ASSERT_TRUE(dmGameObject::Update(m_Collection, &m_UpdateContext));
ASSERT_TRUE(dmGameObject::PostUpdate(m_Collection));

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

// Test that animation done event reaches callback
TEST_F(ParticleFxTest, PlayAnim)
{
Expand Down Expand Up @@ -4850,14 +4849,7 @@ TEST_F(MaterialTest, DynamicVertexAttributes)

TEST_F(MaterialTest, DynamicVertexAttributesWithGoAnimate)
{
dmGameSystem::ScriptLibContext scriptlibcontext;
scriptlibcontext.m_Factory = m_Factory;
scriptlibcontext.m_Register = m_Register;
scriptlibcontext.m_LuaState = dmScript::GetLuaState(m_ScriptContext);
scriptlibcontext.m_GraphicsContext = m_GraphicsContext;
scriptlibcontext.m_ScriptContext = m_ScriptContext;

dmGameSystem::InitializeScriptLibs(scriptlibcontext);
dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

ASSERT_TRUE(dmGameObject::Init(m_Collection));

Expand All @@ -4870,85 +4862,57 @@ TEST_F(MaterialTest, DynamicVertexAttributesWithGoAnimate)
}

ASSERT_TRUE(dmGameObject::Final(m_Collection));
dmGameSystem::FinalizeScriptLibs(scriptlibcontext);
dmGameSystem::FinalizeScriptLibs(m_Scriptlibcontext);
}

TEST_F(MaterialTest, DynamicVertexAttributesGoSetGetSparse)
{
dmGameSystem::ScriptLibContext scriptlibcontext;
scriptlibcontext.m_Factory = m_Factory;
scriptlibcontext.m_Register = m_Register;
scriptlibcontext.m_LuaState = dmScript::GetLuaState(m_ScriptContext);
scriptlibcontext.m_GraphicsContext = m_GraphicsContext;
scriptlibcontext.m_ScriptContext = m_ScriptContext;

dmGameSystem::InitializeScriptLibs(scriptlibcontext);
dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

ASSERT_TRUE(dmGameObject::Init(m_Collection));

dmGameObject::HInstance go = Spawn(m_Factory, m_Collection, "/material/attributes_dynamic_go_set_get_sparse.goc", dmHashString64("/attributes_dynamic_go_set_get_sparse"), 0, 0, Point3(0, 0, 0), Quat(0, 0, 0, 1), Vector3(1, 1, 1));
ASSERT_NE((void*)0, go);

ASSERT_TRUE(dmGameObject::Final(m_Collection));
dmGameSystem::FinalizeScriptLibs(scriptlibcontext);
dmGameSystem::FinalizeScriptLibs(m_Scriptlibcontext);
}

TEST_F(MaterialTest, GoGetSetConstants)
{
dmGameSystem::ScriptLibContext scriptlibcontext;
scriptlibcontext.m_Factory = m_Factory;
scriptlibcontext.m_Register = m_Register;
scriptlibcontext.m_LuaState = dmScript::GetLuaState(m_ScriptContext);
scriptlibcontext.m_GraphicsContext = m_GraphicsContext;
scriptlibcontext.m_ScriptContext = m_ScriptContext;

dmGameSystem::InitializeScriptLibs(scriptlibcontext);
dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

ASSERT_TRUE(dmGameObject::Init(m_Collection));

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

ASSERT_TRUE(dmGameObject::Final(m_Collection));
dmGameSystem::FinalizeScriptLibs(scriptlibcontext);
dmGameSystem::FinalizeScriptLibs(m_Scriptlibcontext);
}

TEST_F(ComponentTest, GetSetCollisionShape)
{
dmHashEnableReverseHash(true);
lua_State* L = dmScript::GetLuaState(m_ScriptContext);

dmGameSystem::ScriptLibContext scriptlibcontext;
scriptlibcontext.m_Factory = m_Factory;
scriptlibcontext.m_Register = m_Register;
scriptlibcontext.m_LuaState = L;
scriptlibcontext.m_GraphicsContext = m_GraphicsContext;
scriptlibcontext.m_ScriptContext = m_ScriptContext;
dmGameSystem::InitializeScriptLibs(scriptlibcontext);
dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

dmGameObject::HInstance go_base = Spawn(m_Factory, m_Collection, "/collision_object/get_set_shape.goc", dmHashString64("/get_set_shape_go"), 0, 0, Point3(0, 0, 0), Quat(0, 0, 0, 1), Vector3(1, 1, 1));
ASSERT_NE((void*)0, go_base);

ASSERT_TRUE(dmGameObject::Final(m_Collection));
dmGameSystem::FinalizeScriptLibs(m_Scriptlibcontext);
}

TEST_F(ComponentTest, GetSetErrorCollisionShape)
{
dmHashEnableReverseHash(true);
lua_State* L = dmScript::GetLuaState(m_ScriptContext);

dmGameSystem::ScriptLibContext scriptlibcontext;
scriptlibcontext.m_Factory = m_Factory;
scriptlibcontext.m_Register = m_Register;
scriptlibcontext.m_LuaState = L;
scriptlibcontext.m_GraphicsContext = m_GraphicsContext;
scriptlibcontext.m_ScriptContext = m_ScriptContext;
dmGameSystem::InitializeScriptLibs(scriptlibcontext);
dmGameSystem::InitializeScriptLibs(m_Scriptlibcontext);

dmGameObject::HInstance go_base = Spawn(m_Factory, m_Collection, "/collision_object/get_set_error_shape.goc", dmHashString64("/get_set_error_shape_go"), 0, 0, Point3(0, 0, 0), Quat(0, 0, 0, 1), Vector3(1, 1, 1));
ASSERT_NE((void*)0, go_base);

ASSERT_FALSE(dmGameObject::Final(m_Collection));
dmGameSystem::FinalizeScriptLibs(m_Scriptlibcontext);
}

TEST_F(SysTest, LoadBufferSync)
Expand Down