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
282 case 98: mesh->setIndexData(static_cast<const uint16_t*>(data), count);
283 break;
284 case 99: mesh->setIndexData(static_cast<const uint32_t *>(data), static_cast<size_t>(count));
285 break;
286
287 default:
288 LOG_ERROR(logger, "setMeshData: Unsupported mesh data stream index: %d", stream);
289 break;
290 }
291 context->engine->setDirty();
292}
293
294const void * getMeshData(BridgeContext * ctx, ResourceId resourceId, int stream, int * count)
295{
296 auto context = static_cast<Context*>(ctx);
297 MeshHandle mesh = context->meshManager->getHandle(resourceId);
298 if (!mesh) {
299 ::logInvalidResource("getMeshData", resourceId);
300 return nullptr;
301 }
302
303 // Indices are handled separately
304 if (stream == 99) {
305 const std::span<const uint32_t> indexes = mesh->getIndexes();
306 *count = static_cast<int>(indexes.size());
307 return indexes.data();
308 }
309 else if (stream == 98) {
310 const std::span<const uint16_t> indexes = mesh->getIndexesU16();
311 *count = static_cast<int>(indexes.size());
312 return indexes.data();
313 }
314
315 VertexDataType::EVertexDataType streamType = getStreamDataType(stream);
316 if (streamType == VertexDataType::Reserved) {
317 LOG_ERROR(logger, "getMeshData: Unsupported mesh data stream index: %d", stream);
318 *count = 0;
319 return nullptr;
320 }
321
322 const auto & meshStream = mesh->getStream(streamType);
323 *count = static_cast<int>(meshStream.numElements);
324 return meshStream.data();
325}
326
327
328void * mapMeshData(BridgeContext * ctx, ResourceId resourceId, int stream, int start, int count)
329{
330 auto context = static_cast<Context*>(ctx);
331
332 MeshHandle mesh = context->meshManager->getHandle(resourceId);
333 if (!mesh) {
334 ::logInvalidResource("mapMeshData", resourceId);
335 return nullptr;
336 }
337
338 switch (stream)
339 {
340 case 0: return mesh->mapStream(VertexDataType::Positions, VertexFormats::Pos3f, start, count, sizeof(glm::vec3));
341 case 1: return mesh->mapStream(VertexDataType::Normals, VertexFormats::Norm3f, start, count, sizeof(glm::vec3));
342 case 2: return mesh->mapStream(VertexDataType::TexCoords0,VertexFormats::Tex2f, start, count, sizeof(glm::vec2));
343 case 3: return mesh->mapStream(VertexDataType::Tangents, VertexFormats::Tang3f, start, count, sizeof(glm::vec3));
344 case 4: return mesh->mapStream(VertexDataType::Colors0, VertexFormats::Color4f, start, count, sizeof(glm::vec4));
345 case 5: return mesh->mapStream(VertexDataType::Positions, VertexFormats::InstancePos3f, start, count, sizeof(glm::vec3));
346 case 6: return mesh->mapStream(VertexDataType::Colors0, VertexFormats::InstanceColor4f, start, count, sizeof(glm::vec4));
347 }
348
349 LOG_ERROR(logger, "mapMeshData: Unsupported mesh data stream index: %d", stream);
350 return nullptr;
351}
352
353void unmapMeshData(BridgeContext * ctx, ResourceId resourceId, int stream)
354{
355 auto context = static_cast<Context*>(ctx);
356 MeshHandle mesh = context->meshManager->getHandle(resourceId);
357 if (!mesh) {
358 ::logInvalidResource("unmapMeshData", resourceId);
359 return;
360 }
361
362 VertexDataType::EVertexDataType streamType = getStreamDataType(stream);
363 if (streamType == VertexDataType::Reserved) {
364 LOG_ERROR(logger, "unmapMeshData: Unsupported mesh data stream index: %d", stream);
365 }
366 else {
367 mesh->unmap(streamType);
368 context->engine->setDirty();
369 }
370}
371
372void setMeshPrimitiveType(BridgeContext * ctx, ResourceId resourceId, int primitiveType)
373{
374 auto context = static_cast<Context*>(ctx);
375 MeshHandle mesh = context->meshManager->getHandle(resourceId);
376 if (!mesh) {
377 ::logInvalidResource("setMeshPrimitiveType", resourceId);
378 return;
379 }
380 mesh->primitiveType = (Cogs::PrimitiveType::EPrimitiveType)primitiveType;
381 context->engine->setDirty();
382}
383
384void setMeshBoundingBox(BridgeContext * ctx, ResourceId resourceId, const float * data)
385{
386 auto context = static_cast<Context*>(ctx);
387 MeshHandle mesh = context->meshManager->getHandle(resourceId);
388 if (!mesh) {
389 ::logInvalidResource("setMeshBoundingBox", resourceId);
390 return;
391 }
392
393 if (data) {
394 Cogs::Geometry::BoundingBox bbox(std::span<const float, 6>(data, 6));
395 mesh->setBounds(bbox);
396 } else {
398 }
399 context->engine->setDirty();
400}
401
402ResourceId createAsset(BridgeContext * ctx, const char * path, int assetLoadFlags)
403{
404 auto context = static_cast<Context*>(ctx);
405 const auto resourceId = context->assetManager->getNextResourceId();
406
407 AssetHandle handle = context->assetManager->loadAsset(path, resourceId, AssetLoadFlags(assetLoadFlags));
408 context->engine->setDirty();
409
410 return handle->getId();
411}
412
413void releaseAsset(BridgeContext* ctx, ResourceId resourceId)
414{
415 auto context = static_cast<Context*>(ctx);
416 context->assetManager->release(resourceId);
417}
418
419void setAssetField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
420{
421 auto context = static_cast<Context*>(ctx);
422 Cogs::Core::AssetHandle handle = (resourceId == NoResourceId) ? Cogs::Core::AssetHandle() : context->assetManager->getHandle(resourceId);
423 Cogs::setField(context, entityId, componentId, fieldId, handle);
424}
425
426void releaseModel(BridgeContext * ctx, ResourceId resourceId)
427{
428 auto context = static_cast<Context*>(ctx);
429 context->modelManager->release(resourceId);
430}
431
432void setMeshField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
433{
434 auto context = static_cast<Context*>(ctx);
435 Cogs::Core::MeshHandle handle = (resourceId == NoResourceId) ? Cogs::Core::MeshHandle() : context->meshManager->getHandle(resourceId);
436 Cogs::setField(context, entityId, componentId, fieldId, handle);
437}
438
439ResourceId getNextModelId(BridgeContext * ctx)
440{
441 auto context = static_cast<Context*>(ctx);
442 return context->modelManager->getNextResourceId();
443}
444
445ResourceId loadModel(BridgeContext * ctx, const char * resourceName, ResourceId id, int modelLoadFlags)
446{
447 auto context = static_cast<Context*>(ctx);
448 const ModelHandle model = context->modelManager->loadModel(resourceName, id, ModelLoadFlags(modelLoadFlags));
449
450 if (model->getId() == NoResourceId) {
451 context->modelManager->setResourceId(model.resolve(), context->modelManager->getNextResourceId());
452 }
453 context->engine->setDirty();
454
455 return model->getId();
456}
457
458void setModelField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
459{
460 auto context = static_cast<Context*>(ctx);
461 Cogs::Core::ModelHandle handle = (resourceId == NoResourceId) ? Cogs::Core::ModelHandle() : context->modelManager->getHandle(resourceId);
462 Cogs::setField(context, entityId, componentId, fieldId, handle);
463}
464
465ResourceId getNextTextureId(BridgeContext * ctx)
466{
467 auto context = static_cast<Context*>(ctx);
468 return context->textureManager->getNextResourceId();
469}
470
471void loadTexture(BridgeContext * ctx, ResourceId resourceId, const char * resourceName, int textureLoadFlags)
472{
473 auto context = static_cast<Context*>(ctx);
474 context->textureManager->loadTexture(resourceName, resourceId, TextureLoadFlags(textureLoadFlags));
475 context->engine->setDirty();
476}
477
478void loadTextureResource(BridgeContext * ctx, ResourceId resourceId, const void * imageData, int width, int height, int textureFormat, int stride, int textureLoadFlags)
479{
480 auto context = static_cast<Context*>(ctx);
481 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
482 context->textureManager->loadTexture2D(imageData, width, height, format, stride, resourceId, TextureLoadFlags(textureLoadFlags));
483 context->engine->setDirty();
484}
485
486void loadRenderTextureResource(BridgeContext* ctx, ResourceId resourceId, int width, int height, int textureFormat, int textureLoadFlags)
487{
488 auto context = static_cast<Context*>(ctx);
489 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
490 const TextureHandle & handle = context->textureManager->loadTexture2D(nullptr, width, height, format, 0, resourceId, TextureLoadFlags(textureLoadFlags));
491 handle->description.flags |= Cogs::TextureFlags::RenderTarget;
492 context->engine->setDirty();
493}
494
495void loadTextureVolumeResource(BridgeContext * ctx, ResourceId resourceId, const void * imageData, int width, int height, int depth, int textureFormat, int stride, int textureLoadFlags)
496{
497 auto context = static_cast<Context*>(ctx);
498 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
499 context->textureManager->loadTexture(imageData, Cogs::ResourceDimensions::Texture3D, width, height, depth, 1, format, stride, resourceId, TextureLoadFlags(textureLoadFlags));
500 context->engine->setDirty();
501}
502
503void loadExternalTextureResource(BridgeContext * ctx, ResourceId resourceId, intptr_t externalHandle, int width, int height, int bpp, int stride, int textureLoadFlags)
504{
505 auto context = static_cast<Context*>(ctx);
506 assert(stride == 0 && "Stride parameter is not passed on");
507 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));
508 context->engine->setDirty();
509}
510
511namespace {
512
513 bool validateTextureArgs(int target, int width, int height, int depth, int layers)
514 {
515 bool unit_height = true;
516 bool unit_depth = true;
517 bool unit_layers = true;
518 switch (target) {
519 case int(Cogs::ResourceDimensions::Texture1D) :
520 break;
521 case int(Cogs::ResourceDimensions::Texture1DArray) :
522 unit_layers = false;
523 break;
524 case int(Cogs::ResourceDimensions::Texture2D) :
525 unit_height = false;
526 break;
527 case int(Cogs::ResourceDimensions::Texture2DArray) :
528 unit_height = false;
529 unit_layers = false;
530 break;
531 case int(Cogs::ResourceDimensions::Texture3D) :
532 unit_height = false;
533 unit_depth = false;
534 break;
535 case int(Cogs::ResourceDimensions::Texture3DArray) :
536 unit_height = false;
537 unit_depth = false;
538 unit_layers = false;
539 break;
540 case int(Cogs::ResourceDimensions::TextureCube) :
541 unit_height = false;
542 break;
543 case int(Cogs::ResourceDimensions::TextureCubeArray) :
544 unit_height = false;
545 unit_layers = false;
546 break;
547 case int(Cogs::ResourceDimensions::RenderBuffer) :
548 unit_height = false;
549 break;
550 default:
551 LOG_ERROR(logger, "loadTexture: Illegal target");
552 return false;
553 break;
554 }
555 if (width < 1) {
556 LOG_ERROR(logger, "loadTexture: IIlegal width %d", width);
557 return false;
558 }
559 if ((unit_height && height !=1) || (!unit_height && height < 1)) {
560 LOG_ERROR(logger, "loadTexture: IIlegal height %d", height);
561 return false;
562 }
563 if ((unit_depth && depth != 1) || (!unit_depth && depth < 1)) {
564 LOG_ERROR(logger, "loadTexture: IIlegal depth %d", depth);
565 return false;
566 }
567 if ((unit_layers && layers != 1) || (!unit_layers && layers < 1)) {
568 LOG_ERROR(logger, "loadTexture: IIlegal layers %d", layers);
569 return false;
570 }
571 return true;
572 }
573
574}
575
576void loadTextureResource2(BridgeContext * ctx, ResourceId resourceId, const void * imageData, int target, int width, int height, int depth, int layers, int textureFormat, int stride, int textureLoadFlags)
577{
578 auto context = static_cast<Context*>(ctx);
579 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
580 if (!validateTextureArgs(target, width, height, depth, layers)) return;
581
582 context->textureManager->loadTexture(imageData, static_cast<Cogs::ResourceDimensions>(target), width, height, depth, layers, format, stride, resourceId, TextureLoadFlags(textureLoadFlags));
583 context->engine->setDirty();
584}
585
586void loadExternalTextureResource2(BridgeContext * ctx, ResourceId resourceId, intptr_t externalHandle, int target, int width, int height, int depth, int layers, int textureFormat, int stride, int textureLoadFlags)
587{
588 auto context = static_cast<Context*>(ctx);
589 const Cogs::TextureFormat format = static_cast<Cogs::TextureFormat>(textureFormat);
590 assert(stride == 0 && "Stride parameter is not passed on");
591 if (!validateTextureArgs(target, width, height, depth, layers)) return;
592
593 context->textureManager->loadExternalTexture(externalHandle, static_cast<Cogs::ResourceDimensions>(target), width, height, depth, layers, format, resourceId, TextureLoadFlags(textureLoadFlags));
594 context->engine->setDirty();
595}
596
597void setTextureField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
598{
599 auto context = static_cast<Context*>(ctx);
600 Cogs::Core::TextureHandle handle = (resourceId == NoResourceId) ? Cogs::Core::TextureHandle() : context->textureManager->getHandle(resourceId);
601 Cogs::setField(context, entityId, componentId, fieldId, handle);
602}
603
604void setTexturesField(BridgeContext* ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId* resourceIds, int size)
605{
606 Cogs::Core::Context* context = static_cast<Context*>(ctx);
607 std::vector<Cogs::Core::TextureHandle> handles(size);
608 for (int i = 0; i < size; ++i) {
609 const ResourceId resourceId = resourceIds[i];
610 handles[i] = (resourceId == NoResourceId) ? Cogs::Core::TextureHandle() : context->textureManager->getHandle(resourceId);
611 }
612 Cogs::assignField(context, entityId, componentId, fieldId, handles.data(), size);
613}
614
615void setMaterialInstanceField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
616{
617 auto context = static_cast<Context*>(ctx);
618 Cogs::Core::MaterialInstanceHandle handle = (resourceId == NoResourceId) ? Cogs::Core::MaterialInstanceHandle() : context->materialInstanceManager->getHandle(resourceId);
619 Cogs::setField(context, entityId, componentId, fieldId, handle);
620}
621
622void setMaterialInstancesField(BridgeContext* ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId* resourceIds, int size)
623{
624 auto context = static_cast<Context*>(ctx);
625 std::vector<Cogs::Core::MaterialInstanceHandle> handles(size);
626 for (int i = 0; i < size; ++i) {
627 const ResourceId resourceId = resourceIds[i];
628 handles[i] = (resourceId == NoResourceId) ? Cogs::Core::MaterialInstanceHandle() : context->materialInstanceManager->getHandle(resourceId);
629 }
630
631 Cogs::assignField(context, entityId, componentId, fieldId, handles.data(), size);
632}
633
634void setMaterialInstanceArrayField(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId, int index)
635{
636 auto context = static_cast<Context*>(ctx);
637 Cogs::Core::MaterialInstanceHandle handle = (resourceId == NoResourceId) ? Cogs::Core::MaterialInstanceHandle() : context->materialInstanceManager->getHandle(resourceId);
638 Cogs::setVectorField(context, entityId, componentId, fieldId, handle, index);
639}
640
641void setMaterialInstanceOption(BridgeContext * ctx, ResourceId resourceId, const char * name, const char * value)
642{
643 auto context = static_cast<Context*>(ctx);
644 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
645 if (!materialInstance) {
646 ::logInvalidResource("setMaterialInstanceOption", resourceId);
647 return;
648 }
649
650 materialInstance->setOption(name, value);
651 context->engine->setDirty();
652}
653
654void setMaterialInstanceProperty(BridgeContext * ctx, ResourceId resourceId, const char * name, const void * data, const int sizeInBytes)
655{
656 auto context = static_cast<Context*>(ctx);
657 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
658 if (!materialInstance) {
659 ::logInvalidResource("setMaterialInstanceProperty", resourceId);
660 return;
661 }
662
663 materialInstance->setProperty(name, data, static_cast<size_t>(sizeInBytes));
664 context->engine->setDirty();
665}
666
667CogsBool getMaterialInstanceProperty(BridgeContext * ctx, ResourceId resourceId, const char * name, void * data, const int sizeInBytes)
668{
669 auto context = static_cast<Context*>(ctx);
670 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
671 if (!materialInstance) {
672 ::logInvalidResource("getMaterialInstanceProperty", resourceId);
673 return false;
674 }
675
676 return materialInstance->getProperty(name, data, static_cast<size_t>(sizeInBytes));
677}
678
679int getMaterialInstancePropertyDataType(BridgeContext* ctx, ResourceId resourceId, const char* name)
680{
681 auto context = static_cast<Context*>(ctx);
682 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
683 if (!materialInstance) {
684 ::logInvalidResource("getMaterialInstancePropertyDataType", resourceId);
685 return static_cast<int>(MaterialDataType::Unknown);
686 }
687
688 return static_cast<int>(materialInstance->material->getPropertyDataType(name));
689}
690
691void setMaterialInstanceTexture(BridgeContext * ctx, ResourceId resourceId, const char * name, const ResourceId textureId)
692{
693 auto context = static_cast<Context*>(ctx);
694 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
695 if (!materialInstance) {
696 ::logInvalidResource("setMaterialInstanceTexture", resourceId);
697 return;
698 }
699
700 const VariableKey key = materialInstance->material->getTextureKey(name);
701 materialInstance->setTextureProperty(key, context->textureManager->getHandle(textureId));
702 context->engine->setDirty();
703}
704
705void setMaterialInstanceTextureAddressMode(BridgeContext * ctx, ResourceId resourceId, const char * name, const char * mode)
706{
707 auto context = static_cast<Context*>(ctx);
708 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
709 if (!materialInstance) {
710 ::logInvalidResource("setMaterialInstanceTextureAddressMode", resourceId);
711 return;
712 }
713
714 materialInstance->setTextureAddressMode(name, mode);
715 context->engine->setDirty();
716}
717
718void setMaterialInstanceTextureFilterMode(BridgeContext* ctx, ResourceId resourceId, const char* name, const char* filterMode)
719{
720 Context* context = static_cast<Context*>(ctx);
721 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
722 if (!materialInstance) {
723 ::logInvalidResource("setMaterialInstanceTextureFilterMode", resourceId);
724 return;
725 }
726
727 materialInstance->setTextureFilterMode(name, filterMode);
728 context->engine->setDirty();
729}
730
731void setMaterialInstancePermutation(BridgeContext * ctx, ResourceId resourceId, const char * name)
732{
733 auto context = static_cast<Context*>(ctx);
734 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
735 if (!materialInstance) {
736 ::logInvalidResource("setMaterialInstancePermutation", resourceId);
737 return;
738 }
739
740 materialInstance->setPermutation(name);
741 context->engine->setDirty();
742}
743
744void setMaterialInstanceVariant(BridgeContext * ctx, ResourceId resourceId, const char * key, const char * value)
745{
746 auto context = static_cast<Context*>(ctx);
747 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
748 if (!materialInstance) {
749 ::logInvalidResource("setMaterialInstanceVariant", resourceId);
750 return;
751 }
752
753 materialInstance->setVariant(key, value);
754 context->engine->setDirty();
755}
756
757const char * getMaterialInstanceVariant(BridgeContext * ctx, ResourceId resourceId, const char * key)
758{
759 auto context = static_cast<Context*>(ctx);
760 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
761 if (!materialInstance) {
762 ::logInvalidResource("getMaterialInstanceVariant", resourceId);
763 return nullptr;
764 }
765
766 // Static return is OK as single threaded access only is supported in this API.
767 getMaterialInstanceVariantOutput = materialInstance->getVariant(key);
768 return getMaterialInstanceVariantOutput.data();
769}
770
771void setMaterialInstanceFlags(BridgeContext * ctx, ResourceId resourceId, int materialFlags)
772{
773 auto context = static_cast<Context*>(ctx);
774 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(resourceId);
775 if (!materialInstance) {
776 ::logInvalidResource("setMaterialInstanceFlags", resourceId);
777 return;
778 }
779
780 materialInstance->instanceFlags = static_cast<uint16_t>(materialFlags);
781 context->engine->setDirty();
782}
783
784ResourceId getNextFontId(BridgeContext* ctx)
785{
786 auto context = static_cast<Context*>(ctx);
787 return context->fontManager->getNextResourceId();
788}
789
790ResourceId loadFont(BridgeContext* ctx, const char* resourceName, float size, ResourceId resourceId)
791{
792 auto context = static_cast<Context*>(ctx);
793 Cogs::Core::FontHandle loaded = context->fontManager->loadFont(resourceName, size, resourceId);
794 // Must return input resource if given.
795 return loaded->getId();
796}
797
798void releaseFont(BridgeContext* ctx, ResourceId resourceId)
799{
800 auto context = static_cast<Context*>(ctx);
801 context->fontManager->release(resourceId);
802}
803
804void addFontDependency(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId resourceId)
805{
806 auto context = static_cast<Context*>(ctx);
807 Cogs::Core::FontHandle handle = (resourceId == NoResourceId) ? Cogs::Core::FontHandle() : context->fontManager->getHandle(resourceId);
808 Cogs::setField(context, entityId, componentId, fieldId, handle);
809}
810
811void registerStringResource(BridgeContext * ctx, const char * key, const char * value)
812{
813 auto context = static_cast<Context*>(ctx);
814 context->resourceStore->addResource(key, value);
815 context->engine->setDirty();
816}
817
818void registerBinaryResource(BridgeContext* ctx, const char* key, const void* value, int length)
819{
820 auto context = static_cast<Context*>(ctx);
821 context->resourceStore->addResource(key, value, static_cast<size_t>(length));
822}
823
824void addResourceArchive(BridgeContext* ctx, const char* key, CogsBool prepend)
825{
826 auto context = static_cast<Context*>(ctx);
827 context->resourceStore->addResourceArchive(key, prepend != 0);
828 context->engine->setDirty();
829}
830CogsBool hasResource(BridgeContext* ctx, const char* key)
831{
832 auto context = static_cast<Context*>(ctx);
833 return context->resourceStore->hasResource(key);
834}
835
836ResourceId getMaterialInstance(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId)
837{
838 auto context = static_cast<Context*>(ctx);
839 MaterialInstanceHandle& materialInstance = *Cogs::getField<MaterialInstanceHandle>(context, entityId, componentId, fieldId);
840
841 if (materialInstance) {
842 ResourceId id = materialInstance->getId();
843
844 if (id == NoResourceId) {
845 id = context->materialInstanceManager->getNextResourceId();
846
847 context->materialInstanceManager->setResourceId(materialInstance.resolve(), id);
848 }
849
850 return id;
851 }
852
853 return NoResourceId;
854}
855
856int getMaterialInstances(BridgeContext * ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, ResourceId * ids, int idsCount)
857{
858 auto context = static_cast<Context*>(ctx);
859 const auto & materialInstances = *Cogs::getField<std::vector<MaterialInstanceHandle>>(context, entityId, componentId, fieldId);
860
861 for (size_t i = 0; i < static_cast<size_t>(idsCount); ++i) {
862
863 ResourceId id = NoResourceId;
864 if (i < materialInstances.size()) {
865
866 // No Ids allocated. Can possibly return values with 'holes - NoResourceId'.
867 // Setting ids should be done using setMaterialInstanceArrayField
868 const MaterialInstanceHandle& materialInstance = materialInstances[i];
869 if (materialInstance) {
870 id = materialInstance->getId();
871 }
872 }
873
874 ids[i] = id;
875 }
876
877 // Return actual count.
878 return static_cast<int>(materialInstances.size());
879}
880
881void addSearchPath(BridgeContext * ctx, const char * path)
882{
883 auto context = static_cast<Context*>(ctx);
884 context->resourceStore->addSearchPath(path, true);
885 context->engine->setDirty();
886}
887
888void purgeResource(BridgeContext * ctx, const char * resourceName)
889{
890 auto context = static_cast<Context*>(ctx);
891 context->resourceStore->purge(resourceName);
892 context->engine->setDirty();
893}
894
895void releaseTexture(BridgeContext * ctx, ResourceId resourceId)
896{
897 auto context = static_cast<Context*>(ctx);
898 TextureHandle h = context->textureManager->release(resourceId);
899 if (h) {
900 Texture* texture = context->textureManager->get(h);
901 if (texture->externalHandle && texture->ownsExternalTexture.value == false) {
902 LOG_TRACE(logger, "releaseTexture: Setting external handle of texture resource %d to 0", resourceId);
903 // External code wants to release the texture, don't use it anymore
904 texture->description = Cogs::TextureDescription{};
905 texture->externalHandle = 0; // Texture already released by external code.
906 texture->ownsExternalTexture = true; // Trigger removal of render texture.
907 texture->setChanged();
908 }
909 }
910 context->engine->setDirty();
911}
912
913ResourceId loadMaterial(BridgeContext * ctx, const char * resourceName)
914{
915 auto context = static_cast<Context*>(ctx);
916 const auto resourceId = context->materialManager->getNextResourceId();
917
918 MaterialHandle handle = context->materialManager->loadMaterial(resourceName, MaterialLoadFlags::None, resourceId);
919
920 context->materialManager->processLoading();
921
922 if (handle->getId() == NoResourceId) {
923 context->materialManager->setResourceId(handle.resolve(), resourceId);
924 }
925 context->engine->setDirty();
926
927 return handle->getId();
928}
929
930void setMaterialSharedProperty(BridgeContext* ctx, ResourceId materialId, const char* name, const void* data, const int sizeInBytes)
931{
932 auto context = static_cast<Context*>(ctx);
933 MaterialHandle material = context->materialManager->getHandle(materialId);
934 if (!material) {
935 // Error
936 ::logInvalidResource("setMaterialSharedProperty(materialId)", materialId);
937 return;
938 }
939
940 material->setProperty(name, data, static_cast<size_t>(sizeInBytes));
941 context->engine->setDirty();
942}
943
944void setMaterialsField(BridgeContext* ctx, EntityId entityId, const ComponentId componentId, const FieldId fieldId, const ResourceId* resourceIds, int size)
945{
946 Context* context = static_cast<Context*>(ctx);
947
948 std::vector<Cogs::Core::MaterialHandle> handles(size);
949 for (int i = 0; i < size; ++i) {
950 const ResourceId resourceId = resourceIds[i];
951 handles[i] = (resourceId == NoResourceId) ? Cogs::Core::MaterialHandle() : context->materialManager->getHandle(resourceId);
952 }
953 Cogs::assignField(context, entityId, componentId, fieldId, handles.data(), size);
954}
955
956int getMaterialPropertyDataType(BridgeContext* ctx, ResourceId resourceId, const char* name)
957{
958 auto context = static_cast<Context*>(ctx);
959 MaterialHandle material = context->materialManager->getHandle(resourceId);
960 if (!material) {
961 ::logInvalidResource("getMaterialPropertyDataType", resourceId);
962 return static_cast<int>(MaterialDataType::Unknown);
963 }
964
965 return static_cast<int>(material->getPropertyDataType(name));
966}
967
968ResourceId loadMaterialInstance(BridgeContext * ctx, ResourceId materialId)
969{
970 auto context = static_cast<Context*>(ctx);
971 ResourceId resourceId = context->materialInstanceManager->getNextResourceId();
972
973 MaterialHandle material = context->materialManager->getHandle(materialId);
974 if (!material) {
975 // Error
976 ::logInvalidResource("loadMaterialInstance(materialId)", materialId);
977 return NoResourceId;
978 }
979
980 MaterialInstanceHandle materialInstance = context->materialInstanceManager->createMaterialInstance(material);
981 context->materialInstanceManager->setResourceId(materialInstance.resolve(), resourceId);
982 context->engine->setDirty();
983
984 return resourceId;
985}
986
987void releaseMaterialInstance(BridgeContext * ctx, ResourceId resourceId)
988{
989 auto context = static_cast<Context*>(ctx);
990 context->materialInstanceManager->release(resourceId);
991}
992
993const char * getMaterialInstanceName(BridgeContext * ctx, ResourceId materialInstanceId)
994{
995 auto context = static_cast<Context *>(ctx);
996 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(materialInstanceId);
997 if (materialInstance) {
998 return materialInstance->getName().data();
999 }
1000
1001 ::logInvalidResource("getMaterialInstanceName", materialInstanceId);
1002 return nullptr;
1003}
1004
1005void setMaterialInstanceName(BridgeContext * ctx, ResourceId materialInstanceId, const char * name)
1006{
1007 auto context = static_cast<Context *>(ctx);
1008 MaterialInstanceHandle materialInstance = context->materialInstanceManager->getHandle(materialInstanceId);
1009 if (materialInstance) {
1010 materialInstance->setName(name);
1011 context->engine->setDirty();
1012 }
1013 else {
1014 ::logInvalidResource("setMaterialInstanceName", materialInstanceId);
1015 }
1016}
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:139
Provides a weakly referenced view over the contents of a string.
Definition: StringView.h:24
constexpr const char * data() const noexcept
Get the sequence of characters referenced by the string view.
Definition: StringView.h:171
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:47
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:180
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:44
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:35
void resize(size_t size)
Resize the buffer to accomodate the given number of bytes.
Definition: Buffer.cpp:17
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
EPrimitiveType
Primitive type enumeration.
Definition: Common.h:114
@ RenderTarget
The texture can be used as a render target and drawn into.
Definition: Flags.h:120