Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions defold-rive/src/comp_rive_databinding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,12 @@ uint32_t CompRiveCreateViewModelInstanceRuntime(RiveComponent* component, dmhash
return handle;
}

rive::ViewModelInstanceRuntime* CompRiveGetViewModelInstance(RiveComponent* component)
{
rive::ViewModelInstanceRuntime* vmir = FromHandle(component, component->m_CurrentViewModelInstanceRuntime);
return vmir;
}

bool CompRiveDestroyViewModelInstanceRuntime(RiveComponent* component, uint32_t handle)
{
rive::ViewModelInstanceRuntime* vmir = FromHandle(component, handle);
Expand Down
3 changes: 2 additions & 1 deletion defold-rive/src/comp_rive_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ namespace dmRive
bool CompRiveRuntimeListAddInstance(RiveComponent* component, uint32_t handle, const char* path, uint32_t instance);
bool CompRiveRuntimeListRemoveInstance(RiveComponent* component, uint32_t handle, const char* path, uint32_t instance);

RiveSceneData* CompRiveGetRiveSceneData(RiveComponent* component);
RiveSceneData* CompRiveGetRiveSceneData(RiveComponent* component);
rive::ViewModelInstanceRuntime* CompRiveGetViewModelInstance(RiveComponent* component);
}

#endif //DM_COMP_RIVE_PRIVATE_H
13 changes: 7 additions & 6 deletions defold-rive/src/res_rive_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace dmRive
{
static void SetupData(RiveSceneData* scene_data, rive::File* file, const char* path, HRenderContext rive_render_context)
{
scene_data->m_PathHash = dmHashString64(path);
scene_data->m_File = file;
scene_data->m_RiveRenderContext = rive_render_context;
scene_data->m_ArtboardDefault = scene_data->m_File->artboardDefault();
Expand Down Expand Up @@ -98,13 +99,13 @@ namespace dmRive
rive::Span<const uint8_t> data((const uint8_t*)params->m_Buffer, params->m_BufferSize);

// Creates DefoldRenderImage with a hashed name for each image resource
AtlasNameResolver atlas_resolver = AtlasNameResolver(params->m_Factory, render_context_res);
rive::rcp<AtlasNameResolver> atlas_resolver(new AtlasNameResolver(params->m_Factory, render_context_res));

rive::ImportResult result;
rive::rcp<rive::File> file = rive::File::import(data,
rive_factory,
&result,
(rive::FileAssetLoader*) &atlas_resolver);
atlas_resolver);

if (result != rive::ImportResult::success)
{
Expand All @@ -113,7 +114,7 @@ namespace dmRive
}

RiveSceneData* scene_data = new RiveSceneData();
scene_data->m_FileAssets.Swap(atlas_resolver.GetAssets());
scene_data->m_FileAssets.Swap(atlas_resolver->GetAssets());
SetupData(scene_data, file.release(), params->m_Filename, render_context_res);

dmResource::SetResource(params->m_Resource, scene_data);
Expand Down Expand Up @@ -146,13 +147,13 @@ namespace dmRive

rive::Factory* rive_factory = GetRiveFactory(render_context_res);

AtlasNameResolver atlas_resolver = AtlasNameResolver(params->m_Factory, render_context_res);
rive::rcp<AtlasNameResolver> atlas_resolver(new AtlasNameResolver(params->m_Factory, render_context_res));

rive::ImportResult result;
rive::rcp<rive::File> file = rive::File::import(data,
rive_factory,
&result,
&atlas_resolver);
atlas_resolver);

