Cogs.Core
ResourceFunctions.cpp
1#include "ResourceFunctions.h"
2#include "BridgeResourceType.h"
3
4#include "Context.h"
5#include "FieldSetter.h"
6#include "Types.h"
7
8#include "Resources/BufferManager.h"
9#include "Resources/MeshManager.h"
10#include "Resources/AssetManager.h"
11#include "Resources/ModelManager.h"
12#include "Resources/TextureManager.h"
13#include "Resources/FontManager.h"
14#include "Resources/ResourceStore.h"
15
16#include "Resources/MaterialInstance.h"
17#include "Resources/MaterialManager.h"
18#include "Resources/ModelManager.h"
19
20#include "Rendering/DataFormat.h"
21
22#include "Foundation/Logging/Logger.h"
23
24using namespace Cogs::Core;
25
26namespace
27{
29
30
32 constexpr std::array typeMap = {
33 VertexDataType::Positions, // VertexFormats::Pos3f;
34 VertexDataType::Normals, // VertexFormats::Norm3f;
35 VertexDataType::TexCoords0, // VertexFormats::Tex2f;
36 VertexDataType::Tangents, // VertexFormats::Tang3f;
37 VertexDataType::Colors0, // VertexFormats::Color4f;
38 VertexDataType::Positions, // VertexFormats::InstancePos3f;
39 VertexDataType::Colors0 // VertexFormats::InstanceColor4f;
40 };
41
42 VertexDataType::EVertexDataType getStreamDataType(int managedStreamId)
43 {
44 const size_t managedStreamIndex = static_cast<size_t>(managedStreamId);
45 if (managedStreamIndex < typeMap.size()) {
46 return typeMap[managedStreamIndex];
47 }
48 else {
49 return VertexDataType::Reserved;
50 }
51 }
52
53 void logInvalidResource(const char* method, const ResourceId resourceId)
54 {
55 LOG_ERROR(logger, "%s: Invalid Resource id: %d", method, resourceId);
56 }
57
63 Cogs::Core::ResourceManagerBase* getResourceManager(Cogs::Core::Context* context, BridgeResourceType resourceType)
64 {
65 switch (resourceType) {
66 case BridgeResourceType::Asset:
67 return context->assetManager;
68 case BridgeResourceType::Buffer:
69 return context->bufferManager;
70 case BridgeResourceType::Font:
71 return context->fontManager;
72 case BridgeResourceType::Material:
73 return context->materialManager;
74 case BridgeResourceType::MaterialInstance:
75 return context->materialInstanceManager;
76 case BridgeResourceType::Mesh:
77 return context->meshManager;
78 case BridgeResourceType::Model:
79 return context->modelManager;
80 case BridgeResourceType::Texture:
81 return context->textureManager;
82 default:
83 return nullptr;
84 }
85 }
86
88 std::string getMaterialInstanceVariantOutput;
89
90}
91
92// The bridge API uses "BridgeContext" in callbacks. Internally, Cogs.Core uses "Cogs::Core::Context"
93// Add ActualXXXCallback here to catch at compile time if the definitions in definition in Cogs.Core is modified,
94// to avoid undefined behavior when reinterpret_casting between function pointers.
95void setResourceLoadCallback(BridgeContext * ctx, ::ResourceLoadCallback * callback)
96{
97 auto context = static_cast<Context*>(ctx);
98
99 using ActualResourceLoadCallback = void (Cogs::Core::Context* context, int resourceType, ResourceId resourceId, int code);
100 context->callbacks.resourceLoadCallback = reinterpret_cast<ActualResourceLoadCallback*>(callback);
101}
102
103void setHierarchyChangeCallback(BridgeContext * ctx, ::HierarchyChangeCallback * callback)
104{
105 auto context = static_cast<Context*>(ctx);
106
107 using ActualHierarchyChangeCallback = void (Cogs::Core::Context* context, EntityId entityId);
108 context->callbacks.hierarchyChangeCallback = reinterpret_cast<ActualHierarchyChangeCallback*>(callback);
109}
110
111void setReadbackCallback(BridgeContext * ctx, ::ReadbackCallback * callback)
112{
113 auto context = static_cast<Context*>(ctx);
114
115 using ActualReadbackCallback = void (Cogs::Core::Context* context, const char* key, const void* data, int size);
116 context->callbacks.readbackCallback = reinterpret_cast<ActualReadbackCallback*>(callback);
117}
118
119ResourceId findResource(BridgeContext* ctx, int resourceType, const char* resourceName)
120{
121 Context* context = static_cast<Context*>(ctx);
122 const BridgeResourceType type = static_cast<BridgeResourceType>(resourceType);
123 Cogs::StringView name(resourceName);
124 Cogs::Core::ResourceManagerBase* manager = getResourceManager(context, type);
125 if (manager) {
126 Cogs::Core::ResourceHandleBase handle = manager->getByName(name);
127
128 // Assign handle if only loaded as resource, but not yet used.
129 if (handle.getId() == NoResourceId && handle.get()) {
130 manager->setResourceId(handle.get(), manager->getNextResourceId());
131 }
132
133 return handle.getId();
134 }
135 else {
136 LOG_ERROR(logger, "findResource: Invalid Resource type: %d", resourceType);
137 return NoResourceId;
138 }
139}
140
141ResourceId getNextBufferId(BridgeContext * ctx)
142{
143 auto context = static_cast<Context*>(ctx);
144 return context->bufferManager->getNextResourceId();
145}
146
147void loadBuffer(BridgeContext * ctx, int size, const unsigned char * data, ResourceId resourceId, int resourceLoadFlags)
148{
149 auto context = static_cast<Context*>(ctx);
150 context->bufferManager->loadBuffer(size, data, resourceId, static_cast<ResourceLoadFlags>(resourceLoadFlags));
151 context->engine->setDirty();
152}
153
154void resizeBuffer(BridgeContext * ctx, const ResourceId resourceId, int size)
155{
156 auto context = static_cast<Context*>(ctx);
157 ResourceBufferHandle buffer = context->bufferManager->getHandle(resourceId);
158 if (!buffer) {
159 ::logInvalidResource("resizeBuffer", resourceId);
160 return;
161 }
162
163 buffer->resize(size);
164 context->engine->setDirty();
165}
166
167void * mapBuffer(BridgeContext * ctx, const ResourceId resourceId, int flags)
168{
169 auto context = static_cast<Context*>(ctx);
170 ResourceBufferHandle buffer = context->bufferManager->getHandle(resourceId);
171 if (!buffer) {
172 ::logInvalidResource("mapBuffer", resourceId);
173 return nullptr;
174 }
175
176 return buffer->map(flags);
177}
178
179void unmapBuffer(BridgeContext * ctx, const ResourceId resourceId)
180{
181 auto context = static_cast<Context*>(ctx);
182 ResourceBufferHandle buffer = context->bufferManager->getHandle(resourceId);
183 if (!buffer) {
184 ::logInvalidResource("unmapBuffer", resourceId);
185 return;
186 }
187
188 buffer->unmap();
189 context->engine->setDirty();
190}
191
192void updateBufferRange(BridgeContext * ctx, const ResourceId resourceId, int offset, int size, const unsigned char * data)
193{
194 auto context = static_cast<Context*>(ctx);
195 ResourceBufferHandle buffer = context->bufferManager->getHandle(resourceId);
196 if (!buffer) {
197 ::logInvalidResource("updateBufferRange", resourceId);
198 return;
199 }
200
201 buffer->set(offset, size, data);
202 context->engine->setDirty();
203}
204
205void invalidateBufferRange(BridgeContext * ctx, const ResourceId resourceId, int offset, int size)
206{
207 auto context = static_cast<Context*>(ctx);
208 ResourceBufferHandle buffer = context->bufferManager->getHandle(resourceId);
209 if (!buffer) {
210 ::logInvalidResource("invalidateBufferRange", resourceId);
211 return;
212 }
213
214 buffer->invalidate(offset, size);
215 context->engine->setDirty();
216}
217
218void setBufferField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
219{
220 auto context = static_cast<Context*>(ctx);
221 Cogs::Core::ResourceBufferHandle handle = (resourceId == NoResourceId) ? Cogs::Core::ResourceBufferHandle() : context->bufferManager->getHandle(resourceId);
222 Cogs::setField(context, entityId, componentId, fieldId, handle);
223}
224
225void releaseBuffer(BridgeContext* ctx, ResourceId resourceId)
226{
227 auto context = static_cast<Context*>(ctx);
228 context->bufferManager->release(resourceId);
229}
230
231ResourceId loadMesh(BridgeContext * ctx)
232{
233 auto context = static_cast<Context*>(ctx);
234 const auto resourceId = context->meshManager->getNextResourceId();
235
236 auto & loadInfo = *context->meshManager->createLoadInfo();
237 loadInfo.resourceId = resourceId;
238 loadInfo.loadFlags = ResourceLoadFlags::ForceSynchronous;
239
240 MeshHandle mesh = context->meshManager->loadResource(&loadInfo);
241 context->engine->setDirty();
242
243 return resourceId;
244}
245
246void releaseMesh(BridgeContext * ctx, ResourceId resourceId)
247{
248 auto context = static_cast<Context*>(ctx);
249 context->meshManager->release(resourceId);
250}
251
252namespace
253{
254 template<typename T>
255 void setStream(MeshHandle & mesh, Cogs::Core::VertexDataType::EVertexDataType stream, Cogs::VertexFormatHandle format, const void * data, int count)
256 {
257 auto t = static_cast<const T *>(data);
258 mesh->set(stream, format, t, t + count);
259 }
260}
261
262void setMeshData(BridgeContext * ctx, ResourceId resourceId, int stream, const void * data, int count)
263{
264 auto context = static_cast<Context*>(ctx);
265
266 MeshHandle mesh = context->meshManager->getHandle(resourceId);
267 if (!mesh) {
268 ::logInvalidResource("setMeshData", resourceId);
269 return;
270 }
271
272 switch (stream)
273 {
274 case 0: setStream<glm::vec3>(mesh, VertexDataType::Positions, VertexFormats::Pos3f, data, count); break;
275 case 1: setStream<glm::vec3>(mesh, VertexDataType::Normals, VertexFormats::Norm3f, data, count); break;
276 case 2: setStream<glm::vec2>(mesh, VertexDataType::TexCoords0,VertexFormats::Tex2f, data, count); break;
277 case 3: setStream<glm::vec3>(mesh, VertexDataType::Tangents, VertexFormats::Tang3f, data, count); break;
278 case 4: setStream<glm::vec4>(mesh, VertexDataType::Colors0, VertexFormats::Color4f, data, count); break;
279 case 5: setStream<glm::vec3>(mesh, VertexDataType::Positions, VertexFormats::InstancePos3f, data, count); break;
280 case 6: setStream<glm::vec4>(mesh, VertexDataType::Colors0, VertexFormats::InstanceColor4f, data, count); break;
281 case 7: setStream<glm::mat4>(mesh, VertexDataType::Positions, VertexFormats::InstanceMat4f, data, count); break;
282
283 case 98: mesh->setIndexData(static_cast<const uint16_t*>(data), count);
284 break;
285 case 99: mesh->setIndexData(static_cast<const uint32_t *>(data), static_cast<size_t>(count));
286 break;
287
288 default:
289 LOG_ERROR(logger, "setMeshData: Unsupported mesh data stream index: %d", stream);
290 break;
291 }
292 context->engine->setDirty();
293}
294
295const void * getMeshData(BridgeContext * ctx, ResourceId resourceId, int stream, int * count)
296{
297 auto context = static_cast<Context*>(ctx);
298 MeshHandle mesh = context->meshManager->getHandle(resourceId);
299 if (!mesh) {
300 ::logInvalidResource("getMeshData", resourceId);
301 return nullptr;
302 }
303
304 // Indices are handled separately
305 if (stream == 99) {
306 const std::span<const uint32_t> indexes = mesh->getIndexes();
307 *count = static_cast<int>(indexes.size());
308 return indexes.data();
309 }
310 else if (stream == 98) {
311 const std::span<const uint16_t> indexes = mesh->getIndexesU16();
312 *count = static_cast<int>(indexes.size());
313 return indexes.data();
314 }
315
316 VertexDataType::EVertexDataType streamType = getStreamDataType(stream);
317 if (streamType == VertexDataType::Reserved) {
318 LOG_ERROR(logger, "getMeshData: Unsupported mesh data stream index: %d", stream);
319 *count = 0;
320 return nullptr;
321 }
322
323 const auto & meshStream = mesh->getStream(streamType);
324 *count = static_cast<int>(meshStream.numElements);
325 return meshStream.data();
326}
327
328
329void * mapMeshData(BridgeContext * ctx, ResourceId resourceId, int stream, int start, int count)
330{
331 auto context = static_cast<Context*>(ctx);
332
333 MeshHandle mesh = context->meshManager->getHandle(resourceId);
334 if (!mesh) {
335 ::logInvalidResource("mapMeshData", resourceId);
336 return nullptr;
337 }
338
339 switch (stream)
340 {
341 case 0: return mesh->mapStream(VertexDataType::Positions, VertexFormats::Pos3f, start, count, sizeof(glm::vec3));
342 case 1: return mesh->mapStream(VertexDataType::Normals, VertexFormats::Norm3f, start, count, sizeof(glm::vec3));
343 case 2: return mesh->mapStream(VertexDataType::TexCoords0,VertexFormats::Tex2f, start, count, sizeof(glm::vec2));
344 case 3: return mesh->mapStream(VertexDataType::Tangents, VertexFormats::Tang3f, start, count, sizeof(glm::vec3));
345 case 4: return mesh->mapStream(VertexDataType::Colors0, VertexFormats::Color4f, start, count, sizeof(glm::vec4));
346 case 5: return mesh->mapStream(VertexDataType::Positions, VertexFormats::InstancePos3f, start, count, sizeof(glm::vec3));
347 case 6: return mesh->mapStream(VertexDataType::Colors0, VertexFormats::InstanceColor4f, start, count, sizeof(glm::vec4));
348 case 7: return mesh->mapStream(VertexDataType::Positions, VertexFormats::InstanceMat4f, start, count, sizeof(glm::mat4));
349 }
350
351 LOG_ERROR(logger, "mapMeshData: Unsupported mesh data stream index: %d", stream);
352 return nullptr;
353}
354
355void unmapMeshData(BridgeContext * ctx, ResourceId resourceId, int stream)
356{
357 auto context = static_cast<Context*>(ctx);
358 MeshHandle mesh = context->meshManager->getHandle(resourceId);
359 if (!mesh) {
360 ::logInvalidResource("unmapMeshData", resourceId);
361 return;
362 }
363
364 VertexDataType::EVertexDataType streamType = getStreamDataType(stream);
365 if (streamType == VertexDataType::Reserved) {
366 LOG_ERROR(logger, "unmapMeshData: Unsupported mesh data stream index: %d", stream);
367 }
368 else {
369 mesh->unmap(streamType);
370 context->engine->setDirty();
371 }
372}
373
374void setMeshPrimitiveType(BridgeContext * ctx, ResourceId resourceId, int primitiveType)
375{
376 auto context = static_cast<Context*>(ctx);
377 MeshHandle mesh = context->meshManager->getHandle(resourceId);
378 if (!mesh) {
379 ::logInvalidResource("setMeshPrimitiveType", resourceId);
380 return;
381 }
382 mesh->primitiveType = (Cogs::PrimitiveType)primitiveType;
383 context->engine->setDirty();
384}
385
386void setMeshBoundingBox(BridgeContext * ctx, ResourceId resourceId, const float * data)
387{
388 auto context = static_cast<Context*>(ctx);
389 MeshHandle mesh = context->meshManager->getHandle(resourceId);
390 if (!mesh) {
391 ::logInvalidResource("setMeshBoundingBox", resourceId);
392 return;
393 }
394
395 if (data) {
396 Cogs::Geometry::BoundingBox bbox(std::span<const float, 6>(data, 6));
397 mesh->setBounds(bbox);
398 } else {
400 }
401 context->engine->setDirty();
402}
403
404ResourceId createAsset(BridgeContext * ctx, const char * path, int assetLoadFlags)
405{
406 auto context = static_cast<Context*>(ctx);
407 const auto resourceId = context->assetManager->getNextResourceId();
408
409 AssetHandle handle = context->assetManager->loadAsset(path, resourceId, AssetLoadFlags(assetLoadFlags));
410 context->engine->setDirty();
411
412 return handle->getId();
413}
414
415void releaseAsset(BridgeContext* ctx, ResourceId resourceId)
416{
417 auto context = static_cast<Context*>(ctx);
418 context->assetManager->release(resourceId);
419}
420
421void setAssetField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
422{
423 auto context = static_cast<Context*>(ctx);
424 Cogs::Core::AssetHandle handle = (resourceId == NoResourceId) ? Cogs::Core::AssetHandle() : context->assetManager->getHandle(resourceId);
425 Cogs::setField(context, entityId, componentId, fieldId, handle);
426}
427
428void releaseModel(BridgeContext * ctx, ResourceId resourceId)
429{
430 auto context = static_cast<Context*>(ctx);
431 context->modelManager->release(resourceId);
432}
433
434void setMeshField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
435{
436 auto context = static_cast<Context*>(ctx);
437 Cogs::Core::MeshHandle handle = (resourceId == NoResourceId) ? Cogs::Core::MeshHandle() : context->meshManager->getHandle(resourceId);
438 Cogs::setField(context, entityId, componentId, fieldId, handle);
439}
440
441ResourceId getNextModelId(BridgeContext * ctx)
442{
443 auto context = static_cast<Context*>(ctx);
444 return context->modelManager->getNextResourceId();
445}
446
447ResourceId loadModel(BridgeContext * ctx, const char * resourceName, ResourceId id, int modelLoadFlags)
448{
449 auto context = static_cast<Context*>(ctx);
450 const ModelHandle model = context->modelManager->loadModel(resourceName, id, ModelLoadFlags(modelLoadFlags));
451
452 if (model->getId() == NoResourceId) {
453 context->modelManager->setResourceId(model.resolve(), context->modelManager->getNextResourceId());
454 }
455 context->engine->setDirty();
456
457 return model->getId();
458}
459
460void setModelField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
461{
462 auto context = static_cast<Context*>(ctx);
463 Cogs::Core::ModelHandle handle = (resourceId == NoResourceId) ? Cogs::Core::ModelHandle() : context->modelManager->getHandle(resourceId);
464 Cogs::setField(context, entityId, componentId, fieldId, handle);
465}
466
467ResourceId getNextTextureId(BridgeContext * ctx)
468{
469 auto context = static_cast<Context*>(ctx);
470 return context->textureManager->getNextResourceId();
471}
472
473void loadTexture(BridgeContext * ctx, ResourceId resourceId, const char * resourceName, int textureLoadFlags)
474{
475 auto context = static_cast<Context*>(ctx);
476 context->textureManager->loadTexture(resourceName, resourceId, TextureLoadFlags(textureLoadFlags));
477 context->engine->setDirty();
478}
479
480void loadTextureResource(BridgeContext * ctx, ResourceId resourceId, const void * imageData, int width, int height, int textureFormat, int stride, int textureLoadFlags)
481{
482 auto context = static_cast<Context*>(ctx);
483 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
484 context->textureManager->loadTexture2D(imageData, width, height, format, stride, resourceId, TextureLoadFlags(textureLoadFlags));
485 context->engine->setDirty();
486}
487
488void loadRenderTextureResource(BridgeContext* ctx, ResourceId resourceId, int width, int height, int textureFormat, int textureLoadFlags)
489{
490 auto context = static_cast<Context*>(ctx);
491 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
492 const TextureHandle & handle = context->textureManager->loadTexture2D(nullptr, width, height, format, 0, resourceId, TextureLoadFlags(textureLoadFlags));
493 handle->description.flags |= Cogs::TextureFlags::RenderTarget;
494 context->engine->setDirty();
495}
496
497void loadTextureVolumeResource(BridgeContext * ctx, ResourceId resourceId, const void * imageData, int width, int height, int depth, int textureFormat, int stride, int textureLoadFlags)
498{
499 auto context = static_cast<Context*>(ctx);
500 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
501 context->textureManager->loadTexture(imageData, Cogs::ResourceDimensions::Texture3D, width, height, depth, 1, format, stride, resourceId, TextureLoadFlags(textureLoadFlags));
502 context->engine->setDirty();
503}
504
505void loadExternalTextureResource(BridgeContext * ctx, ResourceId resourceId, intptr_t externalHandle, int width, int height, int bpp, int stride, int textureLoadFlags)
506{
507 auto context = static_cast<Context*>(ctx);
508 assert(stride == 0 && "Stride parameter is not passed on");
509 context->textureManager->loadExternalTexture(externalHandle, Cogs::ResourceDimensions::Texture2D, width, height, 1, 1, bpp == 4 ? Cogs::TextureFormat::R8G8B8A8_UNORM_SRGB : Cogs::TextureFormat::R8G8B8_UNORM, resourceId, TextureLoadFlags(textureLoadFlags));
510 context->engine->setDirty();
511}
512
513namespace {
514
515 bool validateTextureArgs(int target, int width, int height, int depth, int layers)
516 {
517 bool unit_height = true;
518 bool unit_depth = true;
519 bool unit_layers = true;
520 switch (target) {
521 case int(Cogs::ResourceDimensions::Texture1D) :
522 break;
523 case int(Cogs::ResourceDimensions::Texture1DArray) :
524 unit_layers = false;
525 break;
526 case int(Cogs::ResourceDimensions::Texture2D) :
527 unit_height = false;
528 break;
529 case int(Cogs::ResourceDimensions::Texture2DArray) :
530 unit_height = false;
531 unit_layers = false;
532 break;
533 case int(Cogs::ResourceDimensions::Texture3D) :
534 unit_height = false;
535 unit_depth = false;
536 break;
537 case int(Cogs::ResourceDimensions::Texture3DArray) :
538 unit_height = false;
539 unit_depth = false;
540 unit_layers = false;
541 break;
542 case int(Cogs::ResourceDimensions::TextureCube) :
543 unit_height = false;
544 break;
545 case int(Cogs::ResourceDimensions::TextureCubeArray) :
546 unit_height = false;
547 unit_layers = false;
548 break;
549 case int(Cogs::ResourceDimensions::RenderBuffer) :
550 unit_height = false;
551 break;
552 default:
553 LOG_ERROR(logger, "loadTexture: Illegal target");
554 return false;
555 break;
556 }
557 if (width < 1) {
558 LOG_ERROR(logger, "loadTexture: IIlegal width %d", width);
559 return false;
560 }
561 if ((unit_height && height !=1) || (!unit_height && height < 1)) {
562 LOG_ERROR(logger, "loadTexture: IIlegal height %d", height);
563 return false;
564 }
565 if ((unit_depth && depth != 1) || (!unit_depth && depth < 1)) {
566 LOG_ERROR(logger, "loadTexture: IIlegal depth %d", depth);
567 return false;
568 }
569 if ((unit_layers && layers != 1) || (!unit_layers && layers < 1)) {
570 LOG_ERROR(logger, "loadTexture: IIlegal layers %d", layers);
571 return false;
572 }
573 return true;
574 }
575
576}
577
578void loadTextureResource2(BridgeContext * ctx, ResourceId resourceId, const void * imageData, int target, int width, int height, int depth, int layers, int textureFormat, int stride, int textureLoadFlags)
579{
580 auto context = static_cast<Context*>(ctx);
581 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
582 if (!validateTextureArgs(target, width, height, depth, layers)) return;
583
584 context->textureManager->loadTexture(imageData, static_cast<Cogs::ResourceDimensions>(target), width, height, depth, layers, format, stride, resourceId, TextureLoadFlags(textureLoadFlags));
585 context->engine->setDirty();
586}
587
588void loadExternalTextureResource2(BridgeContext * ctx, ResourceId resourceId, intptr_t externalHandle, int target, int width, int height, int depth, int layers, int textureFormat, int stride, int textureLoadFlags)
589{
590 auto context = static_cast<Context*>(ctx);
591 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
592 assert(stride == 0 && "Stride parameter is not passed on");
593 if (!validateTextureArgs(target, width, height, depth, layers)) return;
594
595 context->textureManager->loadExternalTexture(externalHandle, static_cast<Cogs::ResourceDimensions>(target), width, height, depth, layers, format, resourceId, TextureLoadFlags(textureLoadFlags));
596 context->engine->setDirty();
597}
598
599void setTextureField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
600{
601 auto context = static_cast<Context*>(ctx);
602 Cogs::Core::TextureHandle handle = (resourceId == NoResourceId) ? Cogs::Core::TextureHandle() : context->textureManager->getHandle(resourceId);
603 Cogs::setField(context, entityId, componentId, fieldId, handle);
604}
605
606void setTexturesField(BridgeContext* ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId* resourceIds, int size)
607{
608 Cogs::Core::Context* context = static_cast<Context*>(ctx);
609 std::vector<Cogs::Core::TextureHandle> handles(size);
610 for (int i = 0; i < size; ++i) {
611 const ResourceId resourceId = resourceIds[i];
612 handles[i] = (resourceId == NoResourceId) ? Cogs::Core::TextureHandle() : context->textureManager->getHandle(resourceId);
613 }
614 Cogs::assignField(context, entityId, componentId, fieldId, handles.data(), size);
615}
616
617void setMaterialInstanceField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
618{
619 auto context = static_cast<Context*>(ctx);
620 Cogs::Core::MaterialInstanceHandle handle = (resourceId == NoResourceId) ? Cogs::Core::MaterialInstanceHandle() : context->materialInstanceManager->getHandle(resourceId);
621 Cogs::setField(context, entityId, componentId, fieldId, handle);
622}
623
624void setMaterialInstancesField(BridgeContext* ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId* resourceIds, int size)
625{
626 auto context = static_cast<Context*>(ctx);
627 std::vector<Cogs::Core::MaterialInstanceHandle> handles(size);
628 for (int i = 0; i < size; ++i) {
629 const ResourceId resourceId = resourceIds[i];
630 handles[i] = (resourceId == NoResourceId) ? Cogs::Core::MaterialInstanceHandle() : context->materialInstanceManager->getHandle(resourceId);
631 }
632
633 Cogs::assignField(context, entityId, componentId, fieldId, handles.data(), size);
634}
635
636void setMaterialInstanceArrayField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId, int index)
637{
638 auto context = static_cast<Context*>(ctx);
639 Cogs::Core::MaterialInstanceHandle handle = (resourceId == NoResourceId) ? Cogs::Core::MaterialInstanceHandle() : context->materialInstanceManager->getHandle(resourceId);
640 Cogs::setVectorField(context, entityId, componentId, fieldId, handle, index);
641}
642
643void setMaterialInstanceOption(BridgeContext * ctx, ResourceId resourceId, const char * name, const char * value)
644{
645 auto context = static_cast<Context*>(ctx);
646 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
647 if (!materialInstance) {
648 ::logInvalidResource("setMaterialInstanceOption", resourceId);
649 return;
650 }
651
652 materialInstance->setOption(name, value);
653 context->engine->setDirty();
654}
655
656void setMaterialInstanceProperty(BridgeContext * ctx, ResourceId resourceId, const char * name, const void * data, const int sizeInBytes)
657{
658 auto context = static_cast<Context*>(ctx);
659 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
660 if (!materialInstance) {
661 ::logInvalidResource("setMaterialInstanceProperty", resourceId);
662 return;
663 }
664
665 materialInstance->setProperty(name, data, static_cast<size_t>(sizeInBytes));
666 context->engine->setDirty();
667}
668
669CogsBool getMaterialInstanceProperty(BridgeContext * ctx, ResourceId resourceId, const char * name, void * data, const int sizeInBytes)
670{
671 auto context = static_cast<Context*>(ctx);
672 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
673 if (!materialInstance) {
674 ::logInvalidResource("getMaterialInstanceProperty", resourceId);
675 return false;
676 }
677
678 return materialInstance->getProperty(name, data, static_cast<size_t>(sizeInBytes));
679}
680
681int getMaterialInstancePropertyDataType(BridgeContext* ctx, ResourceId resourceId, const char* name)
682{
683 auto context = static_cast<Context*>(ctx);
684 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
685 if (!materialInstance) {
686 ::logInvalidResource("getMaterialInstancePropertyDataType", resourceId);
687 return static_cast<int>(MaterialDataType::Unknown);
688 }
689
690 return static_cast<int>(materialInstance->material->getPropertyDataType(name));
691}
692
693void setMaterialInstanceTexture(BridgeContext * ctx, ResourceId resourceId, const char * name, const ResourceId textureId)
694{
695 auto context = static_cast<Context*>(ctx);
696 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
697 if (!materialInstance) {
698 ::logInvalidResource("setMaterialInstanceTexture", resourceId);
699 return;
700 }
701
702 const VariableKey key = materialInstance->material->getTextureKey(name);
703 materialInstance->setTextureProperty(key, context->textureManager->getHandle(textureId));
704 context->engine->setDirty();
705}
706
707void setMaterialInstanceTextureAddressMode(BridgeContext * ctx, ResourceId resourceId, const char * name, const char * mode)
708{
709 auto context = static_cast<Context*>(ctx);
710 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
711 if (!materialInstance) {
712 ::logInvalidResource("setMaterialInstanceTextureAddressMode", resourceId);
713 return;
714 }
715
716 materialInstance->setTextureAddressMode(name, mode);
717 context->engine->setDirty();
718}
719
720void setMaterialInstanceTextureFilterMode(BridgeContext* ctx, ResourceId resourceId, const char* name, const char* filterMode)
721{
722 Context* context = static_cast<Context*>(ctx);
723 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
724 if (!materialInstance) {
725 ::logInvalidResource("setMaterialInstanceTextureFilterMode", resourceId);
726 return;
727 }
728
729 materialInstance->setTextureFilterMode(name, filterMode);
730 context->engine->setDirty();
731}
732
733void setMaterialInstancePermutation(BridgeContext * ctx, ResourceId resourceId, const char * name)
734{
735 auto context = static_cast<Context*>(ctx);
736 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
737 if (!materialInstance) {
738 ::logInvalidResource("setMaterialInstancePermutation", resourceId);
739 return;
740 }
741
742 materialInstance->setPermutation(name);
743 context->engine->setDirty();
744}
745
746void setMaterialInstanceVariant(BridgeContext * ctx, ResourceId resourceId, const char * key, const char * value)
747{
748 auto context = static_cast<Context*>(ctx);
749 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
750 if (!materialInstance) {
751 ::logInvalidResource("setMaterialInstanceVariant", resourceId);
752 return;
753 }
754
755 materialInstance->setVariant(key, value);
756 context->engine->setDirty();
757}
758
759const char * getMaterialInstanceVariant(BridgeContext * ctx, ResourceId resourceId, const char * key)
760{
761 auto context = static_cast<Context*>(ctx);
762 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
763 if (!materialInstance) {
764 ::logInvalidResource("getMaterialInstanceVariant", resourceId);
765 return nullptr;
766 }
767
768 // Static return is OK as single threaded access only is supported in this API.
769 getMaterialInstanceVariantOutput = materialInstance->getVariant(key);
770 return getMaterialInstanceVariantOutput.data();
771}
772
773void setMaterialInstanceFlags(BridgeContext * ctx, ResourceId resourceId, int materialFlags)
774{
775 auto context = static_cast<Context*>(ctx);
776 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
777 if (!materialInstance) {
778 ::logInvalidResource("setMaterialInstanceFlags", resourceId);
779 return;
780 }
781
782 materialInstance->instanceFlags = static_cast<uint16_t>(materialFlags);
783 context->engine->setDirty();
784}
785
786ResourceId getNextFontId(BridgeContext* ctx)
787{
788 auto context = static_cast<Context*>(ctx);
789 return context->fontManager->getNextResourceId();
790}
791
792ResourceId loadFont(BridgeContext* ctx, const char* resourceName, float size, ResourceId resourceId)
793{
794 auto context = static_cast<Context*>(ctx);
795 Cogs::Core::FontHandle loaded = context->fontManager->loadFont(resourceName, size, resourceId);
796 // Must return input resource if given.
797 return loaded->getId();
798}
799
800void releaseFont(BridgeContext* ctx, ResourceId resourceId)
801{
802 auto context = static_cast<Context*>(ctx);
803 context->fontManager->release(resourceId);
804}
805
806void addFontDependency(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
807{
808 auto context = static_cast<Context*>(ctx);
809 Cogs::Core::FontHandle handle = (resourceId == NoResourceId) ? Cogs::Core::FontHandle() : context->fontManager->getHandle(resourceId);
810 Cogs::setField(context, entityId, componentId, fieldId, handle);
811}
812
813void registerStringResource(BridgeContext * ctx, const char * key, const char * value)
814{
815 auto context = static_cast<Context*>(ctx);
816 context->resourceStore->addResource(key, value);
817 context->engine->setDirty();
818}
819
820void registerBinaryResource(BridgeContext* ctx, const char* key, const void* value, int length)
821{
822 auto context = static_cast<Context*>(ctx);
823 context->resourceStore->addResource(key, value, static_cast<size_t>(length));
824}
825
826void addResourceArchive(BridgeContext* ctx, const char* key, CogsBool prepend)
827{
828 auto context = static_cast<Context*>(ctx);
829 context->resourceStore->addResourceArchive(key, prepend != 0);
830 context->engine->setDirty();
831}
832CogsBool hasResource(BridgeContext* ctx, const char* key)
833{
834 auto context = static_cast<Context*>(ctx);
835 return context->resourceStore->hasResource(key);
836}
837
838ResourceId getMaterialInstance(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId)
839{
840 auto context = static_cast<Context*>(ctx);
841 MaterialInstanceHandle& materialInstance = *Cogs::getField<MaterialInstanceHandle>(context, entityId, componentId, fieldId);
842
843 if (materialInstance) {
844 ResourceId id = materialInstance->getId();
845
846 if (id == NoResourceId) {
847 id = context->materialInstanceManager->getNextResourceId();
848
849 context->materialInstanceManager->setResourceId(materialInstance.resolve(), id);
850 }
851
852 return id;
853 }
854
855 return NoResourceId;
856}
857
858int getMaterialInstances(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, ResourceId * ids, int idsCount)
859{
860 auto context = static_cast<Context*>(ctx);
861 const auto & materialInstances = *Cogs::getField<std::vector<MaterialInstanceHandle>>(context, entityId, componentId, fieldId);
862
863 for (size_t i = 0; i < static_cast<size_t>(idsCount); ++i) {
864
865 ResourceId id = NoResourceId;
866 if (i < materialInstances.size()) {
867
868 // No Ids allocated. Can possibly return values with 'holes - NoResourceId'.
869 // Setting ids should be done using setMaterialInstanceArrayField
870 const MaterialInstanceHandle& materialInstance = materialInstances[i];
871 if (materialInstance) {
872 id = materialInstance->getId();
873 }
874 }
875
876 ids[i] = id;
877 }
878
879 // Return actual count.
880 return static_cast<int>(materialInstances.size());
881}
882
883void addSearchPath(BridgeContext * ctx, const char * path)
884{
885 auto context = static_cast<Context*>(ctx);
886 context->resourceStore->addSearchPath(path, true);
887 context->engine->setDirty();
888}
889
890void purgeResource(BridgeContext * ctx, const char * resourceName)
891{
892 auto context = static_cast<Context*>(ctx);
893 context->resourceStore->purge(resourceName);
894 context->engine->setDirty();
895}
896
897void releaseTexture(BridgeContext * ctx, ResourceId resourceId)
898{
899 auto context = static_cast<Context*>(ctx);
900 TextureHandle h = context->textureManager->release(resourceId);
901 if (h) {
902 Texture* texture = context->textureManager->get(h);
903 if (texture->externalHandle && texture->ownsExternalTexture.value == false) {
904 LOG_TRACE(logger, "releaseTexture: Setting external handle of texture resource %d to 0", resourceId);
905 // External code wants to release the texture, don't use it anymore
906 texture->description = Cogs::TextureDescription{};
907 texture->externalHandle = 0; // Texture already released by external code.
908 texture->ownsExternalTexture = true; // Trigger removal of render texture.
909 texture->setChanged();
910 }
911 }
912 context->engine->setDirty();
913}
914
915ResourceId loadMaterial(BridgeContext * ctx, const char * resourceName)
916{
917 auto context = static_cast<Context*>(ctx);
918 const auto resourceId = context->materialManager->getNextResourceId();
919
920 MaterialHandle handle = context->materialManager->loadMaterial(resourceName, MaterialLoadFlags::None, resourceId);
921
922 context->materialManager->processLoading();
923
924 if (handle->getId() == NoResourceId) {
925 context->materialManager->setResourceId(handle.resolve(), resourceId);
926 }
927 context->engine->setDirty();
928
929 return handle->getId();
930}
931
932void setMaterialSharedProperty(BridgeContext* ctx, ResourceId materialId, const char* name, const void* data, const int sizeInBytes)
933{
934 auto context = static_cast<Context*>(ctx);
935 MaterialHandle material = context->materialManager->getHandle(materialId);
936 if (!material) {
937 // Error
938 ::logInvalidResource("setMaterialSharedProperty(materialId)", materialId);
939 return;
940 }
941
942 material->setProperty(name, data, static_cast<size_t>(sizeInBytes));
943 context->engine->setDirty();
944}
945
946void setMaterialsField(BridgeContext* ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId* resourceIds, int size)
947{
948 Context* context = static_cast<Context*>(ctx);
949
950 std::vector<Cogs::Core::MaterialHandle> handles(size);
951 for (int i = 0; i < size; ++i) {
952 const ResourceId resourceId = resourceIds[i];
953 handles[i] = (resourceId == NoResourceId) ? Cogs::Core::MaterialHandle() : context->materialManager->getHandle(resourceId);
954 }
955 Cogs::assignField(context, entityId, componentId, fieldId, handles.data(), size);
956}
957
958int getMaterialPropertyDataType(BridgeContext* ctx, ResourceId resourceId, const char* name)
959{
960 auto context = static_cast<Context*>(ctx);
961 MaterialHandle material = context->materialManager->getHandle(resourceId);
962 if (!material) {
963 ::logInvalidResource("getMaterialPropertyDataType", resourceId);
964 return static_cast<int>(MaterialDataType::Unknown);
965 }
966
967 return static_cast<int>(material->getPropertyDataType(name));
968}
969
970ResourceId loadMaterialInstance(BridgeContext * ctx, ResourceId materialId)
971{
972 auto context = static_cast<Context*>(ctx);
973 ResourceId resourceId = context->materialInstanceManager->getNextResourceId();
974
975 MaterialHandle material = context->materialManager->getHandle(materialId);
976 if (!material) {
977 // Error
978 ::logInvalidResource("loadMaterialInstance(materialId)", materialId);
979 return NoResourceId;
980 }
981
982 MaterialInstanceHandle materialInstance = context->materialInstanceManager->createMaterialInstance(material);
983 context->materialInstanceManager->setResourceId(materialInstance.resolve(), resourceId);
984 context->engine->setDirty();
985
986 return resourceId;
987}
988
989void releaseMaterialInstance(BridgeContext * ctx, ResourceId resourceId)
990{
991 auto context = static_cast<Context*>(ctx);
992 context->materialInstanceManager->release(resourceId);
993}
994
995const char * getMaterialInstanceName(BridgeContext * ctx, ResourceId materialInstanceId)
996{
997 auto context = static_cast<Context *>(ctx);
998 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(materialInstanceId);
999 if (materialInstance) {
1000 return materialInstance->getName().data();
1001 }
1002
1003 ::logInvalidResource("getMaterialInstanceName", materialInstanceId);
1004 return nullptr;
1005}
1006
1007void setMaterialInstanceName(BridgeContext * ctx, ResourceId materialInstanceId, const char * name)
1008{
1009 auto context = static_cast<Context *>(ctx);
1010 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(materialInstanceId);
1011 if (materialInstance) {
1012 materialInstance->setName(name);
1013 context->engine->setDirty();
1014 }
1015 else {
1016 ::logInvalidResource("setMaterialInstanceName", materialInstanceId);
1017 }
1018}
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
std::unique_ptr< class ResourceStore > resourceStore
ResourceStore service instance.
Definition: Context.h:210
std::unique_ptr< class Engine > engine
Engine instance.
Definition: Context.h:222
void setResourceId(ResourceBase *resource, ResourceId id) override
Assign the given id to a previously created resource.
ResourceId getNextResourceId() override
Get the next unique resource id.
Log implementation class.
Definition: LogManager.h:140
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:50
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
Definition: StringView.h:197
Contains the Engine, Renderer, resource managers and other systems needed to run Cogs....
ModelLoadFlags
Model loading flags. May be combined with resource loading flags.
ResourceLoadFlags
Flags for describing how to load a resource.
Definition: ResourceFlags.h:16
TextureLoadFlags
Texture loading flags. May be combined with resource load flags.
Definition: ResourceFlags.h:50
Cogs::Geometry::BoundingBox COGSCORE_DLL_API calculateBounds(Mesh *mesh)
Calculate a bounding box for the given mesh.
Definition: MeshHelper.cpp:283
uint16_t VariableKey
Used to lookup material properties.
Definition: Resources.h:46
AssetLoadFlags
Asset and Scene loading flags. May be combined with resource loading flags.
constexpr Log getLogger(const char(&name)[LEN]) noexcept
Definition: LogManager.h:181
PrimitiveType
Primitive types for interpreting vertex data sent to the graphics pipeline.
Definition: Common.h:112
void assignField(Cogs::Core::Context *context, EntityId entityId, const ComponentId componentId, const Cogs::Reflection::FieldId fieldId, const DataType *data, int count)
Assign value to a Component field.
Definition: FieldSetter.h:35
void unmap()
Unmap the buffer, signaling writes to mapped buffer memory are done.
Definition: Buffer.cpp:49
void invalidate(size_t offset, size_t size)
Invalidates buffer contents, signaling data should be updated/transfered to GPU.
Definition: Buffer.cpp:12
void * map(uint32_t flags)
Map the buffer data backing storage, returning a writable pointer.
Definition: Buffer.cpp:40
void resize(size_t size)
Resize the buffer to accomodate the given number of bytes.
Definition: Buffer.cpp:22
void set(size_t offset, size_t size, const uint8_t *data)
Definition: Buffer.cpp:3
void setOption(const StringView &key, const StringView &value)
Sets the option with the given key to a value parsed from the value string.
void setTextureAddressMode(const StringView &key, const StringView &addressMode)
Set texture address mode with textual name.
void setTextureProperty(const StringView &key, TextureHandle value)
Set the texture property with the given key to the texture resource held by value.
void setTextureFilterMode(const StringView &key, const StringView &filterMode)
Set texture filter mode with textual name.
Material * material
Material resource this MaterialInstance is created from.
uint16_t instanceFlags
Material instance flags.
MaterialDataType getPropertyDataType(const StringView &key)
Gets data type for the given property. Returns MaterialDataType::Unknown if not found.
Definition: Material.cpp:130
void unmap(VertexDataType::EVertexDataType type)
Unmap the stream with the given vertex data type index.
Definition: Mesh.h:900
uint8_t * mapStream(const VertexDataType::EVertexDataType type, VertexFormatHandle format, const size_t start, const size_t count, const size_t elementSize, bool resize=false)
Raw stream mapping method.
Definition: Mesh.cpp:46
void setIndexData(const uint32_t *data, size_t count)
Convenience method for setting index data from a raw pointer to data and count number of elements.
Definition: Mesh.h:705
void setBounds(Geometry::BoundingBox box)
Set custom bounds for the mesh.
Definition: Mesh.h:298
void set(const VertexDataType::EVertexDataType type, VertexFormatHandle format, Element *begin, Element *end)
Set the data of the vertex stream indexed by type.
Definition: Mesh.h:792
DataStream & getStream(const VertexDataType::EVertexDataType dataType)
Get the stream corresponding to the given dataType.
Definition: Mesh.cpp:85
ResourceId getId() const
Get the resource id of this instance.
Definition: ResourceBase.h:215
StringView getName() const
Get the name of the resource.
Definition: ResourceBase.h:307
void setName(const StringView &name)
Set the user friendly name of the resource.
Definition: ResourceBase.h:298
Resource handle base class handling reference counting of resources derived from ResourceBase.
ResourceId getId() const
Get the resource id of the held resource.
ResourceType * resolve() const
Resolve the handle, returning a pointer to the actual resource.
Texture resources contain raster bitmap data to use for texturing.
Definition: Texture.h:91
EVertexDataType
Contains data types.
Definition: Mesh.h:26
@ RenderTarget
The texture can be used as a render target and drawn into.
Definition: Flags.h:120