Support directories in VFS via mj_addBufferVFS.
PiperOrigin-RevId: 655286683 Change-Id: I846376a0571d8df28d979beb5981a0cbccd7a04f
This commit is contained in:
committed by
Copybara-Service
parent
2746cb8559
commit
5ac5cfb618
@@ -900,12 +900,12 @@ bool mjCFlexcomp::MakeMesh(mjCModel* model, char* error, int error_sz) {
|
||||
}
|
||||
|
||||
// load resource
|
||||
std::string filename = mjuu_combinePaths(mjs_getString(model->spec.modelfiledir),
|
||||
mjs_getString(model->spec.meshdir), file);
|
||||
std::string filename = mjuu_combinePaths(mjs_getString(model->spec.meshdir), file);
|
||||
mjResource* resource = nullptr;
|
||||
|
||||
try {
|
||||
resource = mjCBase::LoadResource(filename, 0);
|
||||
resource = mjCBase::LoadResource(mjs_getString(model->spec.modelfiledir),
|
||||
filename, 0);
|
||||
} catch (mjCError err) {
|
||||
return comperr(error, err.message, error_sz);
|
||||
}
|
||||
@@ -999,12 +999,11 @@ bool mjCFlexcomp::MakeGMSH(mjCModel* model, char* error, int error_sz) {
|
||||
}
|
||||
|
||||
// open resource
|
||||
std::string filename = mjuu_combinePaths(mjs_getString(model->spec.modelfiledir),
|
||||
mjs_getString(model->spec.meshdir), file);
|
||||
mjResource* resource = nullptr;
|
||||
|
||||
try {
|
||||
resource = mjCBase::LoadResource(filename, 0);
|
||||
std::string filename = mjuu_combinePaths(mjs_getString(model->spec.meshdir), file);
|
||||
resource = mjCBase::LoadResource(mjs_getString(model->spec.modelfiledir),
|
||||
filename, 0);
|
||||
} catch (mjCError err) {
|
||||
return comperr(error, err.message, error_sz);
|
||||
}
|
||||
|
||||
@@ -402,8 +402,8 @@ void mjCMesh::Compile(const mjVFS* vfs) {
|
||||
throw mjCError(this, "unsupported content type: '%s'", asset_type.c_str());
|
||||
}
|
||||
|
||||
std::string filename = mjuu_combinePaths(model->modelfiledir_, model->meshdir_, file_);
|
||||
mjResource* resource = LoadResource(filename, vfs);
|
||||
std::string filename = mjuu_combinePaths(model->meshdir_, file_);
|
||||
mjResource* resource = LoadResource(model->modelfiledir_, filename, vfs);
|
||||
|
||||
try {
|
||||
if (asset_type == "model/stl") {
|
||||
@@ -2095,8 +2095,8 @@ void mjCSkin::Compile(const mjVFS* vfs) {
|
||||
throw mjCError(this, "Unknown skin file type: %s", file_.c_str());
|
||||
}
|
||||
|
||||
std::string filename = mjuu_combinePaths(model->modelfiledir_, model->meshdir_, file_);
|
||||
mjResource* resource = LoadResource(filename, vfs);
|
||||
std::string filename = mjuu_combinePaths(model->meshdir_, file_);
|
||||
mjResource* resource = LoadResource(model->modelfiledir_, filename, vfs);
|
||||
|
||||
try {
|
||||
LoadSKN(resource);
|
||||
|
||||
@@ -701,10 +701,12 @@ void mjCBase::NameSpace(const mjCModel* m) {
|
||||
|
||||
|
||||
// load resource if found (fallback to OS filesystem)
|
||||
mjResource* mjCBase::LoadResource(std::string filename, const mjVFS* vfs) {
|
||||
mjResource* mjCBase::LoadResource(const std::string& modelfiledir,
|
||||
const std::string& filename,
|
||||
const mjVFS* vfs) {
|
||||
// try reading from provided VFS or fallback to OS filesystem
|
||||
std::array<char, 1024> error;
|
||||
mjResource* resource = mju_openResource(filename.c_str(), vfs,
|
||||
mjResource* resource = mju_openResource(modelfiledir.c_str(), filename.c_str(), vfs,
|
||||
error.data(), error.size());
|
||||
if (!resource) {
|
||||
throw mjCError(nullptr, "%s", error.data());
|
||||
@@ -3159,8 +3161,8 @@ void mjCHField::Compile(const mjVFS* vfs) {
|
||||
throw mjCError(this, "unsupported content type: '%s'", asset_type.c_str());
|
||||
}
|
||||
|
||||
std::string filename = mjuu_combinePaths(model->modelfiledir_, model->meshdir_, file_);
|
||||
mjResource* resource = LoadResource(filename, vfs);
|
||||
std::string filename = mjuu_combinePaths(model->meshdir_, file_);
|
||||
mjResource* resource = LoadResource(model->modelfiledir_, filename, vfs);
|
||||
|
||||
try {
|
||||
if (asset_type == "image/png") {
|
||||
@@ -3594,7 +3596,7 @@ void mjCTexture::LoadFlip(std::string filename, const mjVFS* vfs,
|
||||
throw mjCError(this, "unsupported content type: '%s'", asset_type.c_str());
|
||||
}
|
||||
|
||||
mjResource* resource = LoadResource(filename, vfs);
|
||||
mjResource* resource = LoadResource(model->modelfiledir_, filename, vfs);
|
||||
|
||||
try {
|
||||
if (asset_type == "image/png") {
|
||||
@@ -3797,7 +3799,7 @@ void mjCTexture::LoadCubeSeparate(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// make filename
|
||||
std::string filename = mjuu_combinePaths(model->modelfiledir_, model->texturedir_, cubefiles_[i]);
|
||||
std::string filename = mjuu_combinePaths(model->texturedir_, cubefiles_[i]);
|
||||
|
||||
// load PNG or custom
|
||||
unsigned int w, h;
|
||||
@@ -3895,7 +3897,7 @@ void mjCTexture::Compile(const mjVFS* vfs) {
|
||||
}
|
||||
|
||||
// make filename
|
||||
std::string filename = mjuu_combinePaths(model->modelfiledir_, model->texturedir_, file_);
|
||||
std::string filename = mjuu_combinePaths(model->texturedir_, file_);
|
||||
|
||||
// dispatch
|
||||
if (type==mjTEXTURE_2D) {
|
||||
|
||||
@@ -181,7 +181,8 @@ class mjCBase : public mjCBase_ {
|
||||
|
||||
public:
|
||||
// load resource if found (fallback to OS filesystem)
|
||||
static mjResource* LoadResource(std::string filename, const mjVFS* vfs);
|
||||
static mjResource* LoadResource(const std::string& modelfiledir,
|
||||
const std::string& filename, const mjVFS* vfs);
|
||||
|
||||
// Get and sanitize content type from raw_text if not empty, otherwise parse
|
||||
// content type from resource_name; throw on failure
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
|
||||
@@ -117,8 +118,8 @@ int FileModified(const mjResource* resource, const char*timestamp) {
|
||||
|
||||
// open the given resource; if the name doesn't have a prefix matching with a
|
||||
// resource provider, then the OS filesystem is used
|
||||
mjResource* mju_openResource(const char* name, const mjVFS* vfs,
|
||||
char* error, size_t nerror) {
|
||||
mjResource* mju_openResource(const char* dir, const char* name,
|
||||
const mjVFS* vfs, char* error, size_t nerror) {
|
||||
// no error so far
|
||||
if (error) {
|
||||
error[0] = '\0';
|
||||
@@ -136,8 +137,10 @@ mjResource* mju_openResource(const char* name, const mjVFS* vfs,
|
||||
// clear out resource
|
||||
memset(resource, 0, sizeof(mjResource));
|
||||
|
||||
// copy name
|
||||
resource->name = (char*) mju_malloc(sizeof(char) * (strlen(name) + 1));
|
||||
// make space for filename
|
||||
std::string fullname = mjuu_combinePaths(dir, name);
|
||||
std::size_t n = fullname.size();
|
||||
resource->name = (char*) mju_malloc(sizeof(char) * (n + 1));
|
||||
if (resource->name == nullptr) {
|
||||
if (error) {
|
||||
strncpy(error, "could not allocate memory", nerror);
|
||||
@@ -146,10 +149,11 @@ mjResource* mju_openResource(const char* name, const mjVFS* vfs,
|
||||
mju_closeResource(resource);
|
||||
return nullptr;
|
||||
}
|
||||
memcpy(resource->name, name, sizeof(char) * (strlen(name) + 1));
|
||||
|
||||
// first priority is to check the VFS
|
||||
if (vfs != nullptr) {
|
||||
memcpy(resource->name, name,
|
||||
sizeof(char) * (std::strlen(name) + 1));
|
||||
const mjpResourceProvider* provider = GetVfsResourceProvider();
|
||||
resource->data = (void*) vfs;
|
||||
resource->provider = provider;
|
||||
@@ -158,8 +162,11 @@ mjResource* mju_openResource(const char* name, const mjVFS* vfs,
|
||||
}
|
||||
}
|
||||
|
||||
// copy full path over
|
||||
memcpy(resource->name, fullname.c_str(), sizeof(char) * (n + 1));
|
||||
|
||||
// find provider based off prefix of name
|
||||
const mjpResourceProvider* provider = mjp_getResourceProvider(name);
|
||||
const mjpResourceProvider* provider = mjp_getResourceProvider(resource->name);
|
||||
if (provider != nullptr) {
|
||||
resource->provider = provider;
|
||||
resource->data = nullptr;
|
||||
@@ -170,7 +177,7 @@ mjResource* mju_openResource(const char* name, const mjVFS* vfs,
|
||||
if (error) {
|
||||
snprintf(error, nerror, "could not open '%s'"
|
||||
"using a resource provider matching prefix '%s'",
|
||||
name, provider->prefix);
|
||||
resource->name, provider->prefix);
|
||||
}
|
||||
|
||||
mju_closeResource(resource);
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
#define MUJOCO_SRC_ENGINE_ENGINE_RESOURCE_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
|
||||
#include <mujoco/mjexport.h>
|
||||
#include <mujoco/mujoco.h>
|
||||
@@ -30,8 +28,8 @@ extern "C" {
|
||||
|
||||
// open the given resource; if the name doesn't have a prefix matching with a
|
||||
// resource provider, then the OS filesystem is used
|
||||
MJAPI mjResource* mju_openResource(const char* name, const mjVFS* vfs,
|
||||
char* error, std::size_t nerror);
|
||||
MJAPI mjResource* mju_openResource(const char* dir, const char* name,
|
||||
const mjVFS* vfs, char* error, size_t nerror);
|
||||
|
||||
// close the given resource; no-op if resource is NULL
|
||||
MJAPI void mju_closeResource(mjResource* resource);
|
||||
|
||||
+12
-7
@@ -142,9 +142,13 @@ int Open(mjResource* resource) {
|
||||
const VFS* cvfs = GetVFSImpl(vfs);
|
||||
const VFSFile* file = cvfs->GetFile(StripPath(resource->name));
|
||||
if (file == nullptr) {
|
||||
return 0;
|
||||
file = cvfs->GetFile(FilePath(resource->name));
|
||||
if (file == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
resource->data = (void*) file;
|
||||
resource->timestamp[0] = '\0';
|
||||
if (file->filestamp) {
|
||||
mju_encodeBase64(resource->timestamp, (uint8_t*) &file->filestamp,
|
||||
@@ -160,8 +164,7 @@ int Read(mjResource* resource, const void** buffer) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const VFS* vfs = GetVFSImpl(static_cast<const mjVFS*>(resource->data));
|
||||
const VFSFile* file = vfs->GetFile(StripPath(resource->name));
|
||||
const VFSFile* file = static_cast<const VFSFile*>(resource->data);
|
||||
if (file == nullptr) {
|
||||
*buffer = nullptr;
|
||||
return -1;
|
||||
@@ -193,8 +196,7 @@ int Modified(const mjResource* resource, const char* timestamp) {
|
||||
if (!filestamp) return 3; // no hash (assume modified)
|
||||
|
||||
if (resource) {
|
||||
const VFS* cvfs = GetVFSImpl(static_cast<const mjVFS*>(resource->data));
|
||||
const VFSFile* file = cvfs->GetFile(StripPath(resource->name));
|
||||
const VFSFile* file = static_cast<const VFSFile*>(resource->data);
|
||||
if (file == nullptr) return 4; // missing file (assume modified)
|
||||
if (!file->filestamp) return 5; // missing filestamp (assume modified)
|
||||
|
||||
@@ -245,7 +247,7 @@ int mj_addBufferVFS(mjVFS* vfs, const char* name, const void* buffer,
|
||||
std::vector<uint8_t> inbuffer;
|
||||
VFS* cvfs = GetVFSImpl(vfs);
|
||||
VFSFile* file;
|
||||
if (!(file = cvfs->AddFile(StripPath(name), std::move(inbuffer), 0))) {
|
||||
if (!(file = cvfs->AddFile(FilePath(name), std::move(inbuffer), 0))) {
|
||||
return 2; // AddFile failed, repeated name
|
||||
}
|
||||
file->filedata.reserve(nbuffer);
|
||||
@@ -256,7 +258,10 @@ int mj_addBufferVFS(mjVFS* vfs, const char* name, const void* buffer,
|
||||
// delete file from VFS, return 0: success, -1: not found in VFS
|
||||
int mj_deleteFileVFS(mjVFS* vfs, const char* filename) {
|
||||
VFS* cvfs = GetVFSImpl(vfs);
|
||||
return cvfs->DeleteFile(StripPath(filename));
|
||||
if (cvfs->DeleteFile(StripPath(filename))) {
|
||||
return cvfs->DeleteFile(FilePath(filename));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// delete all files from VFS
|
||||
|
||||
Reference in New Issue
Block a user