if (result != rive::ImportResult::success)
{
Expand All @@ -169,7 +170,7 @@ namespace dmRive

RiveSceneData* scene_data = new RiveSceneData();

scene_data->m_FileAssets.Swap(atlas_resolver.GetAssets());
scene_data->m_FileAssets.Swap(atlas_resolver->GetAssets());
SetupData(scene_data, file.release(), params->m_Filename, render_context_res);

dmResource::SetResource(params->m_Resource, scene_data);
Expand Down
1 change: 1 addition & 0 deletions defold-rive/src/res_rive_data.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ namespace dmRive

struct RiveSceneData
{
dmhash_t m_PathHash; // for printing debug info
rive::File* m_File;
HRenderContext m_RiveRenderContext;
std::unique_ptr<rive::ArtboardInstance> m_ArtboardDefault;
Expand Down
159 changes: 157 additions & 2 deletions defold-rive/src/script_rive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "comp_rive_private.h"
#include "rive_ddf.h"
#include "res_rive_data.h"
#include "script_rive_private.h"


namespace dmRive
Expand Down Expand Up @@ -490,6 +491,154 @@ namespace dmRive
return 0;
}

static dmhash_t GetCanonicalPathHash(const char* path)
{
char canonical_path[1024];
uint32_t path_len = dmResource::GetCanonicalPath(path, canonical_path, sizeof(canonical_path));
return dmHashBuffer64(canonical_path, path_len);
}

// TODO: Move this function into dmScript namespace
static void PreCreateResources(lua_State* L, const char* path_str, const char** supported_exts, uint32_t num_supported_exts, dmhash_t* canonical_path_hash_out)
{
const char* path_ext = dmResource::GetExtFromPath(path_str);
while (path_ext[0] == '.')
path_ext++;

bool path_ok = false;
if (path_ext)
{
for (uint32_t i = 0; i < num_supported_exts; ++i)
{
const char* ext = supported_exts[i];

if (dmStrCaseCmp(path_ext, ext) == 0)
{
path_ok = true;
break;
}
}
}

if (!path_ok)
{
char message[1024];
dmSnPrintf(message, sizeof(message), "Unable to create resource, path '%s' must have any of the following extensions: ", path_str);
for (uint32_t i = 0; i < num_supported_exts; ++i)
{
dmStrlCat(message, supported_exts[i], sizeof(message));
}
luaL_error(L, "%s", message);
}

dmhash_t canonical_path_hash = GetCanonicalPathHash(path_str);

HResourceDescriptor rd = 0;
ResourceResult r = ResourceGetDescriptorByHash((HResourceFactory)g_Factory, canonical_path_hash, &rd);
if (r == RESOURCE_RESULT_OK || rd != 0)
{
luaL_error(L, "Unable to create resource, a resource is already registered at path '%s'", path_str);
}

*canonical_path_hash_out = canonical_path_hash;
}

static void PreCreateResource(lua_State* L, const char* path_str, const char* path_ext_wanted, dmhash_t* canonical_path_hash_out)
{
PreCreateResources(L, path_str, &path_ext_wanted, 1, canonical_path_hash_out);
}

static void PushResourceError(lua_State* L, ResourceResult result, dmhash_t path_hash)
{
const char* format = 0;
switch(result)
{
case RESOURCE_RESULT_RESOURCE_NOT_FOUND: format = "The resource was not found (%d): %llu, %s"; break;
case RESOURCE_RESULT_NOT_SUPPORTED: format = "The resource type does not support this operation (%d): %llu, %s"; break;
default: format = "The resource was not updated (%d): %llu, %s"; break;
}
lua_pushfstring(L, format, (unsigned long long)path_hash, dmHashReverseSafe64(path_hash));
}

// TODO: from internal script_resource.cpp. Move to public dmsdk
static int ReportPathError(lua_State* L, ResourceResult result, dmhash_t path_hash)
{
char msg[256];
const char* format = 0;
switch(result)
{
case RESOURCE_RESULT_RESOURCE_NOT_FOUND: format = "The resource was not found (%d): %llu, %s"; break;
case RESOURCE_RESULT_NOT_SUPPORTED: format = "The resource type does not support this operation (%d): %llu, %s"; break;
default: format = "The resource was not updated (%d): %llu, %s"; break;
}
dmSnPrintf(msg, sizeof(msg), format, result, (unsigned long long)path_hash, dmHashReverseSafe64(path_hash));
return luaL_error(L, "%s", msg);
}

// TODO: from internal script_resource.cpp. Move to public dmsdk
static void* CheckResource(lua_State* L, dmResource::HFactory factory, dmhash_t path_hash, const char* resource_ext)
{
HResourceDescriptor rd = 0;
ResourceResult r = ResourceGetDescriptorByHash((HResourceFactory)factory, path_hash, &rd);
if (r != RESOURCE_RESULT_OK)
{
luaL_error(L, "Could not get %s type resource: %s", resource_ext, dmHashReverseSafe64(path_hash));
return 0;
}

HResourceType expected_resource_type;
r = ResourceGetTypeFromExtension(factory, resource_ext, &expected_resource_type);
if( r != RESOURCE_RESULT_OK )
{
ReportPathError(L, r, path_hash);
}

HResourceType resource_type = ResourceDescriptorGetType(rd);
if (resource_type != expected_resource_type)
{
luaL_error(L, "Resource %s is not of type %s.", dmHashReverseSafe64(path_hash), resource_ext);
return 0;
}

return ResourceDescriptorGetResource(rd);
}

static int RiveComp_CreateRivFromMemory(lua_State* L)
{
int top = lua_gettop(L);

const char* path = luaL_checkstring(L, 1); // path to be associated with this resource

size_t data_length = 0;
const char* data = luaL_checklstring(L, 2, &data_length);

dmGameObject::HInstance instance = dmScript::CheckGOInstance(L);
dmGameObject::HCollection collection = dmGameObject::GetCollection(instance);

dmhash_t path_hash;
PreCreateResource(L, path, "rivc", &path_hash); // create the hash, and check that no other resource is registered with the same hash

void* resource = 0;
ResourceResult r = ResourceCreateResource(g_Factory, path, (void*)data, data_length, &resource);
if (r != RESOURCE_RESULT_OK)
{
assert(top == lua_gettop(L));

lua_pushnil(L);
PushResourceError(L, r, path_hash);
return 2;
}

// Pass ownership of the resource to the current collection
dmGameObject::AddDynamicResourceHash(collection, path_hash);
dmScript::PushHash(L, path_hash);
lua_pushnil(L);

assert((top+2) == lua_gettop(L));
return 2;
}


// This is an "all bets are off" mode.
static int RiveComp_DebugSetBlitMode(lua_State* L)
{
Expand Down Expand Up @@ -521,17 +670,23 @@ namespace dmRive
{"debug_set_blit_mode", RiveComp_DebugSetBlitMode},

{"riv_swap_asset", RiveComp_RivSwapAsset},

{"create_riv_from_memory", RiveComp_CreateRivFromMemory},
{0, 0}
};

extern void ScriptInitializeDataBinding(lua_State* L, dmResource::HFactory factory);

void ScriptRegister(lua_State* L, dmResource::HFactory factory)
{
// deprecated
luaL_register(L, "rive", RIVE_FUNCTIONS);
ScriptInitializeDataBinding(L, factory);
lua_pop(L, 1);

ScriptInitializeFile(L, factory);
ScriptInitializeArtboard(L, factory);
ScriptInitializeViewModel(L, factory);
ScriptInitializeViewModelProperty(L, factory);

g_Factory = factory;
}
}
Expand Down
Loading
Loading