Working on studio resources and adding folder suport
This commit is contained in:
parent
1af4547c97
commit
7489393d3d
@ -2,14 +2,16 @@
|
|||||||
#include "DeerCore/Serialization/WorldSettings.h"
|
#include "DeerCore/Serialization/WorldSettings.h"
|
||||||
#include "DeerCore/Tools/Path.h"
|
#include "DeerCore/Tools/Path.h"
|
||||||
|
|
||||||
|
#include <strstream>
|
||||||
|
|
||||||
namespace Deer {
|
namespace Deer {
|
||||||
class World;
|
class World;
|
||||||
class WorldSettings;
|
class WorldSettings;
|
||||||
|
|
||||||
namespace Universe {
|
namespace Universe {
|
||||||
World* createWorld(const WorldSettings&);
|
World* createWorld(const WorldSettings&);
|
||||||
World* loadWorldFromJson(const WorldSettings&, WorldSerializationSettings&, const Path&);
|
|
||||||
|
|
||||||
|
World* loadWorldFromJson(const WorldSettings&, WorldSerializationSettings&, const Path&);
|
||||||
void saveWorldInJson(World*, WorldSerializationSettings& serializationSettings, const Path& path);
|
void saveWorldInJson(World*, WorldSerializationSettings& serializationSettings, const Path& path);
|
||||||
|
|
||||||
void destroyAllWorlds();
|
void destroyAllWorlds();
|
||||||
|
|||||||
@ -42,13 +42,11 @@ namespace Deer {
|
|||||||
template <typename DataSource>
|
template <typename DataSource>
|
||||||
class StorageBackend {
|
class StorageBackend {
|
||||||
public:
|
public:
|
||||||
static StorageData loadData(const std::string& location);
|
static StorageData loadData(const std::string& id);
|
||||||
static void saveData(const std::string& location, const StorageData& data);
|
static void saveData(const std::string& id, const StorageData& data);
|
||||||
|
|
||||||
static StorageMetadata loadMetadata(const std::string& location);
|
static StorageMetadata loadMetadata(const std::string& id);
|
||||||
static void saveMetadata(const StorageMetadata& metadata, const std::string& location);
|
static void saveMetadata(const StorageMetadata& metadata, const std::string& id);
|
||||||
|
|
||||||
static std::vector<std::string> indexResources(const std::string& location);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename DataSource>
|
template <typename DataSource>
|
||||||
|
|||||||
36
DeerStudio/headers/DeerStudio/StudioResources.h
Normal file
36
DeerStudio/headers/DeerStudio/StudioResources.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "cereal/cereal.hpp"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
enum class ResourceType : int {
|
||||||
|
NONE = 0,
|
||||||
|
MESH = 1,
|
||||||
|
SHADER = 2,
|
||||||
|
TEXTURE = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ResourceInformation {
|
||||||
|
time_t lastUpdate;
|
||||||
|
std::string resourcePath;
|
||||||
|
ResourceType resourceType;
|
||||||
|
uint32_t resourceId;
|
||||||
|
|
||||||
|
// Metadata...
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void serialize(Archive& archive) {
|
||||||
|
archive(cereal::make_nvp("Id", resourceId));
|
||||||
|
archive(cereal::make_nvp("Path", resourcePath));
|
||||||
|
archive(cereal::make_nvp("Type", resourceType));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace StudioResources {
|
||||||
|
ResourceInformation* getResourceInfoFromPath(const std::string& path);
|
||||||
|
ResourceInformation* getResourceInfoFromId(uint32_t resource);
|
||||||
|
|
||||||
|
void scanResources();
|
||||||
|
} // namespace StudioResources
|
||||||
|
} // namespace Deer
|
||||||
@ -10,6 +10,7 @@
|
|||||||
#include "DeerStudio/EditorDataImporter.h"
|
#include "DeerStudio/EditorDataImporter.h"
|
||||||
#include "DeerStudio/EditorDataSource.h"
|
#include "DeerStudio/EditorDataSource.h"
|
||||||
#include "DeerStudio/ResourceDataSource.h"
|
#include "DeerStudio/ResourceDataSource.h"
|
||||||
|
#include "DeerStudio/StudioResources.h"
|
||||||
|
|
||||||
// TMP
|
// TMP
|
||||||
#include "DeerCore/EntityEnviroment.h"
|
#include "DeerCore/EntityEnviroment.h"
|
||||||
@ -52,6 +53,7 @@ namespace Deer {
|
|||||||
world = Universe::createWorld(worldSettings);
|
world = Universe::createWorld(worldSettings);
|
||||||
|
|
||||||
while (world) {
|
while (world) {
|
||||||
|
StudioResources::scanResources();
|
||||||
StudioPanel::setWorld(world);
|
StudioPanel::setWorld(world);
|
||||||
world->execute();
|
world->execute();
|
||||||
}
|
}
|
||||||
|
|||||||
234
DeerStudio/src/DeerStudio/StudioResources.cpp
Normal file
234
DeerStudio/src/DeerStudio/StudioResources.cpp
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
#include "DeerStudio/StudioResources.h"
|
||||||
|
#include "DeerCore/Tools/Path.h"
|
||||||
|
|
||||||
|
#include "cereal/archives/json.hpp"
|
||||||
|
|
||||||
|
#include "cereal/types/string.hpp"
|
||||||
|
#include "cereal/types/vector.hpp"
|
||||||
|
|
||||||
|
#include "DeerCore/Log.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <random>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace cereal {
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
std::string save_minimal(Archive const&, const Deer::ResourceType& type) {
|
||||||
|
switch (type) {
|
||||||
|
case Deer::ResourceType::NONE:
|
||||||
|
return "NONE";
|
||||||
|
case Deer::ResourceType::MESH:
|
||||||
|
return "MESH";
|
||||||
|
case Deer::ResourceType::SHADER:
|
||||||
|
return "SHADER";
|
||||||
|
case Deer::ResourceType::TEXTURE:
|
||||||
|
return "TEXTURE";
|
||||||
|
}
|
||||||
|
return "NONE";
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Archive>
|
||||||
|
void load_minimal(Archive const&, Deer::ResourceType& type, const std::string& value) {
|
||||||
|
if (value == "MESH")
|
||||||
|
type = Deer::ResourceType::MESH;
|
||||||
|
else if (value == "SHADER")
|
||||||
|
type = Deer::ResourceType::SHADER;
|
||||||
|
else if (value == "TEXTURE")
|
||||||
|
type = Deer::ResourceType::TEXTURE;
|
||||||
|
else
|
||||||
|
type = Deer::ResourceType::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cereal
|
||||||
|
|
||||||
|
namespace Deer {
|
||||||
|
struct FolderInfo {
|
||||||
|
std::string name;
|
||||||
|
std::string parent;
|
||||||
|
std::vector<uint32_t> resources;
|
||||||
|
std::vector<std::string> subfolders;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace StudioResources {
|
||||||
|
std::vector<ResourceInformation> resources;
|
||||||
|
std::unordered_map<std::string, size_t> resourcePathToIndex;
|
||||||
|
std::unordered_map<uint32_t, size_t> resourceIdToIndex;
|
||||||
|
|
||||||
|
std::vector<FolderInfo> folders;
|
||||||
|
std::unordered_map<uint32_t, size_t> resourceIdToFolderIndex;
|
||||||
|
std::unordered_map<std::string, size_t> folderPathToFolderIndex;
|
||||||
|
|
||||||
|
ResourceType getResourceType(const std::string& dir) {
|
||||||
|
Path path(dir);
|
||||||
|
std::string extension = path.extension().string();
|
||||||
|
|
||||||
|
if (extension == ".obj" || extension == ".fbx" || extension == ".dae" ||
|
||||||
|
extension == ".3ds" || extension == ".ply" || extension == ".stl" ||
|
||||||
|
extension == ".glb" || extension == ".gltf") {
|
||||||
|
return ResourceType::MESH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extension == ".glsl")
|
||||||
|
return ResourceType::SHADER;
|
||||||
|
|
||||||
|
if (extension == ".png")
|
||||||
|
return ResourceType::TEXTURE;
|
||||||
|
|
||||||
|
return ResourceType::NONE;
|
||||||
|
};
|
||||||
|
} // namespace StudioResources
|
||||||
|
|
||||||
|
ResourceInformation* StudioResources::getResourceInfoFromPath(const std::string& path) {
|
||||||
|
if (!resourceMap.contains(path))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return resources[resourceMap[path]];
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceInformation* StudioResources::getResourceInfoFromId(uint32_t resource) {
|
||||||
|
if (!resourceIdToIndex.contains(resource))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return resources[resourceIdToIndex[resource]];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getFolderIndex(std::string folder) {
|
||||||
|
size_t folderIndex;
|
||||||
|
|
||||||
|
FolderInfo & folder;
|
||||||
|
if (folderPathToFolderIndex.contains(folderIndex)) {
|
||||||
|
folderIndex = folderPathToFolderIndex[folderPathStr];
|
||||||
|
folder = folders[folderIndex];
|
||||||
|
} else {
|
||||||
|
newFolder.name = folderPath.filename().string();
|
||||||
|
newFolder.fullPath = folderPathStr;
|
||||||
|
folders.push_back(std::move(newFolder));
|
||||||
|
folder = folders.back();
|
||||||
|
|
||||||
|
folderPathToFolderIndex[folderPathStr] = folders.size() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void addFolderToFolder(std::string childFolder, std::string parentFolder) {
|
||||||
|
FolderInfo & folder;
|
||||||
|
if (folderPathToFolderIndex.contains(folderIndex)) {
|
||||||
|
folderIndex = folderPathToFolderIndex[folderPathStr];
|
||||||
|
folder = folders[folderIndex];
|
||||||
|
} else {
|
||||||
|
newFolder.name = folderPath.filename().string();
|
||||||
|
newFolder.fullPath = folderPathStr;
|
||||||
|
folders.push_back(std::move(newFolder));
|
||||||
|
folder = folders.back();
|
||||||
|
|
||||||
|
folderPathToFolderIndex[folderPathStr] = folders.size() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void StudioResources::scanResources() {
|
||||||
|
resources.clear();
|
||||||
|
resourcePathToIndex.clear();
|
||||||
|
resourceIdToIndex.clear();
|
||||||
|
|
||||||
|
folders.clear();
|
||||||
|
resourceIdToFolderIndex.clear();
|
||||||
|
folderPathToFolderIndex.clear();
|
||||||
|
|
||||||
|
Path resourcePath("Resources");
|
||||||
|
Path resourceJsonPath = resourcePath / "ResourceData.json";
|
||||||
|
if (std::filesystem::exists(resourceJsonPath)) {
|
||||||
|
std::ifstream inputStream(resourceJsonPath);
|
||||||
|
if (inputStream) {
|
||||||
|
try {
|
||||||
|
cereal::JSONInputArchive archive(inputStream);
|
||||||
|
archive(cereal::make_nvp("Resources", resources));
|
||||||
|
} catch (cereal::Exception& exception) {
|
||||||
|
DEER_CORE_ERROR("Error loading resources JSON \n{}", exception.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& file : std::filesystem::recursive_directory_iterator(resourcePath)) {
|
||||||
|
Path filePath = file.path();
|
||||||
|
ResourceType type = getResourceType(filePath);
|
||||||
|
|
||||||
|
if (type == ResourceType::NONE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::string pathId = filePath.lexically_relative(resourcePath).generic_string().c_str();
|
||||||
|
ResourceInformation* referencingResource = getResourceInfoFromPath(pathId);
|
||||||
|
|
||||||
|
if (!referencingResource) {
|
||||||
|
ResourceInformation resourceInformation = {
|
||||||
|
.resourceId = std::random_device{}(),
|
||||||
|
.resourcePath = pathId,
|
||||||
|
.resourceType = type};
|
||||||
|
|
||||||
|
resources.push_back(resourceInformation);
|
||||||
|
referencingResource = &resources.back();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ftime = file.last_write_time();
|
||||||
|
auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(ftime - std::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now());
|
||||||
|
|
||||||
|
referencingResource->lastUpdate = std::chrono::system_clock::to_time_t(sctp);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < resources.size(); i++) {
|
||||||
|
const ResourceInformation& ri = resources[i];
|
||||||
|
|
||||||
|
resourceIdToIndex[ri.resourceId] = i;
|
||||||
|
resourcePathToIndex[ri.resourcePath] = i;
|
||||||
|
|
||||||
|
Path resourceFullPath = ri.resourcePath;
|
||||||
|
Path folderPath = resourceFullPath.parent_path();
|
||||||
|
|
||||||
|
std::string folderPathStr = folderPath.generic_string();
|
||||||
|
size_t folderIndex;
|
||||||
|
|
||||||
|
FolderInfo & folder;
|
||||||
|
if (folderPathToFolderIndex.contains(folderIndex)) {
|
||||||
|
folderIndex = folderPathToFolderIndex[folderPathStr];
|
||||||
|
folder = folders[folderIndex];
|
||||||
|
} else {
|
||||||
|
newFolder.name = folderPath.filename().string();
|
||||||
|
newFolder.fullPath = folderPathStr;
|
||||||
|
folders.push_back(std::move(newFolder));
|
||||||
|
folder = folders.back();
|
||||||
|
|
||||||
|
folderPathToFolderIndex[folderPathStr] = folders.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
newFolder.resources.push_back(ri.resourceId);
|
||||||
|
|
||||||
|
// Check if folder already exists
|
||||||
|
auto it = folderPathToIndex.find(folderPathStr);
|
||||||
|
if (it != folderPathToIndex.end()) {
|
||||||
|
folderIndex = it->second;
|
||||||
|
} else {
|
||||||
|
// Create new folder
|
||||||
|
}
|
||||||
|
|
||||||
|
// If folder exists, just append resource
|
||||||
|
if (it != folderPathToIndex.end()) {
|
||||||
|
folders[folderIndex].resources.push_back(ri.resourceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map resource -> folder ID for fast lookup
|
||||||
|
resourceIdToFolderIndex[ri.resourceId] = static_cast<uint32_t>(folderIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::ofstream outputStream(resourceJsonPath);
|
||||||
|
if (!outputStream) {
|
||||||
|
DEER_CORE_ERROR("Failed opening {} for writing", resourceJsonPath.string());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cereal::JSONOutputArchive archive(outputStream);
|
||||||
|
archive(cereal::make_nvp("Resources", resources));
|
||||||
|
}
|
||||||
|
} // namespace Deer
|
||||||
|
} // namespace Deer
|
||||||
269
Resources/ResourceData.json
Normal file
269
Resources/ResourceData.json
Normal file
@ -0,0 +1,269 @@
|
|||||||
|
{
|
||||||
|
"Resources": [
|
||||||
|
{
|
||||||
|
"Id": 3069814959,
|
||||||
|
"Path": "shader_uv.glsl",
|
||||||
|
"Type": "SHADER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 104674944,
|
||||||
|
"Path": "shader_darkBlue.glsl",
|
||||||
|
"Type": "SHADER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2366771542,
|
||||||
|
"Path": "normal.glsl",
|
||||||
|
"Type": "SHADER"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2694733599,
|
||||||
|
"Path": "train-locomotive-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 4256579129,
|
||||||
|
"Path": "Kenney/OBJ format/ship-ocean-liner.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3739632882,
|
||||||
|
"Path": "Kenney/OBJ format/boat-fan.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3532984180,
|
||||||
|
"Path": "Kenney/OBJ format/boat-row-small.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1925528477,
|
||||||
|
"Path": "Kenney/OBJ format/boat-tug-b.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2275934537,
|
||||||
|
"Path": "Kenney/OBJ format/ship-large.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 95651136,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2559379043,
|
||||||
|
"Path": "Kenney/OBJ format/cargo-pile-b.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 4114347144,
|
||||||
|
"Path": "Kenney/OBJ format/cargo-container-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1349019805,
|
||||||
|
"Path": "Kenney/OBJ format/ship-ocean-liner-small.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1178824383,
|
||||||
|
"Path": "Kenney/OBJ format/boat-house-b.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1756987657,
|
||||||
|
"Path": "Kenney/OBJ format/boat-house-d.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2681564794,
|
||||||
|
"Path": "Kenney/OBJ format/cargo-pile-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3501520615,
|
||||||
|
"Path": "Kenney/OBJ format/cargo-container-b.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3889696810,
|
||||||
|
"Path": "Kenney/OBJ format/boat-tug-c.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 852751301,
|
||||||
|
"Path": "Kenney/OBJ format/boat-sail-b.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1602018002,
|
||||||
|
"Path": "Kenney/OBJ format/boat-house-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3198781315,
|
||||||
|
"Path": "Kenney/OBJ format/ship-small-ghost.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 311499906,
|
||||||
|
"Path": "Kenney/OBJ format/cargo-container-c.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 4215786342,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-h.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 4100856350,
|
||||||
|
"Path": "Kenney/OBJ format/ramp.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3814904649,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-e.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2019280713,
|
||||||
|
"Path": "Kenney/OBJ format/arrow.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1507032232,
|
||||||
|
"Path": "Kenney/OBJ format/boat-tow-b.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 198501249,
|
||||||
|
"Path": "Kenney/OBJ format/ramp-wide.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 4136095909,
|
||||||
|
"Path": "Kenney/OBJ format/boat-tow-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1565745400,
|
||||||
|
"Path": "Kenney/OBJ format/boat-sail-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 919433681,
|
||||||
|
"Path": "Kenney/OBJ format/boat-fishing-small.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1374732749,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-i.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 434341145,
|
||||||
|
"Path": "Kenney/OBJ format/arrow-standing.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 500626431,
|
||||||
|
"Path": "Kenney/OBJ format/boat-tug-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3009449850,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-c.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1928134758,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-d.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 815434663,
|
||||||
|
"Path": "Kenney/OBJ format/gate-finish.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 584294637,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-g.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2079718166,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-b.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2407778965,
|
||||||
|
"Path": "Kenney/OBJ format/buoy.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2607493592,
|
||||||
|
"Path": "Kenney/OBJ format/ship-cargo-c.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2561363166,
|
||||||
|
"Path": "Kenney/OBJ format/ship-cargo-a.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3016804499,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-j.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2318332737,
|
||||||
|
"Path": "Kenney/OBJ format/ship-small.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3596619090,
|
||||||
|
"Path": "Kenney/OBJ format/boat-speed-f.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2289035505,
|
||||||
|
"Path": "Kenney/OBJ format/boat-row-large.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 4228274168,
|
||||||
|
"Path": "Kenney/OBJ format/gate.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 202169080,
|
||||||
|
"Path": "Kenney/OBJ format/ship-cargo-b.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 2037323258,
|
||||||
|
"Path": "Kenney/OBJ format/buoy-flag.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3045406746,
|
||||||
|
"Path": "Kenney/OBJ format/boat-house-c.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 1098769283,
|
||||||
|
"Path": "Kenney/Textures/colormap.png",
|
||||||
|
"Type": "TEXTURE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 360224249,
|
||||||
|
"Path": "monkey.obj",
|
||||||
|
"Type": "MESH"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Id": 3705973655,
|
||||||
|
"Path": "shader.glsl",
|
||||||
|
"Type": "SHADER"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user