no message
This commit is contained in:
33
cocos/core/Any.h
Normal file
33
cocos/core/Any.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Any {
|
||||
public:
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
116
cocos/core/ArrayBuffer.h
Normal file
116
cocos/core/ArrayBuffer.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "base/Ptr.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "base/memory/Memory.h"
|
||||
#include "bindings/jswrapper/Object.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class ArrayBuffer : public RefCounted {
|
||||
public:
|
||||
using Ptr = IntrusivePtr<ArrayBuffer>;
|
||||
|
||||
explicit ArrayBuffer(uint32_t length) : _byteLength{length} {
|
||||
_jsArrayBuffer = se::Object::createArrayBufferObject(nullptr, length);
|
||||
_jsArrayBuffer->root();
|
||||
_jsArrayBuffer->getArrayBufferData(static_cast<uint8_t **>(&_data), nullptr);
|
||||
memset(_data, 0x00, _byteLength);
|
||||
}
|
||||
|
||||
ArrayBuffer(const uint8_t *data, uint32_t length) {
|
||||
reset(data, length);
|
||||
}
|
||||
|
||||
ArrayBuffer() = default;
|
||||
|
||||
~ArrayBuffer() override {
|
||||
if (_jsArrayBuffer) {
|
||||
_jsArrayBuffer->unroot();
|
||||
_jsArrayBuffer->decRef();
|
||||
}
|
||||
}
|
||||
|
||||
inline void setJSArrayBuffer(se::Object *arrayBuffer) {
|
||||
if (_jsArrayBuffer) {
|
||||
_jsArrayBuffer->unroot();
|
||||
_jsArrayBuffer->decRef();
|
||||
}
|
||||
|
||||
_jsArrayBuffer = arrayBuffer;
|
||||
_jsArrayBuffer->incRef();
|
||||
_jsArrayBuffer->root();
|
||||
size_t length{0};
|
||||
_jsArrayBuffer->getArrayBufferData(static_cast<uint8_t **>(&_data), &length);
|
||||
_byteLength = static_cast<uint32_t>(length);
|
||||
}
|
||||
inline se::Object *getJSArrayBuffer() const { return _jsArrayBuffer; }
|
||||
|
||||
inline uint32_t byteLength() const { return _byteLength; }
|
||||
|
||||
Ptr slice(uint32_t begin) {
|
||||
return slice(begin, _byteLength);
|
||||
}
|
||||
|
||||
Ptr slice(uint32_t begin, uint32_t end) {
|
||||
CC_ASSERT_GT(end, begin);
|
||||
CC_ASSERT_LT(begin, _byteLength);
|
||||
CC_ASSERT_LE(end, _byteLength);
|
||||
uint32_t newBufByteLength = (end - begin);
|
||||
Ptr buffer = ccnew ArrayBuffer(newBufByteLength);
|
||||
memcpy(buffer->getData(), _data + begin, newBufByteLength);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// Just use it to copy data. Use TypedArray to get/set data.
|
||||
inline const uint8_t *getData() const { return _data; }
|
||||
inline uint8_t *getData() { return _data; }
|
||||
|
||||
inline void reset(const uint8_t *data, uint32_t length) {
|
||||
if (_jsArrayBuffer != nullptr) {
|
||||
_jsArrayBuffer->unroot();
|
||||
_jsArrayBuffer->decRef();
|
||||
}
|
||||
_jsArrayBuffer = se::Object::createArrayBufferObject(data, length);
|
||||
_jsArrayBuffer->getArrayBufferData(static_cast<uint8_t **>(&_data), nullptr);
|
||||
_byteLength = length;
|
||||
}
|
||||
|
||||
private:
|
||||
se::Object *_jsArrayBuffer{nullptr};
|
||||
uint8_t *_data{nullptr};
|
||||
uint32_t _byteLength{0};
|
||||
|
||||
template <class T>
|
||||
friend class TypedArrayTemp;
|
||||
friend class DataView;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(ArrayBuffer);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
186
cocos/core/DataView.cpp
Normal file
186
cocos/core/DataView.cpp
Normal file
@@ -0,0 +1,186 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/DataView.h"
|
||||
#include "base/TemplateUtils.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "core/ArrayBuffer.h"
|
||||
|
||||
ccstd::unordered_map<ccstd::string, DataView::ReaderVariant> DataView::intReaderMap{
|
||||
{"getUint8", &DataView::getUint8},
|
||||
{"getUint16", &DataView::getUint16},
|
||||
{"getUint32", &DataView::getUint32},
|
||||
{"getInt8", &DataView::getInt8},
|
||||
{"getInt16", &DataView::getInt16},
|
||||
{"getInt32", &DataView::getInt32},
|
||||
};
|
||||
|
||||
ccstd::unordered_map<ccstd::string, DataView::IntWritter> DataView::intWritterMap{
|
||||
{"setUint8", reinterpret_cast<DataView::IntWritter>(&DataView::setUint8)},
|
||||
{"setUint16", reinterpret_cast<DataView::IntWritter>(&DataView::setUint16)},
|
||||
{"setUint32", reinterpret_cast<DataView::IntWritter>(&DataView::setUint32)},
|
||||
{"setInt8", reinterpret_cast<DataView::IntWritter>(&DataView::setInt8)},
|
||||
{"setInt16", reinterpret_cast<DataView::IntWritter>(&DataView::setInt16)},
|
||||
{"setInt32", reinterpret_cast<DataView::IntWritter>(&DataView::setInt32)},
|
||||
};
|
||||
|
||||
int32_t DataView::readInt(ReaderVariant &readerVariant, uint32_t offset) {
|
||||
return ccstd::visit(overloaded{
|
||||
[offset, this](auto &reader) {
|
||||
return static_cast<int32_t>((this->*reader)(offset));
|
||||
},
|
||||
[](ccstd::monostate & /*unused*/) { return 0; }},
|
||||
readerVariant);
|
||||
}
|
||||
|
||||
DataView::DataView(ArrayBuffer *buffer) : DataView(buffer, 0) {}
|
||||
|
||||
DataView::DataView(ArrayBuffer *buffer, uint32_t byteOffset)
|
||||
: DataView(buffer, byteOffset, buffer ? (buffer->byteLength() - byteOffset) : 0) {}
|
||||
|
||||
DataView::DataView(ArrayBuffer *buffer, uint32_t byteOffset, uint32_t byteLength) {
|
||||
assign(buffer, byteOffset, byteLength);
|
||||
}
|
||||
|
||||
void DataView::assign(ArrayBuffer *buffer) {
|
||||
assign(buffer, 0);
|
||||
}
|
||||
|
||||
void DataView::assign(ArrayBuffer *buffer, uint32_t byteOffset) {
|
||||
assign(buffer, byteOffset, buffer ? buffer->byteLength() : 0);
|
||||
}
|
||||
|
||||
void DataView::assign(ArrayBuffer *buffer, uint32_t byteOffset, uint32_t byteLength) {
|
||||
CC_ASSERT_NOT_NULL(buffer);
|
||||
CC_ASSERT_GT(byteLength, 0);
|
||||
_buffer = buffer;
|
||||
_byteOffset = byteOffset;
|
||||
_byteEndPos = byteLength + byteOffset;
|
||||
CC_ASSERT(_byteEndPos <= buffer->_byteLength);
|
||||
|
||||
_data = buffer->_data;
|
||||
}
|
||||
|
||||
uint8_t DataView::getUint8(uint32_t offset) const {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT_LT(offset, _byteEndPos);
|
||||
|
||||
return _data[offset];
|
||||
}
|
||||
|
||||
uint16_t DataView::getUint16(uint32_t offset) const {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < (_byteEndPos - 1));
|
||||
|
||||
return *reinterpret_cast<uint16_t *>(_data + offset);
|
||||
}
|
||||
|
||||
uint32_t DataView::getUint32(uint32_t offset) const {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < (_byteEndPos - 3));
|
||||
|
||||
return *reinterpret_cast<uint32_t *>(_data + offset);
|
||||
}
|
||||
|
||||
int8_t DataView::getInt8(uint32_t offset) const {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT_LT(offset, _byteEndPos);
|
||||
|
||||
return static_cast<int8_t>(_data[offset]);
|
||||
}
|
||||
|
||||
int16_t DataView::getInt16(uint32_t offset) const {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < (_byteEndPos - 1));
|
||||
|
||||
return *reinterpret_cast<int16_t *>(_data + offset);
|
||||
}
|
||||
|
||||
int32_t DataView::getInt32(uint32_t offset) const {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < (_byteEndPos - 3));
|
||||
|
||||
return *reinterpret_cast<int32_t *>(_data + offset);
|
||||
}
|
||||
|
||||
float DataView::getFloat32(uint32_t offset) const {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < (_byteEndPos - 3));
|
||||
|
||||
return *reinterpret_cast<float *>(_data + offset);
|
||||
}
|
||||
|
||||
void DataView::setUint8(uint32_t offset, uint8_t value) {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT_LT(offset, _byteEndPos);
|
||||
|
||||
_data[offset] = value;
|
||||
}
|
||||
|
||||
void DataView::setUint16(uint32_t offset, uint16_t value) {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < _byteEndPos - 1);
|
||||
|
||||
*reinterpret_cast<uint16_t *>(_data + offset) = value;
|
||||
}
|
||||
|
||||
void DataView::setUint32(uint32_t offset, uint32_t value) {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < _byteEndPos - 3);
|
||||
|
||||
*reinterpret_cast<uint32_t *>(_data + offset) = value;
|
||||
}
|
||||
|
||||
void DataView::setInt8(uint32_t offset, int8_t value) {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT_LT(offset, _byteEndPos);
|
||||
|
||||
*reinterpret_cast<int8_t *>(_data + offset) = value;
|
||||
}
|
||||
|
||||
void DataView::setInt16(uint32_t offset, int16_t value) {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < _byteEndPos - 1);
|
||||
|
||||
*reinterpret_cast<int16_t *>(_data + offset) = value;
|
||||
}
|
||||
|
||||
void DataView::setInt32(uint32_t offset, int32_t value) {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < _byteEndPos - 3);
|
||||
|
||||
*reinterpret_cast<int32_t *>(_data + offset) = value;
|
||||
}
|
||||
|
||||
void DataView::setFloat32(uint32_t offset, float value) {
|
||||
offset += _byteOffset;
|
||||
CC_ASSERT(offset < _byteEndPos - 3);
|
||||
|
||||
*(reinterpret_cast<float *>(_data + offset)) = value;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
88
cocos/core/DataView.h
Normal file
88
cocos/core/DataView.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "base/std/variant.h"
|
||||
#include "core/ArrayBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class DataView final {
|
||||
public:
|
||||
DataView() = default;
|
||||
explicit DataView(ArrayBuffer *buffer);
|
||||
DataView(ArrayBuffer *buffer, uint32_t byteOffset);
|
||||
DataView(ArrayBuffer *buffer, uint32_t byteOffset, uint32_t byteLength);
|
||||
~DataView() = default;
|
||||
|
||||
void assign(ArrayBuffer *buffer);
|
||||
void assign(ArrayBuffer *buffer, uint32_t byteOffset);
|
||||
void assign(ArrayBuffer *buffer, uint32_t byteOffset, uint32_t byteLength);
|
||||
|
||||
uint8_t getUint8(uint32_t offset) const;
|
||||
uint16_t getUint16(uint32_t offset) const;
|
||||
uint32_t getUint32(uint32_t offset) const;
|
||||
int8_t getInt8(uint32_t offset) const;
|
||||
int16_t getInt16(uint32_t offset) const;
|
||||
int32_t getInt32(uint32_t offset) const;
|
||||
float getFloat32(uint32_t offset) const;
|
||||
|
||||
void setUint8(uint32_t offset, uint8_t value);
|
||||
void setUint16(uint32_t offset, uint16_t value);
|
||||
void setUint32(uint32_t offset, uint32_t value);
|
||||
void setInt8(uint32_t offset, int8_t value);
|
||||
void setInt16(uint32_t offset, int16_t value);
|
||||
void setInt32(uint32_t offset, int32_t value);
|
||||
void setFloat32(uint32_t offset, float value);
|
||||
|
||||
inline const ArrayBuffer *buffer() const { return _buffer; }
|
||||
inline ArrayBuffer *buffer() { return _buffer; }
|
||||
inline uint32_t byteOffset() const { return _byteOffset; }
|
||||
inline uint32_t byteLength() const {
|
||||
return _byteEndPos - _byteOffset;
|
||||
}
|
||||
|
||||
using Int32Reader = int32_t (DataView::*)(uint32_t) const;
|
||||
using UInt32Reader = uint32_t (DataView::*)(uint32_t) const;
|
||||
using Int16Reader = int16_t (DataView::*)(uint32_t) const;
|
||||
using UInt16Reader = uint16_t (DataView::*)(uint32_t) const;
|
||||
using Int8Reader = int8_t (DataView::*)(uint32_t) const;
|
||||
using UInt8Reader = uint8_t (DataView::*)(uint32_t) const;
|
||||
using ReaderVariant = ccstd::variant<ccstd::monostate, Int32Reader, UInt32Reader, Int16Reader, UInt16Reader, Int8Reader, UInt8Reader>;
|
||||
static ccstd::unordered_map<ccstd::string, ReaderVariant> intReaderMap;
|
||||
int32_t readInt(ReaderVariant &readerVariant, uint32_t offset);
|
||||
|
||||
using IntWritter = void (DataView::*)(uint32_t, uint32_t);
|
||||
static ccstd::unordered_map<ccstd::string, IntWritter> intWritterMap;
|
||||
|
||||
private:
|
||||
ArrayBuffer::Ptr _buffer;
|
||||
uint8_t *_data{nullptr};
|
||||
uint32_t _byteOffset{0};
|
||||
uint32_t _byteEndPos{0};
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
676
cocos/core/Root.cpp
Normal file
676
cocos/core/Root.cpp
Normal file
@@ -0,0 +1,676 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/Root.h"
|
||||
#include "2d/renderer/Batcher2d.h"
|
||||
#include "application/ApplicationManager.h"
|
||||
#include "bindings/event/EventDispatcher.h"
|
||||
#include "pipeline/custom/RenderingModule.h"
|
||||
#include "platform/interfaces/modules/IScreen.h"
|
||||
#include "platform/interfaces/modules/ISystemWindow.h"
|
||||
#include "platform/interfaces/modules/ISystemWindowManager.h"
|
||||
#include "platform/interfaces/modules/IXRInterface.h"
|
||||
#if CC_USE_DEBUG_RENDERER
|
||||
#include "profiler/DebugRenderer.h"
|
||||
#endif
|
||||
#include "engine/EngineEvents.h"
|
||||
#include "profiler/Profiler.h"
|
||||
#include "renderer/gfx-base/GFXDevice.h"
|
||||
#include "renderer/gfx-base/GFXSwapchain.h"
|
||||
#include "renderer/pipeline/Define.h"
|
||||
#include "renderer/pipeline/GeometryRenderer.h"
|
||||
#include "renderer/pipeline/PipelineSceneData.h"
|
||||
#include "renderer/pipeline/custom/NativePipelineTypes.h"
|
||||
#include "renderer/pipeline/custom/RenderInterfaceTypes.h"
|
||||
#include "renderer/pipeline/deferred/DeferredPipeline.h"
|
||||
#include "renderer/pipeline/forward/ForwardPipeline.h"
|
||||
#include "scene/Camera.h"
|
||||
#include "scene/DirectionalLight.h"
|
||||
#include "scene/SpotLight.h"
|
||||
#include "scene/Skybox.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
Root *instance = nullptr;
|
||||
}
|
||||
|
||||
Root *Root::getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
Root::Root(gfx::Device *device)
|
||||
: _device(device) {
|
||||
instance = this;
|
||||
// TODO(minggo):
|
||||
// this._dataPoolMgr = legacyCC.internal.DataPoolManager && new legacyCC.internal.DataPoolManager(device) as DataPoolManager;
|
||||
|
||||
_cameraList.reserve(6);
|
||||
_swapchains.reserve(2);
|
||||
}
|
||||
|
||||
Root::~Root() {
|
||||
destroy();
|
||||
instance = nullptr;
|
||||
}
|
||||
|
||||
void Root::initialize(gfx::Swapchain * /*swapchain*/) {
|
||||
auto *windowMgr = CC_GET_PLATFORM_INTERFACE(ISystemWindowManager);
|
||||
const auto &windows = windowMgr->getWindows();
|
||||
for (const auto &pair : windows) {
|
||||
auto *window = pair.second.get();
|
||||
scene::RenderWindow *renderWindow = createRenderWindowFromSystemWindow(window);
|
||||
if (!_mainRenderWindow && (window->getWindowId() == ISystemWindow::mainWindowId)) {
|
||||
_mainRenderWindow = renderWindow;
|
||||
}
|
||||
}
|
||||
_curRenderWindow = _mainRenderWindow;
|
||||
_xr = CC_GET_XR_INTERFACE();
|
||||
addWindowEventListener();
|
||||
// TODO(minggo):
|
||||
// return Promise.resolve(builtinResMgr.initBuiltinRes(this._device));
|
||||
const uint32_t usedUBOVectorCount = (pipeline::UBOGlobal::COUNT + pipeline::UBOCamera::COUNT + pipeline::UBOShadow::COUNT + pipeline::UBOLocal::COUNT + pipeline::UBOWorldBound::COUNT) / 4;
|
||||
uint32_t maxJoints = (_device->getCapabilities().maxVertexUniformVectors - usedUBOVectorCount) / 3;
|
||||
maxJoints = maxJoints < 256 ? maxJoints : 256;
|
||||
pipeline::localDescriptorSetLayoutResizeMaxJoints(maxJoints);
|
||||
|
||||
_debugView = std::make_unique<pipeline::DebugView>();
|
||||
}
|
||||
|
||||
render::Pipeline *Root::getCustomPipeline() const {
|
||||
return dynamic_cast<render::Pipeline *>(_pipelineRuntime.get());
|
||||
}
|
||||
|
||||
scene::RenderWindow *Root::createRenderWindowFromSystemWindow(ISystemWindow *window) {
|
||||
if (!window) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t windowId = window->getWindowId();
|
||||
auto handle = window->getWindowHandle();
|
||||
const auto &size = window->getViewSize();
|
||||
|
||||
gfx::SwapchainInfo info;
|
||||
info.width = static_cast<uint32_t>(size.width);
|
||||
info.height = static_cast<uint32_t>(size.height);
|
||||
info.windowHandle = reinterpret_cast<void *>(handle); // NOLINT
|
||||
info.windowId = window->getWindowId();
|
||||
|
||||
gfx::Swapchain *swapchain = gfx::Device::getInstance()->createSwapchain(info);
|
||||
_swapchains.emplace_back(swapchain);
|
||||
|
||||
gfx::RenderPassInfo renderPassInfo;
|
||||
|
||||
gfx::ColorAttachment colorAttachment;
|
||||
colorAttachment.format = swapchain->getColorTexture()->getFormat();
|
||||
renderPassInfo.colorAttachments.emplace_back(colorAttachment);
|
||||
|
||||
auto &depthStencilAttachment = renderPassInfo.depthStencilAttachment;
|
||||
depthStencilAttachment.format = swapchain->getDepthStencilTexture()->getFormat();
|
||||
depthStencilAttachment.depthStoreOp = gfx::StoreOp::DISCARD;
|
||||
depthStencilAttachment.stencilStoreOp = gfx::StoreOp::DISCARD;
|
||||
|
||||
scene::IRenderWindowInfo windowInfo;
|
||||
windowInfo.title = StringUtil::format("renderWindow_%d", windowId);
|
||||
windowInfo.width = swapchain->getWidth();
|
||||
windowInfo.height = swapchain->getHeight();
|
||||
windowInfo.renderPassInfo = renderPassInfo;
|
||||
windowInfo.swapchain = swapchain;
|
||||
|
||||
return createWindow(windowInfo);
|
||||
}
|
||||
|
||||
cc::scene::RenderWindow *Root::createRenderWindowFromSystemWindow(uint32_t windowId) {
|
||||
if (windowId == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return createRenderWindowFromSystemWindow(CC_GET_SYSTEM_WINDOW(windowId));
|
||||
}
|
||||
|
||||
void Root::destroy() {
|
||||
destroyScenes();
|
||||
removeWindowEventListener();
|
||||
if (_pipelineRuntime) {
|
||||
_pipelineRuntime->destroy();
|
||||
}
|
||||
_pipelineRuntime.reset();
|
||||
|
||||
CC_SAFE_DESTROY_NULL(_pipeline);
|
||||
|
||||
CC_SAFE_DELETE(_batcher);
|
||||
|
||||
for (auto *swapchain : _swapchains) {
|
||||
CC_SAFE_DELETE(swapchain);
|
||||
}
|
||||
_swapchains.clear();
|
||||
|
||||
_debugView.reset();
|
||||
|
||||
// TODO(minggo):
|
||||
// this.dataPoolManager.clear();
|
||||
}
|
||||
|
||||
void Root::resize(uint32_t width, uint32_t height, uint32_t windowId) { // NOLINT
|
||||
for (const auto &window : _renderWindows) {
|
||||
auto *swapchain = window->getSwapchain();
|
||||
if (swapchain && (swapchain->getWindowId() == windowId)) {
|
||||
if (_xr) {
|
||||
// xr, window's width and height should not change by device
|
||||
width = window->getWidth();
|
||||
height = window->getHeight();
|
||||
}
|
||||
window->resize(width, height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class RenderPipelineBridge final : public render::PipelineRuntime {
|
||||
public:
|
||||
explicit RenderPipelineBridge(pipeline::RenderPipeline *pipelineIn)
|
||||
: pipeline(pipelineIn) {}
|
||||
|
||||
bool activate(gfx::Swapchain *swapchain) override {
|
||||
return pipeline->activate(swapchain);
|
||||
}
|
||||
bool destroy() noexcept override {
|
||||
return pipeline->destroy();
|
||||
}
|
||||
void render(const ccstd::vector<scene::Camera *> &cameras) override {
|
||||
pipeline->render(cameras);
|
||||
}
|
||||
gfx::Device *getDevice() const override {
|
||||
return pipeline->getDevice();
|
||||
}
|
||||
const MacroRecord &getMacros() const override {
|
||||
return pipeline->getMacros();
|
||||
}
|
||||
pipeline::GlobalDSManager *getGlobalDSManager() const override {
|
||||
return pipeline->getGlobalDSManager();
|
||||
}
|
||||
gfx::DescriptorSetLayout *getDescriptorSetLayout() const override {
|
||||
return pipeline->getDescriptorSetLayout();
|
||||
}
|
||||
gfx::DescriptorSet *getDescriptorSet() const override {
|
||||
return pipeline->getDescriptorSet();
|
||||
}
|
||||
const ccstd::vector<gfx::CommandBuffer *> &getCommandBuffers() const override {
|
||||
return pipeline->getCommandBuffers();
|
||||
}
|
||||
pipeline::PipelineSceneData *getPipelineSceneData() const override {
|
||||
return pipeline->getPipelineSceneData();
|
||||
}
|
||||
const ccstd::string &getConstantMacros() const override {
|
||||
return pipeline->getConstantMacros();
|
||||
}
|
||||
scene::Model *getProfiler() const override {
|
||||
return pipeline->getProfiler();
|
||||
}
|
||||
void setProfiler(scene::Model *profiler) override {
|
||||
pipeline->setProfiler(profiler);
|
||||
}
|
||||
pipeline::GeometryRenderer *getGeometryRenderer() const override {
|
||||
return pipeline->getGeometryRenderer();
|
||||
}
|
||||
float getShadingScale() const override {
|
||||
return pipeline->getShadingScale();
|
||||
}
|
||||
void setShadingScale(float scale) override {
|
||||
pipeline->setShadingScale(scale);
|
||||
}
|
||||
const ccstd::string &getMacroString(const ccstd::string &name) const override {
|
||||
static const ccstd::string EMPTY_STRING;
|
||||
const auto ¯os = pipeline->getMacros();
|
||||
auto iter = macros.find(name);
|
||||
if (iter == macros.end()) {
|
||||
return EMPTY_STRING;
|
||||
}
|
||||
return ccstd::get<ccstd::string>(iter->second);
|
||||
}
|
||||
int32_t getMacroInt(const ccstd::string &name) const override {
|
||||
const auto ¯os = pipeline->getMacros();
|
||||
auto iter = macros.find(name);
|
||||
if (iter == macros.end()) {
|
||||
return 0;
|
||||
}
|
||||
return ccstd::get<int32_t>(iter->second);
|
||||
}
|
||||
bool getMacroBool(const ccstd::string &name) const override {
|
||||
const auto ¯os = pipeline->getMacros();
|
||||
auto iter = macros.find(name);
|
||||
if (iter == macros.end()) {
|
||||
return false;
|
||||
}
|
||||
return ccstd::get<bool>(iter->second);
|
||||
}
|
||||
void setMacroString(const ccstd::string &name, const ccstd::string &value) override {
|
||||
pipeline->setValue(name, value);
|
||||
}
|
||||
void setMacroInt(const ccstd::string &name, int32_t value) override {
|
||||
pipeline->setValue(name, value);
|
||||
}
|
||||
void setMacroBool(const ccstd::string &name, bool value) override {
|
||||
pipeline->setValue(name, value);
|
||||
}
|
||||
void onGlobalPipelineStateChanged() override {
|
||||
pipeline->onGlobalPipelineStateChanged();
|
||||
}
|
||||
void setValue(const ccstd::string &name, int32_t value) override {
|
||||
pipeline->setValue(name, value);
|
||||
}
|
||||
void setValue(const ccstd::string &name, bool value) override {
|
||||
pipeline->setValue(name, value);
|
||||
}
|
||||
bool isOcclusionQueryEnabled() const override {
|
||||
return pipeline->isOcclusionQueryEnabled();
|
||||
}
|
||||
|
||||
void resetRenderQueue(bool reset) override {
|
||||
pipeline->resetRenderQueue(reset);
|
||||
}
|
||||
|
||||
bool isRenderQueueReset() const override {
|
||||
return pipeline->isRenderQueueReset();
|
||||
}
|
||||
|
||||
pipeline::RenderPipeline *pipeline = nullptr;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool Root::setRenderPipeline(pipeline::RenderPipeline *rppl /* = nullptr*/) {
|
||||
if (rppl) {
|
||||
if (dynamic_cast<pipeline::DeferredPipeline *>(rppl) != nullptr) {
|
||||
_useDeferredPipeline = true;
|
||||
}
|
||||
|
||||
_pipeline = rppl;
|
||||
_pipelineRuntime = std::make_unique<RenderPipelineBridge>(rppl);
|
||||
rppl->setPipelineRuntime(_pipelineRuntime.get());
|
||||
|
||||
// now cluster just enabled in deferred pipeline
|
||||
if (!_useDeferredPipeline || !_device->hasFeature(gfx::Feature::COMPUTE_SHADER)) {
|
||||
// disable cluster
|
||||
_pipeline->setClusterEnabled(false);
|
||||
}
|
||||
_pipeline->setBloomEnabled(false);
|
||||
|
||||
if (!_pipeline->activate(_mainRenderWindow->getSwapchain())) {
|
||||
_pipeline = nullptr;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
CC_ASSERT(!_pipelineRuntime);
|
||||
_pipelineRuntime.reset(render::Factory::createPipeline());
|
||||
if (!_pipelineRuntime->activate(_mainRenderWindow->getSwapchain())) {
|
||||
_pipelineRuntime->destroy();
|
||||
_pipelineRuntime.reset();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(minggo):
|
||||
// auto *scene = Director::getInstance()->getScene();
|
||||
// if (scene) {
|
||||
// scene->getSceneGlobals()->activate();
|
||||
// }
|
||||
|
||||
#if CC_EDITOR
|
||||
emit<PipelineChanged>();
|
||||
#endif
|
||||
|
||||
onGlobalPipelineStateChanged();
|
||||
|
||||
if (_batcher == nullptr) {
|
||||
_batcher = ccnew Batcher2d(this);
|
||||
if (!_batcher->initialize()) {
|
||||
destroy();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Root::onGlobalPipelineStateChanged() {
|
||||
for (const auto &scene : _scenes) {
|
||||
scene->onGlobalPipelineStateChanged();
|
||||
}
|
||||
|
||||
if (_pipelineRuntime->getPipelineSceneData()->getSkybox()->isEnabled())
|
||||
{
|
||||
_pipelineRuntime->getPipelineSceneData()->getSkybox()->getModel()->onGlobalPipelineStateChanged();
|
||||
}
|
||||
|
||||
_pipelineRuntime->onGlobalPipelineStateChanged();
|
||||
}
|
||||
|
||||
void Root::activeWindow(scene::RenderWindow *window) {
|
||||
_curRenderWindow = window;
|
||||
}
|
||||
|
||||
void Root::resetCumulativeTime() {
|
||||
_cumulativeTime = 0;
|
||||
}
|
||||
|
||||
void Root::frameSync() {
|
||||
if (_device) {
|
||||
_device->frameSync();
|
||||
}
|
||||
}
|
||||
|
||||
void Root::frameMoveBegin() {
|
||||
for (const auto &scene : _scenes) {
|
||||
scene->removeBatches();
|
||||
}
|
||||
|
||||
if (_batcher != nullptr) {
|
||||
_batcher->update();
|
||||
}
|
||||
|
||||
//
|
||||
_cameraList.clear();
|
||||
}
|
||||
|
||||
void Root::frameMoveProcess(bool isNeedUpdateScene, int32_t totalFrames) {
|
||||
for (const auto &window : _renderWindows) {
|
||||
window->extractRenderCameras(_cameraList);
|
||||
}
|
||||
|
||||
if (_pipelineRuntime != nullptr && !_cameraList.empty()) {
|
||||
_device->acquire(_swapchains);
|
||||
|
||||
// NOTE: c++ doesn't have a Director, so totalFrames need to be set from JS
|
||||
uint32_t stamp = totalFrames;
|
||||
|
||||
if (_batcher != nullptr) {
|
||||
_batcher->uploadBuffers();
|
||||
}
|
||||
|
||||
if (isNeedUpdateScene) {
|
||||
for (const auto &scene : _scenes) {
|
||||
scene->update(stamp);
|
||||
}
|
||||
}
|
||||
|
||||
CC_PROFILER_UPDATE;
|
||||
}
|
||||
}
|
||||
|
||||
void Root::frameMoveEnd() {
|
||||
if (_pipelineRuntime != nullptr && !_cameraList.empty()) {
|
||||
emit<BeforeCommit>();
|
||||
std::stable_sort(_cameraList.begin(), _cameraList.end(), [](const auto *a, const auto *b) {
|
||||
return a->getPriority() < b->getPriority();
|
||||
});
|
||||
#if !defined(CC_SERVER_MODE)
|
||||
|
||||
#if CC_USE_GEOMETRY_RENDERER
|
||||
for (auto *camera : _cameraList) {
|
||||
if (camera->getGeometryRenderer()) {
|
||||
camera->getGeometryRenderer()->update();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if CC_USE_DEBUG_RENDERER
|
||||
CC_DEBUG_RENDERER->update();
|
||||
#endif
|
||||
|
||||
emit<BeforeRender>();
|
||||
_pipelineRuntime->render(_cameraList);
|
||||
emit<AfterRender>();
|
||||
#endif
|
||||
_device->present();
|
||||
}
|
||||
|
||||
if (_batcher != nullptr) {
|
||||
_batcher->reset();
|
||||
}
|
||||
}
|
||||
|
||||
void Root::frameMove(float deltaTime, int32_t totalFrames) { // NOLINT
|
||||
CCObject::deferredDestroy();
|
||||
|
||||
_frameTime = deltaTime;
|
||||
|
||||
++_frameCount;
|
||||
_cumulativeTime += deltaTime;
|
||||
_fpsTime += deltaTime;
|
||||
if (_fpsTime > 1.0F) {
|
||||
_fps = _frameCount;
|
||||
_frameCount = 0;
|
||||
_fpsTime = 0.0;
|
||||
}
|
||||
|
||||
if (_xr) {
|
||||
doXRFrameMove(totalFrames);
|
||||
} else {
|
||||
frameMoveBegin();
|
||||
frameMoveProcess(true, totalFrames);
|
||||
frameMoveEnd();
|
||||
}
|
||||
}
|
||||
|
||||
scene::RenderWindow *Root::createWindow(scene::IRenderWindowInfo &info) {
|
||||
IntrusivePtr<scene::RenderWindow> window = ccnew scene::RenderWindow();
|
||||
|
||||
window->initialize(_device, info);
|
||||
_renderWindows.emplace_back(window);
|
||||
return window;
|
||||
}
|
||||
|
||||
void Root::destroyWindow(scene::RenderWindow *window) {
|
||||
auto it = std::find(_renderWindows.begin(), _renderWindows.end(), window);
|
||||
if (it != _renderWindows.end()) {
|
||||
CC_SAFE_DESTROY(*it);
|
||||
_renderWindows.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void Root::destroyWindows() {
|
||||
for (const auto &window : _renderWindows) {
|
||||
CC_SAFE_DESTROY(window);
|
||||
}
|
||||
_renderWindows.clear();
|
||||
}
|
||||
|
||||
uint32_t Root::createSystemWindow(const ISystemWindowInfo &info) {
|
||||
auto *windowMgr = CC_GET_PLATFORM_INTERFACE(ISystemWindowManager);
|
||||
ISystemWindow *window = windowMgr->createWindow(info);
|
||||
if (!window) {
|
||||
return 0;
|
||||
}
|
||||
return window->getWindowId();
|
||||
}
|
||||
|
||||
scene::RenderScene *Root::createScene(const scene::IRenderSceneInfo &info) {
|
||||
IntrusivePtr<scene::RenderScene> scene = ccnew scene::RenderScene();
|
||||
scene->initialize(info);
|
||||
_scenes.emplace_back(scene);
|
||||
return scene.get();
|
||||
}
|
||||
|
||||
void Root::destroyScene(scene::RenderScene *scene) {
|
||||
auto it = std::find(_scenes.begin(), _scenes.end(), scene);
|
||||
if (it != _scenes.end()) {
|
||||
CC_SAFE_DESTROY(*it);
|
||||
_scenes.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void Root::destroyModel(scene::Model *model) { // NOLINT(readability-convert-member-functions-to-static)
|
||||
if (model == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (model->getScene() != nullptr) {
|
||||
model->getScene()->removeModel(model);
|
||||
}
|
||||
model->destroy();
|
||||
}
|
||||
|
||||
void Root::destroyLight(scene::Light *light) { // NOLINT(readability-convert-member-functions-to-static)
|
||||
if (light == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (light->getScene() != nullptr) {
|
||||
if (light->getType() == scene::LightType::DIRECTIONAL) {
|
||||
light->getScene()->removeDirectionalLight(static_cast<scene::DirectionalLight *>(light));
|
||||
} else if (light->getType() == scene::LightType::SPHERE) {
|
||||
light->getScene()->removeSphereLight(static_cast<scene::SphereLight *>(light));
|
||||
} else if (light->getType() == scene::LightType::SPOT) {
|
||||
light->getScene()->removeSpotLight(static_cast<scene::SpotLight *>(light));
|
||||
} else if (light->getType() == scene::LightType::POINT) {
|
||||
light->getScene()->removePointLight(static_cast<scene::PointLight *>(light));
|
||||
} else if (light->getType() == scene::LightType::RANGED_DIRECTIONAL) {
|
||||
light->getScene()->removeRangedDirLight(static_cast<scene::RangedDirectionalLight *>(light));
|
||||
}
|
||||
}
|
||||
light->destroy();
|
||||
}
|
||||
|
||||
scene::Camera *Root::createCamera() const {
|
||||
return ccnew scene::Camera(_device);
|
||||
}
|
||||
|
||||
void Root::destroyScenes() {
|
||||
for (const auto &scene : _scenes) {
|
||||
CC_SAFE_DESTROY(scene);
|
||||
}
|
||||
_scenes.clear();
|
||||
}
|
||||
|
||||
void Root::doXRFrameMove(int32_t totalFrames) {
|
||||
if (_xr->isRenderAllowable()) {
|
||||
bool isSceneUpdated = false;
|
||||
int viewCount = _xr->getXRConfig(xr::XRConfigKey::VIEW_COUNT).getInt();
|
||||
// compatible native pipeline
|
||||
static bool isNativePipeline = dynamic_cast<cc::render::NativePipeline*>(_pipelineRuntime.get()) != nullptr;
|
||||
bool forceUpdateSceneTwice = isNativePipeline ? true : _xr->getXRConfig(xr::XRConfigKey::EYE_RENDER_JS_CALLBACK).getBool();
|
||||
for (int xrEye = 0; xrEye < viewCount; xrEye++) {
|
||||
_xr->beginRenderEyeFrame(xrEye);
|
||||
|
||||
ccstd::vector<IntrusivePtr<scene::Camera>> allCameras;
|
||||
for (const auto &window : _renderWindows) {
|
||||
const ccstd::vector<IntrusivePtr<scene::Camera>> &wndCams = window->getCameras();
|
||||
allCameras.insert(allCameras.end(), wndCams.begin(), wndCams.end());
|
||||
}
|
||||
|
||||
// when choose PreEyeCamera, only hmd has PoseTracker
|
||||
// draw left eye change hmd node's position to -ipd/2 | draw right eye change hmd node's position to ipd/2
|
||||
for (const auto &camera : allCameras) {
|
||||
if (camera->getTrackingType() != cc::scene::TrackingType::NO_TRACKING) {
|
||||
Node *camNode = camera->getNode();
|
||||
if (camNode) {
|
||||
const auto &viewPosition = _xr->getHMDViewPosition(xrEye, static_cast<int>(camera->getTrackingType()));
|
||||
camNode->setPosition({viewPosition[0], viewPosition[1], viewPosition[2]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frameMoveBegin();
|
||||
// condition1: mainwindow has left camera && right camera,
|
||||
// but we only need left/right camera when in left/right eye loop
|
||||
// condition2: main camera draw twice
|
||||
for (const auto &window : _renderWindows) {
|
||||
if (window->getSwapchain()) {
|
||||
// not rt
|
||||
_xr->bindXREyeWithRenderWindow(window, static_cast<xr::XREye>(xrEye));
|
||||
}
|
||||
}
|
||||
|
||||
bool isNeedUpdateScene = xrEye == static_cast<uint32_t>(xr::XREye::LEFT) || (xrEye == static_cast<uint32_t>(xr::XREye::RIGHT) && !isSceneUpdated);
|
||||
if (forceUpdateSceneTwice) {
|
||||
isNeedUpdateScene = true;
|
||||
}
|
||||
frameMoveProcess(isNeedUpdateScene, totalFrames);
|
||||
auto camIter = _cameraList.begin();
|
||||
while (camIter != _cameraList.end()) {
|
||||
scene::Camera *cam = *camIter;
|
||||
bool isMismatchedCam =
|
||||
(static_cast<xr::XREye>(xrEye) == xr::XREye::LEFT && cam->getCameraType() == scene::CameraType::RIGHT_EYE) ||
|
||||
(static_cast<xr::XREye>(xrEye) == xr::XREye::RIGHT && cam->getCameraType() == scene::CameraType::LEFT_EYE);
|
||||
if (isMismatchedCam) {
|
||||
// currently is left eye loop, so right camera do not need active
|
||||
camIter = _cameraList.erase(camIter);
|
||||
} else {
|
||||
camIter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_pipelineRuntime != nullptr && !_cameraList.empty()) {
|
||||
if (isNeedUpdateScene) {
|
||||
isSceneUpdated = true;
|
||||
// only one eye enable culling (without other cameras)
|
||||
if (_cameraList.size() == 1 && _cameraList[0]->getTrackingType() != cc::scene::TrackingType::NO_TRACKING) {
|
||||
_cameraList[0]->setCullingEnable(true);
|
||||
_pipelineRuntime->resetRenderQueue(true);
|
||||
}
|
||||
} else {
|
||||
// another eye disable culling (without other cameras)
|
||||
if (_cameraList.size() == 1 && _cameraList[0]->getTrackingType() != cc::scene::TrackingType::NO_TRACKING) {
|
||||
_cameraList[0]->setCullingEnable(false);
|
||||
_pipelineRuntime->resetRenderQueue(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
frameMoveEnd();
|
||||
_xr->endRenderEyeFrame(xrEye);
|
||||
}
|
||||
// recovery to normal status (condition: xr scene jump to normal scene)
|
||||
if (_pipelineRuntime) {
|
||||
_pipelineRuntime->resetRenderQueue(true);
|
||||
}
|
||||
|
||||
for (scene::Camera *cam : _cameraList) {
|
||||
cam->setCullingEnable(true);
|
||||
}
|
||||
} else {
|
||||
CC_LOG_WARNING("[XR] isRenderAllowable is false !!!");
|
||||
}
|
||||
}
|
||||
|
||||
void Root::addWindowEventListener() {
|
||||
_windowDestroyListener.bind([this](uint32_t windowId) -> void {
|
||||
for (const auto &window : _renderWindows) {
|
||||
window->onNativeWindowDestroy(windowId);
|
||||
}
|
||||
});
|
||||
|
||||
_windowRecreatedListener.bind([this](uint32_t windowId) -> void {
|
||||
for (const auto &window : _renderWindows) {
|
||||
window->onNativeWindowResume(windowId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Root::removeWindowEventListener() {
|
||||
_windowDestroyListener.reset();
|
||||
_windowRecreatedListener.reset();
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
337
cocos/core/Root.h
Normal file
337
cocos/core/Root.h
Normal file
@@ -0,0 +1,337 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
//#include "3d/skeletal-animation/DataPoolManager.h"
|
||||
#include "bindings/event/EventDispatcher.h"
|
||||
#include "core/event/Event.h"
|
||||
#include "core/memop/Pool.h"
|
||||
#include "renderer/pipeline/RenderPipeline.h"
|
||||
#include "renderer/pipeline/DebugView.h"
|
||||
#include "scene/DrawBatch2D.h"
|
||||
#include "scene/Light.h"
|
||||
#include "scene/Model.h"
|
||||
#include "scene/RenderScene.h"
|
||||
#include "scene/RenderWindow.h"
|
||||
#include "scene/SphereLight.h"
|
||||
#include "scene/PointLight.h"
|
||||
#include "scene/RangedDirectionalLight.h"
|
||||
|
||||
namespace cc {
|
||||
class IXRInterface;
|
||||
namespace scene {
|
||||
class Camera;
|
||||
class DrawBatch2D;
|
||||
} // namespace scene
|
||||
namespace gfx {
|
||||
class SwapChain;
|
||||
class Device;
|
||||
} // namespace gfx
|
||||
namespace render {
|
||||
class PipelineRuntime;
|
||||
class Pipeline;
|
||||
} // namespace render
|
||||
class Batcher2d;
|
||||
|
||||
struct ISystemWindowInfo;
|
||||
class ISystemWindow;
|
||||
|
||||
class Root final {
|
||||
IMPL_EVENT_TARGET(Root)
|
||||
DECLARE_TARGET_EVENT_BEGIN(Root)
|
||||
TARGET_EVENT_ARG0(BeforeCommit)
|
||||
TARGET_EVENT_ARG0(BeforeRender)
|
||||
TARGET_EVENT_ARG0(AfterRender)
|
||||
TARGET_EVENT_ARG0(PipelineChanged)
|
||||
DECLARE_TARGET_EVENT_END()
|
||||
public:
|
||||
static Root *getInstance(); // cjh todo: put Root Managerment to Director class.
|
||||
explicit Root(gfx::Device *device);
|
||||
~Root();
|
||||
|
||||
// @minggo IRootInfo seems is not use, and how to return Promise?
|
||||
void initialize(gfx::Swapchain *swapchain);
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 重置大小
|
||||
* @param width 窗口宽度
|
||||
* @param height 窗口高度
|
||||
* @param windowId 窗口 ID
|
||||
*/
|
||||
void resize(uint32_t width, uint32_t height, uint32_t windowId);
|
||||
|
||||
bool setRenderPipeline(pipeline::RenderPipeline *rppl = nullptr);
|
||||
void onGlobalPipelineStateChanged();
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 激活指定窗口为当前窗口
|
||||
* @param window GFX 窗口
|
||||
*/
|
||||
void activeWindow(scene::RenderWindow *);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 重置累计时间
|
||||
*/
|
||||
void resetCumulativeTime();
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 每帧执行函数
|
||||
* @param deltaTime 间隔时间
|
||||
*/
|
||||
void frameMove(float deltaTime, int32_t totalFrames); // NOTE: c++ doesn't have a Director, so totalFrames need to be set from JS
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 创建窗口
|
||||
* @param info GFX 窗口描述信息
|
||||
*/
|
||||
scene::RenderWindow *createWindow(scene::IRenderWindowInfo &);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 销毁指定的窗口
|
||||
* @param window GFX 窗口
|
||||
*/
|
||||
void destroyWindow(scene::RenderWindow *);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 销毁全部窗口
|
||||
*/
|
||||
void destroyWindows();
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 创建一个系统窗口
|
||||
* @param info 系统窗口描述信息
|
||||
* @return 新创建的系统窗口 ID
|
||||
*/
|
||||
static uint32_t createSystemWindow(const cc::ISystemWindowInfo &info);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 创建渲染场景
|
||||
* @param info 渲染场景描述信息
|
||||
*/
|
||||
scene::RenderScene *createScene(const scene::IRenderSceneInfo &);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 销毁指定的渲染场景
|
||||
* @param scene 渲染场景
|
||||
*/
|
||||
void destroyScene(scene::RenderScene *);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 销毁全部场景
|
||||
*/
|
||||
void destroyScenes();
|
||||
|
||||
#ifndef SWIGCOCOS
|
||||
template <typename T, typename = std::enable_if_t<std::is_base_of<scene::Model, T>::value>>
|
||||
T *createModel() {
|
||||
// cjh TODO: need use model pool?
|
||||
T *model = ccnew T();
|
||||
model->initialize();
|
||||
return model;
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroyModel(scene::Model *model);
|
||||
|
||||
#ifndef SWIGCOCOS
|
||||
template <typename T, typename = std::enable_if_t<std::is_base_of<scene::Light, T>::value>>
|
||||
T *createLight() {
|
||||
// TODO(xwx): need use model pool?
|
||||
T *light = ccnew T();
|
||||
light->initialize();
|
||||
return light;
|
||||
}
|
||||
#endif
|
||||
|
||||
void destroyLight(scene::Light *light);
|
||||
|
||||
scene::Camera *createCamera() const;
|
||||
/**
|
||||
* @zh
|
||||
* GFX 设备
|
||||
*/
|
||||
inline gfx::Device *getDevice() const { return _device; }
|
||||
inline void setDevice(gfx::Device *device) { _device = device; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 主窗口
|
||||
*/
|
||||
inline scene::RenderWindow *getMainWindow() const { return _mainRenderWindow.get(); }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 当前窗口
|
||||
*/
|
||||
inline void setCurWindow(scene::RenderWindow *window) { _curRenderWindow = window; }
|
||||
|
||||
inline scene::RenderWindow *getCurWindow() const { return _curRenderWindow.get(); }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 临时窗口(用于数据传输)
|
||||
*/
|
||||
void setTempWindow(scene::RenderWindow *window) { _tempWindow = window; }
|
||||
|
||||
inline scene::RenderWindow *getTempWindow() const { return _tempWindow.get(); }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 窗口列表
|
||||
*/
|
||||
inline const ccstd::vector<IntrusivePtr<scene::RenderWindow>> &getWindows() const { return _renderWindows; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 是否启用自定义渲染管线
|
||||
*/
|
||||
inline bool usesCustomPipeline() const { return _usesCustomPipeline; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 渲染管线
|
||||
*/
|
||||
inline render::PipelineRuntime *getPipeline() const { return _pipelineRuntime.get(); }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 自定义渲染管线
|
||||
*/
|
||||
render::Pipeline *getCustomPipeline() const;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* UI实例
|
||||
* 引擎内部使用,用户无需调用此接口
|
||||
*/
|
||||
inline Batcher2d *getBatcher2D() const { return _batcher; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 场景列表
|
||||
*/
|
||||
inline const ccstd::vector<IntrusivePtr<scene::RenderScene>> &getScenes() const { return _scenes; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 渲染调试数据
|
||||
*/
|
||||
inline pipeline::DebugView *getDebugView() const { return _debugView.get(); }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 累计时间(秒)
|
||||
*/
|
||||
inline float getCumulativeTime() const { return _cumulativeTime; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 帧时间(秒)
|
||||
*/
|
||||
inline float getFrameTime() const { return _frameTime; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 一秒内的累计帧数
|
||||
*/
|
||||
inline uint32_t getFrameCount() const { return _frameCount; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 每秒帧率
|
||||
*/
|
||||
inline uint32_t getFps() const { return _fps; }
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 每秒固定帧率
|
||||
*/
|
||||
void setFixedFPS(uint32_t fps) { _fixedFPS = fps; }
|
||||
|
||||
inline uint32_t getFixedFPS() const { return _fixedFPS; }
|
||||
|
||||
// inline DataPoolManager *getDataPoolManager() { return _dataPoolMgr.get(); }
|
||||
|
||||
inline bool isUsingDeferredPipeline() const { return _useDeferredPipeline; }
|
||||
|
||||
scene::RenderWindow *createRenderWindowFromSystemWindow(uint32_t windowId);
|
||||
scene::RenderWindow *createRenderWindowFromSystemWindow(cc::ISystemWindow *window);
|
||||
|
||||
const ccstd::vector<scene::Camera *> &getCameraList() const {
|
||||
return _cameraList;
|
||||
}
|
||||
|
||||
void frameSync();
|
||||
|
||||
private:
|
||||
void frameMoveBegin();
|
||||
void frameMoveProcess(bool isNeedUpdateScene, int32_t totalFrames);
|
||||
void frameMoveEnd();
|
||||
void doXRFrameMove(int32_t totalFrames);
|
||||
void addWindowEventListener();
|
||||
void removeWindowEventListener();
|
||||
|
||||
gfx::Device *_device{nullptr};
|
||||
gfx::Swapchain *_swapchain{nullptr};
|
||||
Batcher2d *_batcher{nullptr};
|
||||
IntrusivePtr<scene::RenderWindow> _mainRenderWindow;
|
||||
IntrusivePtr<scene::RenderWindow> _curRenderWindow;
|
||||
IntrusivePtr<scene::RenderWindow> _tempWindow;
|
||||
ccstd::vector<IntrusivePtr<scene::RenderWindow>> _renderWindows;
|
||||
IntrusivePtr<pipeline::RenderPipeline> _pipeline{nullptr};
|
||||
std::unique_ptr<render::PipelineRuntime> _pipelineRuntime;
|
||||
// IntrusivePtr<DataPoolManager> _dataPoolMgr;
|
||||
ccstd::vector<IntrusivePtr<scene::RenderScene>> _scenes;
|
||||
std::unique_ptr<pipeline::DebugView> _debugView;
|
||||
float _cumulativeTime{0.F};
|
||||
float _frameTime{0.F};
|
||||
float _fpsTime{0.F};
|
||||
uint32_t _frameCount{0};
|
||||
uint32_t _fps{0};
|
||||
uint32_t _fixedFPS{0};
|
||||
bool _useDeferredPipeline{false};
|
||||
bool _usesCustomPipeline{true};
|
||||
IXRInterface *_xr{nullptr};
|
||||
events::WindowDestroy::Listener _windowDestroyListener;
|
||||
events::WindowRecreated::Listener _windowRecreatedListener;
|
||||
|
||||
// Cache ccstd::vector to avoid allocate every frame in frameMove
|
||||
ccstd::vector<scene::Camera *> _cameraList;
|
||||
ccstd::vector<gfx::Swapchain *> _swapchains;
|
||||
//
|
||||
};
|
||||
} // namespace cc
|
||||
100
cocos/core/System.h
Normal file
100
cocos/core/System.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "base/std/container/string.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace core {
|
||||
|
||||
struct ISchedulable {
|
||||
ccstd::string id;
|
||||
ccstd::string uuid;
|
||||
};
|
||||
|
||||
enum struct Priority : uint32_t {
|
||||
LOW = 0,
|
||||
MEDIUM = 100,
|
||||
HIGH = 200,
|
||||
SCHEDULER = UINT32_MAX,
|
||||
};
|
||||
|
||||
class System : public ISchedulable {
|
||||
private:
|
||||
/* data */
|
||||
protected:
|
||||
Priority _priority{Priority::LOW};
|
||||
bool _executeInEditMode{false};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @en Sorting between different systems.
|
||||
* @zh 不同系统间排序。
|
||||
* @param a System a
|
||||
* @param b System b
|
||||
*/
|
||||
static int32_t sortByPriority(System *a, System *b) {
|
||||
if (a->_priority < b->_priority) return 1;
|
||||
if (a->_priority > b->_priority) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
System() = default;
|
||||
virtual ~System() = default;
|
||||
|
||||
inline const ccstd::string &getId() { return id; }
|
||||
inline void setId(ccstd::string &s) { id = s; }
|
||||
|
||||
inline Priority getPriority() const { return _priority; }
|
||||
inline void setPriority(Priority i) { _priority = i; }
|
||||
|
||||
inline bool getExecuteInEditMode() const { return _executeInEditMode; }
|
||||
inline void setExecuteInEditMode(bool b) { _executeInEditMode = b; }
|
||||
|
||||
/**
|
||||
* @en Init the system, will be invoked by [[Director]] when registered, should be implemented if needed.
|
||||
* @zh 系统初始化函数,会在注册时被 [[Director]] 调用,如果需要的话应该由子类实现
|
||||
*/
|
||||
virtual void init() = 0;
|
||||
|
||||
/**
|
||||
* @en Update function of the system, it will be invoked between all components update phase and late update phase.
|
||||
* @zh 系统的帧更新函数,它会在所有组件的 update 和 lateUpdate 之间被调用
|
||||
* @param dt Delta time after the last frame
|
||||
*/
|
||||
virtual void update(float dt) = 0;
|
||||
|
||||
/**
|
||||
* @en Post update function of the system, it will be invoked after all components late update phase and before the rendering process.
|
||||
* @zh 系统的帧后处理函数,它会在所有组件的 lateUpdate 之后以及渲染之前被调用
|
||||
* @param dt Delta time after the last frame
|
||||
*/
|
||||
virtual void postUpdate(float dt) = 0;
|
||||
};
|
||||
|
||||
} // namespace core
|
||||
|
||||
} // namespace cc
|
||||
124
cocos/core/TypedArray.cpp
Normal file
124
cocos/core/TypedArray.cpp
Normal file
@@ -0,0 +1,124 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/TypedArray.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
uint32_t getTypedArrayLength(const TypedArray &arr) {
|
||||
#define TYPEDARRAY_GET_SIZE(type) \
|
||||
do { \
|
||||
auto *p = ccstd::get_if<type>(&arr); \
|
||||
if (p != nullptr) { \
|
||||
return p->length(); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
TYPEDARRAY_GET_SIZE(Float32Array);
|
||||
TYPEDARRAY_GET_SIZE(Uint32Array);
|
||||
TYPEDARRAY_GET_SIZE(Uint16Array);
|
||||
TYPEDARRAY_GET_SIZE(Uint8Array);
|
||||
TYPEDARRAY_GET_SIZE(Int32Array);
|
||||
TYPEDARRAY_GET_SIZE(Int16Array);
|
||||
TYPEDARRAY_GET_SIZE(Int8Array);
|
||||
TYPEDARRAY_GET_SIZE(Float64Array);
|
||||
|
||||
#undef TYPEDARRAY_GET_SIZE
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t getTypedArrayBytesPerElement(const TypedArray &arr) {
|
||||
#define TYPEDARRAY_GET_BYTES_PER_ELEMENT(type) \
|
||||
do { \
|
||||
auto *p = ccstd::get_if<type>(&arr); \
|
||||
if (p != nullptr) { \
|
||||
return type::BYTES_PER_ELEMENT; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
TYPEDARRAY_GET_BYTES_PER_ELEMENT(Float32Array);
|
||||
TYPEDARRAY_GET_BYTES_PER_ELEMENT(Uint32Array);
|
||||
TYPEDARRAY_GET_BYTES_PER_ELEMENT(Uint16Array);
|
||||
TYPEDARRAY_GET_BYTES_PER_ELEMENT(Uint8Array);
|
||||
TYPEDARRAY_GET_BYTES_PER_ELEMENT(Int32Array);
|
||||
TYPEDARRAY_GET_BYTES_PER_ELEMENT(Int16Array);
|
||||
TYPEDARRAY_GET_BYTES_PER_ELEMENT(Int8Array);
|
||||
TYPEDARRAY_GET_BYTES_PER_ELEMENT(Float64Array);
|
||||
|
||||
#undef TYPEDARRAY_GET_BYPES_PER_ELEMENT
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setTypedArrayValue(TypedArray &arr, uint32_t idx, const TypedArrayElementType &value) {
|
||||
#define TYPEDARRAY_SET_VALUE(type, elemType) \
|
||||
do { \
|
||||
auto *p = ccstd::get_if<elemType>(&value); \
|
||||
if (p != nullptr) { \
|
||||
if (ccstd::holds_alternative<Float32Array>(arr)) { \
|
||||
ccstd::get<Float32Array>(arr)[idx] = static_cast<float>(*p); \
|
||||
return; \
|
||||
} \
|
||||
if (ccstd::holds_alternative<Uint16Array>(arr)) { \
|
||||
ccstd::get<Uint16Array>(arr)[idx] = static_cast<uint16_t>(*p); \
|
||||
return; \
|
||||
} \
|
||||
if (ccstd::holds_alternative<Uint32Array>(arr)) { \
|
||||
ccstd::get<Uint32Array>(arr)[idx] = static_cast<uint32_t>(*p); \
|
||||
return; \
|
||||
} \
|
||||
if (ccstd::holds_alternative<Uint8Array>(arr)) { \
|
||||
ccstd::get<Uint8Array>(arr)[idx] = static_cast<uint8_t>(*p); \
|
||||
return; \
|
||||
} \
|
||||
if (ccstd::holds_alternative<Int32Array>(arr)) { \
|
||||
ccstd::get<Int32Array>(arr)[idx] = static_cast<int32_t>(*p); \
|
||||
return; \
|
||||
} \
|
||||
if (ccstd::holds_alternative<Int16Array>(arr)) { \
|
||||
ccstd::get<Int16Array>(arr)[idx] = static_cast<int16_t>(*p); \
|
||||
return; \
|
||||
} \
|
||||
if (ccstd::holds_alternative<Int8Array>(arr)) { \
|
||||
ccstd::get<Int8Array>(arr)[idx] = static_cast<int8_t>(*p); \
|
||||
return; \
|
||||
} \
|
||||
if (ccstd::holds_alternative<Float64Array>(arr)) { \
|
||||
ccstd::get<Float64Array>(arr)[idx] = static_cast<double>(*p); \
|
||||
return; \
|
||||
} \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
TYPEDARRAY_SET_VALUE(Float32Array, float);
|
||||
TYPEDARRAY_SET_VALUE(Uint32Array, uint32_t);
|
||||
TYPEDARRAY_SET_VALUE(Uint16Array, uint16_t);
|
||||
TYPEDARRAY_SET_VALUE(Uint8Array, uint8_t);
|
||||
TYPEDARRAY_SET_VALUE(Int32Array, int32_t);
|
||||
TYPEDARRAY_SET_VALUE(Int16Array, int16_t);
|
||||
TYPEDARRAY_SET_VALUE(Int8Array, int8_t); // NOLINT
|
||||
TYPEDARRAY_SET_VALUE(Float64Array, double);
|
||||
#undef TYPEDARRAY_SET_VALUE
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
398
cocos/core/TypedArray.h
Normal file
398
cocos/core/TypedArray.h
Normal file
@@ -0,0 +1,398 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
#include "base/TypeDef.h"
|
||||
#include "base/std/variant.h"
|
||||
#include "bindings/jswrapper/Object.h"
|
||||
#include "core/ArrayBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
template <typename T>
|
||||
se::Object::TypedArrayType toTypedArrayType() {
|
||||
return se::Object::TypedArrayType::NONE;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline se::Object::TypedArrayType toTypedArrayType<int8_t>() {
|
||||
return se::Object::TypedArrayType::INT8;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline se::Object::TypedArrayType toTypedArrayType<int16_t>() {
|
||||
return se::Object::TypedArrayType::INT16;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline se::Object::TypedArrayType toTypedArrayType<int32_t>() {
|
||||
return se::Object::TypedArrayType::INT32;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline se::Object::TypedArrayType toTypedArrayType<uint8_t>() {
|
||||
return se::Object::TypedArrayType::UINT8;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline se::Object::TypedArrayType toTypedArrayType<uint16_t>() {
|
||||
return se::Object::TypedArrayType::UINT16;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline se::Object::TypedArrayType toTypedArrayType<uint32_t>() {
|
||||
return se::Object::TypedArrayType::UINT32;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline se::Object::TypedArrayType toTypedArrayType<float>() {
|
||||
return se::Object::TypedArrayType::FLOAT32;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline se::Object::TypedArrayType toTypedArrayType<double>() {
|
||||
return se::Object::TypedArrayType::FLOAT64;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class TypedArrayTemp {
|
||||
public:
|
||||
static constexpr uint32_t BYTES_PER_ELEMENT{sizeof(T)};
|
||||
using value_type = T;
|
||||
|
||||
TypedArrayTemp() = default;
|
||||
|
||||
explicit TypedArrayTemp(uint32_t length) {
|
||||
reset(length);
|
||||
}
|
||||
|
||||
explicit TypedArrayTemp(ArrayBuffer *buffer)
|
||||
: TypedArrayTemp(buffer, 0) {}
|
||||
|
||||
TypedArrayTemp(ArrayBuffer *buffer, uint32_t byteOffset)
|
||||
: TypedArrayTemp(buffer, byteOffset, (buffer->byteLength() - byteOffset) / BYTES_PER_ELEMENT) {}
|
||||
|
||||
TypedArrayTemp(ArrayBuffer *buffer, uint32_t byteOffset, uint32_t length)
|
||||
: _buffer(buffer),
|
||||
_byteOffset(byteOffset),
|
||||
_byteLength(length * BYTES_PER_ELEMENT),
|
||||
_byteEndPos(byteOffset + length * BYTES_PER_ELEMENT) {
|
||||
CC_ASSERT(_byteEndPos <= _buffer->byteLength());
|
||||
_jsTypedArray = se::Object::createTypedArrayWithBuffer(toTypedArrayType<T>(), buffer->getJSArrayBuffer(), byteOffset, _byteLength);
|
||||
_jsTypedArray->root();
|
||||
}
|
||||
|
||||
TypedArrayTemp(const TypedArrayTemp &o) {
|
||||
*this = o;
|
||||
}
|
||||
|
||||
TypedArrayTemp(TypedArrayTemp &&o) noexcept {
|
||||
*this = std::move(o);
|
||||
}
|
||||
|
||||
~TypedArrayTemp() {
|
||||
if (_jsTypedArray != nullptr) {
|
||||
_jsTypedArray->unroot();
|
||||
_jsTypedArray->decRef();
|
||||
}
|
||||
}
|
||||
|
||||
TypedArrayTemp &operator=(const TypedArrayTemp &o) {
|
||||
if (this != &o) {
|
||||
setJSTypedArray(o._jsTypedArray);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TypedArrayTemp &operator=(TypedArrayTemp &&o) noexcept {
|
||||
if (this != &o) {
|
||||
_buffer = o._buffer;
|
||||
_byteOffset = o._byteOffset;
|
||||
_byteLength = o._byteLength;
|
||||
_byteEndPos = o._byteEndPos;
|
||||
|
||||
if (_jsTypedArray != nullptr) {
|
||||
_jsTypedArray->unroot();
|
||||
_jsTypedArray->decRef();
|
||||
}
|
||||
_jsTypedArray = o._jsTypedArray;
|
||||
|
||||
o._buffer = nullptr;
|
||||
o._byteOffset = 0;
|
||||
o._byteLength = 0;
|
||||
o._byteEndPos = 0;
|
||||
o._jsTypedArray = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
T &operator[](uint32_t idx) {
|
||||
CC_ASSERT(idx < length());
|
||||
return *((reinterpret_cast<T *>(_buffer->_data + _byteOffset)) + idx);
|
||||
}
|
||||
|
||||
const T &operator[](uint32_t idx) const {
|
||||
CC_ASSERT(idx < length());
|
||||
return *((reinterpret_cast<T *>(_buffer->_data + _byteOffset)) + idx);
|
||||
}
|
||||
|
||||
TypedArrayTemp subarray(uint32_t begin, uint32_t end) {
|
||||
return TypedArrayTemp(_buffer, begin * BYTES_PER_ELEMENT + _byteOffset, end - begin);
|
||||
}
|
||||
|
||||
TypedArrayTemp subarray(uint32_t begin) {
|
||||
return TypedArrayTemp(_buffer, begin * BYTES_PER_ELEMENT + _byteOffset);
|
||||
}
|
||||
|
||||
TypedArrayTemp slice() {
|
||||
return slice(0);
|
||||
}
|
||||
|
||||
TypedArrayTemp slice(uint32_t start) {
|
||||
return slice(start, _byteLength / BYTES_PER_ELEMENT);
|
||||
}
|
||||
|
||||
TypedArrayTemp slice(uint32_t start, uint32_t end) {
|
||||
CC_ASSERT_GT(end, start);
|
||||
CC_ASSERT(start < (_byteLength / BYTES_PER_ELEMENT));
|
||||
CC_ASSERT(end <= (_byteLength / BYTES_PER_ELEMENT));
|
||||
uint32_t newBufByteLength = (end - start) * BYTES_PER_ELEMENT;
|
||||
auto *buffer = ccnew ArrayBuffer(newBufByteLength);
|
||||
memcpy(buffer->getData(), _buffer->getData() + start * BYTES_PER_ELEMENT + _byteOffset, newBufByteLength);
|
||||
return TypedArrayTemp(buffer);
|
||||
}
|
||||
|
||||
void set(ArrayBuffer *buffer) {
|
||||
set(buffer, 0);
|
||||
}
|
||||
|
||||
void set(ArrayBuffer *buffer, uint32_t offset) {
|
||||
CC_ASSERT(buffer->byteLength() + offset <= _byteEndPos);
|
||||
CC_ASSERT(_buffer);
|
||||
memcpy(_buffer->_data + offset, buffer->_data, buffer->byteLength());
|
||||
}
|
||||
|
||||
template <typename SrcType>
|
||||
void set(const TypedArrayTemp<SrcType> &array) {
|
||||
set(array, 0);
|
||||
}
|
||||
|
||||
template <typename SrcType>
|
||||
typename std::enable_if_t<std::is_same<T, SrcType>::value, void>
|
||||
set(const TypedArrayTemp<SrcType> &array, uint32_t offset);
|
||||
|
||||
template <typename SrcType>
|
||||
typename std::enable_if_t<!std::is_same<T, SrcType>::value, void>
|
||||
set(const TypedArrayTemp<SrcType> &array, uint32_t offset);
|
||||
|
||||
void reset(uint32_t length) {
|
||||
if (_jsTypedArray != nullptr) {
|
||||
_jsTypedArray->unroot();
|
||||
_jsTypedArray->decRef();
|
||||
_jsTypedArray = nullptr;
|
||||
}
|
||||
const uint32_t byteLength = length * BYTES_PER_ELEMENT;
|
||||
_buffer = ccnew ArrayBuffer(byteLength);
|
||||
_byteLength = _buffer->byteLength();
|
||||
_byteOffset = 0;
|
||||
_byteEndPos = byteLength;
|
||||
_jsTypedArray = se::Object::createTypedArrayWithBuffer(toTypedArrayType<T>(), _buffer->getJSArrayBuffer(), 0, byteLength);
|
||||
_jsTypedArray->root();
|
||||
}
|
||||
|
||||
void clear() {
|
||||
if (_jsTypedArray != nullptr) {
|
||||
_jsTypedArray->unroot();
|
||||
_jsTypedArray->decRef();
|
||||
_jsTypedArray = nullptr;
|
||||
}
|
||||
_buffer = nullptr;
|
||||
_byteLength = 0;
|
||||
_byteOffset = 0;
|
||||
_byteEndPos = 0;
|
||||
}
|
||||
|
||||
inline ArrayBuffer *buffer() const { return _buffer; }
|
||||
inline uint32_t byteLength() const { return _byteLength; }
|
||||
inline uint32_t length() const { return _byteLength / BYTES_PER_ELEMENT; }
|
||||
inline uint32_t byteOffset() const { return _byteOffset; }
|
||||
inline bool empty() const { return _byteLength == 0; }
|
||||
inline se::Object *getJSTypedArray() const { return _jsTypedArray; }
|
||||
inline void setJSTypedArray(se::Object *typedArray) {
|
||||
if (_jsTypedArray != nullptr) {
|
||||
_jsTypedArray->unroot();
|
||||
_jsTypedArray->decRef();
|
||||
}
|
||||
_jsTypedArray = typedArray;
|
||||
|
||||
if (_jsTypedArray != nullptr) {
|
||||
_jsTypedArray->root();
|
||||
_jsTypedArray->incRef();
|
||||
|
||||
se::Value tmpVal;
|
||||
_jsTypedArray->getProperty("buffer", &tmpVal, true);
|
||||
CC_ASSERT(tmpVal.isObject());
|
||||
CC_ASSERT(tmpVal.toObject()->isArrayBuffer());
|
||||
|
||||
_buffer = ccnew ArrayBuffer();
|
||||
_buffer->setJSArrayBuffer(tmpVal.toObject());
|
||||
|
||||
_jsTypedArray->getProperty("byteOffset", &tmpVal, true);
|
||||
CC_ASSERT(tmpVal.isNumber());
|
||||
_byteOffset = tmpVal.toUint32();
|
||||
|
||||
_jsTypedArray->getProperty("byteLength", &tmpVal, true);
|
||||
CC_ASSERT(tmpVal.isNumber());
|
||||
_byteLength = tmpVal.toUint32();
|
||||
|
||||
_byteEndPos = _buffer->byteLength();
|
||||
} else {
|
||||
_buffer = nullptr;
|
||||
_byteOffset = 0;
|
||||
_byteLength = 0;
|
||||
_byteEndPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ArrayBuffer::Ptr _buffer;
|
||||
uint32_t _byteOffset{0};
|
||||
uint32_t _byteLength{0};
|
||||
uint32_t _byteEndPos{0};
|
||||
se::Object *_jsTypedArray{nullptr};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
template <typename SrcType>
|
||||
typename std::enable_if_t<std::is_same<T, SrcType>::value, void> TypedArrayTemp<T>::set(const TypedArrayTemp<SrcType> &array, uint32_t offset) {
|
||||
CC_ASSERT(_buffer);
|
||||
uint32_t dstByteOffset = offset * BYTES_PER_ELEMENT;
|
||||
uint32_t srcByteOffset = array.byteOffset();
|
||||
uint32_t srcCount = array.length();
|
||||
CC_ASSERT(dstByteOffset + srcCount * TypedArrayTemp<SrcType>::BYTES_PER_ELEMENT <= _byteEndPos);
|
||||
memcpy(_buffer->_data + dstByteOffset, array._buffer->_data + srcByteOffset, array.byteLength());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename SrcType>
|
||||
typename std::enable_if_t<!std::is_same<T, SrcType>::value, void> TypedArrayTemp<T>::set(const TypedArrayTemp<SrcType> &array, uint32_t offset) {
|
||||
CC_ASSERT(_buffer);
|
||||
uint32_t dstByteOffset = offset * BYTES_PER_ELEMENT;
|
||||
uint32_t srcByteOffset = array.byteOffset();
|
||||
uint32_t srcCount = array.length();
|
||||
uint32_t remainCount = (_byteEndPos - dstByteOffset) / BYTES_PER_ELEMENT;
|
||||
CC_ASSERT_LE(srcCount, remainCount);
|
||||
for (uint32_t i = 0; i < srcCount; ++i) {
|
||||
(*this)[offset + i] = reinterpret_cast<T>(array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
using Int8Array = TypedArrayTemp<int8_t>;
|
||||
using Int16Array = TypedArrayTemp<int16_t>;
|
||||
using Int32Array = TypedArrayTemp<int32_t>;
|
||||
using Uint8Array = TypedArrayTemp<uint8_t>;
|
||||
using Uint16Array = TypedArrayTemp<uint16_t>;
|
||||
using Uint32Array = TypedArrayTemp<uint32_t>;
|
||||
using Float32Array = TypedArrayTemp<float>;
|
||||
using Float64Array = TypedArrayTemp<double>;
|
||||
using TypedArray = ccstd::variant<ccstd::monostate, Int8Array, Int16Array, Int32Array, Uint8Array, Uint16Array, Uint32Array, Float32Array, Float64Array>;
|
||||
using TypedArrayElementType = ccstd::variant<ccstd::monostate, int8_t, int16_t, int32_t, uint8_t, uint16_t, uint32_t, float, double>;
|
||||
|
||||
uint32_t getTypedArrayLength(const TypedArray &arr);
|
||||
uint32_t getTypedArrayBytesPerElement(const TypedArray &arr);
|
||||
|
||||
template <typename T>
|
||||
T getTypedArrayValue(const TypedArray &arr, uint32_t idx) {
|
||||
#define TYPEDARRAY_GET_VALUE(type) \
|
||||
do { \
|
||||
auto *p = ccstd::get_if<type>(&arr); \
|
||||
if (p != nullptr) { \
|
||||
return static_cast<T>((*p)[idx]); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
TYPEDARRAY_GET_VALUE(Float32Array);
|
||||
TYPEDARRAY_GET_VALUE(Uint32Array);
|
||||
TYPEDARRAY_GET_VALUE(Uint16Array);
|
||||
TYPEDARRAY_GET_VALUE(Uint8Array);
|
||||
TYPEDARRAY_GET_VALUE(Int32Array);
|
||||
TYPEDARRAY_GET_VALUE(Int16Array);
|
||||
TYPEDARRAY_GET_VALUE(Int8Array);
|
||||
TYPEDARRAY_GET_VALUE(Float64Array);
|
||||
#undef TYPEDARRAY_GET_VALUE
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void setTypedArrayValue(TypedArray &arr, uint32_t idx, const TypedArrayElementType &value);
|
||||
|
||||
template <typename T>
|
||||
T &getTypedArrayValueRef(const TypedArray &arr, uint32_t idx) {
|
||||
#define TYPEDARRAY_GET_VALUE_REF(type) \
|
||||
do { \
|
||||
auto *p = ccstd::get_if<type>(&arr); \
|
||||
if (p != nullptr) { \
|
||||
return (*p)[idx]; \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
TYPEDARRAY_GET_VALUE_REF(Float32Array);
|
||||
TYPEDARRAY_GET_VALUE_REF(Uint32Array);
|
||||
TYPEDARRAY_GET_VALUE_REF(Uint16Array);
|
||||
TYPEDARRAY_GET_VALUE_REF(Uint8Array);
|
||||
TYPEDARRAY_GET_VALUE_REF(Int32Array);
|
||||
TYPEDARRAY_GET_VALUE_REF(Int16Array);
|
||||
TYPEDARRAY_GET_VALUE_REF(Int8Array);
|
||||
TYPEDARRAY_GET_VALUE_REF(Float64Array);
|
||||
#undef TYPEDARRAY_GET_VALUE_REF
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T getTypedArrayElementValue(const TypedArrayElementType &element) {
|
||||
#define CAST_TO_T(type) \
|
||||
do { \
|
||||
auto *p = ccstd::get_if<type>(&element); \
|
||||
if (p != nullptr) { \
|
||||
return static_cast<T>(*p); \
|
||||
} \
|
||||
} while (false)
|
||||
|
||||
CAST_TO_T(float);
|
||||
CAST_TO_T(uint32_t);
|
||||
CAST_TO_T(uint16_t);
|
||||
CAST_TO_T(uint8_t);
|
||||
CAST_TO_T(int32_t);
|
||||
CAST_TO_T(int16_t);
|
||||
CAST_TO_T(int8_t);
|
||||
CAST_TO_T(double);
|
||||
#undef CAST_TO_T
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
69
cocos/core/Types.h
Normal file
69
cocos/core/Types.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <utility>
|
||||
#include "base/std/container/string.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
#include "base/std/optional.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "base/Value.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
struct Error {
|
||||
ccstd::optional<ccstd::string> msg;
|
||||
};
|
||||
|
||||
struct BoundingBox {
|
||||
Vec3 min;
|
||||
Vec3 max;
|
||||
};
|
||||
|
||||
struct VertexIdChannel {
|
||||
uint32_t stream{0};
|
||||
uint32_t index{0};
|
||||
};
|
||||
|
||||
struct NativeDep {
|
||||
ccstd::string uuid;
|
||||
ccstd::string ext;
|
||||
bool __isNative__{false}; // NOLINT(bugprone-reserved-identifier)
|
||||
|
||||
explicit NativeDep() = default;
|
||||
|
||||
explicit NativeDep(bool isNative, ccstd::string uuid, ccstd::string ext)
|
||||
: uuid(std::move(uuid)), ext(std::move(ext)), __isNative__(isNative), _isValid(true) {}
|
||||
|
||||
inline bool isValid() const { return _isValid; }
|
||||
|
||||
private:
|
||||
bool _isValid{false};
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
110
cocos/core/animation/SkeletalAnimationUtils.cpp
Normal file
110
cocos/core/animation/SkeletalAnimationUtils.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/animation/SkeletalAnimationUtils.h"
|
||||
#include "core/scene-graph/Node.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
ccstd::vector<IJointTransform *> stack;
|
||||
ccstd::unordered_map<ccstd::string, IJointTransform *> pool;
|
||||
} // namespace
|
||||
|
||||
Mat4 getWorldMatrix(IJointTransform *transform, int32_t stamp) {
|
||||
uint32_t i = 0;
|
||||
Mat4 *res = nullptr;
|
||||
while (transform != nullptr) {
|
||||
if ((transform->stamp == stamp || transform->stamp + 1 == stamp) && !transform->node->getChangedFlags()) {
|
||||
res = &transform->world;
|
||||
transform->stamp = stamp;
|
||||
break;
|
||||
}
|
||||
transform->stamp = stamp;
|
||||
stack.resize(i + 1);
|
||||
stack[i++] = transform;
|
||||
transform = transform->parent;
|
||||
}
|
||||
while (i > 0) {
|
||||
transform = stack[--i];
|
||||
stack[i] = nullptr;
|
||||
const auto *node = transform->node;
|
||||
CC_ASSERT_NOT_NULL(node);
|
||||
Mat4::fromRTS(node->getRotation(), node->getPosition(), node->getScale(), &transform->local);
|
||||
if (res != nullptr) {
|
||||
Mat4::multiply(*res, transform->local, &transform->world);
|
||||
} else {
|
||||
transform->world = transform->local;
|
||||
}
|
||||
res = &transform->world;
|
||||
}
|
||||
return res != nullptr ? *res : Mat4::IDENTITY;
|
||||
}
|
||||
|
||||
IJointTransform *getTransform(Node *node, Node *root) {
|
||||
IJointTransform *joint = nullptr;
|
||||
uint32_t i = 0;
|
||||
while (node != root) {
|
||||
const ccstd::string &id = node->getUuid();
|
||||
auto iter = pool.find(id);
|
||||
if (iter != pool.end()) {
|
||||
joint = iter->second;
|
||||
break;
|
||||
}
|
||||
// TODO(): object reuse
|
||||
joint = ccnew IJointTransform;
|
||||
joint->node = node;
|
||||
pool[id] = joint;
|
||||
stack.resize(i + 1);
|
||||
stack[i++] = joint;
|
||||
node = node->getParent();
|
||||
joint = nullptr;
|
||||
}
|
||||
IJointTransform *child;
|
||||
while (i > 0) {
|
||||
child = stack[--i];
|
||||
stack[i] = nullptr;
|
||||
child->parent = joint;
|
||||
joint = child;
|
||||
}
|
||||
return joint;
|
||||
}
|
||||
|
||||
void deleteTransform(Node *node) {
|
||||
IJointTransform *transform = nullptr;
|
||||
auto iter = pool.find(node->getUuid());
|
||||
if (iter != pool.end()) {
|
||||
transform = iter->second;
|
||||
}
|
||||
|
||||
while (transform != nullptr) {
|
||||
iter = pool.find(transform->node->getUuid());
|
||||
if (iter != pool.end()) {
|
||||
pool.erase(iter);
|
||||
}
|
||||
transform = transform->parent;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
61
cocos/core/animation/SkeletalAnimationUtils.h
Normal file
61
cocos/core/animation/SkeletalAnimationUtils.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Ptr.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "math/Mat4.h"
|
||||
#include "renderer/gfx-base/GFXTexture.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Node;
|
||||
|
||||
struct IJointTransform : RefCounted {
|
||||
Node *node{nullptr};
|
||||
Mat4 local;
|
||||
Mat4 world;
|
||||
int stamp{-1};
|
||||
IntrusivePtr<IJointTransform> parent;
|
||||
};
|
||||
|
||||
struct RealTimeJointTexture {
|
||||
~RealTimeJointTexture() {
|
||||
CC_SAFE_DELETE_ARRAY(buffer);
|
||||
for (auto &texture : textures) {
|
||||
texture->destroy();
|
||||
}
|
||||
}
|
||||
std::vector<IntrusivePtr<gfx::Texture>> textures;
|
||||
float *buffer = nullptr;
|
||||
};
|
||||
|
||||
Mat4 getWorldMatrix(IJointTransform *transform, int32_t stamp);
|
||||
|
||||
IJointTransform *getTransform(Node *node, Node *root);
|
||||
|
||||
void deleteTransform(Node *node);
|
||||
|
||||
} // namespace cc
|
||||
109
cocos/core/assets/Asset.cpp
Normal file
109
cocos/core/assets/Asset.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/Asset.h"
|
||||
#include "base/DeferredReleasePool.h"
|
||||
#include "base/Macros.h"
|
||||
#include "core/utils/Path.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
//cjh TODO:
|
||||
ccstd::string getAssetUrlWithUuid(const ccstd::string &uuid, bool isNative, const ccstd::string &nativeExt, const ccstd::string &nativeName = "") { //NOLINT
|
||||
return "";
|
||||
}
|
||||
|
||||
ccstd::string Asset::getNativeUrl() const {
|
||||
if (_nativeUrl.empty()) {
|
||||
if (_native.empty()) {
|
||||
return "";
|
||||
}
|
||||
const auto &name = _native;
|
||||
if (name[0] == 47) { // '/'
|
||||
// remove library tag
|
||||
// not imported in library, just created on-the-fly
|
||||
return name.substr(1);
|
||||
}
|
||||
|
||||
if (name[0] == 46) { // '.'
|
||||
// imported in dir where json exist
|
||||
const_cast<Asset *>(this)->_nativeUrl = getAssetUrlWithUuid(_uuid, true, name);
|
||||
} else {
|
||||
// imported in an independent dir
|
||||
const_cast<Asset *>(this)->_nativeUrl = getAssetUrlWithUuid(_uuid, true, extname(name), name);
|
||||
}
|
||||
}
|
||||
return _nativeUrl;
|
||||
}
|
||||
Asset::Asset() = default;
|
||||
Asset::~Asset() = default;
|
||||
|
||||
NativeDep Asset::getNativeDep() const {
|
||||
if (!_native.empty()) {
|
||||
return NativeDep(true, _uuid, _native);
|
||||
}
|
||||
return NativeDep();
|
||||
}
|
||||
|
||||
void Asset::setRawAsset(const ccstd::string &filename, bool inLibrary /* = true*/) {
|
||||
if (inLibrary) {
|
||||
_native = filename;
|
||||
} else {
|
||||
_native = "/" + filename; // simply use '/' to tag location where is not in the library
|
||||
}
|
||||
}
|
||||
|
||||
void Asset::addAssetRef() {
|
||||
++_assetRefCount;
|
||||
}
|
||||
|
||||
void Asset::decAssetRef(bool autoRelease /* = true*/) {
|
||||
if (_assetRefCount > 0) {
|
||||
--_assetRefCount;
|
||||
}
|
||||
|
||||
if (autoRelease) {
|
||||
//cjh TODO:
|
||||
}
|
||||
}
|
||||
|
||||
void Asset::initDefault(const ccstd::optional<ccstd::string> &uuid) {
|
||||
if (uuid.has_value()) {
|
||||
_uuid = uuid.value();
|
||||
}
|
||||
_isDefault = true;
|
||||
}
|
||||
|
||||
bool Asset::destroy() {
|
||||
//cjh TODO: debug(getError(12101, this._uuid));
|
||||
return Super::destroy();
|
||||
}
|
||||
|
||||
void Asset::destruct() {
|
||||
CCObject::destruct();
|
||||
_native.clear();
|
||||
_nativeUrl.clear();
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
159
cocos/core/assets/Asset.h
Normal file
159
cocos/core/assets/Asset.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include "base/std/any.h"
|
||||
#include "base/std/optional.h"
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "core/Types.h"
|
||||
#include "core/data/Object.h"
|
||||
#include "core/event/EventTarget.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Node;
|
||||
|
||||
class Asset : public CCObject {
|
||||
public:
|
||||
using Super = CCObject;
|
||||
|
||||
Asset();
|
||||
~Asset() override;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Returns the url of this asset's native object, if none it will returns an empty string.
|
||||
* @zh
|
||||
* 返回该资源对应的目标平台资源的 URL,如果没有将返回一个空字符串。
|
||||
* @readOnly
|
||||
*/
|
||||
ccstd::string getNativeUrl() const;
|
||||
|
||||
NativeDep getNativeDep() const;
|
||||
|
||||
inline const ccstd::string &getUuid() const { return _uuid; }
|
||||
inline void setUuid(const ccstd::string &uuid) { _uuid = uuid; }
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The underlying native asset of this asset if one is available.<br>
|
||||
* This property can be used to access additional details or functionality related to the asset.<br>
|
||||
* This property will be initialized by the loader if `_native` is available.
|
||||
* @zh
|
||||
* 此资源的基础资源(如果有)。 此属性可用于访问与资源相关的其他详细信息或功能。<br>
|
||||
* 如果`_native`可用,则此属性将由加载器初始化。
|
||||
* @default null
|
||||
* @private
|
||||
*/
|
||||
virtual ccstd::any getNativeAsset() const {
|
||||
return _file;
|
||||
}
|
||||
|
||||
virtual void setNativeAsset(const ccstd::any &obj) {
|
||||
_file = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param error - null or the error info
|
||||
* @param node - the created node or null
|
||||
*/
|
||||
using CreateNodeCallback = std::function<void(Error, Node *)>;
|
||||
/**
|
||||
* @en
|
||||
* Create a new node using this asset in the scene.<br/>
|
||||
* If this type of asset don't have its corresponding node type, this method should be null.
|
||||
* @zh
|
||||
* 使用该资源在场景中创建一个新节点。<br/>
|
||||
* 如果这类资源没有相应的节点类型,该方法应该是空的。
|
||||
*/
|
||||
virtual void createNode(const CreateNodeCallback &cb) {}
|
||||
|
||||
void addAssetRef();
|
||||
void decAssetRef(bool autoRelease = true);
|
||||
inline uint32_t getAssetRefCount() const { return _assetRefCount; }
|
||||
|
||||
virtual void onLoaded() {}
|
||||
|
||||
virtual void initDefault() { initDefault(ccstd::nullopt); }
|
||||
|
||||
virtual void initDefault(const ccstd::optional<ccstd::string> &uuid);
|
||||
|
||||
virtual bool validate() const { return true; }
|
||||
|
||||
bool isDefault() const { return _isDefault; }
|
||||
|
||||
bool destroy() override;
|
||||
|
||||
void destruct() override;
|
||||
|
||||
// SERIALIZATION
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
virtual ccstd::any serialize(const ccstd::any & /*ctxForExporting*/) { return ccstd::any{}; };
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
virtual void deserialize(const ccstd::any &serializedData, const ccstd::any &handle) {}
|
||||
|
||||
ccstd::string toString() const override { return _nativeUrl; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @en
|
||||
* Set native file name for this asset.
|
||||
* @zh
|
||||
* 为此资源设置原始文件名。
|
||||
* @seealso nativeUrl
|
||||
*
|
||||
* @param filename
|
||||
* @param inLibrary
|
||||
* @private
|
||||
*/
|
||||
void setRawAsset(const ccstd::string &filename, bool inLibrary = true);
|
||||
|
||||
// Make _native, _nativeUrl public for deserialization
|
||||
public:
|
||||
ccstd::string _native;
|
||||
ccstd::string _nativeUrl;
|
||||
|
||||
protected:
|
||||
ccstd::string _uuid;
|
||||
|
||||
ccstd::any _file;
|
||||
uint32_t _assetRefCount{0};
|
||||
|
||||
bool _loaded{true};
|
||||
bool _isDefault{false};
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(Asset);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
305
cocos/core/assets/AssetEnum.h
Normal file
305
cocos/core/assets/AssetEnum.h
Normal file
@@ -0,0 +1,305 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "renderer/gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
// define a specified number for the pixel format which gfx do not have a standard definition.
|
||||
#define CUSTOM_PIXEL_FORMAT (1024)
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The texture pixel format, default value is RGBA8888,<br>
|
||||
* you should note that textures loaded by normal image files (png, jpg) can only support RGBA8888 format,<br>
|
||||
* other formats are supported by compressed file types or raw data.
|
||||
* @zh
|
||||
* 纹理像素格式,默认值为RGBA8888,<br>
|
||||
* 你应该注意到普通图像文件(png,jpg)加载的纹理只能支持RGBA8888格式,<br>
|
||||
* 压缩文件类型或原始数据支持其他格式。
|
||||
*/
|
||||
enum class PixelFormat : uint32_t {
|
||||
/**
|
||||
* @en
|
||||
* 16-bit pixel format containing red, green and blue channels
|
||||
* @zh
|
||||
* 包含 RGB 通道的 16 位纹理。
|
||||
*/
|
||||
RGB565 = static_cast<uint32_t>(gfx::Format::R5G6B5),
|
||||
/**
|
||||
* @en
|
||||
* 16-bit pixel format containing red, green, blue channels with 5 bits per channel and one bit alpha channel: RGB5A1
|
||||
* @zh
|
||||
* 包含 RGB(分别占 5 bits)和 1 bit 的 alpha 通道的 16 位纹理:RGB5A1。
|
||||
*/
|
||||
RGB5A1 = static_cast<uint32_t>(gfx::Format::RGB5A1),
|
||||
/**
|
||||
* @en
|
||||
* 16-bit pixel format containing red, green, blue and alpha channels: RGBA4444
|
||||
* @zh
|
||||
* 包含 RGBA 通道的 16 位纹理:RGBA4444。
|
||||
*/
|
||||
RGBA4444 = static_cast<uint32_t>(gfx::Format::RGBA4),
|
||||
/**
|
||||
* @en
|
||||
* 24-bit pixel format containing red, green and blue channels: RGB888
|
||||
* @zh
|
||||
* 包含 RGB 通道的 24 位纹理:RGB888。
|
||||
*/
|
||||
RGB888 = static_cast<uint32_t>(gfx::Format::RGB8),
|
||||
/**
|
||||
* @en
|
||||
* 32-bit float pixel format containing red, green and blue channels: RGBA32F
|
||||
* @zh
|
||||
* 包含 RGB 通道的 32 位浮点数像素格式:RGBA32F。
|
||||
*/
|
||||
RGB32F = static_cast<uint32_t>(gfx::Format::RGB32F),
|
||||
/**
|
||||
* @en
|
||||
* 32-bit pixel format containing red, green, blue and alpha channels: RGBA8888
|
||||
* @zh
|
||||
* 包含 RGBA 四通道的 32 位整形像素格式:RGBA8888。
|
||||
*/
|
||||
RGBA8888 = static_cast<uint32_t>(gfx::Format::RGBA8),
|
||||
/**
|
||||
* @en
|
||||
* 32-bit float pixel format containing red, green, blue and alpha channels: RGBA32F
|
||||
* @zh
|
||||
* 32位浮点数像素格式:RGBA32F。
|
||||
*/
|
||||
RGBA32F = static_cast<uint32_t>(gfx::Format::RGBA32F),
|
||||
/**
|
||||
* @en
|
||||
* 8-bit pixel format used as masks
|
||||
* @zh
|
||||
* 用作蒙版的8位纹理。
|
||||
*/
|
||||
A8 = static_cast<uint32_t>(gfx::Format::A8),
|
||||
/**
|
||||
* @en
|
||||
* 8-bit intensity pixel format
|
||||
* @zh
|
||||
* 8位强度纹理。
|
||||
*/
|
||||
I8 = static_cast<uint32_t>(gfx::Format::L8),
|
||||
/**
|
||||
* @en
|
||||
* 16-bit pixel format used as masks
|
||||
* @zh
|
||||
* 用作蒙版的16位纹理。
|
||||
*/
|
||||
AI8 = static_cast<uint32_t>(gfx::Format::LA8),
|
||||
/**
|
||||
* @en A pixel format containing red, green, and blue channels that is PVR 2bpp compressed.
|
||||
* @zh 包含 RGB 通道的 PVR 2BPP 压缩纹理格式
|
||||
*/
|
||||
RGB_PVRTC_2BPPV1 = static_cast<uint32_t>(gfx::Format::PVRTC_RGB2),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is PVR 2bpp compressed.
|
||||
* @zh 包含 RGBA 通道的 PVR 2BPP 压缩纹理格式
|
||||
*/
|
||||
RGBA_PVRTC_2BPPV1 = static_cast<uint32_t>(gfx::Format::PVRTC_RGBA2),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is PVR 2bpp compressed.
|
||||
* RGB_A_PVRTC_2BPPV1 texture is a 2x height RGB_PVRTC_2BPPV1 format texture.
|
||||
* It separate the origin alpha channel to the bottom half atlas, the origin rgb channel to the top half atlas.
|
||||
* @zh 包含 RGBA 通道的 PVR 2BPP 压缩纹理格式
|
||||
* 这种压缩纹理格式贴图的高度是普通 RGB_PVRTC_2BPPV1 贴图高度的两倍,使用上半部分作为原始 RGB 通道数据,下半部分用来存储透明通道数据。
|
||||
*/
|
||||
RGB_A_PVRTC_2BPPV1 = CUSTOM_PIXEL_FORMAT,
|
||||
/**
|
||||
* @en A pixel format containing red, green, and blue channels that is PVR 4bpp compressed.
|
||||
* @zh 包含 RGB 通道的 PVR 4BPP 压缩纹理格式
|
||||
*/
|
||||
RGB_PVRTC_4BPPV1 = static_cast<uint32_t>(gfx::Format::PVRTC_RGB4),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue and alpha channels that is PVR 4bpp compressed.
|
||||
* @zh 包含 RGBA 通道的 PVR 4BPP 压缩纹理格式
|
||||
*/
|
||||
RGBA_PVRTC_4BPPV1 = static_cast<uint32_t>(gfx::Format::PVRTC_RGBA4),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is PVR 4bpp compressed.
|
||||
* RGB_A_PVRTC_4BPPV1 texture is a 2x height RGB_PVRTC_4BPPV1 format texture.
|
||||
* It separate the origin alpha channel to the bottom half atlas, the origin rgb channel to the top half atlas.
|
||||
* @zh 包含 RGBA 通道的 PVR 4BPP 压缩纹理格式
|
||||
* 这种压缩纹理格式贴图的高度是普通 RGB_PVRTC_4BPPV1 贴图高度的两倍,使用上半部分作为原始 RGB 通道数据,下半部分用来存储透明通道数据。
|
||||
*/
|
||||
RGB_A_PVRTC_4BPPV1 = CUSTOM_PIXEL_FORMAT + 1,
|
||||
/**
|
||||
* @en A pixel format containing red, green, and blue channels that is ETC1 compressed.
|
||||
* @zh 包含 RGB 通道的 ETC1 压缩纹理格式
|
||||
*/
|
||||
RGB_ETC1 = static_cast<uint32_t>(gfx::Format::ETC_RGB8),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ETC1 compressed.
|
||||
* @zh 包含 RGBA 通道的 ETC1 压缩纹理格式
|
||||
*/
|
||||
RGBA_ETC1 = CUSTOM_PIXEL_FORMAT + 2,
|
||||
/**
|
||||
* @en A pixel format containing red, green, and blue channels that is ETC2 compressed.
|
||||
* @zh 包含 RGB 通道的 ETC2 压缩纹理格式
|
||||
*/
|
||||
RGB_ETC2 = static_cast<uint32_t>(gfx::Format::ETC2_RGB8),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ETC2 compressed.
|
||||
* @zh 包含 RGBA 通道的 ETC2 压缩纹理格式
|
||||
*/
|
||||
RGBA_ETC2 = static_cast<uint32_t>(gfx::Format::ETC2_RGBA8),
|
||||
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 4x4 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 4x4
|
||||
*/
|
||||
RGBA_ASTC_4X4 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_4X4),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 5x4 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 5x4
|
||||
*/
|
||||
RGBA_ASTC_5X4 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_5X4),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 5x5 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 5x5
|
||||
*/
|
||||
RGBA_ASTC_5X5 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_5X5),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 6x5 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 6x5
|
||||
*/
|
||||
RGBA_ASTC_6X5 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_6X5),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 6x6 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 6x6
|
||||
*/
|
||||
RGBA_ASTC_6X6 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_6X6),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 8x5 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 8x5
|
||||
*/
|
||||
RGBA_ASTC_8X5 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_8X5),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 8x6 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 8x6
|
||||
*/
|
||||
RGBA_ASTC_8X6 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_8X6),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 8x8 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 8x8
|
||||
*/
|
||||
RGBA_ASTC_8X8 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_8X8),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 10x5 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 10x5
|
||||
*/
|
||||
RGBA_ASTC_10X5 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_10X5),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 10x6 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 10x6
|
||||
*/
|
||||
RGBA_ASTC_10X6 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_10X6),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 10x8 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 10x8
|
||||
*/
|
||||
RGBA_ASTC_10X8 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_10X8),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 10x10 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 10x10
|
||||
*/
|
||||
RGBA_ASTC_10X10 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_10X10),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 12x10 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 12x10
|
||||
*/
|
||||
RGBA_ASTC_12X10 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_12X10),
|
||||
/**
|
||||
* @en A pixel format containing red, green, blue, and alpha channels that is ASTC compressed with 12x12 block size.
|
||||
* @zh 包含 RGBA 通道的 ASTC 压缩纹理格式,压缩分块大小为 12x12
|
||||
*/
|
||||
RGBA_ASTC_12X12 = static_cast<uint32_t>(gfx::Format::ASTC_RGBA_12X12),
|
||||
};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The texture wrap mode.
|
||||
* @zh
|
||||
* 纹理环绕方式。
|
||||
*/
|
||||
enum class WrapMode : uint32_t {
|
||||
/**
|
||||
* @en
|
||||
* Specifies that the repeat warp mode will be used.
|
||||
* @zh
|
||||
* 指定环绕模式:重复纹理图像。
|
||||
*/
|
||||
REPEAT = static_cast<uint32_t>(gfx::Address::WRAP),
|
||||
/**
|
||||
* @en
|
||||
* Specifies that the clamp to edge warp mode will be used.
|
||||
* @zh
|
||||
* 指定环绕模式:纹理边缘拉伸效果。
|
||||
*/
|
||||
CLAMP_TO_EDGE = static_cast<uint32_t>(gfx::Address::CLAMP),
|
||||
/**
|
||||
* @en
|
||||
* Specifies that the mirrored repeat warp mode will be used.
|
||||
* @zh
|
||||
* 指定环绕模式:以镜像模式重复纹理图像。
|
||||
*/
|
||||
MIRRORED_REPEAT = static_cast<uint32_t>(gfx::Address::MIRROR),
|
||||
/**
|
||||
* @en
|
||||
* Specifies that the clamp to border wrap mode will be used.
|
||||
* @zh
|
||||
* 指定环绕模式:超出纹理坐标部分以用户指定颜色填充。
|
||||
*/
|
||||
CLAMP_TO_BORDER = static_cast<uint32_t>(gfx::Address::BORDER),
|
||||
};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The texture filter mode
|
||||
* @zh
|
||||
* 纹理过滤模式。
|
||||
*/
|
||||
enum class Filter : uint32_t {
|
||||
NONE = static_cast<uint32_t>(gfx::Filter::NONE),
|
||||
/**
|
||||
* @en
|
||||
* Specifies linear filtering.
|
||||
* @zh
|
||||
* 线性过滤模式。
|
||||
*/
|
||||
LINEAR = static_cast<uint32_t>(gfx::Filter::LINEAR),
|
||||
/**
|
||||
* @en
|
||||
* Specifies nearest filtering.
|
||||
* @zh
|
||||
* 临近过滤模式。
|
||||
*/
|
||||
NEAREST = static_cast<uint32_t>(gfx::Filter::POINT),
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
39
cocos/core/assets/AssetsModuleHeader.h
Normal file
39
cocos/core/assets/AssetsModuleHeader.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/assets/Asset.h"
|
||||
#include "core/assets/BufferAsset.h"
|
||||
#include "core/assets/EffectAsset.h"
|
||||
#include "core/assets/ImageAsset.h"
|
||||
//#include "core/assets/JsonAsset.h"
|
||||
#include "core/assets/Material.h"
|
||||
//#include "core/assets/Prefab.h"
|
||||
#include "core/assets/RenderTexture.h"
|
||||
#include "core/assets/RenderingSubMesh.h"
|
||||
#include "core/assets/SceneAsset.h"
|
||||
#include "core/assets/TextAsset.h"
|
||||
#include "core/assets/Texture2D.h"
|
||||
#include "core/assets/TextureCube.h"
|
||||
205
cocos/core/assets/BitmapFont.cpp
Normal file
205
cocos/core/assets/BitmapFont.cpp
Normal file
@@ -0,0 +1,205 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "BitmapFont.h"
|
||||
#include "base/Log.h"
|
||||
#include "gfx-base/GFXDevice.h"
|
||||
#include "platform/Image.h"
|
||||
#include "tinyxml2/tinyxml2.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
/**
|
||||
* BitmapFontFace
|
||||
*/
|
||||
|
||||
BitmapFontFace::BitmapFontFace(Font *font)
|
||||
: FontFace(font) {
|
||||
}
|
||||
void BitmapFontFace::doInit(const FontFaceInfo & /*info*/) {
|
||||
const auto &fontPath = _font->getPath();
|
||||
const auto &fontData = _font->getData();
|
||||
if (fontData.empty()) {
|
||||
CC_LOG_ERROR("BitmapFontFace doInit failed: empty font data.");
|
||||
return;
|
||||
}
|
||||
|
||||
tinyxml2::XMLDocument doc;
|
||||
|
||||
auto error = doc.Parse(reinterpret_cast<const char *>(fontData.data()), fontData.size());
|
||||
if (error) {
|
||||
CC_LOG_ERROR("BitmapFontFace parse failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto *fontNode = doc.RootElement();
|
||||
auto *infoNode = fontNode->FirstChildElement("info");
|
||||
_fontSize = infoNode->UnsignedAttribute("size");
|
||||
|
||||
auto *commonNode = fontNode->FirstChildElement("common");
|
||||
_lineHeight = commonNode->UnsignedAttribute("lineHeight");
|
||||
_textureWidth = commonNode->UnsignedAttribute("scaleW");
|
||||
_textureHeight = commonNode->UnsignedAttribute("scaleH");
|
||||
uint32_t pages = commonNode->UnsignedAttribute("pages");
|
||||
int base = commonNode->IntAttribute("base");
|
||||
|
||||
// load glyphs
|
||||
auto *charsNode = fontNode->FirstChildElement("chars");
|
||||
auto *charNode = charsNode->FirstChildElement("char");
|
||||
while (charNode) {
|
||||
FontGlyph glyph;
|
||||
uint32_t value{0U};
|
||||
|
||||
uint32_t code = charNode->UnsignedAttribute("id");
|
||||
glyph.x = static_cast<int16_t>(charNode->IntAttribute("x"));
|
||||
glyph.y = static_cast<int16_t>(charNode->IntAttribute("y"));
|
||||
glyph.width = static_cast<uint16_t>(charNode->UnsignedAttribute("width"));
|
||||
glyph.height = static_cast<uint16_t>(charNode->UnsignedAttribute("height"));
|
||||
glyph.bearingX = static_cast<int16_t>(charNode->IntAttribute("xoffset"));
|
||||
glyph.bearingY = static_cast<int16_t>(base - charNode->IntAttribute("yoffset"));
|
||||
glyph.advance = static_cast<int16_t>(charNode->IntAttribute("xadvance"));
|
||||
glyph.page = charNode->UnsignedAttribute("page");
|
||||
|
||||
_glyphs[code] = glyph;
|
||||
charNode = charNode->NextSiblingElement();
|
||||
}
|
||||
|
||||
// load textures
|
||||
auto *pagesNode = fontNode->FirstChildElement("pages");
|
||||
auto *pageNode = pagesNode->FirstChildElement("page");
|
||||
_textures.resize(pages, nullptr);
|
||||
|
||||
ccstd::string path = fontPath;
|
||||
auto pos = fontPath.rfind('/');
|
||||
|
||||
if (pos == ccstd::string::npos) {
|
||||
pos = fontPath.rfind('\\');
|
||||
}
|
||||
|
||||
if (pos != ccstd::string::npos) {
|
||||
path = fontPath.substr(0, pos + 1);
|
||||
}
|
||||
|
||||
while (pageNode) {
|
||||
uint32_t id = pageNode->UnsignedAttribute("id");
|
||||
ccstd::string file = pageNode->Attribute("file");
|
||||
_textures[id] = loadTexture(path + file);
|
||||
|
||||
pageNode = pageNode->NextSiblingElement();
|
||||
}
|
||||
|
||||
// load kernings
|
||||
auto *kerningsNode = fontNode->FirstChildElement("kernings");
|
||||
auto *kerningNode = kerningsNode->FirstChildElement("kerning");
|
||||
while (kerningNode) {
|
||||
KerningPair pair;
|
||||
pair.prevCode = kerningNode->UnsignedAttribute("first");
|
||||
pair.nextCode = kerningNode->UnsignedAttribute("second");
|
||||
_kernings[pair] = static_cast<float>(kerningNode->IntAttribute("amount"));
|
||||
|
||||
kerningNode = kerningNode->NextSiblingElement();
|
||||
}
|
||||
}
|
||||
|
||||
const FontGlyph *BitmapFontFace::getGlyph(uint32_t code) {
|
||||
auto iter = _glyphs.find(code);
|
||||
if (iter != _glyphs.end()) {
|
||||
return &iter->second;
|
||||
}
|
||||
|
||||
CC_LOG_WARNING("BitmapFontFace getGlyph failed, character: %u.", code);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float BitmapFontFace::getKerning(uint32_t prevCode, uint32_t nextCode) {
|
||||
if (_kernings.empty()) {
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
const auto &iter = _kernings.find({prevCode, nextCode});
|
||||
if (iter != _kernings.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
gfx::Texture *BitmapFontFace::loadTexture(const ccstd::string &path) {
|
||||
auto *image = ccnew Image();
|
||||
bool success = image->initWithImageFile(path);
|
||||
if (!success) {
|
||||
CC_LOG_WARNING("BitmapFontFace initWithImageFile failed, path: %s.", path.c_str());
|
||||
delete image;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (image->getRenderFormat() != gfx::Format::R8 && image->getRenderFormat() != gfx::Format::L8) {
|
||||
CC_LOG_WARNING("BitmapFontFace loadTexture with invalid format, path: %s.", path.c_str());
|
||||
delete image;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto width = static_cast<uint32_t>(image->getWidth());
|
||||
auto height = static_cast<uint32_t>(image->getHeight());
|
||||
|
||||
auto *device = gfx::Device::getInstance();
|
||||
auto *texture = device->createTexture({gfx::TextureType::TEX2D,
|
||||
gfx::TextureUsageBit::SAMPLED | gfx::TextureUsageBit::TRANSFER_DST,
|
||||
gfx::Format::R8,
|
||||
width,
|
||||
height});
|
||||
|
||||
gfx::BufferDataList buffers{image->getData()};
|
||||
gfx::BufferTextureCopyList regions = {{0U,
|
||||
0U,
|
||||
0U,
|
||||
{0U, 0U, 0U},
|
||||
{width, height, 1U},
|
||||
{0U, 0U, 1U}}};
|
||||
|
||||
device->copyBuffersToTexture(buffers, texture, regions);
|
||||
delete image;
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
/**
|
||||
* BitmapFont
|
||||
*/
|
||||
BitmapFont::BitmapFont(const ccstd::string &path)
|
||||
: Font(FontType::BITMAP, path) {
|
||||
}
|
||||
|
||||
FontFace *BitmapFont::createFace(const FontFaceInfo &info) {
|
||||
auto *face = ccnew BitmapFontFace(this);
|
||||
face->doInit(info);
|
||||
|
||||
uint32_t fontSize = face->getFontSize();
|
||||
_faces[fontSize] = face;
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
67
cocos/core/assets/BitmapFont.h
Normal file
67
cocos/core/assets/BitmapFont.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "Font.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
/**
|
||||
* BitmapFontFace
|
||||
*/
|
||||
class BitmapFontFace : public FontFace {
|
||||
public:
|
||||
explicit BitmapFontFace(Font *font);
|
||||
~BitmapFontFace() override = default;
|
||||
BitmapFontFace(const BitmapFontFace &) = delete;
|
||||
BitmapFontFace(BitmapFontFace &&) = delete;
|
||||
BitmapFontFace &operator=(const BitmapFontFace &) = delete;
|
||||
BitmapFontFace &operator=(BitmapFontFace &&) = delete;
|
||||
|
||||
const FontGlyph *getGlyph(uint32_t code) override;
|
||||
float getKerning(uint32_t prevCode, uint32_t nextCode) override;
|
||||
|
||||
private:
|
||||
void doInit(const FontFaceInfo &info) override;
|
||||
static gfx::Texture *loadTexture(const ccstd::string &path);
|
||||
|
||||
friend class BitmapFont;
|
||||
};
|
||||
|
||||
/**
|
||||
* BitmapFont
|
||||
*/
|
||||
class BitmapFont : public Font {
|
||||
public:
|
||||
explicit BitmapFont(const ccstd::string &path);
|
||||
~BitmapFont() override = default;
|
||||
BitmapFont(const BitmapFont &) = delete;
|
||||
BitmapFont(BitmapFont &&) = delete;
|
||||
BitmapFont &operator=(const BitmapFont &) = delete;
|
||||
BitmapFont &operator=(BitmapFont &&) = delete;
|
||||
|
||||
FontFace *createFace(const FontFaceInfo &info) override;
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
37
cocos/core/assets/BufferAsset.cpp
Normal file
37
cocos/core/assets/BufferAsset.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/BufferAsset.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
ccstd::any BufferAsset::getNativeAsset() const {
|
||||
return _buffer;
|
||||
}
|
||||
|
||||
void BufferAsset::setNativeAsset(const ccstd::any &obj) {
|
||||
_buffer = ccstd::any_cast<ArrayBuffer *>(obj);
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
52
cocos/core/assets/BufferAsset.h
Normal file
52
cocos/core/assets/BufferAsset.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/ArrayBuffer.h"
|
||||
#include "core/assets/Asset.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class BufferAsset final : public Asset {
|
||||
public:
|
||||
BufferAsset() = default;
|
||||
~BufferAsset() override = default;
|
||||
|
||||
inline ArrayBuffer *getBuffer() const { return _buffer; }
|
||||
|
||||
inline void setNativeAssetForJS(ArrayBuffer *buffer) { _buffer = buffer; }
|
||||
inline ArrayBuffer *getNativeAssetForJS() const { return _buffer; }
|
||||
|
||||
ccstd::any getNativeAsset() const override;
|
||||
void setNativeAsset(const ccstd::any &obj) override;
|
||||
bool validate() const override { return _buffer != nullptr; }
|
||||
|
||||
private:
|
||||
ArrayBuffer::Ptr _buffer;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(BufferAsset);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
354
cocos/core/assets/EffectAsset.cpp
Normal file
354
cocos/core/assets/EffectAsset.cpp
Normal file
@@ -0,0 +1,354 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/EffectAsset.h"
|
||||
#include "ProgramUtils.h"
|
||||
#include "cocos.h"
|
||||
#include "cocos/renderer/pipeline/custom/RenderingModule.h"
|
||||
#include "core/Root.h"
|
||||
#include "core/platform/Debug.h"
|
||||
#include "engine/BaseEngine.h"
|
||||
#include "renderer/core/ProgramLib.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
IPassStates::IPassStates(const IPassInfoFull &o) {
|
||||
*this = o;
|
||||
}
|
||||
|
||||
IPassStates &IPassStates::operator=(const IPassInfoFull &o) {
|
||||
priority = o.priority;
|
||||
primitive = o.primitive;
|
||||
stage = o.stage;
|
||||
rasterizerState = o.rasterizerState;
|
||||
depthStencilState = o.depthStencilState;
|
||||
blendState = o.blendState;
|
||||
dynamicStates = o.dynamicStates;
|
||||
phase = o.phase;
|
||||
subpass = o.subpass;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void IPassStates::overrides(const IPassInfoFull &o) {
|
||||
if (o.priority.has_value()) {
|
||||
this->priority = o.priority.value();
|
||||
}
|
||||
if (o.primitive.has_value()) {
|
||||
this->primitive = o.primitive.value();
|
||||
}
|
||||
if (o.stage.has_value()) {
|
||||
this->stage = o.stage.value();
|
||||
}
|
||||
if (o.rasterizerState.has_value()) {
|
||||
this->rasterizerState = o.rasterizerState.value();
|
||||
}
|
||||
if (o.depthStencilState.has_value()) {
|
||||
this->depthStencilState = o.depthStencilState.value();
|
||||
}
|
||||
if (o.blendState.has_value()) {
|
||||
this->blendState = o.blendState.value();
|
||||
}
|
||||
if (o.dynamicStates.has_value()) {
|
||||
this->dynamicStates = o.dynamicStates.value();
|
||||
}
|
||||
if (o.phase.has_value()) {
|
||||
this->phase = o.phase.value();
|
||||
}
|
||||
if (o.subpass.has_value()) {
|
||||
this->subpass = o.subpass.value();
|
||||
}
|
||||
}
|
||||
|
||||
EffectAsset::RegisteredEffectAssetMap EffectAsset::effects;
|
||||
bool EffectAsset::layoutValid = true;
|
||||
|
||||
/* static */
|
||||
void EffectAsset::registerAsset(EffectAsset *asset) {
|
||||
if (asset == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
EffectAsset::effects.emplace(asset->getName(), asset);
|
||||
layoutValid = false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void EffectAsset::remove(const ccstd::string &name) {
|
||||
auto iter = EffectAsset::effects.find(name);
|
||||
if (iter != EffectAsset::effects.end() && iter->second->getName() == name) {
|
||||
EffectAsset::effects.erase(iter);
|
||||
return;
|
||||
}
|
||||
|
||||
iter = EffectAsset::effects.begin();
|
||||
for (; iter != EffectAsset::effects.end(); ++iter) {
|
||||
if (iter->second->getUuid() == name) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iter != EffectAsset::effects.end()) {
|
||||
EffectAsset::effects.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void EffectAsset::remove(EffectAsset *asset) {
|
||||
if (asset == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto iter = EffectAsset::effects.find(asset->getName());
|
||||
if (iter != EffectAsset::effects.end() && iter->second == asset) {
|
||||
EffectAsset::effects.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
EffectAsset *EffectAsset::get(const ccstd::string &name) {
|
||||
auto iter = EffectAsset::effects.find(name);
|
||||
if (iter != EffectAsset::effects.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
iter = EffectAsset::effects.begin();
|
||||
for (; iter != EffectAsset::effects.end(); ++iter) {
|
||||
if (iter->second->getUuid() == name) {
|
||||
return iter->second;
|
||||
}
|
||||
}
|
||||
static ccstd::vector<ccstd::string> legacyBuiltinEffectNames{
|
||||
"planar-shadow",
|
||||
"skybox",
|
||||
"deferred-lighting",
|
||||
"bloom",
|
||||
"copy-pass",
|
||||
"post-process",
|
||||
"profiler",
|
||||
"splash-screen",
|
||||
"standard",
|
||||
"unlit",
|
||||
"sprite",
|
||||
"particle",
|
||||
"particle-gpu",
|
||||
"particle-trail",
|
||||
"billboard",
|
||||
"terrain",
|
||||
"graphics",
|
||||
"clear-stencil",
|
||||
"spine",
|
||||
"occlusion-query",
|
||||
"geometry-renderer",
|
||||
"debug-renderer"};
|
||||
for (auto &legacyName : legacyBuiltinEffectNames) {
|
||||
if (name == legacyName) {
|
||||
debug::warnID(16101, name);
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void EffectAsset::onLoaded() {
|
||||
auto *programLib = render::getProgramLibrary();
|
||||
if (programLib) {
|
||||
render::addEffectDefaultProperties(*this);
|
||||
programLib->addEffect(this);
|
||||
} else {
|
||||
ProgramLib::getInstance()->registerEffect(this);
|
||||
}
|
||||
EffectAsset::registerAsset(this);
|
||||
#if !CC_EDITOR
|
||||
if (CC_CURRENT_ENGINE()->isInited()) {
|
||||
precompile();
|
||||
} else {
|
||||
_engineEventId = CC_CURRENT_ENGINE()->on<BaseEngine::EngineStatusChange>([this](BaseEngine * /*emitter*/, BaseEngine::EngineStatus status) {
|
||||
if (status == BaseEngine::EngineStatus::ON_START) {
|
||||
this->precompile();
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool EffectAsset::destroy() {
|
||||
EffectAsset::remove(this);
|
||||
if (CC_CURRENT_ENGINE()->isInited()) {
|
||||
CC_CURRENT_ENGINE()->off(_engineEventId);
|
||||
}
|
||||
return Super::destroy();
|
||||
}
|
||||
|
||||
void EffectAsset::initDefault(const ccstd::optional<ccstd::string> &uuid) {
|
||||
Super::initDefault(uuid);
|
||||
const auto *effect = EffectAsset::get("builtin-unlit");
|
||||
_name = "builtin-unlit";
|
||||
_shaders = effect->_shaders;
|
||||
_combinations = effect->_combinations;
|
||||
_techniques = effect->_techniques; // NOTE: it will copy effect->_techniques to _techniques and _techniques will kept by SE_HOLD_RETURN_VALUE
|
||||
}
|
||||
|
||||
bool EffectAsset::validate() const {
|
||||
return !_techniques.empty() && !_shaders.empty();
|
||||
}
|
||||
|
||||
void EffectAsset::precompile() {
|
||||
Root *root = Root::getInstance();
|
||||
for (index_t i = 0; i < _shaders.size(); ++i) {
|
||||
auto shader = _shaders[i];
|
||||
if (i >= _combinations.size()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto combination = _combinations[i];
|
||||
if (combination.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Native Program Lib can not precompile shader variant without phaseID.
|
||||
// Shaders are compiled only during the compilation of PSO. A new mechanism may be needed for pre-compilation.
|
||||
auto *programLib = render::getProgramLibrary();
|
||||
if (programLib == nullptr) {
|
||||
ccstd::vector<MacroRecord> defines = EffectAsset::doCombine(
|
||||
ccstd::vector<MacroRecord>(), combination, combination.begin());
|
||||
for (auto &define: defines) {
|
||||
ProgramLib::getInstance()->getGFXShader(root->getDevice(), shader.name, define,
|
||||
root->getPipeline());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// input
|
||||
|
||||
const combination = {
|
||||
USE_TEXTURE: [true, false],
|
||||
COLOR_MODE: [0, 1, 2, 3],
|
||||
ROUGHNESS_CHANNEL: ['r', 'g', 'b'],
|
||||
};
|
||||
|
||||
// output
|
||||
|
||||
const defines = [
|
||||
{
|
||||
USE_TEXTURE: true,
|
||||
COLOR_MODE: 0,
|
||||
ROUGHNESS_CHANNEL: 'r'
|
||||
},
|
||||
{
|
||||
USE_TEXTURE: true,
|
||||
COLOR_MODE: 0,
|
||||
ROUGHNESS_CHANNEL: 'g'
|
||||
},
|
||||
{
|
||||
USE_TEXTURE: true,
|
||||
COLOR_MODE: 0,
|
||||
ROUGHNESS_CHANNEL: 'b'
|
||||
},
|
||||
{
|
||||
USE_TEXTURE: true,
|
||||
COLOR_MODE: 1,
|
||||
ROUGHNESS_CHANNEL: 'r'
|
||||
},
|
||||
// ... all the combinations (2x4x3 in this case)
|
||||
];
|
||||
*/
|
||||
ccstd::vector<MacroRecord> EffectAsset::doCombine(const ccstd::vector<MacroRecord> &cur, const IPreCompileInfo &info, IPreCompileInfo::iterator iter) { // NOLINT(misc-no-recursion)
|
||||
if (iter == info.end()) {
|
||||
return cur;
|
||||
}
|
||||
|
||||
const IPreCompileInfoValueType &values = iter->second;
|
||||
const ccstd::string &key = iter->first;
|
||||
|
||||
ccstd::vector<MacroRecord> records;
|
||||
if (cur.empty()) {
|
||||
records = EffectAsset::generateRecords(key, values);
|
||||
} else {
|
||||
records = EffectAsset::insertInfoValue(cur, key, values);
|
||||
}
|
||||
|
||||
return EffectAsset::doCombine(records, info, ++iter);
|
||||
}
|
||||
|
||||
ccstd::vector<MacroRecord> EffectAsset::generateRecords(const ccstd::string &key, const IPreCompileInfoValueType &infoValue) {
|
||||
ccstd::vector<MacroRecord> ret;
|
||||
if (const auto *boolValues = ccstd::get_if<ccstd::vector<bool>>(&infoValue)) {
|
||||
for (const bool value : *boolValues) {
|
||||
MacroRecord record;
|
||||
record[key] = value;
|
||||
ret.emplace_back(record);
|
||||
}
|
||||
} else if (const auto *intValues = ccstd::get_if<ccstd::vector<int32_t>>(&infoValue)) {
|
||||
for (const int32_t value : *intValues) {
|
||||
MacroRecord record;
|
||||
record[key] = value;
|
||||
ret.emplace_back(record);
|
||||
}
|
||||
} else if (const auto *stringValues = ccstd::get_if<ccstd::vector<ccstd::string>>(&infoValue)) {
|
||||
for (const ccstd::string &value : *stringValues) {
|
||||
MacroRecord record;
|
||||
record[key] = value;
|
||||
ret.emplace_back(record);
|
||||
}
|
||||
} else {
|
||||
CC_ABORT();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ccstd::vector<MacroRecord> EffectAsset::insertInfoValue(const ccstd::vector<MacroRecord> &records,
|
||||
const ccstd::string &key,
|
||||
const IPreCompileInfoValueType &infoValue) {
|
||||
ccstd::vector<MacroRecord> ret;
|
||||
for (const auto &record : records) {
|
||||
if (const auto *boolValues = ccstd::get_if<ccstd::vector<bool>>(&infoValue)) {
|
||||
for (const bool value : *boolValues) {
|
||||
MacroRecord tmpRecord = record;
|
||||
tmpRecord[key] = value;
|
||||
ret.emplace_back(tmpRecord);
|
||||
}
|
||||
} else if (const auto *intValues = ccstd::get_if<ccstd::vector<int32_t>>(&infoValue)) {
|
||||
for (const int32_t value : *intValues) {
|
||||
MacroRecord tmpRecord = record;
|
||||
tmpRecord[key] = value;
|
||||
ret.emplace_back(tmpRecord);
|
||||
}
|
||||
} else if (const auto *stringValues = ccstd::get_if<ccstd::vector<ccstd::string>>(&infoValue)) {
|
||||
for (const ccstd::string &value : *stringValues) {
|
||||
MacroRecord tmpRecord = record;
|
||||
tmpRecord[key] = value;
|
||||
ret.emplace_back(tmpRecord);
|
||||
}
|
||||
} else {
|
||||
CC_ABORT();
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
706
cocos/core/assets/EffectAsset.h
Normal file
706
cocos/core/assets/EffectAsset.h
Normal file
@@ -0,0 +1,706 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include "base/std/container/string.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
#include "base/std/optional.h"
|
||||
|
||||
#include "base/Value.h"
|
||||
#include "core/Types.h"
|
||||
#include "core/assets/Asset.h"
|
||||
#include "engine/BaseEngine.h"
|
||||
#include "renderer/core/PassUtils.h"
|
||||
#include "renderer/gfx-base/GFXDef.h"
|
||||
#include "renderer/pipeline/Define.h"
|
||||
namespace cc {
|
||||
|
||||
// To avoid errors when generating code using SWIG.
|
||||
#if !SWIGCOCOS
|
||||
|
||||
// The properties in Pass are obtained from an asset file. If they are directly stored in an unordered_map,
|
||||
// the order of these properties may become scrambled. To maintain their order, a vector<pair> is used
|
||||
// instead. Since there is no scenario where these data objects are randomly inserted,
|
||||
// only a find interface is provided.
|
||||
template <typename K, typename V>
|
||||
class StablePropertyMap : public ccstd::vector<std::pair<K, V>> { // NOLINT
|
||||
using Super = ccstd::vector<std::pair<K, V>>;
|
||||
|
||||
public:
|
||||
auto find(const K &key) const {
|
||||
auto *self = static_cast<const Super *>(this);
|
||||
return std::find_if(self->begin(), self->end(), [&](auto &ele) {
|
||||
return ele.first == key;
|
||||
});
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
template <typename K, typename V>
|
||||
using UnstablePropertyContainer = ccstd::unordered_map<K, V>;
|
||||
|
||||
template <typename K, typename V>
|
||||
using StablePropertyContainer = StablePropertyMap<K, V>;
|
||||
|
||||
#if CC_EDITOR
|
||||
template <typename K, typename V>
|
||||
using PropertyContainer = StablePropertyContainer<K, V>;
|
||||
#else
|
||||
template <typename K, typename V>
|
||||
using PropertyContainer = UnstablePropertyContainer<K, V>;
|
||||
#endif
|
||||
|
||||
using IPropertyHandleInfo = std::tuple<ccstd::string, uint32_t, gfx::Type>;
|
||||
|
||||
using IPropertyValue = ccstd::variant<ccstd::monostate, ccstd::vector<float>, ccstd::string>;
|
||||
|
||||
using IPropertyEditorValueType = ccstd::variant<ccstd::monostate, ccstd::string, bool, float, ccstd::vector<float>>;
|
||||
using IPropertyEditorInfo = PropertyContainer<ccstd::string, IPropertyEditorValueType>;
|
||||
|
||||
struct IPropertyInfo {
|
||||
int32_t type{0}; // auto-extracted from shader
|
||||
ccstd::optional<IPropertyHandleInfo> handleInfo; // auto-generated from 'target'
|
||||
ccstd::optional<ccstd::hash_t> samplerHash; // auto-generated from 'sampler'
|
||||
ccstd::optional<IPropertyValue> value; // default value
|
||||
ccstd::optional<bool> linear; // whether to convert the input to linear space first before applying
|
||||
IPropertyEditorInfo editor; // NOTE: used only by editor.
|
||||
};
|
||||
|
||||
struct IPassInfoFull;
|
||||
|
||||
struct RasterizerStateInfo {
|
||||
ccstd::optional<bool> isDiscard;
|
||||
ccstd::optional<bool> isFrontFaceCCW;
|
||||
ccstd::optional<bool> depthBiasEnabled;
|
||||
ccstd::optional<bool> isDepthClip;
|
||||
ccstd::optional<bool> isMultisample;
|
||||
|
||||
ccstd::optional<gfx::PolygonMode> polygonMode;
|
||||
ccstd::optional<gfx::ShadeModel> shadeModel;
|
||||
ccstd::optional<gfx::CullMode> cullMode;
|
||||
|
||||
ccstd::optional<float> depthBias;
|
||||
ccstd::optional<float> depthBiasClamp;
|
||||
ccstd::optional<float> depthBiasSlop;
|
||||
ccstd::optional<float> lineWidth;
|
||||
|
||||
void fromGFXRasterizerState(const gfx::RasterizerState &rs) {
|
||||
isDiscard = rs.isDiscard;
|
||||
isFrontFaceCCW = rs.isFrontFaceCCW;
|
||||
depthBiasEnabled = rs.depthBiasEnabled;
|
||||
isDepthClip = rs.isDepthClip;
|
||||
isMultisample = rs.isMultisample;
|
||||
|
||||
polygonMode = rs.polygonMode;
|
||||
shadeModel = rs.shadeModel;
|
||||
cullMode = rs.cullMode;
|
||||
|
||||
depthBias = rs.depthBias;
|
||||
depthBiasClamp = rs.depthBiasClamp;
|
||||
depthBiasSlop = rs.depthBiasSlop;
|
||||
lineWidth = rs.lineWidth;
|
||||
}
|
||||
|
||||
void assignToGFXRasterizerState(gfx::RasterizerState &rs) const {
|
||||
if (isDiscard.has_value()) {
|
||||
rs.isDiscard = isDiscard.value();
|
||||
}
|
||||
if (isFrontFaceCCW.has_value()) {
|
||||
rs.isFrontFaceCCW = isFrontFaceCCW.value();
|
||||
}
|
||||
if (depthBiasEnabled.has_value()) {
|
||||
rs.depthBiasEnabled = depthBiasEnabled.value();
|
||||
}
|
||||
if (isDepthClip.has_value()) {
|
||||
rs.isDepthClip = isDepthClip.value();
|
||||
}
|
||||
if (isMultisample.has_value()) {
|
||||
rs.isMultisample = isMultisample.value();
|
||||
}
|
||||
if (polygonMode.has_value()) {
|
||||
rs.polygonMode = polygonMode.value();
|
||||
}
|
||||
if (shadeModel.has_value()) {
|
||||
rs.shadeModel = shadeModel.value();
|
||||
}
|
||||
if (cullMode.has_value()) {
|
||||
rs.cullMode = cullMode.value();
|
||||
}
|
||||
if (depthBias.has_value()) {
|
||||
rs.depthBias = depthBias.value();
|
||||
}
|
||||
if (depthBiasClamp.has_value()) {
|
||||
rs.depthBiasClamp = depthBiasClamp.value();
|
||||
}
|
||||
if (depthBiasSlop.has_value()) {
|
||||
rs.depthBiasSlop = depthBiasSlop.value();
|
||||
}
|
||||
if (lineWidth.has_value()) {
|
||||
rs.lineWidth = lineWidth.value();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct DepthStencilStateInfo {
|
||||
ccstd::optional<bool> depthTest;
|
||||
ccstd::optional<bool> depthWrite;
|
||||
ccstd::optional<bool> stencilTestFront;
|
||||
ccstd::optional<bool> stencilTestBack;
|
||||
|
||||
ccstd::optional<gfx::ComparisonFunc> depthFunc;
|
||||
ccstd::optional<gfx::ComparisonFunc> stencilFuncFront;
|
||||
ccstd::optional<uint32_t> stencilReadMaskFront;
|
||||
ccstd::optional<uint32_t> stencilWriteMaskFront;
|
||||
ccstd::optional<gfx::StencilOp> stencilFailOpFront;
|
||||
ccstd::optional<gfx::StencilOp> stencilZFailOpFront;
|
||||
ccstd::optional<gfx::StencilOp> stencilPassOpFront;
|
||||
ccstd::optional<uint32_t> stencilRefFront;
|
||||
|
||||
ccstd::optional<gfx::ComparisonFunc> stencilFuncBack;
|
||||
ccstd::optional<uint32_t> stencilReadMaskBack;
|
||||
ccstd::optional<uint32_t> stencilWriteMaskBack;
|
||||
ccstd::optional<gfx::StencilOp> stencilFailOpBack;
|
||||
ccstd::optional<gfx::StencilOp> stencilZFailOpBack;
|
||||
ccstd::optional<gfx::StencilOp> stencilPassOpBack;
|
||||
ccstd::optional<uint32_t> stencilRefBack;
|
||||
|
||||
void fromGFXDepthStencilState(const gfx::DepthStencilState &ds) {
|
||||
depthTest = ds.depthTest;
|
||||
depthWrite = ds.depthWrite;
|
||||
stencilTestFront = ds.stencilTestFront;
|
||||
stencilTestBack = ds.stencilTestBack;
|
||||
|
||||
depthFunc = ds.depthFunc;
|
||||
stencilFuncFront = ds.stencilFuncFront;
|
||||
stencilReadMaskFront = ds.stencilReadMaskFront;
|
||||
stencilWriteMaskFront = ds.stencilWriteMaskFront;
|
||||
stencilFailOpFront = ds.stencilFailOpFront;
|
||||
stencilZFailOpFront = ds.stencilZFailOpFront;
|
||||
stencilPassOpFront = ds.stencilPassOpFront;
|
||||
stencilRefFront = ds.stencilRefFront;
|
||||
|
||||
stencilFuncBack = ds.stencilFuncBack;
|
||||
stencilReadMaskBack = ds.stencilReadMaskBack;
|
||||
stencilWriteMaskBack = ds.stencilWriteMaskBack;
|
||||
stencilFailOpBack = ds.stencilFailOpBack;
|
||||
stencilZFailOpBack = ds.stencilZFailOpBack;
|
||||
stencilPassOpBack = ds.stencilPassOpBack;
|
||||
stencilRefBack = ds.stencilRefBack;
|
||||
}
|
||||
|
||||
void assignToGFXDepthStencilState(gfx::DepthStencilState &ds) const {
|
||||
if (depthTest.has_value()) {
|
||||
ds.depthTest = depthTest.value();
|
||||
}
|
||||
if (depthWrite.has_value()) {
|
||||
ds.depthWrite = depthWrite.value();
|
||||
}
|
||||
if (stencilTestFront.has_value()) {
|
||||
ds.stencilTestFront = stencilTestFront.value();
|
||||
}
|
||||
if (stencilTestBack.has_value()) {
|
||||
ds.stencilTestBack = stencilTestBack.value();
|
||||
}
|
||||
if (depthFunc.has_value()) {
|
||||
ds.depthFunc = depthFunc.value();
|
||||
}
|
||||
if (stencilFuncFront.has_value()) {
|
||||
ds.stencilFuncFront = stencilFuncFront.value();
|
||||
}
|
||||
if (stencilReadMaskFront.has_value()) {
|
||||
ds.stencilReadMaskFront = stencilReadMaskFront.value();
|
||||
}
|
||||
if (stencilWriteMaskFront.has_value()) {
|
||||
ds.stencilWriteMaskFront = stencilWriteMaskFront.value();
|
||||
}
|
||||
if (stencilFailOpFront.has_value()) {
|
||||
ds.stencilFailOpFront = stencilFailOpFront.value();
|
||||
}
|
||||
if (stencilZFailOpFront.has_value()) {
|
||||
ds.stencilZFailOpFront = stencilZFailOpFront.value();
|
||||
}
|
||||
if (stencilPassOpFront.has_value()) {
|
||||
ds.stencilPassOpFront = stencilPassOpFront.value();
|
||||
}
|
||||
if (stencilRefFront.has_value()) {
|
||||
ds.stencilRefFront = stencilRefFront.value();
|
||||
}
|
||||
if (stencilFuncBack.has_value()) {
|
||||
ds.stencilFuncBack = stencilFuncBack.value();
|
||||
}
|
||||
if (stencilReadMaskBack.has_value()) {
|
||||
ds.stencilReadMaskBack = stencilReadMaskBack.value();
|
||||
}
|
||||
if (stencilWriteMaskBack.has_value()) {
|
||||
ds.stencilWriteMaskBack = stencilWriteMaskBack.value();
|
||||
}
|
||||
if (stencilFailOpBack.has_value()) {
|
||||
ds.stencilFailOpBack = stencilFailOpBack.value();
|
||||
}
|
||||
if (stencilZFailOpBack.has_value()) {
|
||||
ds.stencilZFailOpBack = stencilZFailOpBack.value();
|
||||
}
|
||||
if (stencilPassOpBack.has_value()) {
|
||||
ds.stencilPassOpBack = stencilPassOpBack.value();
|
||||
}
|
||||
if (stencilRefBack.has_value()) {
|
||||
ds.stencilRefBack = stencilRefBack.value();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct BlendTargetInfo {
|
||||
ccstd::optional<bool> blend;
|
||||
ccstd::optional<gfx::BlendFactor> blendSrc;
|
||||
ccstd::optional<gfx::BlendFactor> blendDst;
|
||||
ccstd::optional<gfx::BlendOp> blendEq;
|
||||
ccstd::optional<gfx::BlendFactor> blendSrcAlpha;
|
||||
ccstd::optional<gfx::BlendFactor> blendDstAlpha;
|
||||
ccstd::optional<gfx::BlendOp> blendAlphaEq;
|
||||
ccstd::optional<gfx::ColorMask> blendColorMask;
|
||||
|
||||
void fromGFXBlendTarget(const gfx::BlendTarget &target) {
|
||||
blend = target.blend;
|
||||
blendSrc = target.blendSrc;
|
||||
blendDst = target.blendDst;
|
||||
blendEq = target.blendEq;
|
||||
blendSrcAlpha = target.blendSrcAlpha;
|
||||
blendDstAlpha = target.blendDstAlpha;
|
||||
blendAlphaEq = target.blendAlphaEq;
|
||||
blendColorMask = target.blendColorMask;
|
||||
}
|
||||
|
||||
void assignToGFXBlendTarget(gfx::BlendTarget &target) const {
|
||||
if (blend.has_value()) {
|
||||
target.blend = blend.value();
|
||||
}
|
||||
if (blendSrc.has_value()) {
|
||||
target.blendSrc = blendSrc.value();
|
||||
}
|
||||
if (blendDst.has_value()) {
|
||||
target.blendDst = blendDst.value();
|
||||
}
|
||||
if (blendEq.has_value()) {
|
||||
target.blendEq = blendEq.value();
|
||||
}
|
||||
if (blendSrcAlpha.has_value()) {
|
||||
target.blendSrcAlpha = blendSrcAlpha.value();
|
||||
}
|
||||
if (blendDstAlpha.has_value()) {
|
||||
target.blendDstAlpha = blendDstAlpha.value();
|
||||
}
|
||||
if (blendAlphaEq.has_value()) {
|
||||
target.blendAlphaEq = blendAlphaEq.value();
|
||||
}
|
||||
if (blendColorMask.has_value()) {
|
||||
target.blendColorMask = blendColorMask.value();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
using BlendTargetInfoList = ccstd::vector<BlendTargetInfo>;
|
||||
|
||||
struct BlendStateInfo {
|
||||
ccstd::optional<bool> isA2C;
|
||||
ccstd::optional<bool> isIndepend;
|
||||
ccstd::optional<gfx::Color> blendColor;
|
||||
ccstd::optional<BlendTargetInfoList> targets;
|
||||
|
||||
void fromGFXBlendState(const gfx::BlendState &bs) {
|
||||
isA2C = bs.isA2C;
|
||||
isIndepend = bs.isIndepend;
|
||||
blendColor = bs.blendColor;
|
||||
size_t len = bs.targets.size();
|
||||
if (len > 0) {
|
||||
BlendTargetInfoList targetsList(len);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
targetsList[i].fromGFXBlendTarget(bs.targets[i]);
|
||||
}
|
||||
targets = targetsList;
|
||||
}
|
||||
}
|
||||
|
||||
void assignToGFXBlendState(gfx::BlendState &bs) const {
|
||||
if (targets.has_value()) {
|
||||
const auto &targetsVal = targets.value();
|
||||
bs.targets.resize(targetsVal.size());
|
||||
for (size_t i = 0, len = targetsVal.size(); i < len; ++i) {
|
||||
targetsVal[i].assignToGFXBlendTarget(bs.targets[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isA2C.has_value()) {
|
||||
bs.isA2C = isA2C.value();
|
||||
}
|
||||
|
||||
if (isIndepend.has_value()) {
|
||||
bs.isIndepend = isIndepend.value();
|
||||
}
|
||||
|
||||
if (blendColor.has_value()) {
|
||||
bs.blendColor = blendColor.value();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Pass instance itself are compliant to IPassStates too
|
||||
struct IPassStates {
|
||||
ccstd::optional<int32_t> priority;
|
||||
ccstd::optional<gfx::PrimitiveMode> primitive;
|
||||
ccstd::optional<pipeline::RenderPassStage> stage;
|
||||
ccstd::optional<RasterizerStateInfo> rasterizerState;
|
||||
ccstd::optional<DepthStencilStateInfo> depthStencilState;
|
||||
ccstd::optional<BlendStateInfo> blendState;
|
||||
ccstd::optional<gfx::DynamicStateFlags> dynamicStates;
|
||||
ccstd::optional<ccstd::string> phase;
|
||||
ccstd::optional<ccstd::string> pass;
|
||||
ccstd::optional<ccstd::string> subpass;
|
||||
|
||||
IPassStates() = default;
|
||||
explicit IPassStates(const IPassInfoFull &o);
|
||||
IPassStates &operator=(const IPassInfoFull &o);
|
||||
void overrides(const IPassInfoFull &o);
|
||||
};
|
||||
using PassOverrides = IPassStates;
|
||||
|
||||
using PassPropertyInfoMap = PropertyContainer<ccstd::string, IPropertyInfo>;
|
||||
|
||||
struct IPassInfoFull final { // cjh } : public IPassInfo {
|
||||
// IPassStates
|
||||
ccstd::optional<int32_t> priority;
|
||||
ccstd::optional<gfx::PrimitiveMode> primitive;
|
||||
ccstd::optional<pipeline::RenderPassStage> stage;
|
||||
ccstd::optional<RasterizerStateInfo> rasterizerState;
|
||||
ccstd::optional<DepthStencilStateInfo> depthStencilState;
|
||||
ccstd::optional<BlendStateInfo> blendState;
|
||||
ccstd::optional<gfx::DynamicStateFlags> dynamicStates;
|
||||
ccstd::optional<ccstd::string> phase;
|
||||
ccstd::optional<ccstd::string> pass;
|
||||
ccstd::optional<ccstd::string> subpass;
|
||||
// IPassInfo
|
||||
ccstd::string program; // auto-generated from 'vert' and 'frag'
|
||||
ccstd::optional<MacroRecord> embeddedMacros;
|
||||
ccstd::optional<index_t> propertyIndex; // NOTE: needs to use ccstd::optional<> since jsb should return 'undefined' instead of '-1' to avoid wrong value checking logic.
|
||||
ccstd::optional<ccstd::string> switch_;
|
||||
ccstd::optional<PassPropertyInfoMap> properties;
|
||||
|
||||
// IPassInfoFull
|
||||
// generated part
|
||||
index_t passIndex{0};
|
||||
uint32_t passID = 0xFFFFFFFF;
|
||||
uint32_t subpassID = 0xFFFFFFFF;
|
||||
uint32_t phaseID = 0xFFFFFFFF;
|
||||
MacroRecord defines;
|
||||
ccstd::optional<PassOverrides> stateOverrides;
|
||||
|
||||
IPassInfoFull() = default;
|
||||
explicit IPassInfoFull(const IPassStates &o) {
|
||||
*this = o;
|
||||
}
|
||||
IPassInfoFull &operator=(const IPassStates &o) {
|
||||
priority = o.priority;
|
||||
primitive = o.primitive;
|
||||
stage = o.stage;
|
||||
rasterizerState = o.rasterizerState;
|
||||
depthStencilState = o.depthStencilState;
|
||||
blendState = o.blendState;
|
||||
dynamicStates = o.dynamicStates;
|
||||
phase = o.phase;
|
||||
subpass = o.subpass;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
using IPassInfo = IPassInfoFull;
|
||||
|
||||
struct ITechniqueInfo {
|
||||
ccstd::vector<IPassInfoFull> passes;
|
||||
ccstd::optional<ccstd::string> name;
|
||||
};
|
||||
|
||||
struct IBlockInfo {
|
||||
uint32_t binding{UINT32_MAX};
|
||||
ccstd::string name;
|
||||
ccstd::vector<gfx::Uniform> members;
|
||||
|
||||
gfx::ShaderStageFlags stageFlags{gfx::ShaderStageFlags::NONE};
|
||||
|
||||
ccstd::vector<ccstd::string> defines;
|
||||
};
|
||||
|
||||
struct ISamplerTextureInfo {
|
||||
uint32_t binding{UINT32_MAX};
|
||||
ccstd::string name;
|
||||
gfx::Type type{gfx::Type::UNKNOWN};
|
||||
uint32_t count{0};
|
||||
gfx::ShaderStageFlags stageFlags{gfx::ShaderStageFlags::NONE};
|
||||
ccstd::vector<ccstd::string> defines; // NOTE: used in Editor only
|
||||
};
|
||||
|
||||
struct ITextureInfo {
|
||||
uint32_t set{0};
|
||||
uint32_t binding{UINT32_MAX};
|
||||
ccstd::string name;
|
||||
gfx::Type type{gfx::Type::UNKNOWN};
|
||||
uint32_t count{0};
|
||||
gfx::ShaderStageFlags stageFlags{gfx::ShaderStageFlags::NONE};
|
||||
};
|
||||
|
||||
struct ISamplerInfo {
|
||||
uint32_t set{0};
|
||||
uint32_t binding{UINT32_MAX};
|
||||
ccstd::string name;
|
||||
uint32_t count{0};
|
||||
gfx::ShaderStageFlags stageFlags{gfx::ShaderStageFlags::NONE};
|
||||
};
|
||||
|
||||
struct IBufferInfo {
|
||||
uint32_t binding{UINT32_MAX};
|
||||
ccstd::string name;
|
||||
gfx::MemoryAccess memoryAccess{gfx::MemoryAccess::NONE};
|
||||
gfx::ShaderStageFlags stageFlags{gfx::ShaderStageFlags::NONE};
|
||||
};
|
||||
|
||||
struct IImageInfo {
|
||||
uint32_t binding{UINT32_MAX};
|
||||
ccstd::string name;
|
||||
gfx::Type type{gfx::Type::UNKNOWN};
|
||||
uint32_t count{0};
|
||||
gfx::MemoryAccess memoryAccess{gfx::MemoryAccess::NONE};
|
||||
gfx::ShaderStageFlags stageFlags{gfx::ShaderStageFlags::NONE};
|
||||
};
|
||||
|
||||
struct IInputAttachmentInfo {
|
||||
uint32_t set{0};
|
||||
uint32_t binding{UINT32_MAX};
|
||||
ccstd::string name;
|
||||
uint32_t count{0};
|
||||
gfx::ShaderStageFlags stageFlags{gfx::ShaderStageFlags::NONE};
|
||||
};
|
||||
|
||||
struct IAttributeInfo {
|
||||
ccstd::string name;
|
||||
gfx::Format format{gfx::Format::UNKNOWN};
|
||||
bool isNormalized{false};
|
||||
uint32_t stream{0U};
|
||||
bool isInstanced{false};
|
||||
uint32_t location{0U};
|
||||
|
||||
ccstd::vector<ccstd::string> defines;
|
||||
};
|
||||
|
||||
struct IDefineInfo {
|
||||
ccstd::string name;
|
||||
ccstd::string type;
|
||||
ccstd::optional<ccstd::vector<int32_t>> range; // cjh number is float? ?: number[];
|
||||
ccstd::optional<ccstd::vector<ccstd::string>> options;
|
||||
ccstd::optional<ccstd::string> defaultVal;
|
||||
ccstd::optional<ccstd::vector<ccstd::string>> defines; // NOTE: it's only used in Editor
|
||||
ccstd::optional<ccstd::unordered_map<ccstd::string, ccstd::variant<ccstd::string, bool>>> editor; // NOTE: it's only used in Editor
|
||||
};
|
||||
|
||||
struct IBuiltin {
|
||||
ccstd::string name;
|
||||
ccstd::vector<ccstd::string> defines;
|
||||
};
|
||||
|
||||
struct IBuiltinInfo {
|
||||
ccstd::vector<IBuiltin> buffers;
|
||||
ccstd::vector<IBuiltin> blocks;
|
||||
ccstd::vector<IBuiltin> samplerTextures;
|
||||
ccstd::vector<IBuiltin> images;
|
||||
};
|
||||
|
||||
using BuiltinsStatisticsType = ccstd::unordered_map<ccstd::string, int32_t>;
|
||||
|
||||
struct IBuiltins {
|
||||
IBuiltinInfo globals;
|
||||
IBuiltinInfo locals;
|
||||
BuiltinsStatisticsType statistics;
|
||||
};
|
||||
|
||||
struct IDescriptorInfo {
|
||||
uint32_t rate{0};
|
||||
ccstd::vector<IBlockInfo> blocks;
|
||||
ccstd::vector<ISamplerTextureInfo> samplerTextures;
|
||||
ccstd::vector<ISamplerInfo> samplers;
|
||||
ccstd::vector<ITextureInfo> textures;
|
||||
ccstd::vector<IBufferInfo> buffers;
|
||||
ccstd::vector<IImageInfo> images;
|
||||
ccstd::vector<IInputAttachmentInfo> subpassInputs;
|
||||
};
|
||||
|
||||
struct IShaderSource {
|
||||
ccstd::string vert;
|
||||
ccstd::string frag;
|
||||
ccstd::optional<ccstd::string> compute;
|
||||
};
|
||||
|
||||
struct IShaderInfo {
|
||||
ccstd::string name;
|
||||
ccstd::hash_t hash{gfx::INVALID_SHADER_HASH};
|
||||
IShaderSource glsl4;
|
||||
IShaderSource glsl3;
|
||||
IShaderSource glsl1;
|
||||
IBuiltins builtins;
|
||||
ccstd::vector<IDefineInfo> defines;
|
||||
ccstd::vector<IAttributeInfo> attributes;
|
||||
ccstd::vector<IBlockInfo> blocks;
|
||||
ccstd::vector<ISamplerTextureInfo> samplerTextures;
|
||||
ccstd::vector<ISamplerInfo> samplers;
|
||||
ccstd::vector<ITextureInfo> textures;
|
||||
ccstd::vector<IBufferInfo> buffers;
|
||||
ccstd::vector<IImageInfo> images;
|
||||
ccstd::vector<IInputAttachmentInfo> subpassInputs;
|
||||
ccstd::vector<IDescriptorInfo> descriptors;
|
||||
|
||||
const IShaderSource *getSource(const ccstd::string &version) const {
|
||||
if (version == "glsl1") return &glsl1;
|
||||
if (version == "glsl3") return &glsl3;
|
||||
if (version == "glsl4") return &glsl4;
|
||||
return nullptr;
|
||||
}
|
||||
IShaderSource *getSource(const ccstd::string &version) {
|
||||
if (version == "glsl1") return &glsl1;
|
||||
if (version == "glsl3") return &glsl3;
|
||||
if (version == "glsl4") return &glsl4;
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
using IPreCompileInfoValueType = ccstd::variant<ccstd::monostate, ccstd::vector<bool>, ccstd::vector<int32_t>, ccstd::vector<ccstd::string>>;
|
||||
using IPreCompileInfo = ccstd::unordered_map<ccstd::string, IPreCompileInfoValueType>;
|
||||
|
||||
class EffectAsset final : public Asset {
|
||||
public:
|
||||
using Super = Asset;
|
||||
|
||||
EffectAsset() = default;
|
||||
~EffectAsset() override = default;
|
||||
/**
|
||||
* @en Register the effect asset to the static map
|
||||
* @zh 将指定 effect 注册到全局管理器。
|
||||
*/
|
||||
static void registerAsset(EffectAsset *asset);
|
||||
|
||||
/**
|
||||
* @en Unregister the effect asset from the static map
|
||||
* @zh 将指定 effect 从全局管理器移除。
|
||||
*/
|
||||
static void remove(const ccstd::string &name);
|
||||
static void remove(EffectAsset *asset);
|
||||
|
||||
/**
|
||||
* @en Get the effect asset by the given name.
|
||||
* @zh 获取指定名字的 effect 资源。
|
||||
*/
|
||||
static EffectAsset *get(const ccstd::string &name);
|
||||
|
||||
using RegisteredEffectAssetMap = ccstd::unordered_map<ccstd::string, IntrusivePtr<EffectAsset>>;
|
||||
/**
|
||||
* @en Get all registered effect assets.
|
||||
* @zh 获取所有已注册的 effect 资源。
|
||||
*/
|
||||
static RegisteredEffectAssetMap &getAll() { return EffectAsset::effects; }
|
||||
|
||||
static bool isLayoutValid() { return layoutValid; }
|
||||
static void setLayoutValid() { layoutValid = true; }
|
||||
|
||||
inline void setTechniques(const ccstd::vector<ITechniqueInfo> &val) { _techniques = val; }
|
||||
inline void setShaders(const ccstd::vector<IShaderInfo> &val) { _shaders = val; }
|
||||
inline void setCombinations(const ccstd::vector<IPreCompileInfo> &val) { _combinations = val; }
|
||||
|
||||
inline const ccstd::vector<ITechniqueInfo> &getTechniques() const { return _techniques; }
|
||||
inline const ccstd::vector<IShaderInfo> &getShaders() const { return _shaders; }
|
||||
inline const ccstd::vector<IPreCompileInfo> &getCombinations() const { return _combinations; }
|
||||
|
||||
/*
|
||||
@serializable
|
||||
@editorOnly
|
||||
*/
|
||||
bool hideInEditor = false;
|
||||
|
||||
/**
|
||||
* @en The loaded callback which should be invoked by the [[Loader]], will automatically register the effect.
|
||||
* @zh 通过 [[Loader]] 加载完成时的回调,将自动注册 effect 资源。
|
||||
*/
|
||||
void onLoaded() override;
|
||||
bool destroy() override;
|
||||
void initDefault(const ccstd::optional<ccstd::string> &uuid) override;
|
||||
bool validate() const override;
|
||||
|
||||
protected:
|
||||
BaseEngine::EngineStatusChange::EventID _engineEventId;
|
||||
|
||||
static ccstd::vector<MacroRecord> doCombine(const ccstd::vector<MacroRecord> &cur, const IPreCompileInfo &info, IPreCompileInfo::iterator iter);
|
||||
static ccstd::vector<MacroRecord> generateRecords(const ccstd::string &key, const IPreCompileInfoValueType &value);
|
||||
static ccstd::vector<MacroRecord> insertInfoValue(const ccstd::vector<MacroRecord> &records,
|
||||
const ccstd::string &key,
|
||||
const IPreCompileInfoValueType &value);
|
||||
|
||||
void precompile();
|
||||
|
||||
// We need make it to public for deserialization
|
||||
public:
|
||||
/**
|
||||
* @en The techniques used by the current effect.
|
||||
* @zh 当前 effect 的所有可用 technique。
|
||||
|
||||
@serializable
|
||||
@editable*/
|
||||
ccstd::vector<ITechniqueInfo> _techniques;
|
||||
|
||||
/**
|
||||
* @en The shaders used by the current effect.
|
||||
* @zh 当前 effect 使用的所有 shader。
|
||||
|
||||
@serializable
|
||||
@editable*/
|
||||
ccstd::vector<IShaderInfo> _shaders;
|
||||
|
||||
/**
|
||||
* @en The preprocess macro combinations for the shader
|
||||
* @zh 每个 shader 需要预编译的宏定义组合。
|
||||
|
||||
@serializable
|
||||
@editable*/
|
||||
ccstd::vector<IPreCompileInfo> _combinations;
|
||||
//
|
||||
protected:
|
||||
static RegisteredEffectAssetMap effects; // cjh TODO: how to clear when game exits.
|
||||
static bool layoutValid;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(EffectAsset);
|
||||
|
||||
friend class EffectAssetDeserializer;
|
||||
friend class Material;
|
||||
friend class ProgramLib;
|
||||
friend class MaterialInstance;
|
||||
friend class BuiltinResMgr;
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
116
cocos/core/assets/Font.cpp
Normal file
116
cocos/core/assets/Font.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "Font.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include "base/Data.h"
|
||||
#include "base/Log.h"
|
||||
#include "base/Macros.h"
|
||||
#include "base/memory/Memory.h"
|
||||
#include "base/std/hash/hash.h"
|
||||
#include "gfx-base/GFXTexture.h"
|
||||
#include "math/Math.h"
|
||||
#include "platform/FileUtils.h"
|
||||
#include "profiler/Profiler.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
ccstd::hash_t KerningHash::operator()(const KerningPair &k) const {
|
||||
ccstd::hash_t seed = 2;
|
||||
ccstd::hash_combine(seed, k.prevCode);
|
||||
ccstd::hash_combine(seed, k.nextCode);
|
||||
return seed;
|
||||
}
|
||||
|
||||
/**
|
||||
* FontFaceInfo
|
||||
*/
|
||||
FontFaceInfo::FontFaceInfo(uint32_t size)
|
||||
: fontSize(size) {}
|
||||
|
||||
FontFaceInfo::FontFaceInfo(uint32_t size, uint32_t width, uint32_t height)
|
||||
: fontSize(size), textureWidth(width), textureHeight(height) {
|
||||
CC_ASSERT(math::isPowerOfTwo(width) && math::isPowerOfTwo(height)); // Font texture size must be power of 2.
|
||||
|
||||
// preload digit & alphabet characters by default
|
||||
for (auto i = 0U; i < 128; i++) {
|
||||
if (std::isdigit(i) || std::isalpha(i)) {
|
||||
preLoadedCharacters.emplace_back(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FontFaceInfo::FontFaceInfo(uint32_t size, uint32_t width, uint32_t height, ccstd::vector<uint32_t> chars)
|
||||
: fontSize(size), textureWidth(width), textureHeight(height), preLoadedCharacters(std::move(chars)) {
|
||||
CC_ASSERT(math::isPowerOfTwo(width) && math::isPowerOfTwo(height)); // Font texture size must be power of 2.
|
||||
}
|
||||
|
||||
/**
|
||||
* FontFace
|
||||
*/
|
||||
FontFace::FontFace(Font *font)
|
||||
: _font(font) {
|
||||
}
|
||||
|
||||
FontFace::~FontFace() {
|
||||
for (auto *texture : _textures) {
|
||||
CC_SAFE_DESTROY_AND_DELETE(texture);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Font
|
||||
*/
|
||||
Font::Font(FontType type, const ccstd::string &path)
|
||||
: _type(type), _path(path) {
|
||||
load(path);
|
||||
}
|
||||
|
||||
Font::~Font() {
|
||||
releaseFaces();
|
||||
CC_PROFILE_MEMORY_DEC(Font, _data.size());
|
||||
}
|
||||
|
||||
void Font::load(const ccstd::string &path) {
|
||||
Data data = FileUtils::getInstance()->getDataFromFile(path);
|
||||
if (data.isNull()) {
|
||||
CC_LOG_WARNING("Font load failed, path: %s.", path.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
_data.resize(data.getSize());
|
||||
memcpy(&_data[0], data.getBytes(), data.getSize());
|
||||
CC_PROFILE_MEMORY_INC(Font, _data.size());
|
||||
}
|
||||
|
||||
void Font::releaseFaces() {
|
||||
for (auto &iter : _faces) {
|
||||
delete iter.second;
|
||||
}
|
||||
|
||||
_faces.clear();
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
157
cocos/core/assets/Font.h
Normal file
157
cocos/core/assets/Font.h
Normal file
@@ -0,0 +1,157 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "base/std/container/unordered_map.h"
|
||||
#include "base/std/container/vector.h"
|
||||
#include "core/assets/Asset.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace gfx {
|
||||
class Texture;
|
||||
}
|
||||
|
||||
class Font;
|
||||
|
||||
constexpr uint32_t DEFAULT_FREETYPE_TEXTURE_SIZE = 512U;
|
||||
constexpr uint32_t MIN_FONT_SIZE = 1U;
|
||||
constexpr uint32_t MAX_FONT_SIZE = 128U;
|
||||
|
||||
enum class FontType {
|
||||
INVALID,
|
||||
FREETYPE,
|
||||
BITMAP,
|
||||
};
|
||||
|
||||
struct FontGlyph {
|
||||
int16_t x{0};
|
||||
int16_t y{0};
|
||||
uint16_t width{0U};
|
||||
uint16_t height{0U};
|
||||
int16_t bearingX{0};
|
||||
int16_t bearingY{0};
|
||||
int32_t advance{0};
|
||||
uint32_t page{0U}; // index of textures
|
||||
};
|
||||
|
||||
struct KerningPair {
|
||||
uint32_t prevCode{0U};
|
||||
uint32_t nextCode{0U};
|
||||
|
||||
inline bool operator==(const KerningPair &k) const noexcept {
|
||||
return prevCode == k.prevCode && nextCode == k.nextCode;
|
||||
}
|
||||
|
||||
inline bool operator!=(const KerningPair &k) const noexcept {
|
||||
return !(*this == k);
|
||||
}
|
||||
};
|
||||
|
||||
struct KerningHash {
|
||||
ccstd::hash_t operator()(const KerningPair &k) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* FontFaceInfo
|
||||
*/
|
||||
struct FontFaceInfo {
|
||||
explicit FontFaceInfo(uint32_t size);
|
||||
FontFaceInfo(uint32_t size, uint32_t width, uint32_t height);
|
||||
FontFaceInfo(uint32_t size, uint32_t width, uint32_t height, ccstd::vector<uint32_t> chars);
|
||||
|
||||
// only used in freetype, for bitmap font, fontSize is determined by file.
|
||||
uint32_t fontSize{1U};
|
||||
uint32_t textureWidth{DEFAULT_FREETYPE_TEXTURE_SIZE};
|
||||
uint32_t textureHeight{DEFAULT_FREETYPE_TEXTURE_SIZE};
|
||||
ccstd::vector<uint32_t> preLoadedCharacters;
|
||||
//~
|
||||
};
|
||||
|
||||
/**
|
||||
* FontFace
|
||||
*/
|
||||
class FontFace {
|
||||
public:
|
||||
explicit FontFace(Font *font);
|
||||
virtual ~FontFace();
|
||||
FontFace(const FontFace &) = delete;
|
||||
FontFace(FontFace &&) = delete;
|
||||
FontFace &operator=(const FontFace &) = delete;
|
||||
FontFace &operator=(FontFace &&) = delete;
|
||||
|
||||
virtual const FontGlyph *getGlyph(uint32_t code) = 0;
|
||||
virtual float getKerning(uint32_t prevCode, uint32_t nextCode) = 0;
|
||||
|
||||
inline Font *getFont() const { return _font; }
|
||||
inline uint32_t getFontSize() const { return _fontSize; }
|
||||
inline uint32_t getLineHeight() const { return _lineHeight; }
|
||||
inline const ccstd::vector<gfx::Texture *> &getTextures() const { return _textures; }
|
||||
inline gfx::Texture *getTexture(uint32_t page) const { return _textures[page]; }
|
||||
inline uint32_t getTextureWidth() const { return _textureWidth; }
|
||||
inline uint32_t getTextureHeight() const { return _textureHeight; }
|
||||
|
||||
protected:
|
||||
virtual void doInit(const FontFaceInfo &info) = 0;
|
||||
|
||||
Font *_font{nullptr};
|
||||
uint32_t _fontSize{1U};
|
||||
uint32_t _lineHeight{0U};
|
||||
ccstd::unordered_map<uint32_t, FontGlyph> _glyphs;
|
||||
ccstd::unordered_map<KerningPair, float, KerningHash> _kernings;
|
||||
ccstd::vector<gfx::Texture *> _textures;
|
||||
uint32_t _textureWidth{0U};
|
||||
uint32_t _textureHeight{0U};
|
||||
};
|
||||
|
||||
/**
|
||||
* Font
|
||||
*/
|
||||
class Font : public Asset {
|
||||
public:
|
||||
Font(FontType type, const ccstd::string &path);
|
||||
~Font() override;
|
||||
Font(const Font &) = delete;
|
||||
Font(Font &&) = delete;
|
||||
Font &operator=(const Font &) = delete;
|
||||
Font &operator=(Font &&) = delete;
|
||||
|
||||
virtual FontFace *createFace(const FontFaceInfo &info) = 0;
|
||||
|
||||
inline FontType getType() const { return _type; }
|
||||
inline const ccstd::string &getPath() const { return _path; }
|
||||
inline const ccstd::vector<uint8_t> &getData() const { return _data; }
|
||||
inline FontFace *getFace(uint32_t fontSize) { return _faces[fontSize]; }
|
||||
void releaseFaces();
|
||||
|
||||
protected:
|
||||
void load(const ccstd::string &path);
|
||||
|
||||
FontType _type{FontType::INVALID};
|
||||
ccstd::string _path;
|
||||
ccstd::vector<uint8_t> _data;
|
||||
ccstd::unordered_map<uint32_t, FontFace *> _faces;
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
316
cocos/core/assets/FreeTypeFont.cpp
Normal file
316
cocos/core/assets/FreeTypeFont.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
Portions of this software are copyright ? <2022> The FreeType
|
||||
Project (www.freetype.org). All rights reserved.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "FreeTypeFont.h"
|
||||
#include <freetype/ft2build.h>
|
||||
#include FT_FREETYPE_H
|
||||
#include <cstdint>
|
||||
#include "base/Log.h"
|
||||
#include "gfx-base/GFXDevice.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
/**
|
||||
* FTLibrary
|
||||
*/
|
||||
struct FTLibrary {
|
||||
FTLibrary() {
|
||||
FT_Error error = FT_Init_FreeType(&lib);
|
||||
if (error) {
|
||||
CC_LOG_ERROR("FreeType init failed, error code: %d.", error);
|
||||
}
|
||||
}
|
||||
|
||||
~FTLibrary() {
|
||||
if (lib) {
|
||||
FT_Error error = FT_Done_FreeType(lib);
|
||||
if (error) {
|
||||
CC_LOG_ERROR("FreeType exit failed, error code: %d.", error);
|
||||
}
|
||||
|
||||
lib = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FT_Library lib{nullptr};
|
||||
};
|
||||
|
||||
/**
|
||||
* FTFace
|
||||
*/
|
||||
struct FTFace {
|
||||
explicit FTFace(FT_Face f)
|
||||
: face(f) {
|
||||
}
|
||||
|
||||
~FTFace() {
|
||||
if (face) {
|
||||
FT_Done_Face(face);
|
||||
face = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
FT_Face face{nullptr};
|
||||
};
|
||||
|
||||
/**
|
||||
* GlyphAllocator: allocate space for glyph from top to down, from left to right.
|
||||
*/
|
||||
class GlyphAllocator {
|
||||
public:
|
||||
GlyphAllocator(uint32_t maxWidth, uint32_t maxHeight)
|
||||
: _maxWidth(maxWidth), _maxHeight(maxHeight) {}
|
||||
|
||||
inline void reset() {
|
||||
_nextX = 0U;
|
||||
_nextY = 0U;
|
||||
_maxLineHeight = 0U;
|
||||
}
|
||||
|
||||
bool allocate(uint32_t width, uint32_t height, uint32_t &x, uint32_t &y) {
|
||||
// try current line
|
||||
if (_nextX + width <= _maxWidth && _nextY + height <= _maxHeight) {
|
||||
x = _nextX;
|
||||
y = _nextY;
|
||||
|
||||
_nextX += width;
|
||||
_maxLineHeight = std::max(_maxLineHeight, height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// try next line
|
||||
uint32_t nextY = _nextY + _maxLineHeight;
|
||||
if (width <= _maxWidth && nextY + height <= _maxHeight) {
|
||||
x = 0U;
|
||||
y = nextY;
|
||||
|
||||
_nextX = width;
|
||||
_nextY = nextY;
|
||||
_maxLineHeight = height;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
// texture resolution
|
||||
const uint32_t _maxWidth{0U};
|
||||
const uint32_t _maxHeight{0U};
|
||||
|
||||
// next space
|
||||
uint32_t _nextX{0U};
|
||||
uint32_t _nextY{0U};
|
||||
|
||||
// max height of current line
|
||||
uint32_t _maxLineHeight{0U};
|
||||
};
|
||||
|
||||
/**
|
||||
* FreeTypeFontFace
|
||||
*/
|
||||
FTLibrary *FreeTypeFontFace::library = nullptr;
|
||||
FreeTypeFontFace::FreeTypeFontFace(Font *font)
|
||||
: FontFace(font) {
|
||||
if (!library) {
|
||||
library = ccnew FTLibrary();
|
||||
}
|
||||
}
|
||||
|
||||
void FreeTypeFontFace::doInit(const FontFaceInfo &info) {
|
||||
const auto &fontData = _font->getData();
|
||||
if (fontData.empty()) {
|
||||
CC_LOG_ERROR("FreeTypeFontFace doInit failed: empty font data.");
|
||||
return;
|
||||
}
|
||||
|
||||
_fontSize = info.fontSize < MIN_FONT_SIZE ? MIN_FONT_SIZE : (info.fontSize > MAX_FONT_SIZE ? MAX_FONT_SIZE : info.fontSize);
|
||||
_textureWidth = info.textureWidth;
|
||||
_textureHeight = info.textureHeight;
|
||||
_allocator = std::make_unique<GlyphAllocator>(_textureWidth, _textureHeight);
|
||||
|
||||
FT_Face face{nullptr};
|
||||
FT_Error error = FT_New_Memory_Face(library->lib, fontData.data(), static_cast<FT_Long>(fontData.size()), 0, &face);
|
||||
if (error) {
|
||||
CC_LOG_ERROR("FT_New_Memory_Face failed, error code: %d.", error);
|
||||
return;
|
||||
}
|
||||
|
||||
error = FT_Set_Pixel_Sizes(face, 0, _fontSize);
|
||||
if (error) {
|
||||
CC_LOG_ERROR("FT_Set_Pixel_Sizes failed, error code: %d.", error);
|
||||
return;
|
||||
}
|
||||
|
||||
_face = std::make_unique<FTFace>(face);
|
||||
_lineHeight = static_cast<uint32_t>(face->size->metrics.height >> 6);
|
||||
|
||||
for (const auto &code : info.preLoadedCharacters) {
|
||||
loadGlyph(code);
|
||||
}
|
||||
}
|
||||
|
||||
const FontGlyph *FreeTypeFontFace::getGlyph(uint32_t code) {
|
||||
auto iter = _glyphs.find(code);
|
||||
if (iter != _glyphs.end()) {
|
||||
return &iter->second;
|
||||
}
|
||||
|
||||
return loadGlyph(code);
|
||||
}
|
||||
|
||||
float FreeTypeFontFace::getKerning(uint32_t prevCode, uint32_t nextCode) {
|
||||
FT_Face face = _face->face;
|
||||
if (!FT_HAS_KERNING(face)) {
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
const auto &iter = _kernings.find({prevCode, nextCode});
|
||||
if (iter != _kernings.end()) {
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
FT_Vector kerning;
|
||||
FT_UInt prevIndex = FT_Get_Char_Index(face, prevCode);
|
||||
FT_UInt nextIndex = FT_Get_Char_Index(face, nextCode);
|
||||
FT_Error error = FT_Get_Kerning(face, prevIndex, nextIndex, FT_KERNING_DEFAULT, &kerning);
|
||||
|
||||
if (error) {
|
||||
CC_LOG_WARNING("FT_Get_Kerning failed, error code: %d, prevCode: %d, nextCode: %d", error, prevCode, nextCode);
|
||||
return 0.0F;
|
||||
}
|
||||
|
||||
auto result = static_cast<float>(kerning.x >> 6);
|
||||
_kernings[{prevCode, nextCode}] = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const FontGlyph *FreeTypeFontFace::loadGlyph(uint32_t code) {
|
||||
FT_Face face = _face->face;
|
||||
FT_Error error = FT_Load_Char(face, code, FT_LOAD_RENDER);
|
||||
if (error) {
|
||||
CC_LOG_WARNING("FT_Load_Char failed, error code: %d, character: %u.", error, code);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
FontGlyph glyph;
|
||||
glyph.width = face->glyph->bitmap.width;
|
||||
glyph.height = face->glyph->bitmap.rows;
|
||||
glyph.bearingX = face->glyph->bitmap_left;
|
||||
glyph.bearingY = face->glyph->bitmap_top;
|
||||
glyph.advance = static_cast<int32_t>(face->glyph->advance.x >> 6); // advance.x's unit is 1/64 pixels
|
||||
|
||||
uint32_t x = 0U;
|
||||
uint32_t y = 0U;
|
||||
|
||||
if (_textures.empty()) {
|
||||
createTexture(_textureWidth, _textureHeight);
|
||||
}
|
||||
|
||||
if (glyph.width > 0U && glyph.height > 0U) {
|
||||
// try current texture
|
||||
if (!_allocator->allocate(glyph.width + 1, glyph.height + 1, x, y)) {
|
||||
createTexture(_textureWidth, _textureHeight);
|
||||
|
||||
// try new empty texture
|
||||
_allocator->reset();
|
||||
if (!_allocator->allocate(glyph.width + 1, glyph.height + 1, x, y)) {
|
||||
CC_LOG_WARNING("Glyph allocate failed, character: %u.", code);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
auto page = static_cast<uint32_t>(_textures.size() - 1);
|
||||
updateTexture(page, x, y, glyph.width, glyph.height, face->glyph->bitmap.buffer);
|
||||
|
||||
glyph.x = x;
|
||||
glyph.y = y;
|
||||
glyph.page = page;
|
||||
}
|
||||
|
||||
_glyphs[code] = glyph;
|
||||
|
||||
return &_glyphs[code];
|
||||
}
|
||||
|
||||
void FreeTypeFontFace::createTexture(uint32_t width, uint32_t height) {
|
||||
auto *device = gfx::Device::getInstance();
|
||||
auto *texture = device->createTexture({gfx::TextureType::TEX2D,
|
||||
gfx::TextureUsageBit::SAMPLED | gfx::TextureUsageBit::TRANSFER_DST,
|
||||
gfx::Format::R8,
|
||||
width,
|
||||
height});
|
||||
|
||||
_textures.push_back(texture);
|
||||
|
||||
std::vector<uint8_t> empty(width * height, 0);
|
||||
auto page = static_cast<uint32_t>(_textures.size() - 1);
|
||||
updateTexture(page, 0U, 0U, width, height, empty.data());
|
||||
}
|
||||
|
||||
void FreeTypeFontFace::updateTexture(uint32_t page, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const uint8_t *buffer) {
|
||||
auto *texture = getTexture(page);
|
||||
gfx::BufferDataList buffers{buffer};
|
||||
gfx::BufferTextureCopyList regions = {{0U,
|
||||
0U,
|
||||
0U,
|
||||
{static_cast<int32_t>(x), static_cast<int32_t>(y), 0U},
|
||||
{width, height, 1U},
|
||||
{0U, 0U, 1U}}};
|
||||
|
||||
auto *device = gfx::Device::getInstance();
|
||||
device->copyBuffersToTexture(buffers, texture, regions);
|
||||
}
|
||||
|
||||
void FreeTypeFontFace::destroyFreeType() {
|
||||
if (library) {
|
||||
delete library;
|
||||
library = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* FreeTypeFont
|
||||
*/
|
||||
FreeTypeFont::FreeTypeFont(const ccstd::string &path)
|
||||
: Font(FontType::FREETYPE, path) {
|
||||
}
|
||||
|
||||
FontFace *FreeTypeFont::createFace(const FontFaceInfo &info) {
|
||||
auto *face = ccnew FreeTypeFontFace(this);
|
||||
face->doInit(info);
|
||||
|
||||
uint32_t fontSize = face->getFontSize();
|
||||
_faces[fontSize] = face;
|
||||
|
||||
return face;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
85
cocos/core/assets/FreeTypeFont.h
Normal file
85
cocos/core/assets/FreeTypeFont.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
Portions of this software are copyright ? <2022> The FreeType
|
||||
Project (www.freetype.org). All rights reserved.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include "Font.h"
|
||||
#include "base/std/container/string.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
struct FTLibrary;
|
||||
struct FTFace;
|
||||
class GlyphAllocator;
|
||||
|
||||
/**
|
||||
* FreeTypeFontFace
|
||||
*/
|
||||
class FreeTypeFontFace : public FontFace {
|
||||
public:
|
||||
explicit FreeTypeFontFace(Font *font);
|
||||
~FreeTypeFontFace() override = default;
|
||||
FreeTypeFontFace(const FreeTypeFontFace &) = delete;
|
||||
FreeTypeFontFace(FreeTypeFontFace &&) = delete;
|
||||
FreeTypeFontFace &operator=(const FreeTypeFontFace &) = delete;
|
||||
FreeTypeFontFace &operator=(FreeTypeFontFace &&) = delete;
|
||||
|
||||
const FontGlyph *getGlyph(uint32_t code) override;
|
||||
float getKerning(uint32_t prevCode, uint32_t nextCode) override;
|
||||
static void destroyFreeType();
|
||||
|
||||
private:
|
||||
void doInit(const FontFaceInfo &info) override;
|
||||
const FontGlyph *loadGlyph(uint32_t code);
|
||||
void createTexture(uint32_t width, uint32_t height);
|
||||
void updateTexture(uint32_t page, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const uint8_t *buffer);
|
||||
|
||||
std::unique_ptr<GlyphAllocator> _allocator{nullptr};
|
||||
std::unique_ptr<FTFace> _face;
|
||||
static FTLibrary *library;
|
||||
|
||||
friend class FreeTypeFont;
|
||||
};
|
||||
|
||||
/**
|
||||
* FreeTypeFont
|
||||
*/
|
||||
class FreeTypeFont : public Font {
|
||||
public:
|
||||
explicit FreeTypeFont(const ccstd::string &path);
|
||||
~FreeTypeFont() override = default;
|
||||
FreeTypeFont(const FreeTypeFont &) = delete;
|
||||
FreeTypeFont(FreeTypeFont &&) = delete;
|
||||
FreeTypeFont &operator=(const FreeTypeFont &) = delete;
|
||||
FreeTypeFont &operator=(FreeTypeFont &&) = delete;
|
||||
|
||||
FontFace *createFace(const FontFaceInfo &info) override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
137
cocos/core/assets/ImageAsset.cpp
Normal file
137
cocos/core/assets/ImageAsset.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/ImageAsset.h"
|
||||
|
||||
#include "platform/Image.h"
|
||||
|
||||
#include "base/Log.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
ImageAsset::~ImageAsset() {
|
||||
if (_needFreeData && _data) {
|
||||
free(_data);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageAsset::setNativeAsset(const ccstd::any &obj) {
|
||||
if (obj.has_value()) {
|
||||
auto **pImage = const_cast<Image **>(ccstd::any_cast<Image *>(&obj));
|
||||
if (pImage != nullptr) {
|
||||
Image *image = *pImage;
|
||||
image->takeData(&_data);
|
||||
_needFreeData = true;
|
||||
|
||||
_width = image->getWidth();
|
||||
_height = image->getHeight();
|
||||
_format = static_cast<PixelFormat>(image->getRenderFormat());
|
||||
_url = image->getFilePath();
|
||||
_mipmapLevelDataSize = image->getMipmapLevelDataSize();
|
||||
} else {
|
||||
const auto *imageSource = ccstd::any_cast<IMemoryImageSource>(&obj);
|
||||
if (imageSource != nullptr) {
|
||||
_arrayBuffer = imageSource->data;
|
||||
_data = const_cast<uint8_t *>(_arrayBuffer->getData());
|
||||
_width = imageSource->width;
|
||||
_height = imageSource->height;
|
||||
_format = imageSource->format;
|
||||
_mipmapLevelDataSize = imageSource->mipmapLevelDataSize;
|
||||
} else {
|
||||
CC_LOG_WARNING("ImageAsset::setNativeAsset, unknown type!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IntrusivePtr<ImageAsset> ImageAsset::extractMipmap0() {
|
||||
auto *res = new ImageAsset;
|
||||
|
||||
res->_data = nullptr;
|
||||
res->_needFreeData = false;
|
||||
res->_width = _width;
|
||||
res->_height = _height;
|
||||
res->_format = _format;
|
||||
res->_uuid = _uuid;
|
||||
res->_data = _data;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
std::vector<IntrusivePtr<ImageAsset>> ImageAsset::extractMipmaps() {
|
||||
std::vector<IntrusivePtr<ImageAsset>> res{};
|
||||
|
||||
if (!_mipmapLevelDataSize.empty()) {
|
||||
size_t offset = 0UL;
|
||||
auto height = _height;
|
||||
auto width = _width;
|
||||
for (auto mipmapSize : _mipmapLevelDataSize) {
|
||||
auto *mipmap = new ImageAsset;
|
||||
mipmap->_data = _data + offset;
|
||||
mipmap->_needFreeData = false;
|
||||
mipmap->_width = width;
|
||||
mipmap->_height = height;
|
||||
mipmap->_format = _format;
|
||||
mipmap->_uuid = _uuid;
|
||||
|
||||
offset += mipmapSize;
|
||||
width = std::max(width >> 1, 1U);
|
||||
height = std::max(height >> 1, 1U);
|
||||
res.emplace_back(mipmap);
|
||||
}
|
||||
} else {
|
||||
res.emplace_back(this);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const uint8_t *ImageAsset::getData() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
uint32_t ImageAsset::getWidth() const {
|
||||
return _width;
|
||||
}
|
||||
|
||||
uint32_t ImageAsset::getHeight() const {
|
||||
return _height;
|
||||
}
|
||||
|
||||
PixelFormat ImageAsset::getFormat() const {
|
||||
return _format;
|
||||
}
|
||||
|
||||
const std::vector<uint32_t> &ImageAsset::getMipmapLevelDataSize() const {
|
||||
return _mipmapLevelDataSize;
|
||||
}
|
||||
|
||||
bool ImageAsset::isCompressed() const {
|
||||
return (_format >= PixelFormat::RGB_ETC1 && _format <= PixelFormat::RGBA_ASTC_12X12) || (_format >= PixelFormat::RGB_A_PVRTC_2BPPV1 && _format <= PixelFormat::RGBA_ETC1);
|
||||
}
|
||||
|
||||
const ccstd::string &ImageAsset::getUrl() const {
|
||||
return _url;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
138
cocos/core/assets/ImageAsset.h
Normal file
138
cocos/core/assets/ImageAsset.h
Normal file
@@ -0,0 +1,138 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/assets/Asset.h"
|
||||
#include "core/assets/AssetEnum.h"
|
||||
|
||||
#include "core/ArrayBuffer.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Image;
|
||||
|
||||
/**
|
||||
* @en Image source in memory
|
||||
* @zh 内存图像源。
|
||||
*/
|
||||
struct IMemoryImageSource {
|
||||
ArrayBuffer::Ptr data;
|
||||
bool compressed{false};
|
||||
uint32_t width{0};
|
||||
uint32_t height{0};
|
||||
PixelFormat format{PixelFormat::RGBA8888};
|
||||
ccstd::vector<uint32_t> mipmapLevelDataSize;
|
||||
};
|
||||
|
||||
/**
|
||||
* @en Image Asset.
|
||||
* @zh 图像资源。
|
||||
*/
|
||||
class ImageAsset final : public Asset {
|
||||
public:
|
||||
using Super = Asset;
|
||||
|
||||
ImageAsset() = default;
|
||||
~ImageAsset() override;
|
||||
|
||||
//minggo: do not need it in c++.
|
||||
// ccstd::any getNativeAsset() const override { return ccstd::any(_nativeData); }
|
||||
void setNativeAsset(const ccstd::any &obj) override;
|
||||
|
||||
/**
|
||||
* @en Image data.
|
||||
* @zh 此图像资源的图像数据。
|
||||
*/
|
||||
const uint8_t *getData() const;
|
||||
|
||||
/**
|
||||
* @en The pixel width of the image.
|
||||
* @zh 此图像资源的像素宽度。
|
||||
*/
|
||||
uint32_t getWidth() const;
|
||||
|
||||
/**
|
||||
* @en The pixel height of the image.
|
||||
* @zh 此图像资源的像素高度。
|
||||
*/
|
||||
uint32_t getHeight() const;
|
||||
|
||||
/**
|
||||
* @en The pixel format of the image.
|
||||
* @zh 此图像资源的像素格式。
|
||||
*/
|
||||
PixelFormat getFormat() const;
|
||||
|
||||
/**
|
||||
* @en The pixel mipmap level data size of the image.
|
||||
* @zh 此图像资源的mipmap层级大小。
|
||||
*/
|
||||
const ccstd::vector<uint32_t> &getMipmapLevelDataSize() const;
|
||||
|
||||
/**
|
||||
* @en Whether the image is in compressed texture format.
|
||||
* @zh 此图像资源是否为压缩像素格式。
|
||||
*/
|
||||
bool isCompressed() const;
|
||||
|
||||
/**
|
||||
* @en The original source image URL, it could be empty.
|
||||
* @zh 此图像资源的原始图像源的 URL。当原始图像元不是 HTML 文件时可能为空。
|
||||
* @deprecated Please use [[nativeUrl]]
|
||||
*/
|
||||
const ccstd::string &getUrl() const;
|
||||
|
||||
// Functions for TS.
|
||||
inline void setWidth(uint32_t width) { _width = width; }
|
||||
inline void setHeight(uint32_t height) { _height = height; }
|
||||
inline void setFormat(PixelFormat format) { _format = format; }
|
||||
inline void setData(uint8_t *data) { _data = data; }
|
||||
inline void setNeedFreeData(bool v) { _needFreeData = v; }
|
||||
inline void setUrl(const ccstd::string &url) { _url = url; }
|
||||
inline void setMipmapLevelDataSize(const ccstd::vector<uint32_t> &mipmapLevelDataSize) { _mipmapLevelDataSize = mipmapLevelDataSize; }
|
||||
|
||||
// Functions for Utils.
|
||||
IntrusivePtr<ImageAsset> extractMipmap0();
|
||||
std::vector<IntrusivePtr<ImageAsset>> extractMipmaps();
|
||||
|
||||
private:
|
||||
uint8_t *_data{nullptr};
|
||||
|
||||
PixelFormat _format{PixelFormat::RGBA8888};
|
||||
uint32_t _width{0};
|
||||
uint32_t _height{0};
|
||||
|
||||
bool _needFreeData{false}; // Should free data if the data is assigned in C++.
|
||||
|
||||
ArrayBuffer::Ptr _arrayBuffer; //minggo: hold the data from ImageSource.
|
||||
|
||||
ccstd::string _url;
|
||||
|
||||
ccstd::vector<uint32_t> _mipmapLevelDataSize;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(ImageAsset);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
447
cocos/core/assets/Material.cpp
Normal file
447
cocos/core/assets/Material.cpp
Normal file
@@ -0,0 +1,447 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/Material.h"
|
||||
|
||||
#include "base/Utils.h"
|
||||
#include "core/Root.h"
|
||||
#include "core/assets/EffectAsset.h"
|
||||
#include "core/builtin/BuiltinResMgr.h"
|
||||
#include "core/platform/Debug.h"
|
||||
#include "math/Color.h"
|
||||
#include "renderer/pipeline/helper/Utils.h"
|
||||
#include "scene/Pass.h"
|
||||
namespace cc {
|
||||
|
||||
/* static */
|
||||
ccstd::hash_t Material::getHashForMaterial(Material *material) {
|
||||
if (material == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ccstd::hash_t hash = 0U;
|
||||
const auto &passes = *material->_passes;
|
||||
for (const auto &pass : passes) {
|
||||
hash ^= pass->getHash();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
Material::Material() {
|
||||
_passes = std::make_shared<ccstd::vector<IntrusivePtr<scene::Pass>>>();
|
||||
}
|
||||
|
||||
Material::~Material() = default;
|
||||
|
||||
void Material::initialize(const IMaterialInfo &info) {
|
||||
auto &passes = *_passes;
|
||||
if (!passes.empty()) {
|
||||
debug::warnID(12005);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_defines.empty()) {
|
||||
_defines.clear();
|
||||
}
|
||||
if (!_states.empty()) {
|
||||
_states.clear();
|
||||
}
|
||||
if (!_props.empty()) {
|
||||
_props.clear();
|
||||
}
|
||||
|
||||
fillInfo(info);
|
||||
update();
|
||||
}
|
||||
|
||||
void Material::reset(const IMaterialInfo &info) { // to be consistent with other assets
|
||||
initialize(info);
|
||||
}
|
||||
|
||||
bool Material::destroy() {
|
||||
doDestroy();
|
||||
return Super::destroy();
|
||||
}
|
||||
|
||||
void Material::doDestroy() {
|
||||
auto &passes = *_passes;
|
||||
if (!passes.empty()) {
|
||||
for (const auto &pass : passes) {
|
||||
pass->destroy();
|
||||
}
|
||||
}
|
||||
passes.clear();
|
||||
emit<PassesUpdated>();
|
||||
}
|
||||
|
||||
void Material::recompileShaders(const MacroRecord & /*overrides*/, index_t /*passIdx*/) {
|
||||
CC_ABORT();
|
||||
CC_LOG_WARNING("Shaders in material asset '%s' cannot be modified at runtime, please instantiate the material first.", _name.c_str());
|
||||
}
|
||||
|
||||
void Material::overridePipelineStates(const PassOverrides & /*overrides*/, index_t /*passIdx*/) {
|
||||
CC_ABORT();
|
||||
CC_LOG_WARNING("Pipeline states in material asset '%s' cannot be modified at runtime, please instantiate the material first.", _name.c_str());
|
||||
}
|
||||
|
||||
void Material::onLoaded() {
|
||||
update();
|
||||
}
|
||||
|
||||
void Material::resetUniforms(bool clearPasses /* = true */) {
|
||||
const auto &passes = *_passes;
|
||||
_props.resize(passes.size());
|
||||
|
||||
if (!clearPasses) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto &pass : passes) {
|
||||
pass->resetUBOs();
|
||||
pass->resetTextures();
|
||||
}
|
||||
}
|
||||
|
||||
void Material::setProperty(const ccstd::string &name, const MaterialPropertyVariant &val, index_t passIdx /* = CC_INVALID_INDEX */) {
|
||||
const auto &passes = *_passes;
|
||||
bool success = false;
|
||||
if (passIdx == CC_INVALID_INDEX) { // try set property for all applicable passes
|
||||
size_t len = passes.size();
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
const auto &pass = passes[i];
|
||||
if (uploadProperty(pass, name, val)) {
|
||||
_props[pass->getPropertyIndex()][name] = val;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (passIdx >= passes.size()) {
|
||||
CC_LOG_WARNING("illegal pass index: %d.", passIdx);
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &pass = passes[passIdx];
|
||||
if (uploadProperty(pass, name, val)) {
|
||||
_props[pass->getPropertyIndex()][name] = val;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
CC_LOG_WARNING("illegal property name: %s.", name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void Material::setPropertyNull(const ccstd::string &name, index_t passIdx) {
|
||||
MaterialPropertyVariant val;
|
||||
setProperty(name, val, passIdx);
|
||||
}
|
||||
|
||||
#define CC_MATERIAL_SETPROPERTY_IMPL(funcNameSuffix, type) \
|
||||
void Material::setProperty##funcNameSuffix(const ccstd::string &name, type val, index_t passIdx /* = CC_INVALID_INDEX*/) { \
|
||||
setProperty(name, val, passIdx); \
|
||||
}
|
||||
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Float32, float)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Int32, int32_t)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Vec2, const Vec2 &)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Vec3, const Vec3 &)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Vec4, const Vec4 &)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Color, const cc::Color &)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Mat3, const Mat3 &)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Mat4, const Mat4 &)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(Quaternion, const Quaternion &)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(TextureBase, TextureBase *)
|
||||
CC_MATERIAL_SETPROPERTY_IMPL(GFXTexture, gfx::Texture *)
|
||||
|
||||
#undef CC_MATERIAL_SETPROPERTY_IMPL
|
||||
|
||||
#define CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(funcNameSuffix, type) \
|
||||
void Material::setProperty##funcNameSuffix##Array(const ccstd::string &name, const ccstd::vector<type> &val, index_t /*passIdx = CC_INVALID_INDEX*/) { \
|
||||
MaterialPropertyList propertyArr; \
|
||||
propertyArr.reserve(val.size()); \
|
||||
for (const auto &e : val) { \
|
||||
propertyArr.emplace_back(e); \
|
||||
} \
|
||||
setProperty(name, propertyArr); \
|
||||
}
|
||||
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Float32, float)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Int32, int32_t)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Vec2, Vec2)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Vec3, Vec3)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Vec4, Vec4)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Color, Color)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Mat3, Mat3)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Mat4, Mat4)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(Quaternion, Quaternion)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(TextureBase, TextureBase *)
|
||||
CC_MATERIAL_SETPROPERTY_ARRAY_IMPL(GFXTexture, gfx::Texture *)
|
||||
|
||||
#undef CC_MATERIAL_SETPROPERTY_ARRAY_IMPL
|
||||
|
||||
const MaterialPropertyVariant *Material::getProperty(const ccstd::string &name, index_t passIdx) const {
|
||||
if (passIdx == CC_INVALID_INDEX) { // try get property in all possible passes
|
||||
const auto &propsArray = _props;
|
||||
size_t len = propsArray.size();
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
const auto &props = propsArray[i];
|
||||
auto iter = props.find(name);
|
||||
if (iter != props.end()) {
|
||||
return &iter->second;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (passIdx >= _props.size()) {
|
||||
CC_LOG_WARNING("illegal pass index: %d.", passIdx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const auto &passes = *_passes;
|
||||
const auto &props = _props[passes[passIdx]->getPropertyIndex()];
|
||||
auto iter = props.find(name);
|
||||
if (iter != props.end()) {
|
||||
return &iter->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Material::fillInfo(const IMaterialInfo &info) {
|
||||
if (info.technique != ccstd::nullopt) {
|
||||
_techIdx = info.technique.value();
|
||||
}
|
||||
|
||||
if (info.effectAsset != nullptr) {
|
||||
_effectAsset = info.effectAsset;
|
||||
} else if (info.effectName != ccstd::nullopt) {
|
||||
_effectAsset = EffectAsset::get(info.effectName.value());
|
||||
}
|
||||
|
||||
if (info.defines != ccstd::nullopt) {
|
||||
prepareInfo(info.defines.value(), _defines);
|
||||
}
|
||||
if (info.states != ccstd::nullopt) {
|
||||
prepareInfo(info.states.value(), _states);
|
||||
}
|
||||
}
|
||||
|
||||
void Material::copy(const Material *mat, IMaterialInfo *overrides) {
|
||||
if (mat == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
_techIdx = mat->_techIdx;
|
||||
_props.resize(mat->_props.size());
|
||||
for (size_t i = 0, len = mat->_props.size(); i < len; ++i) {
|
||||
_props[i] = mat->_props[i];
|
||||
}
|
||||
_defines.resize(mat->_defines.size());
|
||||
for (size_t i = 0, len = mat->_defines.size(); i < len; ++i) {
|
||||
_defines[i] = mat->_defines[i];
|
||||
}
|
||||
_states.resize(mat->_states.size());
|
||||
for (size_t i = 0, len = mat->_states.size(); i < len; ++i) {
|
||||
_states[i] = mat->_states[i];
|
||||
}
|
||||
_effectAsset = mat->_effectAsset;
|
||||
if (overrides) {
|
||||
fillInfo(*overrides);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void Material::update(bool keepProps /* = true*/) {
|
||||
if (_effectAsset) {
|
||||
*_passes = createPasses();
|
||||
CC_ASSERT(!_effectAsset->_techniques.empty());
|
||||
// handle property values
|
||||
size_t totalPasses = _effectAsset->_techniques[_techIdx].passes.size();
|
||||
_props.resize(totalPasses);
|
||||
if (keepProps) {
|
||||
auto cb = [this](auto *pass, size_t i) {
|
||||
if (i >= _props.size()) {
|
||||
_props.resize(i + 1);
|
||||
}
|
||||
|
||||
auto &props = _props[i];
|
||||
|
||||
if (pass->getPropertyIndex() != CC_INVALID_INDEX) {
|
||||
props = _props[pass->getPropertyIndex()];
|
||||
}
|
||||
|
||||
for (const auto &prop : props) {
|
||||
uploadProperty(pass, prop.first, prop.second);
|
||||
}
|
||||
};
|
||||
|
||||
const auto &passes = *_passes;
|
||||
for (size_t i = 0, len = passes.size(); i < len; ++i) {
|
||||
cb(passes[i].get(), i);
|
||||
}
|
||||
}
|
||||
|
||||
emit<PassesUpdated>();
|
||||
}
|
||||
_hash = Material::getHashForMaterial(this);
|
||||
}
|
||||
|
||||
ccstd::vector<IntrusivePtr<scene::Pass>> Material::createPasses() {
|
||||
ccstd::vector<IntrusivePtr<scene::Pass>> passes;
|
||||
ITechniqueInfo *tech = nullptr;
|
||||
if (_techIdx < _effectAsset->_techniques.size()) {
|
||||
tech = &_effectAsset->_techniques[_techIdx];
|
||||
}
|
||||
|
||||
if (tech == nullptr) {
|
||||
return passes;
|
||||
}
|
||||
|
||||
size_t passNum = tech->passes.size();
|
||||
for (size_t k = 0; k < passNum; ++k) {
|
||||
auto &passInfo = tech->passes[k];
|
||||
index_t propIdx = passInfo.passIndex = static_cast<index_t>(k);
|
||||
|
||||
if (propIdx >= _defines.size()) {
|
||||
_defines.resize(propIdx + 1);
|
||||
}
|
||||
passInfo.defines = _defines[propIdx];
|
||||
auto &defines = passInfo.defines;
|
||||
|
||||
if (propIdx >= _states.size()) {
|
||||
_states.resize(propIdx + 1);
|
||||
}
|
||||
passInfo.stateOverrides = _states[propIdx];
|
||||
|
||||
if (passInfo.propertyIndex.has_value()) {
|
||||
utils::mergeToMap(defines, _defines[passInfo.propertyIndex.value()]);
|
||||
}
|
||||
|
||||
if (passInfo.embeddedMacros.has_value()) {
|
||||
utils::mergeToMap(defines, passInfo.embeddedMacros.value());
|
||||
}
|
||||
|
||||
if (passInfo.switch_.has_value() && defines.find(passInfo.switch_.value()) == defines.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto *pass = ccnew scene::Pass(Root::getInstance());
|
||||
pass->initialize(passInfo);
|
||||
passes.emplace_back(pass);
|
||||
}
|
||||
return passes;
|
||||
}
|
||||
|
||||
bool Material::uploadProperty(scene::Pass *pass, const ccstd::string &name, const MaterialPropertyVariant &val) {
|
||||
uint32_t handle = pass->getHandle(name);
|
||||
if (!handle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto type = scene::Pass::getTypeFromHandle(handle);
|
||||
if (type < gfx::Type::SAMPLER1D) {
|
||||
if (val.index() == MATERIAL_PROPERTY_INDEX_LIST) {
|
||||
pass->setUniformArray(handle, ccstd::get<MaterialPropertyList>(val));
|
||||
} else if (val.index() == MATERIAL_PROPERTY_INDEX_SINGLE) {
|
||||
const auto &passProps = pass->getProperties();
|
||||
auto iter = passProps.find(name);
|
||||
if (iter != passProps.end() && iter->second.linear.has_value()) {
|
||||
CC_ASSERT(ccstd::holds_alternative<MaterialProperty>(val));
|
||||
const auto &prop = ccstd::get<MaterialProperty>(val);
|
||||
Vec4 srgb;
|
||||
if (ccstd::holds_alternative<cc::Color>(prop)) {
|
||||
srgb = ccstd::get<cc::Color>(prop).toVec4();
|
||||
} else if (ccstd::holds_alternative<Vec4>(prop)) {
|
||||
srgb = ccstd::get<Vec4>(prop);
|
||||
} else {
|
||||
CC_ABORT();
|
||||
}
|
||||
|
||||
Vec4 linear;
|
||||
pipeline::srgbToLinear(&linear, srgb);
|
||||
linear.w = srgb.w;
|
||||
pass->setUniform(handle, linear);
|
||||
} else {
|
||||
pass->setUniform(handle, ccstd::get<MaterialProperty>(val));
|
||||
}
|
||||
} else {
|
||||
pass->resetUniform(name);
|
||||
}
|
||||
} else if (val.index() == MATERIAL_PROPERTY_INDEX_LIST) {
|
||||
const auto &textureArray = ccstd::get<MaterialPropertyList>(val);
|
||||
for (size_t i = 0; i < textureArray.size(); i++) {
|
||||
bindTexture(pass, handle, textureArray[i], static_cast<index_t>(i));
|
||||
}
|
||||
} else if (val.index() == MATERIAL_PROPERTY_INDEX_SINGLE) {
|
||||
bindTexture(pass, handle, ccstd::get<MaterialProperty>(val));
|
||||
} else {
|
||||
pass->resetTexture(name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Material::bindTexture(scene::Pass *pass, uint32_t handle, const MaterialProperty &val, uint32_t index) {
|
||||
if (pass == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t binding = scene::Pass::getBindingFromHandle(handle);
|
||||
if (const auto *pTexture = ccstd::get_if<IntrusivePtr<gfx::Texture>>(&val)) {
|
||||
pass->bindTexture(binding, const_cast<gfx::Texture *>(pTexture->get()), index);
|
||||
} else if (const auto *pTextureBase = ccstd::get_if<IntrusivePtr<TextureBase>>(&val)) {
|
||||
auto *textureBase = pTextureBase->get();
|
||||
gfx::Texture *texture = nullptr;
|
||||
if (textureBase != nullptr) {
|
||||
texture = textureBase->getGFXTexture();
|
||||
}
|
||||
|
||||
if (texture == nullptr) {
|
||||
CC_LOG_WARNING("Material(%p, %s)::bindTexture failed, texture is nullptr", this, _uuid.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (texture->getWidth() == 0 || texture->getHeight() == 0) {
|
||||
CC_LOG_WARNING("Material(%p, %s)::bindTexture failed, texture size is 0", this, _uuid.c_str());
|
||||
return;
|
||||
}
|
||||
pass->bindTexture(binding, texture, index);
|
||||
pass->bindSampler(binding, textureBase->getGFXSampler(), index);
|
||||
}
|
||||
}
|
||||
|
||||
void Material::initDefault(const ccstd::optional<ccstd::string> &uuid) {
|
||||
Super::initDefault(uuid);
|
||||
MacroRecord defines{{"USE_COLOR", true}};
|
||||
IMaterialInfo info;
|
||||
info.effectName = ccstd::string{"builtin-unlit"};
|
||||
info.defines = IMaterialInfo::DefinesType{defines};
|
||||
initialize(info);
|
||||
setProperty("mainColor", Color{0xFF, 0x00, 0xFF, 0xFF});
|
||||
}
|
||||
|
||||
bool Material::validate() const {
|
||||
return _effectAsset != nullptr && !_effectAsset->isDefault() && !_passes->empty();
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
361
cocos/core/assets/Material.h
Normal file
361
cocos/core/assets/Material.h
Normal file
@@ -0,0 +1,361 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Ptr.h"
|
||||
#include "base/std/container/string.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
#include "base/std/optional.h"
|
||||
#include "base/std/variant.h"
|
||||
#include "core/assets/EffectAsset.h"
|
||||
#include "core/event/Event.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
// class RenderableComponent;
|
||||
|
||||
namespace scene {
|
||||
class Pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en The basic infos for material initialization.
|
||||
* @zh 用来初始化材质的基本信息。
|
||||
*/
|
||||
struct IMaterialInfo {
|
||||
/**
|
||||
* @en The EffectAsset to use. Must provide if `effectName` is not specified.
|
||||
* @zh
|
||||
* 这个材质将使用的 EffectAsset,直接提供资源引用,和 `effectName` 至少要指定一个。
|
||||
*/
|
||||
EffectAsset *effectAsset{nullptr};
|
||||
/**
|
||||
* @en
|
||||
* The name of the EffectAsset to use. Must provide if `effectAsset` is not specified.
|
||||
* @zh
|
||||
* 这个材质将使用的 EffectAsset,通过 effect 名指定,和 `effectAsset` 至少要指定一个。
|
||||
*/
|
||||
ccstd::optional<ccstd::string> effectName;
|
||||
/**
|
||||
* @en
|
||||
* The index of the technique to use.
|
||||
* @zh
|
||||
* 这个材质将使用第几个 technique,默认为 0。
|
||||
*/
|
||||
ccstd::optional<uint32_t> technique;
|
||||
|
||||
using DefinesType = ccstd::variant<ccstd::monostate, MacroRecord, ccstd::vector<MacroRecord>>;
|
||||
/**
|
||||
* @en
|
||||
* The shader macro definitions. Default to 0 or the specified value in [[EffectAsset]].
|
||||
* @zh
|
||||
* 这个材质定义的预处理宏,默认全为 0,或 [[EffectAsset]] 中的指定值。
|
||||
*/
|
||||
ccstd::optional<DefinesType> defines;
|
||||
|
||||
using PassOverridesType = ccstd::variant<ccstd::monostate, PassOverrides, ccstd::vector<PassOverrides>>;
|
||||
/**
|
||||
* @en
|
||||
* The override values on top of the pipeline states specified in [[EffectAsset]].
|
||||
* @zh
|
||||
* 这个材质的自定义管线状态,将覆盖 effect 中的属性。<br>
|
||||
* 注意在可能的情况下请尽量少的自定义管线状态,以减小对渲染效率的影响。
|
||||
*/
|
||||
ccstd::optional<PassOverridesType> states;
|
||||
};
|
||||
|
||||
class Material : public Asset {
|
||||
IMPL_EVENT_TARGET(Material)
|
||||
DECLARE_TARGET_EVENT_BEGIN(Material)
|
||||
TARGET_EVENT_ARG0(PassesUpdated)
|
||||
DECLARE_TARGET_EVENT_END()
|
||||
public:
|
||||
using Super = Asset;
|
||||
/**
|
||||
* @en Get hash for a material
|
||||
* @zh 获取一个材质的哈希值
|
||||
* @param material
|
||||
*/
|
||||
static ccstd::hash_t getHashForMaterial(Material *material);
|
||||
|
||||
Material();
|
||||
~Material() override;
|
||||
|
||||
/**
|
||||
* @en Initialize this material with the given information.
|
||||
* @zh 根据所给信息初始化这个材质,初始化正常结束后材质即可立即用于渲染。
|
||||
* @param info Material description info.
|
||||
*/
|
||||
void initialize(const IMaterialInfo &info);
|
||||
void reset(const IMaterialInfo &info);
|
||||
|
||||
void initDefault(const ccstd::optional<ccstd::string> &uuid) override;
|
||||
bool validate() const override;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Destroy the material definitively.<br>
|
||||
* Cannot re-initialize after destroy.<br>
|
||||
* Modifications on active materials can be acheived by<br>
|
||||
* creating a new Material, invoke the `copy` function<br>
|
||||
* with the desired overrides, and assigning it to the target components.
|
||||
* @zh
|
||||
* 彻底销毁材质,注意销毁后无法重新初始化。<br>
|
||||
* 如需修改现有材质,请创建一个新材质,<br>
|
||||
* 调用 copy 函数传入需要的 overrides 并赋给目标组件。
|
||||
*/
|
||||
bool destroy() override;
|
||||
|
||||
/**
|
||||
* @en Recompile the shader with the specified macro overrides. Allowed only on material instances.
|
||||
* @zh 使用指定预处理宏重新编译当前 pass(数组)中的 shader。只允许对材质实例执行。
|
||||
* @param overrides The shader macro override values.
|
||||
* @param passIdx The pass to apply to. Will apply to all passes if not specified.
|
||||
*/
|
||||
virtual void recompileShaders(const MacroRecord &overrides) {
|
||||
Material::recompileShaders(overrides, CC_INVALID_INDEX);
|
||||
}
|
||||
virtual void recompileShaders(const MacroRecord &overrides, index_t passIdx);
|
||||
|
||||
/**
|
||||
* @en Override the passes with the specified pipeline states. Allowed only on material instances.
|
||||
* @zh 使用指定管线状态重载当前的 pass(数组)。只允许对材质实例执行。
|
||||
* @param overrides The pipeline state override values.
|
||||
* @param passIdx The pass to apply to. Will apply to all passes if not specified.
|
||||
*/
|
||||
virtual void overridePipelineStates(const PassOverrides &overrides) {
|
||||
Material::overridePipelineStates(overrides, CC_INVALID_INDEX);
|
||||
}
|
||||
virtual void overridePipelineStates(const PassOverrides &overrides, index_t passIdx);
|
||||
|
||||
/**
|
||||
* @en Callback function after material is loaded in [[Loader]]. Initialize the resources automatically.
|
||||
* @zh 通过 [[Loader]] 加载完成时的回调,将自动初始化材质资源。
|
||||
*/
|
||||
void onLoaded() override;
|
||||
|
||||
/**
|
||||
* @en Reset all the uniforms to the default value specified in [[EffectAsset]].
|
||||
* @zh 重置材质的所有 uniform 参数数据为 [[EffectAsset]] 中的默认初始值。
|
||||
* @param clearPasses Will the rendering data be cleared too?
|
||||
*/
|
||||
void resetUniforms(bool clearPasses = true);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Convenient property setter provided for quick material setup.<br>
|
||||
* [[Pass.setUniform]] should be used instead if you need to do per-frame uniform update.
|
||||
* @zh
|
||||
* 设置材质 uniform 参数的统一入口。<br>
|
||||
* 注意如果需要每帧更新 uniform,建议使用 [[Pass.setUniform]] 以获得更好的性能。
|
||||
* @param name The target uniform name.
|
||||
* @param val The target value.
|
||||
* @param passIdx The pass to apply to. Will apply to all passes if not specified.
|
||||
*/
|
||||
void setProperty(const ccstd::string &name, const MaterialPropertyVariant &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
|
||||
void setPropertyNull(const ccstd::string &name, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyFloat32(const ccstd::string &name, float val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyInt32(const ccstd::string &name, int32_t val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyVec2(const ccstd::string &name, const Vec2 &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyVec3(const ccstd::string &name, const Vec3 &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyVec4(const ccstd::string &name, const Vec4 &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyColor(const ccstd::string &name, const Color &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyMat3(const ccstd::string &name, const Mat3 &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyMat4(const ccstd::string &name, const Mat4 &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyQuaternion(const ccstd::string &name, const Quaternion &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyTextureBase(const ccstd::string &name, TextureBase *val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyGFXTexture(const ccstd::string &name, gfx::Texture *val, index_t passIdx = CC_INVALID_INDEX);
|
||||
|
||||
void setPropertyFloat32Array(const ccstd::string &name, const ccstd::vector<float> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyInt32Array(const ccstd::string &name, const ccstd::vector<int32_t> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyVec2Array(const ccstd::string &name, const ccstd::vector<Vec2> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyVec3Array(const ccstd::string &name, const ccstd::vector<Vec3> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyVec4Array(const ccstd::string &name, const ccstd::vector<Vec4> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyColorArray(const ccstd::string &name, const ccstd::vector<cc::Color> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyMat3Array(const ccstd::string &name, const ccstd::vector<Mat3> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyMat4Array(const ccstd::string &name, const ccstd::vector<Mat4> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyQuaternionArray(const ccstd::string &name, const ccstd::vector<Quaternion> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyTextureBaseArray(const ccstd::string &name, const ccstd::vector<TextureBase *> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
void setPropertyGFXTextureArray(const ccstd::string &name, const ccstd::vector<gfx::Texture *> &val, index_t passIdx = CC_INVALID_INDEX);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Get the specified uniform value for this material.<br>
|
||||
* Note that only uniforms set through [[Material.setProperty]] can be acquired here.<br>
|
||||
* For the complete rendering data, use [[Pass.getUniform]] instead.
|
||||
* @zh
|
||||
* 获取当前材质的指定 uniform 参数的值。<br>
|
||||
* 注意只有通过 [[Material.setProperty]] 函数设置的参数才能从此函数取出,<br>
|
||||
* 如需取出完整的渲染数据,请使用 [[Pass.getUniform]]。
|
||||
* @param name The property or uniform name.
|
||||
* @param passIdx The target pass index. If not specified, return the first found value in all passes.
|
||||
*/
|
||||
const MaterialPropertyVariant *getProperty(const ccstd::string &name, index_t passIdx = CC_INVALID_INDEX) const;
|
||||
|
||||
/**
|
||||
* @en Copy the target material, with optional overrides.
|
||||
* @zh 复制目标材质到当前实例,允许提供重载信息。。
|
||||
* @param mat The material to be copied.
|
||||
* @param overrides The overriding states on top of the original material.
|
||||
*/
|
||||
void copy(const Material *mat, IMaterialInfo *overrides = nullptr);
|
||||
|
||||
void fillInfo(const IMaterialInfo &info);
|
||||
|
||||
// For deserialization, we need to make the following properties public
|
||||
/* @type(EffectAsset) */
|
||||
IntrusivePtr<EffectAsset> _effectAsset;
|
||||
|
||||
/* @serializable */
|
||||
uint32_t _techIdx{0};
|
||||
|
||||
/* @serializable */
|
||||
ccstd::vector<MacroRecord> _defines;
|
||||
|
||||
/* @serializable */
|
||||
ccstd::vector<PassOverrides> _states;
|
||||
|
||||
/* @serializable */
|
||||
ccstd::vector<ccstd::unordered_map<ccstd::string, MaterialPropertyVariant>> _props;
|
||||
//
|
||||
|
||||
protected:
|
||||
std::shared_ptr<ccstd::vector<IntrusivePtr<scene::Pass>>> _passes;
|
||||
|
||||
ccstd::hash_t _hash{0U};
|
||||
|
||||
public:
|
||||
/**
|
||||
* @en Set current [[EffectAsset]].
|
||||
* @zh 设置使用的 [[EffectAsset]] 资源。
|
||||
*/
|
||||
inline void setEffectAsset(EffectAsset *val) {
|
||||
_effectAsset = val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en The current [[EffectAsset]].
|
||||
* @zh 当前使用的 [[EffectAsset]] 资源。
|
||||
*/
|
||||
inline EffectAsset *getEffectAsset() const {
|
||||
return _effectAsset.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Name of the current [[EffectAsset]].
|
||||
* @zh 当前使用的 [[EffectAsset]] 资源名。
|
||||
*/
|
||||
inline ccstd::string getEffectName() const {
|
||||
return _effectAsset ? _effectAsset->getName() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @en The current technique index.
|
||||
* @zh 当前的 technique 索引。
|
||||
*/
|
||||
inline uint32_t getTechniqueIndex() const {
|
||||
return _techIdx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en The passes defined in this material.
|
||||
* @zh 当前正在使用的 pass 数组。
|
||||
*/
|
||||
std::shared_ptr<ccstd::vector<IntrusivePtr<scene::Pass>>> &getPasses() {
|
||||
return _passes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en The hash value of this material.
|
||||
* @zh 材质的 hash。
|
||||
*/
|
||||
inline ccstd::hash_t getHash() const {
|
||||
return _hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en The parent material
|
||||
* @zh 父材质
|
||||
*/
|
||||
virtual Material *getParent() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en The owner render component
|
||||
* @zh 该材质所归属的渲染组件
|
||||
*/
|
||||
// virtual RenderableComponent *getOwner() const {
|
||||
// return nullptr;
|
||||
// }
|
||||
|
||||
protected:
|
||||
void update(bool keepProps = true);
|
||||
bool uploadProperty(scene::Pass *pass, const ccstd::string &name, const MaterialPropertyVariant &val);
|
||||
void bindTexture(scene::Pass *pass, uint32_t handle, const MaterialProperty &val, uint32_t index = 0);
|
||||
|
||||
template <typename T1, typename T2>
|
||||
void prepareInfo(const T1 &patch, ccstd::vector<T2> &cur) {
|
||||
auto *pOneElement = ccstd::get_if<T2>(&patch);
|
||||
if (pOneElement != nullptr) {
|
||||
size_t len = _effectAsset != nullptr ? _effectAsset->_techniques[_techIdx].passes.size() : 1;
|
||||
|
||||
ccstd::vector<T2> patchArray;
|
||||
patchArray.reserve(len);
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
patchArray.emplace_back(*pOneElement);
|
||||
}
|
||||
|
||||
cur.resize(patchArray.size());
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
cur[i] = patchArray[i];
|
||||
}
|
||||
} else {
|
||||
auto *pPatchArray = ccstd::get_if<ccstd::vector<T2>>(&patch);
|
||||
if (pPatchArray != nullptr) {
|
||||
const auto &patchArray = *pPatchArray;
|
||||
size_t len = patchArray.size();
|
||||
cur.resize(len);
|
||||
|
||||
for (size_t i = 0; i < len; ++i) {
|
||||
cur[i] = patchArray[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void doDestroy();
|
||||
|
||||
virtual ccstd::vector<IntrusivePtr<scene::Pass>> createPasses();
|
||||
|
||||
private:
|
||||
friend class MaterialDeserializer;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(Material);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
175
cocos/core/assets/RenderTexture.cpp
Normal file
175
cocos/core/assets/RenderTexture.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/RenderTexture.h"
|
||||
#include "core/Root.h"
|
||||
#include "core/platform/Debug.h"
|
||||
#include "core/utils/IDGenerator.h"
|
||||
#include "renderer/gfx-base/GFXDef-common.h"
|
||||
#include "scene/RenderWindow.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
gfx::RenderPassInfo getDefaultRenderPassInfo(gfx::Device *device) {
|
||||
gfx::RenderPassInfo info;
|
||||
info.colorAttachments.push_back({
|
||||
gfx::Format::RGBA8,
|
||||
gfx::SampleCount::X1,
|
||||
gfx::LoadOp::CLEAR,
|
||||
gfx::StoreOp::STORE,
|
||||
device->getGeneralBarrier({
|
||||
gfx::AccessFlagBit::FRAGMENT_SHADER_READ_TEXTURE,
|
||||
gfx::AccessFlagBit::FRAGMENT_SHADER_READ_TEXTURE,
|
||||
}),
|
||||
});
|
||||
info.depthStencilAttachment.format = gfx::Format::DEPTH_STENCIL;
|
||||
return info;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
RenderTexture::RenderTexture() = default;
|
||||
RenderTexture::~RenderTexture() = default;
|
||||
|
||||
void RenderTexture::initialize(const IRenderTextureCreateInfo &info) {
|
||||
_name = info.name.has_value() ? info.name.value() : "";
|
||||
_width = info.width;
|
||||
_height = info.height;
|
||||
initWindow(info);
|
||||
}
|
||||
|
||||
void RenderTexture::reset(const IRenderTextureCreateInfo &info) {
|
||||
initialize(info);
|
||||
}
|
||||
|
||||
bool RenderTexture::destroy() {
|
||||
if (_window != nullptr) {
|
||||
Root::getInstance()->destroyWindow(_window);
|
||||
_window = nullptr;
|
||||
}
|
||||
return Super::destroy();
|
||||
}
|
||||
|
||||
void RenderTexture::resize(uint32_t width, uint32_t height) {
|
||||
_width = std::floor(clampf(static_cast<float>(width), 1.F, 2048.F));
|
||||
_height = std::floor(clampf(static_cast<float>(height), 1.F, 2048.F));
|
||||
if (_window != nullptr) {
|
||||
_window->resize(_width, _height);
|
||||
}
|
||||
// emit(ccstd::string("resize"), _window); //TODO(xwx): not inherit form Eventify in Asset base class
|
||||
}
|
||||
|
||||
gfx::Texture *RenderTexture::getGFXTexture() const {
|
||||
return _window ? _window->getFramebuffer()->getColorTextures()[0] : nullptr;
|
||||
}
|
||||
|
||||
void RenderTexture::onLoaded() {
|
||||
initWindow();
|
||||
}
|
||||
|
||||
void RenderTexture::initWindow() {
|
||||
auto *device{Root::getInstance()->getDevice()};
|
||||
|
||||
cc::scene::IRenderWindowInfo windowInfo;
|
||||
windowInfo.title = _name;
|
||||
windowInfo.width = _width;
|
||||
windowInfo.height = _height;
|
||||
windowInfo.renderPassInfo = getDefaultRenderPassInfo(device);
|
||||
|
||||
if (_window != nullptr) {
|
||||
_window->destroy();
|
||||
_window->initialize(device, windowInfo);
|
||||
} else {
|
||||
_window = Root::getInstance()->createWindow(windowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTexture::initWindow(const IRenderTextureCreateInfo &info) {
|
||||
auto *device{Root::getInstance()->getDevice()};
|
||||
|
||||
cc::scene::IRenderWindowInfo windowInfo;
|
||||
windowInfo.title = _name;
|
||||
windowInfo.width = _width;
|
||||
windowInfo.height = _height;
|
||||
if (info.passInfo.has_value()) {
|
||||
windowInfo.renderPassInfo = info.passInfo.value();
|
||||
} else {
|
||||
windowInfo.renderPassInfo = getDefaultRenderPassInfo(device);
|
||||
}
|
||||
|
||||
if (info.externalResLow.has_value()) {
|
||||
windowInfo.externalResLow = info.externalResLow.value();
|
||||
}
|
||||
|
||||
if (info.externalResHigh.has_value()) {
|
||||
windowInfo.externalResHigh = info.externalResHigh.value();
|
||||
}
|
||||
|
||||
if (info.externalFlag.has_value()) {
|
||||
windowInfo.externalFlag = info.externalFlag.value();
|
||||
}
|
||||
|
||||
if (_window != nullptr) {
|
||||
_window->destroy();
|
||||
_window->initialize(device, windowInfo);
|
||||
} else {
|
||||
_window = Root::getInstance()->createWindow(windowInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void RenderTexture::initDefault(const ccstd::optional<ccstd::string> &uuid) {
|
||||
Super::initDefault(uuid);
|
||||
_width = 1;
|
||||
_height = 1;
|
||||
initWindow();
|
||||
}
|
||||
|
||||
bool RenderTexture::validate() const {
|
||||
return _width >= 1 && _width <= 2048 && _height >= 1 && _height <= 2048;
|
||||
}
|
||||
|
||||
ccstd::vector<uint8_t> RenderTexture::readPixels(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const {
|
||||
auto *gfxTexture = getGFXTexture();
|
||||
if (!gfxTexture) {
|
||||
debug::errorID(7606);
|
||||
return {};
|
||||
}
|
||||
|
||||
auto *gfxDevice = getGFXDevice();
|
||||
|
||||
gfx::BufferTextureCopy region0{};
|
||||
region0.texOffset.x = static_cast<int32_t>(x);
|
||||
region0.texOffset.y = static_cast<int32_t>(y);
|
||||
region0.texExtent.width = width;
|
||||
region0.texExtent.height = height;
|
||||
|
||||
ccstd::vector<uint8_t> buffer;
|
||||
buffer.resize(width * height * 4);
|
||||
uint8_t *pBuffer = buffer.data();
|
||||
gfxDevice->copyTextureToBuffers(gfxTexture, &pBuffer, ®ion0, 1);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
123
cocos/core/assets/RenderTexture.h
Normal file
123
cocos/core/assets/RenderTexture.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/assets/TextureBase.h"
|
||||
#include "renderer/gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
struct IRenderTextureCreateInfo {
|
||||
ccstd::optional<ccstd::string> name;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
ccstd::optional<gfx::RenderPassInfo> passInfo;
|
||||
ccstd::optional<uint32_t> externalResLow; // for vulkan vkImage/opengl es texture created from external
|
||||
ccstd::optional<uint32_t> externalResHigh; // for vulkan vkImage created from external
|
||||
ccstd::optional<gfx::TextureFlags> externalFlag; // external texture type normal or oes
|
||||
};
|
||||
namespace scene {
|
||||
class RenderWindow;
|
||||
}
|
||||
|
||||
namespace gfx {
|
||||
class Texture;
|
||||
class Sampler;
|
||||
} // namespace gfx
|
||||
|
||||
/**
|
||||
* @en Render texture is a render target for [[Camera]] or [[Canvas]] component,
|
||||
* the render pipeline will use its [[RenderWindow]] as the target of the rendering process.
|
||||
* @zh 渲染贴图是 [[Camera]] 或 [[Canvas]] 组件的渲染目标对象,渲染管线会使用它的 [[RenderWindow]] 作为渲染的目标窗口。
|
||||
*/
|
||||
class RenderTexture final : public TextureBase {
|
||||
public:
|
||||
using Super = TextureBase;
|
||||
|
||||
RenderTexture();
|
||||
~RenderTexture() override;
|
||||
|
||||
/**
|
||||
* @en The render window for the render pipeline, it's created internally and cannot be modified.
|
||||
* @zh 渲染管线所使用的渲染窗口,内部逻辑创建,无法被修改。
|
||||
*/
|
||||
inline scene::RenderWindow *getWindow() const { return _window; }
|
||||
|
||||
void initialize(const IRenderTextureCreateInfo &info);
|
||||
void reset(const IRenderTextureCreateInfo &info); // to be consistent with other assets
|
||||
|
||||
bool destroy() override;
|
||||
|
||||
/**
|
||||
* @en Resize the render texture
|
||||
* @zh 修改渲染贴图的尺寸
|
||||
* @param width The pixel width, the range is from 1 to 2048
|
||||
* @param height The pixel height, the range is from 1 to 2048
|
||||
*/
|
||||
void resize(uint32_t width, uint32_t height);
|
||||
|
||||
// TODO(minggo): migration with TextureBase data
|
||||
// @ts-expect-error Hack
|
||||
// get _serialize () { return null; }
|
||||
// @ts-expect-error Hack
|
||||
// get _deserialize () { return null; }
|
||||
|
||||
// To be compatible with material property interface
|
||||
/**
|
||||
* @en Gets the related [[Texture]] resource, it's also the color attachment for the render window
|
||||
* @zh 获取渲染贴图的 GFX 资源,同时也是渲染窗口所指向的颜色缓冲贴图资源
|
||||
*/
|
||||
gfx::Texture *getGFXTexture() const override;
|
||||
|
||||
void onLoaded() override;
|
||||
|
||||
void initWindow();
|
||||
void initWindow(const IRenderTextureCreateInfo &info);
|
||||
|
||||
void initDefault(const ccstd::optional<ccstd::string> &uuid) override;
|
||||
|
||||
bool validate() const override;
|
||||
|
||||
/**
|
||||
* @en Read pixel buffer from render texture
|
||||
* @param x The location on x axis
|
||||
* @param y The location on y axis
|
||||
* @param width The pixel width
|
||||
* @param height The pixel height
|
||||
* @zh 从 render texture 读取像素数据
|
||||
* @param x 起始位置X轴坐标
|
||||
* @param y 起始位置Y轴坐标
|
||||
* @param width 像素宽度
|
||||
* @param height 像素高度
|
||||
*/
|
||||
ccstd::vector<uint8_t> readPixels(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const;
|
||||
|
||||
private:
|
||||
scene::RenderWindow *_window{nullptr};
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(RenderTexture);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
380
cocos/core/assets/RenderingSubMesh.cpp
Normal file
380
cocos/core/assets/RenderingSubMesh.cpp
Normal file
@@ -0,0 +1,380 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/RenderingSubMesh.h"
|
||||
#include <cstdint>
|
||||
#include "3d/assets/Mesh.h"
|
||||
#include "3d/misc/Buffer.h"
|
||||
#include "core/DataView.h"
|
||||
#include "core/TypedArray.h"
|
||||
#include "math/Utils.h"
|
||||
#include "math/Vec3.h"
|
||||
#include "renderer/gfx-base/GFXBuffer.h"
|
||||
#include "renderer/gfx-base/GFXDevice.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
RenderingSubMesh::RenderingSubMesh(const gfx::BufferList &vertexBuffers,
|
||||
const gfx::AttributeList &attributes,
|
||||
gfx::PrimitiveMode primitiveMode)
|
||||
: RenderingSubMesh(vertexBuffers, attributes, primitiveMode, nullptr, nullptr, true) {
|
||||
}
|
||||
|
||||
RenderingSubMesh::RenderingSubMesh(const gfx::BufferList &vertexBuffers,
|
||||
const gfx::AttributeList &attributes,
|
||||
gfx::PrimitiveMode primitiveMode,
|
||||
gfx::Buffer *indexBuffer)
|
||||
: RenderingSubMesh(vertexBuffers, attributes, primitiveMode, indexBuffer, nullptr, true) {
|
||||
}
|
||||
|
||||
RenderingSubMesh::RenderingSubMesh(const gfx::BufferList &vertexBuffers,
|
||||
const gfx::AttributeList &attributes,
|
||||
gfx::PrimitiveMode primitiveMode,
|
||||
gfx::Buffer *indexBuffer,
|
||||
gfx::Buffer *indirectBuffer)
|
||||
: RenderingSubMesh(vertexBuffers, attributes, primitiveMode, indexBuffer, indirectBuffer, true) {
|
||||
}
|
||||
|
||||
RenderingSubMesh::RenderingSubMesh(const gfx::BufferList &vertexBuffers,
|
||||
const gfx::AttributeList &attributes,
|
||||
gfx::PrimitiveMode primitiveMode,
|
||||
gfx::Buffer *indexBuffer,
|
||||
gfx::Buffer *indirectBuffer,
|
||||
bool isOwnerOfIndexBuffer)
|
||||
: _vertexBuffers(vertexBuffers),
|
||||
_attributes(attributes),
|
||||
_primitiveMode(primitiveMode),
|
||||
_indexBuffer(indexBuffer),
|
||||
_indirectBuffer(indirectBuffer),
|
||||
_isOwnerOfIndexBuffer(isOwnerOfIndexBuffer) {
|
||||
_iaInfo.attributes = attributes;
|
||||
_iaInfo.vertexBuffers = vertexBuffers;
|
||||
_iaInfo.indexBuffer = indexBuffer;
|
||||
_iaInfo.indirectBuffer = indirectBuffer;
|
||||
}
|
||||
|
||||
RenderingSubMesh::~RenderingSubMesh() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
const IGeometricInfo &RenderingSubMesh::getGeometricInfo() {
|
||||
if (_geometricInfo.has_value()) {
|
||||
return _geometricInfo.value();
|
||||
}
|
||||
// NOLINTNEXTLINE
|
||||
static const IGeometricInfo EMPTY_GEOMETRIC_INFO;
|
||||
if (_mesh == nullptr) {
|
||||
return EMPTY_GEOMETRIC_INFO;
|
||||
}
|
||||
|
||||
if (!_subMeshIdx.has_value()) {
|
||||
return EMPTY_GEOMETRIC_INFO;
|
||||
}
|
||||
|
||||
auto iter = std::find_if(_attributes.cbegin(), _attributes.cend(), [](const gfx::Attribute &element) -> bool {
|
||||
return element.name == gfx::ATTR_NAME_POSITION;
|
||||
});
|
||||
if (iter == _attributes.end()) {
|
||||
return EMPTY_GEOMETRIC_INFO;
|
||||
}
|
||||
|
||||
const auto &attri = *iter;
|
||||
const uint32_t count = gfx::GFX_FORMAT_INFOS[static_cast<uint32_t>(attri.format)].count;
|
||||
|
||||
auto index = static_cast<index_t>(_subMeshIdx.value());
|
||||
const auto &positionsVar = _mesh->readAttribute(index, gfx::ATTR_NAME_POSITION);
|
||||
|
||||
Float32Array const *pPositions = nullptr;
|
||||
switch (attri.format) {
|
||||
case gfx::Format::RG32F:
|
||||
case gfx::Format::RGB32F: {
|
||||
pPositions = ccstd::get_if<Float32Array>(&positionsVar);
|
||||
if (pPositions == nullptr) {
|
||||
return EMPTY_GEOMETRIC_INFO;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case gfx::Format::RGBA32F: {
|
||||
const auto *data = ccstd::get_if<Float32Array>(&positionsVar);
|
||||
if (data == nullptr) {
|
||||
return EMPTY_GEOMETRIC_INFO;
|
||||
}
|
||||
const auto count = data->length() / 4;
|
||||
auto *pos = ccnew Float32Array(count * 3);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
const auto dstPtr = i * 3;
|
||||
const auto srcPtr = i * 4;
|
||||
(*pos)[dstPtr] = (*data)[srcPtr];
|
||||
(*pos)[dstPtr + 1] = (*data)[srcPtr + 1];
|
||||
(*pos)[dstPtr + 2] = (*data)[srcPtr + 2];
|
||||
}
|
||||
pPositions = pos;
|
||||
break;
|
||||
}
|
||||
case gfx::Format::RG16F:
|
||||
case gfx::Format::RGB16F: {
|
||||
const auto *data = ccstd::get_if<Uint16Array>(&positionsVar);
|
||||
if (data == nullptr) {
|
||||
return EMPTY_GEOMETRIC_INFO;
|
||||
}
|
||||
auto *pos = ccnew Float32Array(data->length());
|
||||
for (uint32_t i = 0; i < data->length(); ++i) {
|
||||
(*pos)[i] = mathutils::halfToFloat((*data)[i]);
|
||||
}
|
||||
pPositions = pos;
|
||||
break;
|
||||
}
|
||||
case gfx::Format::RGBA16F: {
|
||||
const auto *data = ccstd::get_if<Uint16Array>(&positionsVar);
|
||||
if (data == nullptr) {
|
||||
return EMPTY_GEOMETRIC_INFO;
|
||||
}
|
||||
const auto count = data->length() / 4;
|
||||
auto *pos = ccnew Float32Array(count * 3);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
const auto dstPtr = i * 3;
|
||||
const auto srcPtr = i * 4;
|
||||
(*pos)[dstPtr] = mathutils::halfToFloat((*data)[srcPtr]);
|
||||
(*pos)[dstPtr + 1] = mathutils::halfToFloat((*data)[srcPtr + 1]);
|
||||
(*pos)[dstPtr + 2] = mathutils::halfToFloat((*data)[srcPtr + 2]);
|
||||
}
|
||||
pPositions = pos;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return EMPTY_GEOMETRIC_INFO;
|
||||
};
|
||||
|
||||
const auto &positions = *pPositions;
|
||||
const auto &indicesVar = _mesh->readIndices(index);
|
||||
|
||||
Vec3 max;
|
||||
Vec3 min;
|
||||
|
||||
if (count == 2) {
|
||||
max.set(positions[0], positions[1], 0);
|
||||
min.set(positions[0], positions[1], 0);
|
||||
} else {
|
||||
max.set(positions[0], positions[1], positions[2]);
|
||||
min.set(positions[0], positions[1], positions[2]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < positions.length(); i += static_cast<int>(count)) {
|
||||
if (count == 2) {
|
||||
max.x = positions[i] > max.x ? positions[i] : max.x;
|
||||
max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y;
|
||||
min.x = positions[i] < min.x ? positions[i] : min.x;
|
||||
min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y;
|
||||
} else {
|
||||
max.x = positions[i] > max.x ? positions[i] : max.x;
|
||||
max.y = positions[i + 1] > max.y ? positions[i + 1] : max.y;
|
||||
max.z = positions[i + 2] > max.z ? positions[i + 2] : max.z;
|
||||
min.x = positions[i] < min.x ? positions[i] : min.x;
|
||||
min.y = positions[i + 1] < min.y ? positions[i + 1] : min.y;
|
||||
min.z = positions[i + 2] < min.z ? positions[i + 2] : min.z;
|
||||
}
|
||||
}
|
||||
|
||||
IGeometricInfo info;
|
||||
info.positions = positions;
|
||||
info.indices = indicesVar;
|
||||
info.boundingBox.max = max;
|
||||
info.boundingBox.min = min;
|
||||
|
||||
_geometricInfo = info;
|
||||
return _geometricInfo.value();
|
||||
}
|
||||
|
||||
void RenderingSubMesh::genFlatBuffers() {
|
||||
if (!_flatBuffers.empty() || _mesh == nullptr || !_subMeshIdx.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t idxCount = 0;
|
||||
const auto &prim = _mesh->getStruct().primitives[_subMeshIdx.value()];
|
||||
if (prim.indexView.has_value()) {
|
||||
idxCount = prim.indexView.value().count;
|
||||
}
|
||||
for (size_t i = 0; i < prim.vertexBundelIndices.size(); i++) {
|
||||
const uint32_t bundleIdx = prim.vertexBundelIndices[i];
|
||||
const Mesh::IVertexBundle &vertexBundle = _mesh->getStruct().vertexBundles[bundleIdx];
|
||||
const uint32_t vbCount = prim.indexView.has_value() ? prim.indexView.value().count : vertexBundle.view.count;
|
||||
const uint32_t vbStride = vertexBundle.view.stride;
|
||||
const uint32_t vbSize = vbStride * vbCount;
|
||||
Uint8Array view(_mesh->getData().buffer(), vertexBundle.view.offset, vertexBundle.view.length);
|
||||
Uint8Array sharedView(prim.indexView.has_value() ? vbSize : vertexBundle.view.length);
|
||||
|
||||
if (!prim.indexView.has_value()) {
|
||||
sharedView.set(_mesh->getData().subarray(vertexBundle.view.offset, vertexBundle.view.offset + vertexBundle.view.length));
|
||||
_flatBuffers.emplace_back(IFlatBuffer{vbStride, vbCount, sharedView});
|
||||
continue;
|
||||
}
|
||||
|
||||
IBArray ibView = _mesh->readIndices(static_cast<int>(_subMeshIdx.value()));
|
||||
// transform to flat buffer
|
||||
for (uint32_t n = 0; n < idxCount; ++n) {
|
||||
auto idx = getIBArrayValue<int32_t>(ibView, static_cast<int>(n));
|
||||
uint32_t offset = n * vbStride;
|
||||
uint32_t srcOffset = idx * vbStride;
|
||||
for (uint32_t m = 0; m < vbStride; ++m) {
|
||||
sharedView[static_cast<int>(offset + m)] = view[static_cast<int>(srcOffset + m)];
|
||||
}
|
||||
}
|
||||
_flatBuffers.emplace_back(IFlatBuffer{vbStride, vbCount, std::move(sharedView)});
|
||||
}
|
||||
}
|
||||
|
||||
void RenderingSubMesh::enableVertexIdChannel(gfx::Device *device) {
|
||||
if (_vertexIdChannel.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto streamIndex = static_cast<uint32_t>(_vertexBuffers.size());
|
||||
const auto attributeIndex = static_cast<uint32_t>(_attributes.size());
|
||||
|
||||
gfx::Buffer *vertexIdBuffer = allocVertexIdBuffer(device);
|
||||
_vertexBuffers.pushBack(vertexIdBuffer);
|
||||
_attributes.push_back({"a_vertexId", gfx::Format::R32F, false, streamIndex, false, 0});
|
||||
|
||||
_iaInfo.attributes = _attributes;
|
||||
_iaInfo.vertexBuffers = _vertexBuffers.get();
|
||||
|
||||
_vertexIdChannel = VertexIdChannel{
|
||||
streamIndex,
|
||||
attributeIndex,
|
||||
};
|
||||
}
|
||||
|
||||
bool RenderingSubMesh::destroy() {
|
||||
_vertexBuffers.clear();
|
||||
_indexBuffer = nullptr;
|
||||
_indirectBuffer = nullptr;
|
||||
|
||||
if (!_jointMappedBuffers.empty() && !_jointMappedBufferIndices.empty()) {
|
||||
for (uint32_t index : _jointMappedBufferIndices) {
|
||||
_jointMappedBuffers.at(index)->destroy();
|
||||
}
|
||||
_jointMappedBuffers.clear();
|
||||
_jointMappedBufferIndices.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const gfx::BufferList &RenderingSubMesh::getJointMappedBuffers() {
|
||||
if (!_jointMappedBuffers.empty()) {
|
||||
return _jointMappedBuffers.get();
|
||||
}
|
||||
|
||||
auto &buffers = _jointMappedBuffers;
|
||||
auto &indices = _jointMappedBufferIndices;
|
||||
|
||||
if (!_mesh || !_subMeshIdx.has_value()) {
|
||||
_jointMappedBuffers = _vertexBuffers;
|
||||
return _jointMappedBuffers.get();
|
||||
}
|
||||
|
||||
const auto &structInfo = _mesh->getStruct();
|
||||
const auto &prim = structInfo.primitives[_subMeshIdx.value()];
|
||||
if (!structInfo.jointMaps.has_value() || !prim.jointMapIndex.has_value() || structInfo.jointMaps.value()[prim.jointMapIndex.value()].empty()) {
|
||||
_jointMappedBuffers = _vertexBuffers;
|
||||
return _jointMappedBuffers.get();
|
||||
}
|
||||
gfx::Format jointFormat = gfx::Format::UNKNOWN;
|
||||
int32_t jointOffset = 0;
|
||||
gfx::Device *device = gfx::Device::getInstance();
|
||||
for (size_t i = 0; i < prim.vertexBundelIndices.size(); i++) {
|
||||
const auto &bundle = structInfo.vertexBundles[prim.vertexBundelIndices[i]];
|
||||
jointOffset = 0;
|
||||
jointFormat = gfx::Format::UNKNOWN;
|
||||
for (const auto &attr : bundle.attributes) {
|
||||
if (attr.name == gfx::ATTR_NAME_JOINTS) {
|
||||
jointFormat = attr.format;
|
||||
break;
|
||||
}
|
||||
jointOffset += static_cast<int32_t>(gfx::GFX_FORMAT_INFOS[static_cast<int32_t>(attr.format)].size);
|
||||
}
|
||||
if (jointFormat != gfx::Format::UNKNOWN) {
|
||||
Uint8Array data{_mesh->getData().buffer(), bundle.view.offset, bundle.view.length};
|
||||
DataView dataView(data.slice().buffer());
|
||||
const auto &idxMap = structInfo.jointMaps.value()[prim.jointMapIndex.value()];
|
||||
|
||||
mapBuffer(
|
||||
dataView, [&](const DataVariant &cur, uint32_t /*idx*/, const DataView & /*view*/) -> DataVariant {
|
||||
if (ccstd::holds_alternative<int32_t>(cur)) {
|
||||
auto iter = std::find(idxMap.begin(), idxMap.end(), ccstd::get<int32_t>(cur));
|
||||
if (iter != idxMap.end()) {
|
||||
return static_cast<int32_t>(iter - idxMap.begin());
|
||||
}
|
||||
}
|
||||
CC_ABORT();
|
||||
return -1;
|
||||
},
|
||||
jointFormat, jointOffset, bundle.view.length, bundle.view.stride, &dataView);
|
||||
|
||||
auto *buffer = device->createBuffer(gfx::BufferInfo{
|
||||
gfx::BufferUsageBit::VERTEX | gfx::BufferUsageBit::TRANSFER_DST,
|
||||
gfx::MemoryUsageBit::DEVICE,
|
||||
bundle.view.length,
|
||||
bundle.view.stride});
|
||||
|
||||
buffer->update(dataView.buffer()->getData());
|
||||
buffers.pushBack(buffer);
|
||||
indices.emplace_back(i);
|
||||
} else {
|
||||
buffers.pushBack(_vertexBuffers.at(prim.vertexBundelIndices[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (_vertexIdChannel) {
|
||||
buffers.pushBack(allocVertexIdBuffer(device));
|
||||
}
|
||||
return buffers.get();
|
||||
}
|
||||
|
||||
gfx::Buffer *RenderingSubMesh::allocVertexIdBuffer(gfx::Device *device) {
|
||||
const uint32_t vertexCount = (_vertexBuffers.empty() || _vertexBuffers.at(0)->getStride() == 0)
|
||||
? 0
|
||||
// TODO(minggo): This depends on how stride of a vertex buffer is defined; Consider padding problem.
|
||||
: _vertexBuffers.at(0)->getSize() / _vertexBuffers.at(0)->getStride();
|
||||
|
||||
ccstd::vector<float> vertexIds(vertexCount);
|
||||
for (int iVertex = 0; iVertex < vertexCount; ++iVertex) {
|
||||
// `+0.5` because on some platforms, the "fetched integer" may have small error.
|
||||
// For example `26` may yield `25.99999`, which is convert to `25` instead of `26` using `int()`.
|
||||
vertexIds[iVertex] = static_cast<float>(iVertex) + 0.5F;
|
||||
}
|
||||
|
||||
uint32_t vertexIdxByteLength = sizeof(float) * vertexCount;
|
||||
gfx::Buffer *vertexIdBuffer = device->createBuffer({
|
||||
gfx::BufferUsageBit::VERTEX | gfx::BufferUsageBit::TRANSFER_DST,
|
||||
gfx::MemoryUsageBit::DEVICE,
|
||||
vertexIdxByteLength,
|
||||
sizeof(float),
|
||||
});
|
||||
vertexIdBuffer->update(vertexIds.data(), vertexIdxByteLength);
|
||||
|
||||
return vertexIdBuffer;
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
230
cocos/core/assets/RenderingSubMesh.h
Normal file
230
cocos/core/assets/RenderingSubMesh.h
Normal file
@@ -0,0 +1,230 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "3d/assets/Types.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "base/RefVector.h"
|
||||
#include "base/std/variant.h"
|
||||
#include "core/TypedArray.h"
|
||||
#include "core/Types.h"
|
||||
#include "renderer/gfx-base/GFXDef.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Mesh;
|
||||
|
||||
/**
|
||||
* @en The interface of geometric information
|
||||
* @zh 几何信息。
|
||||
*/
|
||||
struct IGeometricInfo {
|
||||
/**
|
||||
* @en Vertex positions
|
||||
* @zh 顶点位置。
|
||||
*/
|
||||
Float32Array positions;
|
||||
|
||||
/**
|
||||
* @en Indices data
|
||||
* @zh 索引数据。
|
||||
*/
|
||||
ccstd::optional<IBArray> indices;
|
||||
|
||||
/**
|
||||
* @en Whether the geometry is treated as double sided
|
||||
* @zh 是否将图元按双面对待。
|
||||
*/
|
||||
ccstd::optional<bool> doubleSided;
|
||||
|
||||
/**
|
||||
* @en The bounding box
|
||||
* @zh 此几何体的轴对齐包围盒。
|
||||
*/
|
||||
BoundingBox boundingBox;
|
||||
};
|
||||
|
||||
/**
|
||||
* @en Flat vertex buffer
|
||||
* @zh 扁平化顶点缓冲区
|
||||
*/
|
||||
struct IFlatBuffer {
|
||||
uint32_t stride{0};
|
||||
uint32_t count{0};
|
||||
Uint8Array buffer;
|
||||
};
|
||||
|
||||
namespace gfx {
|
||||
class Buffer;
|
||||
}
|
||||
/**
|
||||
* @en Sub mesh for rendering which contains all geometry data, it can be used to create [[InputAssembler]].
|
||||
* @zh 包含所有顶点数据的渲染子网格,可以用来创建 [[InputAssembler]]。
|
||||
*/
|
||||
class RenderingSubMesh : public RefCounted {
|
||||
public:
|
||||
RenderingSubMesh(const gfx::BufferList &vertexBuffers,
|
||||
const gfx::AttributeList &attributes,
|
||||
gfx::PrimitiveMode primitiveMode);
|
||||
|
||||
RenderingSubMesh(const gfx::BufferList &vertexBuffers,
|
||||
const gfx::AttributeList &attributes,
|
||||
gfx::PrimitiveMode primitiveMode,
|
||||
gfx::Buffer *indexBuffer);
|
||||
|
||||
RenderingSubMesh(const gfx::BufferList &vertexBuffers,
|
||||
const gfx::AttributeList &attributes,
|
||||
gfx::PrimitiveMode primitiveMode,
|
||||
gfx::Buffer *indexBuffer,
|
||||
gfx::Buffer *indirectBuffer);
|
||||
|
||||
RenderingSubMesh(const gfx::BufferList &vertexBuffers,
|
||||
const gfx::AttributeList &attributes,
|
||||
gfx::PrimitiveMode primitiveMode,
|
||||
gfx::Buffer *indexBuffer,
|
||||
gfx::Buffer *indirectBuffer,
|
||||
bool isOwnerOfIndexBuffer);
|
||||
|
||||
~RenderingSubMesh() override;
|
||||
|
||||
/**
|
||||
* @en All vertex attributes used by the sub mesh
|
||||
* @zh 所有顶点属性。
|
||||
*/
|
||||
inline const gfx::AttributeList &getAttributes() const { return _attributes; }
|
||||
|
||||
/**
|
||||
* @en All vertex buffers used by the sub mesh
|
||||
* @zh 使用的所有顶点缓冲区。
|
||||
*/
|
||||
inline const gfx::BufferList &getVertexBuffers() const { return _vertexBuffers.get(); }
|
||||
|
||||
/**
|
||||
* @en Index buffer used by the sub mesh
|
||||
* @zh 使用的索引缓冲区,若未使用则无需指定。
|
||||
*/
|
||||
inline gfx::Buffer *getIndexBuffer() const { return _indexBuffer; }
|
||||
|
||||
/**
|
||||
* @en Indirect buffer used by the sub mesh
|
||||
* @zh 间接绘制缓冲区。
|
||||
*/
|
||||
inline gfx::Buffer *indirectBuffer() const { return _indirectBuffer; }
|
||||
|
||||
/**
|
||||
* @en The geometric info of the sub mesh, used for raycast.
|
||||
* @zh (用于射线检测的)几何信息。
|
||||
*/
|
||||
const IGeometricInfo &getGeometricInfo();
|
||||
|
||||
/**
|
||||
* @en Invalidate the geometric info of the sub mesh after geometry changed.
|
||||
* @zh 网格更新后,设置(用于射线检测的)几何信息为无效,需要重新计算。
|
||||
*/
|
||||
inline void invalidateGeometricInfo() { _geometricInfo.reset(); }
|
||||
|
||||
/**
|
||||
* @en Primitive mode used by the sub mesh
|
||||
* @zh 图元类型。
|
||||
*/
|
||||
inline gfx::PrimitiveMode getPrimitiveMode() const { return _primitiveMode; }
|
||||
|
||||
/**
|
||||
* @en Flatted vertex buffers
|
||||
* @zh 扁平化的顶点缓冲区。
|
||||
*/
|
||||
inline const ccstd::vector<IFlatBuffer> &getFlatBuffers() const { return _flatBuffers; }
|
||||
inline void setFlatBuffers(const ccstd::vector<IFlatBuffer> &flatBuffers) { _flatBuffers = flatBuffers; }
|
||||
|
||||
void genFlatBuffers();
|
||||
|
||||
inline const gfx::InputAssemblerInfo &getIaInfo() const { return _iaInfo; }
|
||||
inline gfx::InputAssemblerInfo &getIaInfo() { return _iaInfo; }
|
||||
|
||||
inline void setDrawInfo(const gfx::DrawInfo &info) { _drawInfo = info; }
|
||||
inline ccstd::optional<gfx::DrawInfo> &getDrawInfo() { return _drawInfo; }
|
||||
|
||||
/**
|
||||
* @en The vertex buffer for joint after mapping
|
||||
* @zh 骨骼索引按映射表处理后的顶点缓冲。
|
||||
*/
|
||||
const gfx::BufferList &getJointMappedBuffers();
|
||||
|
||||
bool destroy();
|
||||
|
||||
/**
|
||||
* @en Adds a vertex attribute input called 'a_vertexId' into this sub-mesh.
|
||||
* This is useful if you want to simulate `gl_VertexId` in WebGL context prior to 2.0.
|
||||
* Once you call this function, the vertex attribute is permanently added.
|
||||
* Subsequent calls to this function take no effect.
|
||||
* @param device Device used to create related rendering resources.
|
||||
*/
|
||||
void enableVertexIdChannel(gfx::Device *device);
|
||||
|
||||
inline void setMesh(Mesh *mesh) { _mesh = mesh; }
|
||||
inline Mesh *getMesh() const { return _mesh; }
|
||||
|
||||
inline void setSubMeshIdx(const ccstd::optional<uint32_t> &idx) { _subMeshIdx = idx; }
|
||||
inline const ccstd::optional<uint32_t> &getSubMeshIdx() const { return _subMeshIdx; }
|
||||
|
||||
private:
|
||||
gfx::Buffer *allocVertexIdBuffer(gfx::Device *device);
|
||||
|
||||
bool _isOwnerOfIndexBuffer{true};
|
||||
|
||||
// Mesh will includes RenderingSubMesh, so use Mesh* here.
|
||||
Mesh *_mesh{nullptr};
|
||||
ccstd::optional<uint32_t> _subMeshIdx;
|
||||
|
||||
ccstd::vector<IFlatBuffer> _flatBuffers;
|
||||
|
||||
// As gfx::InputAssemblerInfo needs the data structure, so not use IntrusivePtr.
|
||||
RefVector<gfx::Buffer *> _jointMappedBuffers;
|
||||
|
||||
ccstd::vector<uint32_t> _jointMappedBufferIndices;
|
||||
|
||||
ccstd::optional<VertexIdChannel> _vertexIdChannel;
|
||||
|
||||
ccstd::optional<IGeometricInfo> _geometricInfo;
|
||||
|
||||
// As gfx::InputAssemblerInfo needs the data structure, so not use IntrusivePtr.
|
||||
RefVector<gfx::Buffer *> _vertexBuffers;
|
||||
|
||||
gfx::AttributeList _attributes;
|
||||
|
||||
IntrusivePtr<gfx::Buffer> _indexBuffer;
|
||||
|
||||
IntrusivePtr<gfx::Buffer> _indirectBuffer;
|
||||
|
||||
gfx::PrimitiveMode _primitiveMode{gfx::PrimitiveMode::TRIANGLE_LIST};
|
||||
|
||||
gfx::InputAssemblerInfo _iaInfo;
|
||||
|
||||
ccstd::optional<gfx::DrawInfo> _drawInfo;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(RenderingSubMesh);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
45
cocos/core/assets/SceneAsset.cpp
Normal file
45
cocos/core/assets/SceneAsset.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/SceneAsset.h"
|
||||
#include "base/memory/Memory.h"
|
||||
#include "core/scene-graph/Scene.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
SceneAsset::SceneAsset() = default;
|
||||
SceneAsset::~SceneAsset() = default;
|
||||
|
||||
bool SceneAsset::validate() const {
|
||||
return _scene.get() != nullptr;
|
||||
}
|
||||
|
||||
void SceneAsset::setScene(Scene *scene) { _scene = scene; };
|
||||
|
||||
void SceneAsset::initDefault(const ccstd::optional<ccstd::string> &uuid) {
|
||||
Super::initDefault(uuid);
|
||||
_scene = ccnew Scene("New Scene");
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
59
cocos/core/assets/SceneAsset.h
Normal file
59
cocos/core/assets/SceneAsset.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Ptr.h"
|
||||
#include "core/assets/Asset.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Scene;
|
||||
|
||||
class SceneAsset final : public Asset {
|
||||
public:
|
||||
using Super = Asset;
|
||||
SceneAsset();
|
||||
~SceneAsset() override;
|
||||
|
||||
void initDefault(const ccstd::optional<ccstd::string> &uuid) override;
|
||||
|
||||
bool validate() const override;
|
||||
|
||||
inline Scene *getScene() const { return _scene.get(); }
|
||||
void setScene(Scene *scene);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @en The scene node
|
||||
* @zh 场景节点。
|
||||
|
||||
@editable
|
||||
@serializable*/
|
||||
IntrusivePtr<Scene> _scene;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(SceneAsset);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
233
cocos/core/assets/SimpleTexture.cpp
Normal file
233
cocos/core/assets/SimpleTexture.cpp
Normal file
@@ -0,0 +1,233 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/SimpleTexture.h"
|
||||
#include "core/assets/ImageAsset.h"
|
||||
#include "core/platform/Debug.h"
|
||||
#include "core/platform/Macro.h"
|
||||
#include "renderer/gfx-base/GFXDevice.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
|
||||
uint32_t getMipLevel(uint32_t width, uint32_t height) {
|
||||
uint32_t size = std::max(width, height);
|
||||
uint32_t level = 0;
|
||||
while (size) {
|
||||
size >>= 1;
|
||||
level++;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
bool isPOT(uint32_t n) { return n && (n & (n - 1)) == 0; }
|
||||
|
||||
bool canGenerateMipmap(uint32_t w, uint32_t h) {
|
||||
return isPOT(w) && isPOT(h);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SimpleTexture::SimpleTexture() = default;
|
||||
SimpleTexture::~SimpleTexture() = default;
|
||||
|
||||
bool SimpleTexture::destroy() {
|
||||
tryDestroyTextureView();
|
||||
tryDestroyTexture();
|
||||
return Super::destroy();
|
||||
}
|
||||
|
||||
void SimpleTexture::updateImage() {
|
||||
updateMipmaps(0, 0);
|
||||
}
|
||||
|
||||
void SimpleTexture::uploadDataWithArrayBuffer(const ArrayBuffer &source, uint32_t level /* = 0 */, uint32_t arrayIndex /* = 0 */) {
|
||||
uploadData(source.getData(), level, arrayIndex);
|
||||
}
|
||||
|
||||
void SimpleTexture::uploadData(const uint8_t *source, uint32_t level /* = 0 */, uint32_t arrayIndex /* = 0 */) {
|
||||
if (!_gfxTexture || _mipmapLevel <= level) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *gfxDevice = getGFXDevice();
|
||||
if (!gfxDevice) {
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::BufferTextureCopy region;
|
||||
region.texExtent.width = _textureWidth >> level;
|
||||
region.texExtent.height = _textureHeight >> level;
|
||||
region.texSubres.mipLevel = level;
|
||||
region.texSubres.baseArrayLayer = arrayIndex;
|
||||
|
||||
const uint8_t *buffers[1]{source};
|
||||
gfxDevice->copyBuffersToTexture(buffers, _gfxTexture, ®ion, 1);
|
||||
}
|
||||
|
||||
void SimpleTexture::assignImage(ImageAsset *image, uint32_t level, uint32_t arrayIndex /* = 0 */) {
|
||||
const uint8_t *data = image->getData();
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
||||
uploadData(data, level, arrayIndex);
|
||||
checkTextureLoaded();
|
||||
|
||||
emit<AfterAssignImage>(image);
|
||||
}
|
||||
|
||||
void SimpleTexture::checkTextureLoaded() {
|
||||
textureReady();
|
||||
}
|
||||
|
||||
void SimpleTexture::textureReady() {
|
||||
_loaded = true;
|
||||
//cjh this.emit('load');
|
||||
}
|
||||
|
||||
void SimpleTexture::setMipmapLevel(uint32_t value) {
|
||||
_mipmapLevel = value < 1 ? 1 : value;
|
||||
}
|
||||
|
||||
void SimpleTexture::tryReset() {
|
||||
tryDestroyTextureView();
|
||||
tryDestroyTexture();
|
||||
if (_mipmapLevel == 0) {
|
||||
return;
|
||||
}
|
||||
auto *device = getGFXDevice();
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
createTexture(device);
|
||||
_gfxTextureView = createTextureView(device);
|
||||
}
|
||||
|
||||
void SimpleTexture::createTexture(gfx::Device *device) {
|
||||
if (_width == 0 || _height == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto flags = gfx::TextureFlagBit::NONE;
|
||||
auto usage = gfx::TextureUsageBit::SAMPLED | gfx::TextureUsageBit::TRANSFER_DST;
|
||||
if (_mipFilter != Filter::NONE && canGenerateMipmap(_width, _height)) {
|
||||
_mipmapLevel = getMipLevel(_width, _height);
|
||||
if (!isUsingOfflineMipmaps() && !isCompressed()) {
|
||||
flags = gfx::TextureFlagBit::GEN_MIPMAP;
|
||||
}
|
||||
}
|
||||
|
||||
const auto gfxFormat = getGFXFormat();
|
||||
if (hasFlag(gfx::Device::getInstance()->getFormatFeatures(gfxFormat), gfx::FormatFeatureBit::RENDER_TARGET)) {
|
||||
usage |= gfx::TextureUsageBit::COLOR_ATTACHMENT;
|
||||
}
|
||||
|
||||
auto textureCreateInfo = getGfxTextureCreateInfo(
|
||||
usage,
|
||||
gfxFormat,
|
||||
_mipmapLevel,
|
||||
flags);
|
||||
|
||||
//cjh if (!textureCreateInfo) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
auto *texture = device->createTexture(textureCreateInfo);
|
||||
_textureWidth = textureCreateInfo.width;
|
||||
_textureHeight = textureCreateInfo.height;
|
||||
|
||||
_gfxTexture = texture;
|
||||
|
||||
notifyTextureUpdated();
|
||||
}
|
||||
|
||||
gfx::Texture *SimpleTexture::createTextureView(gfx::Device *device) {
|
||||
if (!_gfxTexture) {
|
||||
return nullptr;
|
||||
}
|
||||
const uint32_t maxLevel = _maxLevel < _mipmapLevel ? _maxLevel : _mipmapLevel - 1;
|
||||
auto textureViewCreateInfo = getGfxTextureViewCreateInfo(
|
||||
_gfxTexture,
|
||||
getGFXFormat(),
|
||||
_baseLevel,
|
||||
maxLevel - _baseLevel + 1);
|
||||
|
||||
//TODO(minggo)
|
||||
// if (!textureViewCreateInfo) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
return device->createTexture(textureViewCreateInfo);
|
||||
}
|
||||
|
||||
void SimpleTexture::tryDestroyTexture() {
|
||||
if (_gfxTexture != nullptr) {
|
||||
_gfxTexture->destroy();
|
||||
_gfxTexture = nullptr;
|
||||
|
||||
notifyTextureUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleTexture::tryDestroyTextureView() {
|
||||
if (_gfxTextureView != nullptr) {
|
||||
_gfxTextureView->destroy();
|
||||
_gfxTextureView = nullptr;
|
||||
|
||||
//TODO(minggo): should notify JS if the performance is low.
|
||||
}
|
||||
}
|
||||
|
||||
void SimpleTexture::setMipRange(uint32_t baseLevel, uint32_t maxLevel) {
|
||||
debug::assertID(baseLevel <= maxLevel, 3124);
|
||||
|
||||
setMipRangeInternal(baseLevel, maxLevel);
|
||||
|
||||
auto *device = getGFXDevice();
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
// create a new texture view before the destruction of the previous one to bypass the bug that
|
||||
// vulkan destroys textureview in use. This is a temporary solution, should be fixed later.
|
||||
gfx::Texture *textureView = createTextureView(device);
|
||||
tryDestroyTextureView();
|
||||
_gfxTextureView = textureView;
|
||||
}
|
||||
|
||||
bool SimpleTexture::isUsingOfflineMipmaps() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void SimpleTexture::setMipRangeInternal(uint32_t baseLevel, uint32_t maxLevel) {
|
||||
_baseLevel = baseLevel < 1 ? 0 : baseLevel;
|
||||
_maxLevel = _maxLevel < 1 ? 0 : maxLevel;
|
||||
}
|
||||
|
||||
void SimpleTexture::notifyTextureUpdated() {
|
||||
emit<TextureUpdated>(_gfxTexture.get());
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
171
cocos/core/assets/SimpleTexture.h
Normal file
171
cocos/core/assets/SimpleTexture.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/ArrayBuffer.h"
|
||||
#include "core/assets/TextureBase.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class ImageAsset;
|
||||
|
||||
/**
|
||||
* @en The simple texture base class.
|
||||
* It create the GFX Texture and can set mipmap levels.
|
||||
* @zh 简单贴图基类。
|
||||
* 简单贴图内部创建了 GFX 贴图和该贴图上的 GFX 贴图视图。
|
||||
* 简单贴图允许指定不同的 Mipmap 层级。
|
||||
*/
|
||||
class SimpleTexture : public TextureBase {
|
||||
IMPL_EVENT_TARGET(SimpleTexture)
|
||||
DECLARE_TARGET_EVENT_BEGIN_WITH_PARENTS(SimpleTexture, TextureBase)
|
||||
TARGET_EVENT_ARG1(TextureUpdated, cc::gfx::Texture *)
|
||||
TARGET_EVENT_ARG1(AfterAssignImage, cc::ImageAsset *)
|
||||
DECLARE_TARGET_EVENT_END()
|
||||
public:
|
||||
~SimpleTexture() override;
|
||||
|
||||
using Super = TextureBase;
|
||||
/**
|
||||
* @en The mipmap level of the texture
|
||||
* @zh 贴图中的 Mipmap 层级数量
|
||||
*/
|
||||
inline uint32_t mipmapLevel() const {
|
||||
return _mipmapLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en The GFX Texture resource
|
||||
* @zh 获取此贴图底层的 GFX 贴图对象。
|
||||
*/
|
||||
gfx::Texture *getGFXTexture() const override {
|
||||
return _gfxTextureView.get();
|
||||
}
|
||||
|
||||
bool destroy() override;
|
||||
|
||||
/**
|
||||
* @en Update the level 0 mipmap image.
|
||||
* @zh 更新 0 级 Mipmap。
|
||||
*/
|
||||
void updateImage();
|
||||
|
||||
/**
|
||||
* @en Update the given level mipmap image.
|
||||
* @zh 更新指定层级范围内的 Mipmap。当 Mipmap 数据发生了改变时应调用此方法提交更改。
|
||||
* 若指定的层级范围超出了实际已有的层级范围,只有覆盖的那些层级范围会被更新。
|
||||
* @param firstLevel First level to be updated
|
||||
* @param count Mipmap level count to be updated
|
||||
*/
|
||||
virtual void updateMipmaps(uint32_t firstLevel, uint32_t count) {}
|
||||
|
||||
/**
|
||||
* @en Upload data to the given mipmap level.
|
||||
* The size of the image will affect how the mipmap is updated.
|
||||
* - When the image is an ArrayBuffer, the size of the image must match the mipmap size.
|
||||
* - If the image size matches the mipmap size, the mipmap data will be updated entirely.
|
||||
* - If the image size is smaller than the mipmap size, the mipmap will be updated from top left corner.
|
||||
* - If the image size is larger, an error will be raised
|
||||
* @zh 上传图像数据到指定层级的 Mipmap 中。
|
||||
* 图像的尺寸影响 Mipmap 的更新范围:
|
||||
* - 当图像是 `ArrayBuffer` 时,图像的尺寸必须和 Mipmap 的尺寸一致;否则,
|
||||
* - 若图像的尺寸与 Mipmap 的尺寸相同,上传后整个 Mipmap 的数据将与图像数据一致;
|
||||
* - 若图像的尺寸小于指定层级 Mipmap 的尺寸(不管是长或宽),则从贴图左上角开始,图像尺寸范围内的 Mipmap 会被更新;
|
||||
* - 若图像的尺寸超出了指定层级 Mipmap 的尺寸(不管是长或宽),都将引起错误。
|
||||
* @param source The source image or image data
|
||||
* @param level Mipmap level to upload the image to
|
||||
* @param arrayIndex The array index
|
||||
*/
|
||||
void uploadDataWithArrayBuffer(const ArrayBuffer &source, uint32_t level = 0, uint32_t arrayIndex = 0);
|
||||
void uploadData(const uint8_t *source, uint32_t level = 0, uint32_t arrayIndex = 0);
|
||||
|
||||
void assignImage(ImageAsset *image, uint32_t level, uint32_t arrayIndex = 0);
|
||||
|
||||
void checkTextureLoaded();
|
||||
|
||||
/**
|
||||
* Set mipmap level of this texture.
|
||||
* The value is passes as presumed info to `this._getGfxTextureCreateInfo()`.
|
||||
* @param value The mipmap level.
|
||||
* @warn As it is invoked by subclass(TextureCube) in TS, so should make it as public.
|
||||
*/
|
||||
void setMipmapLevel(uint32_t value);
|
||||
|
||||
/**
|
||||
* Set mipmap level range for this texture.
|
||||
* @param baseLevel The base mipmap level.
|
||||
* @param maxLevel The maximum mipmap level.
|
||||
*/
|
||||
void setMipRange(uint32_t baseLevel, uint32_t maxLevel);
|
||||
|
||||
/**
|
||||
* @en Whether mipmaps are baked convolutional maps.
|
||||
* @zh mipmaps是否为烘焙出来的卷积图。
|
||||
*/
|
||||
virtual bool isUsingOfflineMipmaps();
|
||||
|
||||
protected:
|
||||
SimpleTexture();
|
||||
void textureReady();
|
||||
|
||||
/**
|
||||
* @en This method is override by derived classes to provide GFX texture info.
|
||||
* @zh 这个方法被派生类重写以提供 GFX 纹理信息。
|
||||
* @param presumed The presumed GFX texture info.
|
||||
*/
|
||||
virtual gfx::TextureInfo getGfxTextureCreateInfo(gfx::TextureUsageBit usage, gfx::Format format, uint32_t levelCount, gfx::TextureFlagBit flags) = 0;
|
||||
|
||||
/**
|
||||
* @en This method is overrided by derived classes to provide GFX TextureViewInfo.
|
||||
* @zh 这个方法被派生类重写以提供 GFX 纹理视图信息。
|
||||
* @param presumed The presumed GFX TextureViewInfo.
|
||||
*/
|
||||
virtual gfx::TextureViewInfo getGfxTextureViewCreateInfo(gfx::Texture *texture, gfx::Format format, uint32_t baseLevel, uint32_t levelCount) = 0;
|
||||
|
||||
void tryReset();
|
||||
|
||||
void createTexture(gfx::Device *device);
|
||||
gfx::Texture *createTextureView(gfx::Device *device);
|
||||
|
||||
void tryDestroyTexture();
|
||||
void tryDestroyTextureView();
|
||||
void notifyTextureUpdated();
|
||||
void setMipRangeInternal(uint32_t baseLevel, uint32_t maxLevel);
|
||||
|
||||
IntrusivePtr<gfx::Texture> _gfxTexture;
|
||||
IntrusivePtr<gfx::Texture> _gfxTextureView;
|
||||
|
||||
uint32_t _mipmapLevel{1};
|
||||
// Cache these data to reduce JSB invoking.
|
||||
uint32_t _textureWidth{0};
|
||||
uint32_t _textureHeight{0};
|
||||
|
||||
uint32_t _baseLevel{0};
|
||||
uint32_t _maxLevel{1000};
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(SimpleTexture);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
55
cocos/core/assets/TextAsset.h
Normal file
55
cocos/core/assets/TextAsset.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/assets/Asset.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
/**
|
||||
* @en Class for text file.
|
||||
* @zh 文本资源。
|
||||
*/
|
||||
class TextAsset final : public Asset {
|
||||
public:
|
||||
explicit TextAsset() = default;
|
||||
~TextAsset() override = default;
|
||||
/**
|
||||
* @en The text content.
|
||||
* @zh 此资源包含的文本。
|
||||
|
||||
@serializable
|
||||
@editable*/
|
||||
ccstd::string text;
|
||||
|
||||
ccstd::string toString() const override {
|
||||
return text;
|
||||
}
|
||||
|
||||
private:
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(TextAsset);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
242
cocos/core/assets/Texture2D.cpp
Normal file
242
cocos/core/assets/Texture2D.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/Texture2D.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "core/assets/ImageAsset.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
Texture2D::Texture2D() = default;
|
||||
Texture2D::~Texture2D() = default;
|
||||
|
||||
void Texture2D::syncMipmapsForJS(const ccstd::vector<IntrusivePtr<ImageAsset>> &value) {
|
||||
_mipmaps = value;
|
||||
}
|
||||
|
||||
void Texture2D::setMipmaps(const ccstd::vector<IntrusivePtr<ImageAsset>> &value) {
|
||||
_mipmaps = value;
|
||||
|
||||
auto mipmaps = ccstd::vector<IntrusivePtr<ImageAsset>>{};
|
||||
|
||||
if (value.size() == 1) {
|
||||
const auto images = value[0]->extractMipmaps();
|
||||
std::copy(std::cbegin(images), std::cend(images), std::back_inserter(mipmaps));
|
||||
} else if (value.size() > 1) {
|
||||
for (const auto &image : value) {
|
||||
mipmaps.emplace_back(image->extractMipmap0());
|
||||
}
|
||||
}
|
||||
|
||||
setMipmapParams(mipmaps);
|
||||
}
|
||||
|
||||
void Texture2D::setMipmapParams(const ccstd::vector<IntrusivePtr<ImageAsset>> &value) {
|
||||
_generatedMipmaps = value;
|
||||
setMipmapLevel(static_cast<uint32_t>(_generatedMipmaps.size()));
|
||||
if (!_generatedMipmaps.empty()) {
|
||||
ImageAsset *imageAsset = _generatedMipmaps[0];
|
||||
ITexture2DCreateInfo info;
|
||||
info.width = imageAsset->getWidth();
|
||||
info.height = imageAsset->getHeight();
|
||||
info.format = imageAsset->getFormat();
|
||||
info.mipmapLevel = static_cast<uint32_t>(_generatedMipmaps.size());
|
||||
info.baseLevel = _baseLevel;
|
||||
info.maxLevel = _maxLevel;
|
||||
reset(info);
|
||||
|
||||
for (size_t i = 0, len = _generatedMipmaps.size(); i < len; ++i) {
|
||||
assignImage(_generatedMipmaps[i], static_cast<uint32_t>(i));
|
||||
}
|
||||
|
||||
} else {
|
||||
ITexture2DCreateInfo info;
|
||||
info.width = 0;
|
||||
info.height = 0;
|
||||
info.mipmapLevel = static_cast<uint32_t>(_generatedMipmaps.size());
|
||||
info.baseLevel = _baseLevel;
|
||||
info.maxLevel = _maxLevel;
|
||||
reset(info);
|
||||
}
|
||||
}
|
||||
|
||||
void Texture2D::initialize() {
|
||||
setMipmaps(_mipmaps);
|
||||
}
|
||||
|
||||
void Texture2D::onLoaded() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
void Texture2D::reset(const ITexture2DCreateInfo &info) {
|
||||
_width = info.width;
|
||||
_height = info.height;
|
||||
setGFXFormat(info.format);
|
||||
|
||||
const uint32_t mipLevels = info.mipmapLevel.has_value() ? info.mipmapLevel.value() : 1;
|
||||
setMipmapLevel(mipLevels);
|
||||
|
||||
const uint32_t minLod = info.baseLevel.has_value() ? info.baseLevel.value() : 0;
|
||||
const uint32_t maxLod = info.maxLevel.has_value() ? info.maxLevel.value() : 1000;
|
||||
setMipRange(minLod, maxLod);
|
||||
|
||||
tryReset();
|
||||
}
|
||||
|
||||
void Texture2D::create(uint32_t width, uint32_t height, PixelFormat format /* = PixelFormat::RGBA8888*/, uint32_t mipmapLevel /* = 1*/, uint32_t baseLevel, uint32_t maxLevel) {
|
||||
reset({width,
|
||||
height,
|
||||
format,
|
||||
mipmapLevel,
|
||||
baseLevel,
|
||||
maxLevel});
|
||||
}
|
||||
|
||||
ccstd::string Texture2D::toString() const {
|
||||
ccstd::string ret;
|
||||
if (!_mipmaps.empty()) {
|
||||
ret = _mipmaps[0]->getUrl();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Texture2D::updateMipmaps(uint32_t firstLevel, uint32_t count) {
|
||||
if (firstLevel >= _generatedMipmaps.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto nUpdate = static_cast<uint32_t>(std::min(
|
||||
(count == 0 ? _generatedMipmaps.size() : count),
|
||||
(_generatedMipmaps.size() - firstLevel)));
|
||||
|
||||
for (uint32_t i = 0; i < nUpdate; ++i) {
|
||||
const uint32_t level = firstLevel + i;
|
||||
assignImage(_generatedMipmaps[level], level);
|
||||
}
|
||||
}
|
||||
|
||||
bool Texture2D::destroy() {
|
||||
_mipmaps.clear();
|
||||
_generatedMipmaps.clear();
|
||||
return Super::destroy();
|
||||
}
|
||||
|
||||
ccstd::string Texture2D::description() const {
|
||||
std::stringstream ret;
|
||||
ccstd::string url;
|
||||
if (!_mipmaps.empty()) {
|
||||
url = _mipmaps[0]->getUrl();
|
||||
}
|
||||
ret << "<cc.Texture2D | Name = " << url << " | Dimension" << _width << " x " << _height << ">";
|
||||
return ret.str();
|
||||
}
|
||||
|
||||
void Texture2D::releaseTexture() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
ccstd::any Texture2D::serialize(const ccstd::any & /*ctxForExporting*/) {
|
||||
// if (EDITOR || TEST) {
|
||||
// return {
|
||||
// base: super._serialize(ctxForExporting),
|
||||
// mipmaps: this._mipmaps.map((mipmap) => {
|
||||
// if (!mipmap || !mipmap._uuid) {
|
||||
// return null;
|
||||
// }
|
||||
// if (ctxForExporting && ctxForExporting._compressUuid) {
|
||||
// // ctxForExporting.dependsOn('_textureSource', texture); TODO
|
||||
// return EditorExtends.UuidUtils.compressUuid(mipmap._uuid, true);
|
||||
// }
|
||||
// return mipmap._uuid;
|
||||
// }),
|
||||
// };
|
||||
// }
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Texture2D::deserialize(const ccstd::any &serializedData, const ccstd::any &handle) {
|
||||
const auto *data = ccstd::any_cast<ITexture2DSerializeData>(&serializedData);
|
||||
if (data == nullptr) {
|
||||
CC_LOG_WARNING("serializedData is not ITexture2DSerializeData");
|
||||
return;
|
||||
}
|
||||
Super::deserialize(data->base, handle);
|
||||
|
||||
_mipmaps.resize(data->mipmaps.size());
|
||||
for (size_t i = 0; i < data->mipmaps.size(); ++i) {
|
||||
// Prevent resource load failed
|
||||
_mipmaps[i] = ccnew ImageAsset();
|
||||
if (data->mipmaps[i].empty()) {
|
||||
continue;
|
||||
}
|
||||
ccstd::string mipmapUUID = data->mipmaps[i];
|
||||
//cjh TODO: handle.result.push(this._mipmaps, `${i}`, mipmapUUID, js.getClassId(ImageAsset));
|
||||
}
|
||||
}
|
||||
|
||||
gfx::TextureInfo Texture2D::getGfxTextureCreateInfo(gfx::TextureUsageBit usage, gfx::Format format, uint32_t levelCount, gfx::TextureFlagBit flags) {
|
||||
gfx::TextureInfo texInfo;
|
||||
texInfo.type = gfx::TextureType::TEX2D;
|
||||
texInfo.width = _width;
|
||||
texInfo.height = _height;
|
||||
texInfo.usage = usage;
|
||||
texInfo.format = format;
|
||||
texInfo.levelCount = levelCount;
|
||||
texInfo.flags = flags;
|
||||
return texInfo;
|
||||
}
|
||||
|
||||
gfx::TextureViewInfo Texture2D::getGfxTextureViewCreateInfo(gfx::Texture *texture, gfx::Format format, uint32_t baseLevel, uint32_t levelCount) {
|
||||
gfx::TextureViewInfo texViewInfo;
|
||||
texViewInfo.type = gfx::TextureType::TEX2D;
|
||||
texViewInfo.texture = texture;
|
||||
texViewInfo.format = format;
|
||||
texViewInfo.baseLevel = baseLevel;
|
||||
texViewInfo.levelCount = levelCount;
|
||||
return texViewInfo;
|
||||
}
|
||||
|
||||
void Texture2D::initDefault(const ccstd::optional<ccstd::string> &uuid) {
|
||||
Super::initDefault(uuid);
|
||||
auto *imageAsset = ccnew ImageAsset();
|
||||
imageAsset->initDefault(ccstd::nullopt);
|
||||
setImage(imageAsset);
|
||||
}
|
||||
|
||||
void Texture2D::setImage(ImageAsset *value) {
|
||||
ccstd::vector<IntrusivePtr<ImageAsset>> mipmaps;
|
||||
if (value != nullptr) {
|
||||
mipmaps.emplace_back(value);
|
||||
}
|
||||
setMipmaps(mipmaps);
|
||||
}
|
||||
|
||||
bool Texture2D::validate() const {
|
||||
return !_mipmaps.empty();
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
216
cocos/core/assets/Texture2D.h
Normal file
216
cocos/core/assets/Texture2D.h
Normal file
@@ -0,0 +1,216 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Ptr.h"
|
||||
#include "base/std/optional.h"
|
||||
#include "core/assets/Asset.h"
|
||||
#include "core/assets/AssetEnum.h"
|
||||
#include "core/assets/SimpleTexture.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
struct ITexture2DSerializeData {
|
||||
ccstd::string base;
|
||||
ccstd::vector<ccstd::string> mipmaps;
|
||||
};
|
||||
|
||||
/**
|
||||
* @en The create information for [[Texture2D]]
|
||||
* @zh 用来创建贴图的信息。
|
||||
*/
|
||||
struct ITexture2DCreateInfo {
|
||||
/**
|
||||
* @en The pixel width
|
||||
* @zh 像素宽度。
|
||||
*/
|
||||
uint32_t width{0};
|
||||
|
||||
/**
|
||||
* @en The pixel height
|
||||
* @zh 像素高度。
|
||||
*/
|
||||
uint32_t height{0};
|
||||
|
||||
/**
|
||||
* @en The pixel format
|
||||
* @zh 像素格式。
|
||||
* @default PixelFormat.RGBA8888
|
||||
*/
|
||||
ccstd::optional<PixelFormat> format;
|
||||
|
||||
/**
|
||||
* @en The mipmap level count
|
||||
* @zh mipmap 层级。
|
||||
* @default 1
|
||||
*/
|
||||
ccstd::optional<uint32_t> mipmapLevel;
|
||||
|
||||
/**
|
||||
* @en The selected base mipmap level
|
||||
* @zh 选择使用的最小 mipmap 层级。
|
||||
* @default 1
|
||||
*/
|
||||
ccstd::optional<uint32_t> baseLevel;
|
||||
|
||||
/**
|
||||
* @en The selected maximum mipmap level
|
||||
* @zh 选择使用的最大 mipmap 层级。
|
||||
* @default 1
|
||||
*/
|
||||
ccstd::optional<uint32_t> maxLevel;
|
||||
};
|
||||
|
||||
/**
|
||||
* @en The 2D texture asset. It supports mipmap, each level of mipmap use an [[ImageAsset]].
|
||||
* @zh 二维贴图资源。二维贴图资源的每个 Mipmap 层级都为一张 [[ImageAsset]]。
|
||||
*/
|
||||
class Texture2D final : public SimpleTexture {
|
||||
public:
|
||||
using Super = SimpleTexture;
|
||||
|
||||
Texture2D();
|
||||
~Texture2D() override;
|
||||
|
||||
/**
|
||||
* @en All levels of mipmap images, be noted, automatically generated mipmaps are not included.
|
||||
* When setup mipmap, the size of the texture and pixel format could be modified.
|
||||
* @zh 所有层级 Mipmap,注意,这里不包含自动生成的 Mipmap。
|
||||
* 当设置 Mipmap 时,贴图的尺寸以及像素格式可能会改变。
|
||||
*/
|
||||
const ccstd::vector<IntrusivePtr<ImageAsset>> &getMipmaps() const {
|
||||
return _mipmaps;
|
||||
}
|
||||
|
||||
const ccstd::vector<ccstd::string> &getMipmapsUuids() const { // TODO(xwx): temporary use _mipmaps as string array
|
||||
return _mipmapsUuids;
|
||||
}
|
||||
|
||||
//cjh TODO: TextureCube also needs this method.
|
||||
void syncMipmapsForJS(const ccstd::vector<IntrusivePtr<ImageAsset>> &value);
|
||||
|
||||
void setMipmaps(const ccstd::vector<IntrusivePtr<ImageAsset>> &value);
|
||||
|
||||
/**
|
||||
* @en Level 0 mipmap image.
|
||||
* Be noted, `this.image = img` equals `this.mipmaps = [img]`,
|
||||
* sets image will clear all previous mipmaps.
|
||||
* @zh 0 级 Mipmap。
|
||||
* 注意,`this.image = img` 等价于 `this.mipmaps = [img]`,
|
||||
* 也就是说,通过 `this.image` 设置 0 级 Mipmap 时将隐式地清除之前的所有 Mipmap。
|
||||
*/
|
||||
inline ImageAsset *getImage() const {
|
||||
return _mipmaps.empty() ? nullptr : _mipmaps[0].get();
|
||||
}
|
||||
|
||||
void setImage(ImageAsset *value);
|
||||
|
||||
void initialize();
|
||||
|
||||
void onLoaded() override;
|
||||
|
||||
/**
|
||||
* @en Reset the current texture with given size, pixel format and mipmap images.
|
||||
* After reset, the gfx resource will become invalid, you must use [[uploadData]] explicitly to upload the new mipmaps to GPU resources.
|
||||
* @zh 将当前贴图重置为指定尺寸、像素格式以及指定 mipmap 层级。重置后,贴图的像素数据将变为未定义。
|
||||
* mipmap 图像的数据不会自动更新到贴图中,你必须显式调用 [[uploadData]] 来上传贴图数据。
|
||||
* @param info The create information
|
||||
*/
|
||||
void reset(const ITexture2DCreateInfo &info);
|
||||
|
||||
/**
|
||||
* @en Reset the current texture with given size, pixel format and mipmap images.
|
||||
* After reset, the gfx resource will become invalid, you must use [[uploadData]] explicitly to upload the new mipmaps to GPU resources.
|
||||
* @zh 将当前贴图重置为指定尺寸、像素格式以及指定 mipmap 层级。重置后,贴图的像素数据将变为未定义。
|
||||
* mipmap 图像的数据不会自动更新到贴图中,你必须显式调用 [[uploadData]] 来上传贴图数据。
|
||||
* @param width Pixel width
|
||||
* @param height Pixel height
|
||||
* @param format Pixel format
|
||||
* @param mipmapLevel Mipmap level count
|
||||
* @param baseLevel Mipmap base level
|
||||
* @param maxLevel Mipmap maximum level
|
||||
|
||||
* @deprecated since v1.0 please use [[reset]] instead
|
||||
*/
|
||||
void create(uint32_t width, uint32_t height, PixelFormat format = PixelFormat::RGBA8888, uint32_t mipmapLevel = 1, uint32_t baseLevel = 0, uint32_t maxLevel = 1000);
|
||||
|
||||
ccstd::string toString() const override;
|
||||
|
||||
void updateMipmaps(uint32_t firstLevel, uint32_t count) override;
|
||||
|
||||
/**
|
||||
* @en Destroy the current 2d texture, clear up all mipmap levels and the related GPU resources.
|
||||
* @zh 销毁此贴图,清空所有 Mipmap 并释放占用的 GPU 资源。
|
||||
*/
|
||||
bool destroy() override;
|
||||
|
||||
/**
|
||||
* @en Gets the description of the 2d texture
|
||||
* @zh 返回此贴图的描述。
|
||||
* @returns The description
|
||||
*/
|
||||
ccstd::string description() const;
|
||||
|
||||
/**
|
||||
* @en Release used GPU resources.
|
||||
* @zh 释放占用的 GPU 资源。
|
||||
* @deprecated please use [[destroy]] instead
|
||||
*/
|
||||
void releaseTexture();
|
||||
|
||||
// SERIALIZATION
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
ccstd::any serialize(const ccstd::any &ctxForExporting) override;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
void deserialize(const ccstd::any &serializedData, const ccstd::any &handle) override;
|
||||
|
||||
gfx::TextureInfo getGfxTextureCreateInfo(gfx::TextureUsageBit usage, gfx::Format format, uint32_t levelCount, gfx::TextureFlagBit flags) override;
|
||||
gfx::TextureViewInfo getGfxTextureViewCreateInfo(gfx::Texture *texture, gfx::Format format, uint32_t baseLevel, uint32_t levelCount) override;
|
||||
|
||||
void initDefault(const ccstd::optional<ccstd::string> &uuid) override;
|
||||
|
||||
bool validate() const override;
|
||||
|
||||
private:
|
||||
void setMipmapParams(const ccstd::vector<IntrusivePtr<ImageAsset>> &value);
|
||||
|
||||
ccstd::vector<IntrusivePtr<ImageAsset>> _mipmaps;
|
||||
ccstd::vector<IntrusivePtr<ImageAsset>> _generatedMipmaps;
|
||||
|
||||
ccstd::vector<ccstd::string> _mipmapsUuids; // TODO(xwx): temporary use _mipmaps as UUIDs string array
|
||||
|
||||
friend class Texture2DDeserializer;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(Texture2D);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
190
cocos/core/assets/TextureBase.cpp
Normal file
190
cocos/core/assets/TextureBase.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/TextureBase.h"
|
||||
#include "base/StringUtil.h"
|
||||
#include "cocos/core/platform/Debug.h"
|
||||
#include "core/utils/IDGenerator.h"
|
||||
|
||||
#include "renderer/gfx-base/GFXDevice.h"
|
||||
#include "renderer/pipeline/Define.h"
|
||||
|
||||
#include "base/std/hash/hash.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
IDGenerator idGenerator("Tex");
|
||||
}
|
||||
|
||||
TextureBase::TextureBase() {
|
||||
// Id for generate hash in material
|
||||
_id = idGenerator.getNewId();
|
||||
_gfxDevice = getGFXDevice();
|
||||
ccstd::hash_t seed = 666;
|
||||
ccstd::hash_range(seed, _id.begin(), _id.end());
|
||||
_textureHash = seed;
|
||||
}
|
||||
|
||||
TextureBase::~TextureBase() = default;
|
||||
|
||||
void TextureBase::setWrapMode(WrapMode wrapS, WrapMode wrapT, WrapMode wrapR) {
|
||||
_wrapS = wrapS;
|
||||
_samplerInfo.addressU = static_cast<gfx::Address>(wrapS),
|
||||
|
||||
_wrapT = wrapT;
|
||||
_samplerInfo.addressV = static_cast<gfx::Address>(wrapT),
|
||||
|
||||
_wrapR = wrapR;
|
||||
_samplerInfo.addressW = static_cast<gfx::Address>(wrapR);
|
||||
|
||||
if (_gfxDevice != nullptr) {
|
||||
_gfxSampler = _gfxDevice->getSampler(_samplerInfo);
|
||||
}
|
||||
|
||||
notifySamplerUpdated();
|
||||
}
|
||||
|
||||
void TextureBase::setWrapMode(WrapMode wrapS, WrapMode wrapT) {
|
||||
setWrapMode(wrapS, wrapT, wrapS); // wrap modes should be as consistent as possible for performance
|
||||
}
|
||||
|
||||
void TextureBase::setFilters(Filter minFilter, Filter magFilter) {
|
||||
_minFilter = minFilter;
|
||||
_samplerInfo.minFilter = static_cast<gfx::Filter>(minFilter);
|
||||
_magFilter = magFilter;
|
||||
_samplerInfo.magFilter = static_cast<gfx::Filter>(magFilter);
|
||||
|
||||
if (_gfxDevice != nullptr) {
|
||||
_gfxSampler = _gfxDevice->getSampler(_samplerInfo);
|
||||
}
|
||||
|
||||
notifySamplerUpdated();
|
||||
}
|
||||
|
||||
void TextureBase::setMipFilter(Filter mipFilter) {
|
||||
_mipFilter = mipFilter;
|
||||
_samplerInfo.mipFilter = static_cast<gfx::Filter>(mipFilter);
|
||||
|
||||
if (_gfxDevice != nullptr) {
|
||||
_gfxSampler = _gfxDevice->getSampler(_samplerInfo);
|
||||
}
|
||||
|
||||
notifySamplerUpdated();
|
||||
}
|
||||
|
||||
void TextureBase::setAnisotropy(uint32_t anisotropy) {
|
||||
_anisotropy = anisotropy;
|
||||
_samplerInfo.maxAnisotropy = anisotropy;
|
||||
|
||||
if (_gfxDevice != nullptr) {
|
||||
_gfxSampler = _gfxDevice->getSampler(_samplerInfo);
|
||||
}
|
||||
|
||||
notifySamplerUpdated();
|
||||
}
|
||||
|
||||
bool TextureBase::destroy() {
|
||||
const bool destroyed = Super::destroy();
|
||||
//cjh TODO: if (destroyed && legacyCC.director.root?.batcher2D) {
|
||||
// legacyCC.director.root.batcher2D._releaseDescriptorSetCache(this._textureHash);
|
||||
// }
|
||||
return destroyed;
|
||||
}
|
||||
|
||||
gfx::Sampler *TextureBase::getGFXSampler() const {
|
||||
if (_gfxSampler == nullptr) {
|
||||
if (_gfxDevice != nullptr) {
|
||||
const_cast<TextureBase *>(this)->_gfxSampler = _gfxDevice->getSampler(_samplerInfo);
|
||||
} else {
|
||||
debug::errorID(9302);
|
||||
}
|
||||
}
|
||||
return _gfxSampler;
|
||||
}
|
||||
|
||||
ccstd::any TextureBase::serialize(const ccstd::any & /*ctxForExporting*/) {
|
||||
//cjh TODO: if (EDITOR || TEST) {
|
||||
// return `${this._minFilter},${this._magFilter},${
|
||||
// this._wrapS},${this._wrapT},${
|
||||
// this._mipFilter},${this._anisotropy}`;
|
||||
// }
|
||||
return ccstd::string("");
|
||||
}
|
||||
|
||||
void TextureBase::deserialize(const ccstd::any &serializedData, const ccstd::any & /*handle*/) {
|
||||
const auto *pData = ccstd::any_cast<const ccstd::string>(&serializedData);
|
||||
if (pData == nullptr) {
|
||||
return;
|
||||
}
|
||||
const ccstd::string &data = *pData;
|
||||
auto fields = StringUtil::split(data, ",");
|
||||
fields.insert(fields.begin(), "");
|
||||
|
||||
if (fields.size() >= 5) {
|
||||
// decode filters
|
||||
setFilters(static_cast<Filter>(atoi(fields[1].c_str())), static_cast<Filter>(atoi(fields[2].c_str())));
|
||||
// decode wraps
|
||||
setWrapMode(static_cast<WrapMode>(atoi(fields[3].c_str())), static_cast<WrapMode>(atoi(fields[4].c_str())));
|
||||
}
|
||||
|
||||
if (fields.size() >= 7) {
|
||||
setMipFilter(static_cast<Filter>(atoi(fields[5].c_str())));
|
||||
setAnisotropy(atoi(fields[6].c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
gfx::Device *TextureBase::getGFXDevice() {
|
||||
return gfx::Device::getInstance();
|
||||
}
|
||||
|
||||
gfx::Format TextureBase::getGFXFormat() const {
|
||||
return getGFXPixelFormat(_format);
|
||||
}
|
||||
|
||||
void TextureBase::setGFXFormat(const ccstd::optional<PixelFormat> &format) {
|
||||
_format = format.has_value() ? format.value() : PixelFormat::RGBA8888;
|
||||
}
|
||||
|
||||
gfx::Format TextureBase::getGFXPixelFormat(PixelFormat format) {
|
||||
if (format == PixelFormat::RGBA_ETC1) {
|
||||
format = PixelFormat::RGB_ETC1;
|
||||
} else if (format == PixelFormat::RGB_A_PVRTC_4BPPV1) {
|
||||
format = PixelFormat::RGB_PVRTC_4BPPV1;
|
||||
} else if (format == PixelFormat::RGB_A_PVRTC_2BPPV1) {
|
||||
format = PixelFormat::RGB_PVRTC_2BPPV1;
|
||||
}
|
||||
return static_cast<gfx::Format>(format);
|
||||
}
|
||||
|
||||
bool TextureBase::isCompressed() const {
|
||||
return (_format >= PixelFormat::RGB_ETC1 && _format <= PixelFormat::RGBA_ASTC_12X12) || (_format >= PixelFormat::RGB_A_PVRTC_2BPPV1 && _format <= PixelFormat::RGBA_ETC1);
|
||||
}
|
||||
|
||||
void TextureBase::notifySamplerUpdated() {
|
||||
// emit(EventTypesToJS::TEXTURE_BASE_GFX_SAMPLER_UPDATED, _gfxSampler);
|
||||
emit<SamplerUpdated>(_gfxSampler);
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
261
cocos/core/assets/TextureBase.h
Normal file
261
cocos/core/assets/TextureBase.h
Normal file
@@ -0,0 +1,261 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "base/Ptr.h"
|
||||
#include "core/assets/Asset.h"
|
||||
#include "core/assets/AssetEnum.h"
|
||||
#include "renderer/gfx-base/GFXDef.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
|
||||
#include "base/std/any.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace gfx {
|
||||
class Sampler;
|
||||
class Device;
|
||||
class Texture;
|
||||
} // namespace gfx
|
||||
/**
|
||||
* @en The base texture class, it defines features shared by all textures.
|
||||
* @zh 贴图资源基类。它定义了所有贴图共用的概念。
|
||||
*/
|
||||
class TextureBase : public Asset {
|
||||
IMPL_EVENT_TARGET(TextureBase)
|
||||
DECLARE_TARGET_EVENT_BEGIN(TextureBase)
|
||||
TARGET_EVENT_ARG1(SamplerUpdated, cc::gfx::Sampler *)
|
||||
DECLARE_TARGET_EVENT_END()
|
||||
public:
|
||||
using Super = Asset;
|
||||
|
||||
/**
|
||||
* @en The pixel format enum.
|
||||
* @zh 像素格式枚举类型
|
||||
*/
|
||||
using PixelFormat = cc::PixelFormat;
|
||||
|
||||
/**
|
||||
* @en The wrap mode enum.
|
||||
* @zh 环绕模式枚举类型
|
||||
*/
|
||||
using WrapMode = cc::WrapMode;
|
||||
|
||||
/**
|
||||
* @en The texture filter mode enum
|
||||
* @zh 纹理过滤模式枚举类型
|
||||
*/
|
||||
using Filter = cc::Filter;
|
||||
|
||||
TextureBase(); // NOTE: Editor needs to invoke 'new TextureBase' in JS, so we need to make the constructor public.
|
||||
~TextureBase() override;
|
||||
/**
|
||||
* @en Whether the pixel data is compressed.
|
||||
* @zh 此贴图是否为压缩的像素格式。
|
||||
*/
|
||||
bool isCompressed() const;
|
||||
|
||||
/**
|
||||
* @en Pixel width of the texture
|
||||
* @zh 此贴图的像素宽度。
|
||||
*/
|
||||
uint32_t getWidth() const {
|
||||
return _width;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Pixel height of the texture
|
||||
* @zh 此贴图的像素高度。
|
||||
*/
|
||||
uint32_t getHeight() const {
|
||||
return _height;
|
||||
}
|
||||
|
||||
// Functions for TS deserialization.
|
||||
inline void setWidth(uint32_t width) { _width = width; }
|
||||
inline void setHeight(uint32_t height) { _height = height; }
|
||||
|
||||
/**
|
||||
* @en Gets the id of the texture
|
||||
* @zh 获取标识符。
|
||||
* @returns The id
|
||||
*/
|
||||
inline const ccstd::string &getId() const {
|
||||
return _id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the pixel format
|
||||
* @zh 获取像素格式。
|
||||
* @returns The pixel format
|
||||
*/
|
||||
inline PixelFormat getPixelFormat() const {
|
||||
return _format;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the anisotropy
|
||||
* @zh 获取各向异性。
|
||||
* @returns The anisotropy
|
||||
*/
|
||||
inline uint32_t getAnisotropy() const {
|
||||
return _anisotropy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Sets the wrap mode of the texture.
|
||||
* Be noted, if the size of the texture is not power of two, only [[WrapMode.CLAMP_TO_EDGE]] is allowed.
|
||||
* @zh 设置此贴图的缠绕模式。
|
||||
* 注意,若贴图尺寸不是 2 的整数幂,缠绕模式仅允许 [[WrapMode.CLAMP_TO_EDGE]]。
|
||||
* @param wrapS S(U) coordinate wrap mode
|
||||
* @param wrapT T(V) coordinate wrap mode
|
||||
* @param wrapR R(W) coordinate wrap mode
|
||||
*/
|
||||
void setWrapMode(WrapMode wrapS, WrapMode wrapT, WrapMode wrapR);
|
||||
void setWrapMode(WrapMode wrapS, WrapMode wrapT);
|
||||
|
||||
/**
|
||||
* @en Sets the texture's filter mode
|
||||
* @zh 设置此贴图的过滤算法。
|
||||
* @param minFilter Filter mode for scale down
|
||||
* @param magFilter Filter mode for scale up
|
||||
*/
|
||||
void setFilters(Filter minFilter, Filter magFilter);
|
||||
|
||||
/**
|
||||
* @en Sets the texture's mip filter
|
||||
* @zh 设置此贴图的缩小过滤算法。
|
||||
* @param mipFilter Filter mode for scale down
|
||||
*/
|
||||
void setMipFilter(Filter mipFilter);
|
||||
|
||||
/**
|
||||
* @en Sets the texture's anisotropy
|
||||
* @zh 设置此贴图的各向异性。
|
||||
* @param anisotropy
|
||||
*/
|
||||
void setAnisotropy(uint32_t anisotropy);
|
||||
|
||||
/**
|
||||
* @en Destroy the current texture, clear up the related GPU resources.
|
||||
* @zh 销毁此贴图,并释放占用的 GPU 资源。
|
||||
*/
|
||||
bool destroy() override;
|
||||
|
||||
/**
|
||||
* @en Gets the texture hash.
|
||||
* @zh 获取此贴图的哈希值。
|
||||
*/
|
||||
inline ccstd::hash_t getHash() const {
|
||||
return _textureHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the GFX Texture resource
|
||||
* @zh 获取此贴图底层的 GFX 贴图对象。
|
||||
*/
|
||||
virtual gfx::Texture *getGFXTexture() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the internal GFX sampler information.
|
||||
* @zh 获取此贴图内部使用的 GFX 采样器信息。
|
||||
* @private
|
||||
*/
|
||||
virtual const gfx::SamplerInfo &getSamplerInfo() const {
|
||||
return _samplerInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Gets the sampler resource for the texture
|
||||
* @zh 获取此贴图底层的 GFX 采样信息。
|
||||
*/
|
||||
virtual gfx::Sampler *getGFXSampler() const;
|
||||
|
||||
// SERIALIZATION
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
ccstd::any serialize(const ccstd::any &ctxForExporting) override;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
*/
|
||||
void deserialize(const ccstd::any &serializedData, const ccstd::any &handle) override;
|
||||
|
||||
protected:
|
||||
static gfx::Device *getGFXDevice();
|
||||
static gfx::Format getGFXPixelFormat(PixelFormat format);
|
||||
|
||||
gfx::Format getGFXFormat() const;
|
||||
|
||||
void setGFXFormat(const ccstd::optional<PixelFormat> &format);
|
||||
|
||||
private:
|
||||
void notifySamplerUpdated();
|
||||
|
||||
public:
|
||||
/*@serializable*/
|
||||
PixelFormat _format{PixelFormat::RGBA8888};
|
||||
|
||||
/*@serializable*/
|
||||
Filter _minFilter{Filter::LINEAR};
|
||||
|
||||
/*@serializable*/
|
||||
Filter _magFilter{Filter::LINEAR};
|
||||
|
||||
/*@serializable*/
|
||||
Filter _mipFilter{Filter::NONE};
|
||||
|
||||
/*@serializable*/
|
||||
WrapMode _wrapS{WrapMode::REPEAT};
|
||||
|
||||
/*@serializable*/
|
||||
WrapMode _wrapT{WrapMode::REPEAT};
|
||||
|
||||
/*@serializable*/
|
||||
WrapMode _wrapR{WrapMode::REPEAT};
|
||||
|
||||
/*@serializable*/
|
||||
uint32_t _anisotropy{0};
|
||||
|
||||
protected:
|
||||
uint32_t _width{1};
|
||||
uint32_t _height{1};
|
||||
ccstd::string _id;
|
||||
gfx::SamplerInfo _samplerInfo;
|
||||
gfx::Sampler *_gfxSampler{nullptr};
|
||||
gfx::Device *_gfxDevice{nullptr};
|
||||
|
||||
ccstd::hash_t _textureHash{0U};
|
||||
|
||||
private:
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(TextureBase);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
407
cocos/core/assets/TextureCube.cpp
Normal file
407
cocos/core/assets/TextureCube.cpp
Normal file
@@ -0,0 +1,407 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/assets/TextureCube.h"
|
||||
#include "core/assets/ImageAsset.h"
|
||||
#include "core/assets/Texture2D.h"
|
||||
#include "renderer/gfx-base/GFXTexture.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
|
||||
using ForEachFaceCallback = std::function<void(ImageAsset *face, TextureCube::FaceIndex faceIndex)>;
|
||||
/**
|
||||
* @param {Mipmap} mipmap
|
||||
* @param {(face: ImageAsset) => void} callback
|
||||
*/
|
||||
void forEachFace(const ITextureCubeMipmap &mipmap, const ForEachFaceCallback &callback) {
|
||||
callback(mipmap.front, TextureCube::FaceIndex::FRONT);
|
||||
callback(mipmap.back, TextureCube::FaceIndex::BACK);
|
||||
callback(mipmap.left, TextureCube::FaceIndex::LEFT);
|
||||
callback(mipmap.right, TextureCube::FaceIndex::RIGHT);
|
||||
callback(mipmap.top, TextureCube::FaceIndex::TOP);
|
||||
callback(mipmap.bottom, TextureCube::FaceIndex::BOTTOM);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/* static */
|
||||
TextureCube *TextureCube::fromTexture2DArray(const ccstd::vector<Texture2D *> &textures) {
|
||||
size_t nMipmaps = textures.size() / 6;
|
||||
ccstd::vector<ITextureCubeMipmap> mipmaps;
|
||||
mipmaps.reserve(nMipmaps);
|
||||
for (size_t i = 0; i < nMipmaps; i++) {
|
||||
size_t x = i * 6;
|
||||
|
||||
ITextureCubeMipmap mipmap;
|
||||
mipmap.front = textures[x + static_cast<uint32_t>(FaceIndex::FRONT)]->getImage(),
|
||||
mipmap.back = textures[x + static_cast<uint32_t>(FaceIndex::BACK)]->getImage(),
|
||||
mipmap.left = textures[x + static_cast<uint32_t>(FaceIndex::LEFT)]->getImage(),
|
||||
mipmap.right = textures[x + static_cast<uint32_t>(FaceIndex::RIGHT)]->getImage(),
|
||||
mipmap.top = textures[x + static_cast<uint32_t>(FaceIndex::TOP)]->getImage(),
|
||||
mipmap.bottom = textures[x + static_cast<uint32_t>(FaceIndex::BOTTOM)]->getImage(),
|
||||
|
||||
mipmaps.emplace_back(mipmap);
|
||||
}
|
||||
auto *out = ccnew TextureCube();
|
||||
out->setMipmaps(mipmaps);
|
||||
return out;
|
||||
}
|
||||
|
||||
TextureCube::TextureCube() = default;
|
||||
|
||||
TextureCube::~TextureCube() = default;
|
||||
|
||||
void TextureCube::setMipmaps(const ccstd::vector<ITextureCubeMipmap> &value) {
|
||||
_mipmaps = value;
|
||||
|
||||
auto cubeMaps = ccstd::vector<ITextureCubeMipmap>{};
|
||||
if (value.size() == 1) {
|
||||
const auto &cubeMipmap = value.at(0);
|
||||
const auto &front = cubeMipmap.front->extractMipmaps();
|
||||
const auto &back = cubeMipmap.back->extractMipmaps();
|
||||
const auto &left = cubeMipmap.left->extractMipmaps();
|
||||
const auto &right = cubeMipmap.right->extractMipmaps();
|
||||
const auto &top = cubeMipmap.top->extractMipmaps();
|
||||
const auto &bottom = cubeMipmap.bottom->extractMipmaps();
|
||||
|
||||
if (front.size() != back.size() ||
|
||||
front.size() != left.size() ||
|
||||
front.size() != right.size() ||
|
||||
front.size() != top.size() ||
|
||||
front.size() != bottom.size()) {
|
||||
assert("different faces should have the same mipmap level");
|
||||
this->setMipmapParams({});
|
||||
return;
|
||||
}
|
||||
|
||||
const auto level = front.size();
|
||||
|
||||
for (auto i = 0U; i < level; i++) {
|
||||
const auto cubeMap = ITextureCubeMipmap{
|
||||
front[i],
|
||||
back[i],
|
||||
left[i],
|
||||
right[i],
|
||||
top[i],
|
||||
bottom[i],
|
||||
};
|
||||
cubeMaps.emplace_back(cubeMap);
|
||||
}
|
||||
} else if (value.size() > 1) {
|
||||
for (const auto &mipmap : value) {
|
||||
const auto cubeMap = ITextureCubeMipmap{
|
||||
mipmap.front->extractMipmap0(),
|
||||
mipmap.back->extractMipmap0(),
|
||||
mipmap.left->extractMipmap0(),
|
||||
mipmap.right->extractMipmap0(),
|
||||
mipmap.top->extractMipmap0(),
|
||||
mipmap.bottom->extractMipmap0(),
|
||||
};
|
||||
cubeMaps.emplace_back(cubeMap);
|
||||
}
|
||||
}
|
||||
|
||||
setMipmapParams(cubeMaps);
|
||||
}
|
||||
|
||||
void TextureCube::setMipmapParams(const ccstd::vector<ITextureCubeMipmap> &value) {
|
||||
_generatedMipmaps = value;
|
||||
setMipmapLevel(static_cast<uint32_t>(_generatedMipmaps.size()));
|
||||
if (!_generatedMipmaps.empty()) {
|
||||
ImageAsset *imageAsset = _generatedMipmaps[0].front;
|
||||
reset({imageAsset->getWidth(),
|
||||
imageAsset->getHeight(),
|
||||
imageAsset->getFormat(),
|
||||
static_cast<uint32_t>(_generatedMipmaps.size()),
|
||||
_baseLevel,
|
||||
_maxLevel});
|
||||
|
||||
for (size_t level = 0, len = _generatedMipmaps.size(); level < len; ++level) {
|
||||
forEachFace(_generatedMipmaps[level], [this, level](ImageAsset *face, TextureCube::FaceIndex faceIndex) {
|
||||
assignImage(face, static_cast<uint32_t>(level), static_cast<uint32_t>(faceIndex));
|
||||
});
|
||||
}
|
||||
|
||||
} else {
|
||||
reset({0,
|
||||
0,
|
||||
ccstd::nullopt,
|
||||
static_cast<uint32_t>(_generatedMipmaps.size()),
|
||||
_baseLevel,
|
||||
_maxLevel});
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCube::setMipmapAtlas(const TextureCubeMipmapAtlasInfo &value) {
|
||||
if (value.layout.empty()) {
|
||||
return;
|
||||
}
|
||||
_mipmapAtlas = value;
|
||||
const ITextureCubeMipmap &atlas = _mipmapAtlas.atlas;
|
||||
const ccstd::vector<MipmapAtlasLayoutInfo> &layouts = _mipmapAtlas.layout;
|
||||
setMipmapLevel(static_cast<uint32_t>(layouts.size()));
|
||||
|
||||
const MipmapAtlasLayoutInfo &lv0Layout = layouts[0];
|
||||
const ImageAsset *imageAsset = atlas.front;
|
||||
|
||||
reset({lv0Layout.width,
|
||||
lv0Layout.height,
|
||||
imageAsset->getFormat(),
|
||||
static_cast<uint32_t>(layouts.size()),
|
||||
_baseLevel,
|
||||
_maxLevel});
|
||||
|
||||
const uint32_t pixelSize = gfx::GFX_FORMAT_INFOS[static_cast<uint32_t>(imageAsset->getFormat())].size;
|
||||
|
||||
for (size_t level = 0; level < layouts.size(); level++) {
|
||||
const MipmapAtlasLayoutInfo &layoutInfo = layouts[level];
|
||||
uint32_t currentSize = layoutInfo.width * layoutInfo.height * pixelSize;
|
||||
|
||||
//Upload 6 sides by level
|
||||
forEachFace(atlas, [this, currentSize, lv0Layout, layoutInfo, level, pixelSize](ImageAsset *face, TextureCube::FaceIndex faceIndex) {
|
||||
auto *buffer = ccnew uint8_t[currentSize];
|
||||
memset(buffer, 0, currentSize);
|
||||
const uint8_t *data = face->getData();
|
||||
//Splitting Atlas
|
||||
if (level == 0) {
|
||||
memcpy(buffer, data, currentSize);
|
||||
} else {
|
||||
uint32_t bufferOffset = 0;
|
||||
uint32_t dateOffset = lv0Layout.width * lv0Layout.height * pixelSize;
|
||||
uint32_t leftOffset = layoutInfo.left * pixelSize;
|
||||
for (size_t j = 0; j < layoutInfo.height; j++) {
|
||||
memcpy(buffer + bufferOffset, data + dateOffset + leftOffset, layoutInfo.width * pixelSize);
|
||||
bufferOffset += layoutInfo.width * pixelSize;
|
||||
dateOffset += lv0Layout.width * pixelSize;
|
||||
}
|
||||
}
|
||||
auto *tempAsset = ccnew ImageAsset();
|
||||
tempAsset->addRef();
|
||||
auto *arrayBuffer = ccnew ArrayBuffer(buffer, static_cast<uint32_t>(currentSize));
|
||||
IMemoryImageSource source{arrayBuffer, face->isCompressed(), layoutInfo.width, layoutInfo.height, face->getFormat()};
|
||||
tempAsset->setNativeAsset(source);
|
||||
|
||||
assignImage(tempAsset, static_cast<uint32_t>(level), static_cast<uint32_t>(faceIndex));
|
||||
CC_SAFE_DELETE_ARRAY(buffer);
|
||||
tempAsset->release();
|
||||
tempAsset = nullptr;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCube::setMipmapsForJS(const ccstd::vector<ITextureCubeMipmap> &value) {
|
||||
_mipmaps = value;
|
||||
}
|
||||
|
||||
void TextureCube::setMipmapAtlasForJS(const TextureCubeMipmapAtlasInfo &value) {
|
||||
_mipmapAtlas = value;
|
||||
}
|
||||
|
||||
void TextureCube::setImage(const ITextureCubeMipmap *value) {
|
||||
if (value != nullptr) {
|
||||
setMipmaps({*value});
|
||||
} else {
|
||||
setMipmaps({});
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCube::reset(const ITextureCubeCreateInfo &info) {
|
||||
_width = info.width;
|
||||
_height = info.height;
|
||||
setGFXFormat(info.format);
|
||||
|
||||
uint32_t mipLevels = info.mipmapLevel.has_value() ? info.mipmapLevel.value() : 1;
|
||||
setMipmapLevel(mipLevels);
|
||||
|
||||
uint32_t minLod = info.baseLevel.has_value() ? info.baseLevel.value() : 0;
|
||||
uint32_t maxLod = info.maxLevel.has_value() ? info.maxLevel.value() : 1000;
|
||||
setMipRange(minLod, maxLod);
|
||||
|
||||
tryReset();
|
||||
}
|
||||
|
||||
void TextureCube::releaseTexture() {
|
||||
destroy();
|
||||
}
|
||||
|
||||
void TextureCube::updateMipmaps(uint32_t firstLevel, uint32_t count) {
|
||||
if (firstLevel >= _generatedMipmaps.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto nUpdate = static_cast<uint32_t>(std::min(
|
||||
count == 0 ? _generatedMipmaps.size() : count,
|
||||
_generatedMipmaps.size() - firstLevel));
|
||||
|
||||
for (uint32_t i = 0; i < nUpdate; ++i) {
|
||||
uint32_t level = firstLevel + i;
|
||||
forEachFace(_generatedMipmaps[level], [this, level](auto face, auto faceIndex) {
|
||||
assignImage(face, level, static_cast<uint32_t>(faceIndex));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool TextureCube::isUsingOfflineMipmaps() {
|
||||
return _mipmapMode == MipmapMode::BAKED_CONVOLUTION_MAP;
|
||||
}
|
||||
|
||||
void TextureCube::initialize() {
|
||||
if (_mipmapMode == MipmapMode::BAKED_CONVOLUTION_MAP) {
|
||||
setMipmapAtlas(_mipmapAtlas);
|
||||
} else {
|
||||
setMipmaps(_mipmaps);
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCube::onLoaded() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
bool TextureCube::destroy() {
|
||||
_mipmaps.clear();
|
||||
_generatedMipmaps.clear();
|
||||
_mipmapAtlas.layout.clear();
|
||||
return Super::destroy();
|
||||
}
|
||||
|
||||
ccstd::any TextureCube::serialize(const ccstd::any & /*ctxForExporting*/) {
|
||||
//cjh TODO: if (EDITOR || TEST) {
|
||||
// return {
|
||||
// base: super._serialize(ctxForExporting),
|
||||
// rgbe: this.isRGBE,
|
||||
// mipmaps: this._mipmaps.map((mipmap) => ((ctxForExporting && ctxForExporting._compressUuid) ? {
|
||||
// front: EditorExtends.UuidUtils.compressUuid(mipmap.front._uuid, true),
|
||||
// back: EditorExtends.UuidUtils.compressUuid(mipmap.back._uuid, true),
|
||||
// left: EditorExtends.UuidUtils.compressUuid(mipmap.left._uuid, true),
|
||||
// right: EditorExtends.UuidUtils.compressUuid(mipmap.right._uuid, true),
|
||||
// top: EditorExtends.UuidUtils.compressUuid(mipmap.top._uuid, true),
|
||||
// bottom: EditorExtends.UuidUtils.compressUuid(mipmap.bottom._uuid, true),
|
||||
// } : {
|
||||
// front: mipmap.front._uuid,
|
||||
// back: mipmap.back._uuid,
|
||||
// left: mipmap.left._uuid,
|
||||
// right: mipmap.right._uuid,
|
||||
// top: mipmap.top._uuid,
|
||||
// bottom: mipmap.bottom._uuid,
|
||||
// })),
|
||||
// };
|
||||
// }
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TextureCube::deserialize(const ccstd::any &serializedData, const ccstd::any &handle) {
|
||||
const auto *data = ccstd::any_cast<TextureCubeSerializeData>(&serializedData);
|
||||
if (data == nullptr) {
|
||||
return;
|
||||
}
|
||||
Super::deserialize(data->base, handle);
|
||||
isRGBE = data->rgbe;
|
||||
_mipmapMode = data->mipmapMode;
|
||||
|
||||
_mipmaps.resize(data->mipmaps.size());
|
||||
for (size_t i = 0; i < data->mipmaps.size(); ++i) {
|
||||
// Prevent resource load failed
|
||||
ITextureCubeMipmap mipmap;
|
||||
mipmap.front = ccnew ImageAsset(),
|
||||
mipmap.back = ccnew ImageAsset(),
|
||||
mipmap.left = ccnew ImageAsset(),
|
||||
mipmap.right = ccnew ImageAsset(),
|
||||
mipmap.top = ccnew ImageAsset(),
|
||||
mipmap.bottom = ccnew ImageAsset();
|
||||
_mipmaps[i] = mipmap;
|
||||
// auto* mipmap = data->mipmaps[i];
|
||||
|
||||
//cjh TODO: what's handle.result?? const imageAssetClassId = js.getClassId(ImageAsset);
|
||||
//
|
||||
// handle.result.push(this._mipmaps[i], `front`, mipmap.front, imageAssetClassId);
|
||||
// handle.result.push(this._mipmaps[i], `back`, mipmap.back, imageAssetClassId);
|
||||
// handle.result.push(this._mipmaps[i], `left`, mipmap.left, imageAssetClassId);
|
||||
// handle.result.push(this._mipmaps[i], `right`, mipmap.right, imageAssetClassId);
|
||||
// handle.result.push(this._mipmaps[i], `top`, mipmap.top, imageAssetClassId);
|
||||
// handle.result.push(this._mipmaps[i], `bottom`, mipmap.bottom, imageAssetClassId);
|
||||
}
|
||||
}
|
||||
|
||||
gfx::TextureInfo TextureCube::getGfxTextureCreateInfo(gfx::TextureUsageBit usage, gfx::Format format, uint32_t levelCount, gfx::TextureFlagBit flags) {
|
||||
gfx::TextureInfo texInfo;
|
||||
texInfo.type = gfx::TextureType::CUBE;
|
||||
texInfo.width = _width;
|
||||
texInfo.height = _height;
|
||||
texInfo.layerCount = 6;
|
||||
texInfo.usage = usage;
|
||||
texInfo.format = format;
|
||||
texInfo.levelCount = levelCount;
|
||||
texInfo.flags = flags;
|
||||
return texInfo;
|
||||
}
|
||||
|
||||
gfx::TextureViewInfo TextureCube::getGfxTextureViewCreateInfo(gfx::Texture *texture, gfx::Format format, uint32_t baseLevel, uint32_t levelCount) {
|
||||
gfx::TextureViewInfo texViewInfo;
|
||||
texViewInfo.type = gfx::TextureType::CUBE;
|
||||
texViewInfo.baseLayer = 0;
|
||||
texViewInfo.layerCount = 6;
|
||||
texViewInfo.texture = texture;
|
||||
texViewInfo.format = format;
|
||||
texViewInfo.baseLevel = baseLevel;
|
||||
texViewInfo.levelCount = levelCount;
|
||||
return texViewInfo;
|
||||
}
|
||||
|
||||
void TextureCube::initDefault(const ccstd::optional<ccstd::string> &uuid) {
|
||||
Super::initDefault(uuid);
|
||||
|
||||
auto *imageAsset = ccnew ImageAsset();
|
||||
imageAsset->initDefault(ccstd::nullopt);
|
||||
|
||||
ITextureCubeMipmap mipmap;
|
||||
|
||||
mipmap.front = imageAsset;
|
||||
mipmap.back = imageAsset;
|
||||
mipmap.top = imageAsset;
|
||||
mipmap.bottom = imageAsset;
|
||||
mipmap.left = imageAsset;
|
||||
mipmap.right = imageAsset;
|
||||
|
||||
setMipmaps({mipmap});
|
||||
}
|
||||
|
||||
bool TextureCube::validate() const {
|
||||
if (_mipmapMode == MipmapMode::BAKED_CONVOLUTION_MAP) {
|
||||
if (_mipmapAtlas.layout.empty()) {
|
||||
return false;
|
||||
}
|
||||
return (_mipmapAtlas.atlas.top && _mipmapAtlas.atlas.bottom && _mipmapAtlas.atlas.front && _mipmapAtlas.atlas.back && _mipmapAtlas.atlas.left && _mipmapAtlas.atlas.right);
|
||||
}
|
||||
if (_mipmaps.empty()) {
|
||||
return false;
|
||||
}
|
||||
return std::all_of(_mipmaps.begin(),
|
||||
_mipmaps.end(),
|
||||
[&](const ITextureCubeMipmap &mipmap) {
|
||||
return (mipmap.top && mipmap.bottom && mipmap.front && mipmap.back && mipmap.left && mipmap.right);
|
||||
});
|
||||
}
|
||||
} // namespace cc
|
||||
270
cocos/core/assets/TextureCube.h
Normal file
270
cocos/core/assets/TextureCube.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/assets/Asset.h"
|
||||
#include "core/assets/SimpleTexture.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
class ImageAsset;
|
||||
class Texture2D;
|
||||
struct ITexture2DCreateInfo;
|
||||
|
||||
using ITextureCubeCreateInfo = ITexture2DCreateInfo;
|
||||
|
||||
/**
|
||||
* @en The texture cube mipmap interface
|
||||
* @zh 立方体贴图的 Mipmap 接口。
|
||||
*/
|
||||
struct ITextureCubeMipmap {
|
||||
IntrusivePtr<ImageAsset> front;
|
||||
IntrusivePtr<ImageAsset> back;
|
||||
IntrusivePtr<ImageAsset> left;
|
||||
IntrusivePtr<ImageAsset> right;
|
||||
IntrusivePtr<ImageAsset> top;
|
||||
IntrusivePtr<ImageAsset> bottom;
|
||||
};
|
||||
|
||||
struct ITextureCubeSerializeMipmapData {
|
||||
ccstd::string front;
|
||||
ccstd::string back;
|
||||
ccstd::string left;
|
||||
ccstd::string right;
|
||||
ccstd::string top;
|
||||
ccstd::string bottom;
|
||||
};
|
||||
|
||||
/**
|
||||
* @en The MipmapAtlas region interface
|
||||
* @zh MipmapAtlas的region接口。
|
||||
*/
|
||||
struct MipmapAtlasLayoutInfo {
|
||||
uint32_t left{0};
|
||||
uint32_t top{0};
|
||||
uint32_t width{0};
|
||||
uint32_t height{0};
|
||||
uint32_t level{0};
|
||||
};
|
||||
/**
|
||||
* @en The texture cube MipmapAtlas interface
|
||||
* @zh 立方体贴图的 MipmapAtlas 接口。
|
||||
*/
|
||||
struct TextureCubeMipmapAtlasInfo {
|
||||
ITextureCubeMipmap atlas;
|
||||
ccstd::vector<MipmapAtlasLayoutInfo> layout;
|
||||
};
|
||||
|
||||
/**
|
||||
* @en The way to fill mipmaps.
|
||||
* @zh 填充mipmaps的方式。
|
||||
*/
|
||||
enum class MipmapMode {
|
||||
/**
|
||||
* @zh
|
||||
* 不使用mipmaps
|
||||
* @en
|
||||
* Not using mipmaps
|
||||
* @readonly
|
||||
*/
|
||||
NONE = 0,
|
||||
/**
|
||||
* @zh
|
||||
* 使用自动生成的mipmaps
|
||||
* @en
|
||||
* Using the automatically generated mipmaps
|
||||
* @readonly
|
||||
*/
|
||||
AUTO = 1,
|
||||
/**
|
||||
* @zh
|
||||
* 使用卷积图填充mipmaps
|
||||
* @en
|
||||
* Filling mipmaps with convolutional maps.
|
||||
* @readonly
|
||||
*/
|
||||
BAKED_CONVOLUTION_MAP = 2
|
||||
};
|
||||
struct TextureCubeSerializeData {
|
||||
ccstd::string base;
|
||||
bool rgbe{false};
|
||||
MipmapMode mipmapMode{MipmapMode::NONE};
|
||||
ccstd::vector<ITextureCubeSerializeMipmapData> mipmaps;
|
||||
TextureCubeMipmapAtlasInfo mipmapAtlas;
|
||||
};
|
||||
|
||||
/**
|
||||
* @en The texture cube asset.
|
||||
* Each mipmap level of a texture cube have 6 [[ImageAsset]], represents 6 faces of the cube.
|
||||
* @zh 立方体贴图资源。
|
||||
* 立方体贴图资源的每个 Mipmap 层级都为 6 张 [[ImageAsset]],分别代表了立方体贴图的 6 个面。
|
||||
*/
|
||||
class TextureCube final : public SimpleTexture {
|
||||
public:
|
||||
using Super = SimpleTexture;
|
||||
|
||||
TextureCube();
|
||||
~TextureCube() override;
|
||||
|
||||
/**
|
||||
* @en The index for all faces of the cube
|
||||
* @zh 立方体每个面的约定索引。
|
||||
*/
|
||||
enum class FaceIndex {
|
||||
RIGHT = 0,
|
||||
LEFT = 1,
|
||||
TOP = 2,
|
||||
BOTTOM = 3,
|
||||
FRONT = 4,
|
||||
BACK = 5,
|
||||
};
|
||||
|
||||
/**
|
||||
* @en Create a texture cube with an array of [[Texture2D]] which represents 6 faces of the texture cube.
|
||||
* @zh 通过二维贴图数组指定每个 Mipmap 的每个面创建立方体贴图。
|
||||
* @param textures Texture array, the texture count must be multiple of 6. Every 6 textures are 6 faces of a mipmap level.
|
||||
* The order should obey [[FaceIndex]] order.
|
||||
* @param out Output texture cube, if not given, will create a new texture cube.
|
||||
* @returns The created texture cube.
|
||||
* @example
|
||||
* ```ts
|
||||
* const textures = new Array<Texture2D>(6);
|
||||
* textures[TextureCube.FaceIndex.front] = frontImage;
|
||||
* textures[TextureCube.FaceIndex.back] = backImage;
|
||||
* textures[TextureCube.FaceIndex.left] = leftImage;
|
||||
* textures[TextureCube.FaceIndex.right] = rightImage;
|
||||
* textures[TextureCube.FaceIndex.top] = topImage;
|
||||
* textures[TextureCube.FaceIndex.bottom] = bottomImage;
|
||||
* const textureCube = TextureCube.fromTexture2DArray(textures);
|
||||
* ```
|
||||
*/
|
||||
static TextureCube *fromTexture2DArray(const ccstd::vector<Texture2D *> &textures);
|
||||
|
||||
/**
|
||||
* @en All levels of mipmap images, be noted, automatically generated mipmaps are not included.
|
||||
* When setup mipmap, the size of the texture and pixel format could be modified.
|
||||
* @zh 所有层级 Mipmap,注意,这里不包含自动生成的 Mipmap。
|
||||
* 当设置 Mipmap 时,贴图的尺寸以及像素格式可能会改变。
|
||||
*/
|
||||
const ccstd::vector<ITextureCubeMipmap> &getMipmaps() const {
|
||||
return _mipmaps;
|
||||
}
|
||||
|
||||
inline const TextureCubeMipmapAtlasInfo &getMipmapAtlas() const {
|
||||
return _mipmapAtlas;
|
||||
}
|
||||
|
||||
void setMipmaps(const ccstd::vector<ITextureCubeMipmap> &value);
|
||||
|
||||
void setMipmapsForJS(const ccstd::vector<ITextureCubeMipmap> &value);
|
||||
|
||||
void setMipmapAtlasForJS(const TextureCubeMipmapAtlasInfo &value);
|
||||
|
||||
/**
|
||||
* @en Fill mipmaps with convolutional maps.
|
||||
* @zh 使用卷积图填充mipmaps。
|
||||
* @param value All mipmaps of each face of the cube map are stored in the form of atlas.
|
||||
* and the value contains the atlas of the 6 faces and the layout information of each mipmap layer.
|
||||
*/
|
||||
void setMipmapAtlas(const TextureCubeMipmapAtlasInfo &value);
|
||||
|
||||
/**
|
||||
* @en Level 0 mipmap image.
|
||||
* Be noted, `this.image = img` equals `this.mipmaps = [img]`,
|
||||
* sets image will clear all previous mipmaps.
|
||||
* @zh 0 级 Mipmap。
|
||||
* 注意,`this.image = img` 等价于 `this.mipmaps = [img]`,
|
||||
* 也就是说,通过 `this.image` 设置 0 级 Mipmap 时将隐式地清除之前的所有 Mipmap。
|
||||
*/
|
||||
const ITextureCubeMipmap *getImage() const {
|
||||
return _mipmaps.empty() ? nullptr : &_mipmaps[0];
|
||||
}
|
||||
|
||||
void setImage(const ITextureCubeMipmap *value);
|
||||
|
||||
/**
|
||||
* @en Reset the current texture with given size, pixel format and mipmap images.
|
||||
* After reset, the gfx resource will become invalid, you must use [[uploadData]] explicitly to upload the new mipmaps to GPU resources.
|
||||
* @zh 将当前贴图重置为指定尺寸、像素格式以及指定 mipmap 层级。重置后,贴图的像素数据将变为未定义。
|
||||
* mipmap 图像的数据不会自动更新到贴图中,你必须显式调用 [[uploadData]] 来上传贴图数据。
|
||||
* @param info The create information
|
||||
*/
|
||||
void reset(const ITextureCubeCreateInfo &info);
|
||||
|
||||
/**
|
||||
* @en Release used GPU resources.
|
||||
* @zh 释放占用的 GPU 资源。
|
||||
* @deprecated please use [[destroy]] instead
|
||||
*/
|
||||
void releaseTexture();
|
||||
|
||||
// Override functions
|
||||
void updateMipmaps(uint32_t firstLevel, uint32_t count) override;
|
||||
|
||||
/**
|
||||
* @en Whether mipmaps are baked convolutional maps.
|
||||
* @zh mipmaps是否为烘焙出来的卷积图。
|
||||
*/
|
||||
bool isUsingOfflineMipmaps() override;
|
||||
|
||||
void initialize();
|
||||
void onLoaded() override;
|
||||
/**
|
||||
* 销毁此贴图,清空所有 Mipmap 并释放占用的 GPU 资源。
|
||||
*/
|
||||
bool destroy() override;
|
||||
|
||||
ccstd::any serialize(const ccstd::any &ctxForExporting) override;
|
||||
void deserialize(const ccstd::any &serializedData, const ccstd::any &handle) override;
|
||||
|
||||
gfx::TextureInfo getGfxTextureCreateInfo(gfx::TextureUsageBit usage, gfx::Format format, uint32_t levelCount, gfx::TextureFlagBit flags) override;
|
||||
gfx::TextureViewInfo getGfxTextureViewCreateInfo(gfx::Texture *texture, gfx::Format format, uint32_t baseLevel, uint32_t levelCount) override;
|
||||
|
||||
void initDefault(const ccstd::optional<ccstd::string> &uuid) override;
|
||||
|
||||
bool validate() const override;
|
||||
//
|
||||
|
||||
/*@serializable*/
|
||||
MipmapMode _mipmapMode{MipmapMode::NONE};
|
||||
|
||||
/*@serializable*/
|
||||
bool isRGBE{false};
|
||||
|
||||
private:
|
||||
void setMipmapParams(const ccstd::vector<ITextureCubeMipmap> &value);
|
||||
|
||||
/*@serializable*/
|
||||
ccstd::vector<ITextureCubeMipmap> _mipmaps;
|
||||
|
||||
ccstd::vector<ITextureCubeMipmap> _generatedMipmaps;
|
||||
|
||||
/*@serializable*/
|
||||
TextureCubeMipmapAtlasInfo _mipmapAtlas;
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(TextureCube);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
279
cocos/core/builtin/BuiltinResMgr.cpp
Normal file
279
cocos/core/builtin/BuiltinResMgr.cpp
Normal file
@@ -0,0 +1,279 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/builtin/BuiltinResMgr.h"
|
||||
#include "core/assets/EffectAsset.h"
|
||||
#include "core/assets/ImageAsset.h"
|
||||
#include "core/assets/Material.h"
|
||||
#include "core/assets/Texture2D.h"
|
||||
#include "core/assets/TextureCube.h"
|
||||
#include "math/Color.h"
|
||||
#include "platform/Image.h"
|
||||
#include "rapidjson/document.h"
|
||||
#include "renderer/core/ProgramLib.h"
|
||||
#include "scene/Pass.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t BLACK_IMAGE_RGBA_DATA_2X2[2 * 2 * 4] = {
|
||||
// r, g, b, a
|
||||
0x00, 0x00, 0x00, 0xFF,
|
||||
0x00, 0x00, 0x00, 0xFF,
|
||||
0x00, 0x00, 0x00, 0xFF,
|
||||
0x00, 0x00, 0x00, 0xFF};
|
||||
|
||||
constexpr uint8_t GREY_IMAGE_RGBA_DATA_2X2[2 * 2 * 4] = {
|
||||
0x77, 0x77, 0x77, 0xFF,
|
||||
0x77, 0x77, 0x77, 0xFF,
|
||||
0x77, 0x77, 0x77, 0xFF,
|
||||
0x77, 0x77, 0x77, 0xFF};
|
||||
|
||||
constexpr uint8_t WHITE_IMAGE_RGBA_DATA_2X2[2 * 2 * 4] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF};
|
||||
|
||||
constexpr uint8_t NORMAL_IMAGE_RGBA_DATA_2X2[2 * 2 * 4] = {
|
||||
0x7F, 0x7F, 0xFF, 0xFF,
|
||||
0x7F, 0x7F, 0xFF, 0xFF,
|
||||
0x7F, 0x7F, 0xFF, 0xFF,
|
||||
0x7F, 0x7F, 0xFF, 0xFF};
|
||||
|
||||
constexpr uint8_t EMPTY_IMAGE_RGBA_DATA_2X2[2 * 2 * 4] = {
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
const uint8_t DEFAULT_IMAGE_RGBA_DATA_16X16[16 * 16 * 4] = {
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF, 0xDD, 0xDD, 0xDD, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF,
|
||||
0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF, 0x55, 0x55, 0x55, 0xFF};
|
||||
|
||||
} // namespace
|
||||
|
||||
BuiltinResMgr *BuiltinResMgr::instance = nullptr;
|
||||
|
||||
/* static */
|
||||
BuiltinResMgr *BuiltinResMgr::getInstance() {
|
||||
return BuiltinResMgr::instance;
|
||||
}
|
||||
|
||||
BuiltinResMgr::BuiltinResMgr() {
|
||||
BuiltinResMgr::instance = this;
|
||||
}
|
||||
|
||||
BuiltinResMgr::~BuiltinResMgr() {
|
||||
BuiltinResMgr::instance = nullptr;
|
||||
}
|
||||
|
||||
void BuiltinResMgr::addAsset(const ccstd::string &uuid, Asset *asset) {
|
||||
_resources.emplace(uuid, asset);
|
||||
}
|
||||
|
||||
Asset *BuiltinResMgr::getAsset(const ccstd::string &uuid) {
|
||||
auto iter = _resources.find(uuid);
|
||||
if (iter != _resources.end()) {
|
||||
return iter->second.get();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool BuiltinResMgr::initBuiltinRes() {
|
||||
if (_isInitialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
|
||||
// NOTE: C++ use const array to store color value, no need to synchronize ts's valueView logic
|
||||
|
||||
// black texture
|
||||
initTexture2DWithUuid("black-texture", BLACK_IMAGE_RGBA_DATA_2X2, sizeof(BLACK_IMAGE_RGBA_DATA_2X2), 2, 2);
|
||||
|
||||
// empty texture
|
||||
initTexture2DWithUuid("empty-texture", EMPTY_IMAGE_RGBA_DATA_2X2, sizeof(EMPTY_IMAGE_RGBA_DATA_2X2), 2, 2);
|
||||
|
||||
// grey texture
|
||||
initTexture2DWithUuid("grey-texture", GREY_IMAGE_RGBA_DATA_2X2, sizeof(GREY_IMAGE_RGBA_DATA_2X2), 2, 2);
|
||||
|
||||
// white texture
|
||||
initTexture2DWithUuid("white-texture", WHITE_IMAGE_RGBA_DATA_2X2, sizeof(WHITE_IMAGE_RGBA_DATA_2X2), 2, 2);
|
||||
|
||||
// normal texture
|
||||
initTexture2DWithUuid("normal-texture", NORMAL_IMAGE_RGBA_DATA_2X2, sizeof(NORMAL_IMAGE_RGBA_DATA_2X2), 2, 2);
|
||||
|
||||
// default texture
|
||||
initTexture2DWithUuid("default-texture", DEFAULT_IMAGE_RGBA_DATA_16X16, sizeof(DEFAULT_IMAGE_RGBA_DATA_16X16), 16, 16);
|
||||
|
||||
// black cube texture
|
||||
initTextureCubeWithUuid("black-cube-texture", BLACK_IMAGE_RGBA_DATA_2X2, sizeof(BLACK_IMAGE_RGBA_DATA_2X2), 2, 2);
|
||||
|
||||
// grey cube texture
|
||||
initTextureCubeWithUuid("grey-cube-texture", GREY_IMAGE_RGBA_DATA_2X2, sizeof(GREY_IMAGE_RGBA_DATA_2X2), 2, 2);
|
||||
|
||||
// white cube texture
|
||||
initTextureCubeWithUuid("white-cube-texture", WHITE_IMAGE_RGBA_DATA_2X2, sizeof(WHITE_IMAGE_RGBA_DATA_2X2), 2, 2);
|
||||
|
||||
// default cube texture
|
||||
initTextureCubeWithUuid("default-cube-texture", DEFAULT_IMAGE_RGBA_DATA_16X16, sizeof(DEFAULT_IMAGE_RGBA_DATA_16X16), 16, 16);
|
||||
|
||||
//cjh TODO: if (SpriteFrame) {
|
||||
// const spriteFrame = ccnew SpriteFrame() as SpriteFrame;
|
||||
// const image = imgAsset;
|
||||
// const texture = ccnew Texture2D();
|
||||
// texture.image = image;
|
||||
// spriteFrame.texture = texture;
|
||||
// spriteFrame._uuid = 'default-spriteframe";
|
||||
// resources[spriteFrame->getUuid()] = spriteFrame;
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return Promise.resolve().then(() => {
|
||||
|
||||
// initMaterials();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BuiltinResMgr::initTexture2DWithUuid(const ccstd::string &uuid, const uint8_t *data, size_t dataBytes, uint32_t width, uint32_t height) {
|
||||
IMemoryImageSource imageSource;
|
||||
imageSource.width = width;
|
||||
imageSource.height = height;
|
||||
imageSource.data = ccnew ArrayBuffer(data, static_cast<uint32_t>(dataBytes));
|
||||
imageSource.compressed = false;
|
||||
imageSource.format = PixelFormat::RGBA8888;
|
||||
|
||||
auto *texture = ccnew Texture2D();
|
||||
if (texture) {
|
||||
texture->setUuid(uuid);
|
||||
|
||||
auto *imgAsset = ccnew ImageAsset();
|
||||
imgAsset->setNativeAsset(imageSource);
|
||||
texture->setImage(imgAsset);
|
||||
|
||||
texture->initialize();
|
||||
_resources.emplace(texture->getUuid(), texture);
|
||||
}
|
||||
}
|
||||
|
||||
void BuiltinResMgr::initTextureCubeWithUuid(const ccstd::string &uuid, const uint8_t *data, size_t dataBytes, uint32_t width, uint32_t height) {
|
||||
IMemoryImageSource imageSource;
|
||||
imageSource.width = width;
|
||||
imageSource.height = height;
|
||||
imageSource.data = ccnew ArrayBuffer(data, static_cast<uint32_t>(dataBytes));
|
||||
imageSource.compressed = false;
|
||||
imageSource.format = PixelFormat::RGBA8888;
|
||||
|
||||
auto *texture = ccnew TextureCube();
|
||||
if (texture) {
|
||||
texture->setUuid(uuid);
|
||||
texture->setMipFilter(TextureCube::Filter::NEAREST);
|
||||
|
||||
ITextureCubeMipmap mipmap;
|
||||
mipmap.front = ccnew ImageAsset();
|
||||
mipmap.front->setNativeAsset(imageSource);
|
||||
mipmap.back = ccnew ImageAsset();
|
||||
mipmap.back->setNativeAsset(imageSource);
|
||||
mipmap.left = ccnew ImageAsset();
|
||||
mipmap.left->setNativeAsset(imageSource);
|
||||
mipmap.right = ccnew ImageAsset();
|
||||
mipmap.right->setNativeAsset(imageSource);
|
||||
mipmap.top = ccnew ImageAsset();
|
||||
mipmap.top->setNativeAsset(imageSource);
|
||||
mipmap.bottom = ccnew ImageAsset();
|
||||
mipmap.bottom->setNativeAsset(imageSource);
|
||||
|
||||
texture->setImage(&mipmap);
|
||||
|
||||
texture->initialize();
|
||||
_resources.emplace(texture->getUuid(), texture);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
71
cocos/core/builtin/BuiltinResMgr.h
Normal file
71
cocos/core/builtin/BuiltinResMgr.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "base/Ptr.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "core/assets/Asset.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace gfx {
|
||||
class Device;
|
||||
}
|
||||
|
||||
class Material;
|
||||
class Asset;
|
||||
|
||||
class BuiltinResMgr final {
|
||||
public:
|
||||
static BuiltinResMgr *getInstance();
|
||||
|
||||
BuiltinResMgr();
|
||||
~BuiltinResMgr();
|
||||
|
||||
bool initBuiltinRes();
|
||||
inline bool isInitialized() const { return _isInitialized; }
|
||||
|
||||
void addAsset(const ccstd::string &uuid, Asset *asset);
|
||||
Asset *getAsset(const ccstd::string &uuid);
|
||||
|
||||
template <typename T, typename Enabled = std::enable_if_t<std::is_base_of<Asset, T>::value>>
|
||||
T *get(const ccstd::string &uuid) {
|
||||
return static_cast<T *>(getAsset(uuid));
|
||||
}
|
||||
|
||||
private:
|
||||
void initTexture2DWithUuid(const ccstd::string &uuid, const uint8_t *data, size_t dataBytes, uint32_t width, uint32_t height);
|
||||
void initTextureCubeWithUuid(const ccstd::string &uuid, const uint8_t *data, size_t dataBytes, uint32_t width, uint32_t height);
|
||||
|
||||
static BuiltinResMgr *instance;
|
||||
|
||||
ccstd::unordered_map<ccstd::string, IntrusivePtr<Asset>> _resources;
|
||||
bool _isInitialized{false};
|
||||
|
||||
CC_DISALLOW_COPY_MOVE_ASSIGN(BuiltinResMgr);
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
493
cocos/core/builtin/DebugInfos.cpp
Normal file
493
cocos/core/builtin/DebugInfos.cpp
Normal file
@@ -0,0 +1,493 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
// clang-format off
|
||||
|
||||
#include "DebugInfos.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
ccstd::unordered_map<uint32_t, ccstd::string> debugInfos = {
|
||||
{ 0100, "%s not yet implemented." },
|
||||
{ 0200, "You should specify a valid DOM canvas element." },
|
||||
{ 1006, "[Action step]. override me" },
|
||||
{ 1007, "[Action update]. override me" },
|
||||
{ 1008, "[Action reverse]. override me" },
|
||||
{ 1100, "Expected 'data' dict, but not found. Config file: %s" },
|
||||
{ 1101, "Please load the resource first : %s" },
|
||||
{ 1102, "Effect settings not found, effects will not be imported." },
|
||||
{ 1103, "Success to load scene: %s" },
|
||||
{ 1200, "cocos2d: Director: Error in gettimeofday" },
|
||||
{ 1204, "Running scene should not be null" },
|
||||
{ 1205, "The scene should not be null" },
|
||||
{ 1206, "loadScene: The scene index to load (%s) is out of range." },
|
||||
{ 1207, "loadScene: Unknown name type to load: '%s'" },
|
||||
{ 1208, "loadScene: Failed to load scene '%s' because '%s' is already being loaded." },
|
||||
{ 1209, "loadScene: Can not load the scene '%s' because it was not in the build settings before playing." },
|
||||
{ 1210, "Failed to preload '%s', %s" },
|
||||
{ 1211, "loadScene: The scene index to load (%s) is out of range." },
|
||||
{ 1212, "loadScene: Unknown name type to load: '%s'" },
|
||||
{ 1213, "loadScene: Failed to load scene '%s' because '%s' is already loading" },
|
||||
{ 1214, "loadScene: Can not load the scene '%s' because it was not in the build settings before playing." },
|
||||
{ 1215, "Failed to preload '%s', %s" },
|
||||
{ 1216, "Director.runSceneImmediate: scene is not valid" },
|
||||
{ 1217, "Director._initOnEngineInitialized: renderer root initialization failed" },
|
||||
{ 1218, "Forward render pipeline initialized." },
|
||||
{ 1219, "Deferred render pipeline initialized. Note that non-transparent materials with no lighting will not be rendered, such as builtin-unlit." },
|
||||
{ 1220, "Failed to set shading scale, pipelineSceneData is invalid." },
|
||||
{ 1221, "Setting orientation is not supported yet." },
|
||||
{ 1300, "%s is not in the model pool and cannot be destroyed by destroyModel." },
|
||||
{ 1400, "'%s' is deprecated, please use '%s' instead." },
|
||||
{ 1404, "cc.spriteFrameCache is removed, please use cc.loader to load and cache sprite frames of atlas format." },
|
||||
{ 1406, "'%s.%s' is removed" },
|
||||
{ 1408, "'%s' is removed" },
|
||||
{ 1409, "element type is wrong!" },
|
||||
{ 1502, "cc.scheduler.scheduleCallbackForTarget(): target should be non-null." },
|
||||
{ 1503, "cc.Scheduler.pauseTarget():target should be non-null" },
|
||||
{ 1504, "cc.Scheduler.resumeTarget():target should be non-null" },
|
||||
{ 1505, "cc.Scheduler.isTargetPaused():target should be non-null" },
|
||||
{ 1506, "warning: you CANNOT change update priority in scheduled function" },
|
||||
{ 1507, "scheduler#scheduleSelector. Selector already scheduled. Updating interval from: %.4f to %.4f" },
|
||||
{ 1508, "Argument callback must not be empty" },
|
||||
{ 1509, "Argument target must be non-nullptr" },
|
||||
{ 1510, "cc.Scheduler: Illegal target which doesn't have id, you should do Scheduler.enableForTarget(target) before all scheduler API usage on target" },
|
||||
{ 1511, "cc.Scheduler: pause state of the scheduled task doesn't match the element pause state in Scheduler, the given paused state will be ignored." },
|
||||
{ 1513, "cc.Scheduler: scheduler stopped using `__instanceId` as id since v2.0, you should do Scheduler.enableForTarget(target) before all scheduler API usage on target" },
|
||||
{ 1514, "since v3.8.0, `Scheduler.schedule(target, callback, interval)` is deprecated, please use `Scheduler.schedule(callback, target, interval)` instead." },
|
||||
{ 1607, "removeFromParentAndCleanup is deprecated. Use removeFromParent instead" },
|
||||
{ 1619, "callback function must be non-null" },
|
||||
{ 1620, "interval must be positive" },
|
||||
{ 1623, "Set '%s' to normal node (not persist root node)." },
|
||||
{ 1624, "Replacing with the same sgNode" },
|
||||
{ 1625, "The replacement sgNode should not contain any child." },
|
||||
{ 1626, "Should not set alpha via 'color', set 'opacity' please." },
|
||||
{ 1627, "Not support for asynchronous creating node in SG" },
|
||||
{ 1632, "Node name can not include '/'." },
|
||||
{ 1633, "Internal error, should not remove unknown node from parent." },
|
||||
{ 1635, "reorderChild: this child is not in children list." },
|
||||
{ 1636, "Node's zIndex value can't be greater than cc.macro.MAX_ZINDEX, setting to the maximum value" },
|
||||
{ 1637, "Node's zIndex value can't be smaller than cc.macro.MIN_ZINDEX, setting to the minimum value" },
|
||||
{ 1638, "Private node's zIndex can't be set, it will keep cc.macro.MIN_ZINDEX as its value" },
|
||||
{ 1800, "cc._EventListenerKeyboard.checkAvailable(): Invalid EventListenerKeyboard!" },
|
||||
{ 1801, "cc._EventListenerTouchOneByOne.checkAvailable(): Invalid EventListenerTouchOneByOne!" },
|
||||
{ 1802, "cc._EventListenerTouchAllAtOnce.checkAvailable(): Invalid EventListenerTouchAllAtOnce!" },
|
||||
{ 1803, "cc._EventListenerAcceleration.checkAvailable():_onAccelerationEvent must be non-nil" },
|
||||
{ 1900, "Invalid parameter." },
|
||||
{ 2104, "Layer collision. The name of layer (%s) is collided with the name or value of some layer" },
|
||||
{ 2200, "Design resolution not valid" },
|
||||
{ 2201, "should set resolutionPolicy" },
|
||||
{ 2300, "The touches is more than MAX_TOUCHES, nUnusedIndex = %s" },
|
||||
{ 2402, "Forward pipeline startup failed!" },
|
||||
{ 3103, "cc.Texture.addImage(): path should be non-null" },
|
||||
{ 3119, "Lazy init texture with image element failed due to image loading failure: %s" },
|
||||
{ 3120, "Loading texture with unsupported type: '%s'. Add '%s' into 'cc.macro.SUPPORT_TEXTURE_FORMATS' please." },
|
||||
{ 3121, "Can't find a texture format supported by the current platform! Please add a fallback format in the editor." },
|
||||
{ 3122, "Error Texture in %s." },
|
||||
{ 3123, "Set same texture %s." },
|
||||
{ 3124, "Texture: setMipRange failed because base level is larger than max level" },
|
||||
{ 3300, "Rect width exceeds maximum margin: %s" },
|
||||
{ 3301, "Rect height exceeds maximum margin: %s" },
|
||||
{ 3500, "0 priority is forbidden for fixed priority since it's used for scene graph based priority." },
|
||||
{ 3501, "Invalid listener type!" },
|
||||
{ 3502, "Can't set fixed priority with scene graph based listener." },
|
||||
{ 3503, "Invalid parameters." },
|
||||
{ 3504, "listener must be a cc.EventListener object when adding a fixed priority listener" },
|
||||
{ 3505, "The listener has been registered, please don't register it again." },
|
||||
{ 3506, "Unsupported listener target." },
|
||||
{ 3507, "Invalid scene graph priority!" },
|
||||
{ 3508, "If program goes here, there should be event in dispatch." },
|
||||
{ 3509, "_inDispatch should be 1 here." },
|
||||
{ 3510, "%s's scene graph node not contains in the parent's children" },
|
||||
{ 3511, "event is undefined" },
|
||||
{ 3512, "Event manager only support scene graph priority for ui nodes which contain UIComponent" },
|
||||
{ 3520, "Device Motion Event request permission: %s" },
|
||||
{ 3521, "Device Motion Event request permission failed: %s" },
|
||||
{ 3601, "The editor property 'playOnFocus' should be used with 'executeInEditMode' in class '%s'" },
|
||||
{ 3602, "Unknown editor property '%s' in class '%s'." },
|
||||
{ 3603, "Use 'cc.Float' or 'cc.Integer' instead of 'cc.Number' please." },
|
||||
{ 3604, "Can only indicate one type attribute for %s." },
|
||||
{ 3605, "The default value of %s is not instance of %s." },
|
||||
{ 3606, "No needs to indicate the '%s' attribute for %s, which its default value is type of %s." },
|
||||
{ 3607, "The default value of %s must be an empty string." },
|
||||
{ 3608, "The type of %s must be CCString, not String." },
|
||||
{ 3609, "The type of %s must be CCBoolean, not Boolean." },
|
||||
{ 3610, "The type of %s must be CCFloat or CCInteger, not Number." },
|
||||
{ 3611, "Can not indicate the '%s' attribute for %s, which its default value is type of %s." },
|
||||
{ 3612, "%s Just set the default value to 'new %s()' and it will be handled properly." },
|
||||
{ 3613, "'No need to use 'serializable: false' or 'editorOnly: true' for the getter of '%s.%s', every getter is actually non-serialized." },
|
||||
{ 3614, "Should not define constructor for cc.Component %s." },
|
||||
{ 3615, "Each script can have at most one Component." },
|
||||
{ 3616, "Should not specify class name %s for Component which defines in project." },
|
||||
{ 3618, "ctor of '%s' can not be another CCClass" },
|
||||
{ 3623, "Can not use 'editor' attribute, '%s' not inherits from Components." },
|
||||
{ 3625, "[isChildClassOf] superclass should be function type, not" },
|
||||
{ 3626, "Can't remove '%s' because '%s' depends on it." },
|
||||
{ 3627, "Should not add renderer component (%s) to a Canvas node." },
|
||||
{ 3628, "Should not add %s to a node which size is already used by its other component." },
|
||||
{ 3633, "Properties function of '%s' should return an object!" },
|
||||
{ 3634, "Disallow to use '.' in property name" },
|
||||
{ 3637, "Can not declare %s.%s, it is already defined in the prototype of %s" },
|
||||
{ 3639, "Can not apply the specified attribute to the getter of '%s.%s', attribute index: %s" },
|
||||
{ 3640, "'%s': the setter of '%s' is already defined!" },
|
||||
{ 3641, "Can not construct %s because it contains object property." },
|
||||
{ 3644, "Please define 'type' parameter of %s.%s as the actual constructor." },
|
||||
{ 3645, "Please define 'type' parameter of %s.%s as the constructor of %s." },
|
||||
{ 3646, "Unknown 'type' parameter of %s.%s:%s" },
|
||||
{ 3647, "The length of range array must be equal or greater than 2" },
|
||||
{ 3648, "Can not declare %s.%s method, it is already defined in the properties of %s." },
|
||||
{ 3652, "Failed to `new %s()` under the hood, %s\nIt is used for getting default values declared in TypeScript in the first place.\nPlease ensure the constructor can be called during the script's initialization." },
|
||||
{ 3653, "Please do not specifiy 'default' attribute in decorator of '%s' property in '%s' class.\nDefault value must be initialized at their declaration:\n\n \n// Before:\n@property({\n type: cc.SpriteFrame\n default: null // <--\n})\nmyProp;\n// After:\n@property({\n type: cc.SpriteFrame\n})\nmyProp = null; // <--" },
|
||||
{ 3654, "Please specifiy a default value for '%s.%s' property at its declaration:\n\n \n// Before:\n@property(...)\nmyProp;\n// After:\n@property(...)\nmyProp = 0;" },
|
||||
{ 3655, "Can not specifiy 'get' or 'set' attribute in decorator for '%s' property in '%s' class.\nPlease use:\n\n \n@property(...)\nget %s () {\n ...\n}\n@property\nset %s (value) {\n ...\n}" },
|
||||
{ 3659, "Violation error: extending enumerations shall have non-overlaped member names or member values" },
|
||||
{ 3660, "You are explicitly specifying `undefined` type to cc property '%s' of cc class '%s'.\nIs this intended? If not, this may indicate a circular reference.\nFor example:\n\n \n// foo.ts\nimport { _decorator } from 'cc';\nimport { Bar } from './bar'; // Given that './bar' also reference 'foo.ts'.\n // When importing './bar', execution of './bar' is hung on to wait execution of 'foo.ts',\n // the `Bar` imported here is `undefined` until './bar' finish its execution.\n // It leads to that\n@_decorator.ccclass // ↓\nexport class Foo { // ↓\n @_decorator.type(Bar) // → is equivalent to `@_decorator.type(undefined)`\n public bar: Bar; // To eliminate this error, either:\n // - Refactor your module structure(recommended), or\n // - specify the type as cc class name: `@_decorator.type('Bar'/* or any name you specified for `Bar` */)`\n}" },
|
||||
{ 3700, "internal error: _prefab is undefined" },
|
||||
{ 3701, "Failed to load prefab asset for node '%s'" },
|
||||
{ 3800, "The target can not be made persist because it's not a cc.Node or it doesn't have _id property." },
|
||||
{ 3801, "The node can not be made persist because it's not under root node." },
|
||||
{ 3802, "The node can not be made persist because it's not in current scene." },
|
||||
{ 3803, "The target can not be made persist because it's not a cc.Node or it doesn't have _id property." },
|
||||
{ 3804, "getComponent: Type must be non-nil" },
|
||||
{ 3805, "Can't add component '%s' because %s already contains the same component." },
|
||||
{ 3806, "Can't add component '%s' to %s because it conflicts with the existing '%s' derived component." },
|
||||
{ 3807, "addComponent: Failed to get class '%s'" },
|
||||
{ 3808, "addComponent: Should not add component ('%s') when the scripts are still loading." },
|
||||
{ 3809, "addComponent: The component to add must be a constructor" },
|
||||
{ 3810, "addComponent: The component to add must be child class of cc.Component" },
|
||||
{ 3811, "_addComponentAt: The component to add must be a constructor" },
|
||||
{ 3812, "_addComponentAt: Index out of range" },
|
||||
{ 3813, "removeComponent: Component must be non-nil" },
|
||||
{ 3814, "Argument must be non-nil" },
|
||||
{ 3815, "Component not owned by this entity" },
|
||||
{ 3816, "Node '%s' is already activating" },
|
||||
{ 3817, "Sorry, the component of '%s' which with an index of %s is corrupted! It has been removed." },
|
||||
{ 3818, "Failed to read or parse project.json" },
|
||||
{ 3819, "Warning: target element is not a DIV or CANVAS" },
|
||||
{ 3820, "The renderer doesn't support the renderMode %s" },
|
||||
{ 3821, "Cannot change hierarchy while activating or deactivating the parent." },
|
||||
{ 3822, "addComponent: Cannot add any component to the scene." },
|
||||
{ 3823, "The enabled component (id: %s, name: %s) doesn't have a valid node" },
|
||||
{ 3900, "Invalid clip to add" },
|
||||
{ 3901, "Invalid clip to remove" },
|
||||
{ 3902, "clip is defaultClip, set force to true to force remove clip and animation state" },
|
||||
{ 3903, "animation state is playing, set force to true to force stop and remove clip and animation state" },
|
||||
{ 3904, "motion path of target [%s] in prop [%s] frame [%s] is not valid" },
|
||||
{ 3905, "sprite frames must be an Array." },
|
||||
{ 3906, "Can't find easing type [%s]" },
|
||||
{ 3907, "Animation state is not playing or already removed" },
|
||||
{ 3912, "already-playing" },
|
||||
{ 3920, "Current context does not allow root motion." },
|
||||
{ 3921, "You provided a ill-formed track path. The last component of track path should be property key, or the setter should not be empty." },
|
||||
{ 3923, "Root motion is ignored since root bone could not be located in animation." },
|
||||
{ 3924, "Root motion is ignored since the root bone could not be located in scene." },
|
||||
{ 3925, "Target of hierarchy path should be of type Node." },
|
||||
{ 3926, "Node '%s' has no path '%s'." },
|
||||
{ 3927, "Target of component path should be of type Node." },
|
||||
{ 3928, "Node '%s' has no component '%s'." },
|
||||
{ 3929, "Target object has no property '%s'." },
|
||||
{ 3930, "Can not decide type for untyped track: runtime binding does not provide a getter." },
|
||||
{ 3931, "Can not decide type for untyped track: got a unsupported value from runtime binding." },
|
||||
{ 3932, "Common targets should only target Vectors/`Size`/`Color`." },
|
||||
{ 3933, "Each curve that has common target should be numeric curve and targets string property." },
|
||||
{ 3934, "Misconfigured legacy curve: the first keyframe value is number but others aren't." },
|
||||
{ 3935, "We don't currently support conversion of `CubicSplineQuatValue`." },
|
||||
{ 3936, "Instancing/Batching enabled for non-baked skinning model '%s', this may result in unexpected rendering artifacts. Consider turning it off in the material if you do not intend to do this." },
|
||||
{ 3937, "Previous error occurred when instantiating animation clip %s on node %s." },
|
||||
{ 3938, "'%s' is not found from '%s'. It's specified as the root node to play animation clip '%s'." },
|
||||
{ 3940, "Error when animation attempted to bind material uniform target: target %s is not a material." },
|
||||
{ 3941, "Error when animation attempted to bind material uniform target: material %s has no recorded pass %s." },
|
||||
{ 3942, "Error when animation attempted to bind material uniform target: material %s at pass %s has no recorded uniform %s." },
|
||||
{ 3943, "Error when animation attempted to bind material uniform target: material %s at pass %s's uniform %s has no recorded channel %s." },
|
||||
{ 4003, "Label font size can't be shirnked less than 0!" },
|
||||
{ 4004, "force notify all fonts loaded!" },
|
||||
{ 4011, "Property spriteFrame of Font '%s' is invalid. Using system font instead." },
|
||||
{ 4012, "The texture of Font '%s' must be already loaded on JSB. Using system font instead." },
|
||||
{ 4013, "Sorry, lineHeight of system font not supported on JSB." },
|
||||
{ 4200, "MaskType: IMAGE_STENCIL only support WebGL mode." },
|
||||
{ 4201, "The alphaThreshold invalid in Canvas Mode." },
|
||||
{ 4202, "The inverted invalid in Canvas Mode." },
|
||||
{ 4300, "Can not found the %s page." },
|
||||
{ 4301, "Can not add a page without UITransform." },
|
||||
{ 4302, "Can not set the scroll view content when it hasn't UITransform or its parent hasn't UITransform." },
|
||||
{ 4303, "The %s scrollBar on the '%s' node is not available, please check it." },
|
||||
{ 4400, "Invalid RichText img tag! The sprite frame name can't be found in the ImageAtlas!" },
|
||||
{ 4500, "Graphics: There is no model in %s." },
|
||||
{ 4600, "Script attached to '%s' is missing or invalid." },
|
||||
{ 4601, "Failed to load wasm module, WebAssembly is not supported on this platform, but as a fallback Asm.js module is culled by mistake." },
|
||||
{ 4700, "The dom control is not created!" },
|
||||
{ 4800, "unknown asset type" },
|
||||
{ 4901, "loadRes: should not specify the extname in %s %s" },
|
||||
{ 4902, "No need to release non-cached asset." },
|
||||
{ 4914, "Resources url '%s' does not exist." },
|
||||
{ 4915, "Pack indices and data do not match in size" },
|
||||
{ 4916, "Failed to download package for %s" },
|
||||
{ 4921, "Invalid pipe or invalid index provided!" },
|
||||
{ 4922, "The pipe to be inserted is already in the pipeline!" },
|
||||
{ 4923, "Uuid Loader: Parse asset [ %s ] failed : %s" },
|
||||
{ 4924, "JSON Loader: Input item doesn't contain string content" },
|
||||
{ 4925, "Uuid Loader: Deserialize asset [ %s ] failed : %s" },
|
||||
{ 4926, "Audio Downloader: no web audio context." },
|
||||
{ 4927, "Audio Downloader: audio not supported on this browser!" },
|
||||
{ 4928, "Load %s failed!" },
|
||||
{ 4929, "Load Webp ( %s ) failed" },
|
||||
{ 4930, "Load image ( %s ) failed" },
|
||||
{ 4932, "Since v1.10, for any atlas ('%s') in the 'resources' directory, it is not possible to find the contained SpriteFrames via `loadRes`, `getRes` or `releaseRes`. Load the SpriteAtlas first and then use `spriteAtlas.getSpriteFrame(name)` instead please." },
|
||||
{ 4933, "Download Font [ %s ] failed, using Arial or system default font instead" },
|
||||
{ 4934, "Please assure that the full path of sub asset is correct!" },
|
||||
{ 4935, "Failed to skip prefab asset while deserializing PrefabInfo" },
|
||||
{ 5000, "You are trying to destroy a object twice or more." },
|
||||
{ 5001, "object not yet destroyed" },
|
||||
{ 5100, "Not a plist file!" },
|
||||
{ 5200, "Warning: localStorage isn't enabled. Please confirm browser cookie or privacy option" },
|
||||
{ 5201, "browser don't support web audio" },
|
||||
{ 5202, "This feature supports WebGL render mode only." },
|
||||
{ 5300, "Type of target to deserialize not matched with data: target is %s, data is %s" },
|
||||
{ 5301, "Can not find script '%s'" },
|
||||
{ 5302, "Can not find class '%s'" },
|
||||
{ 5303, "Failed to deserialize %s, missing _deserialize function." },
|
||||
{ 5304, "Unable to deserialize version %s data." },
|
||||
{ 5402, "cc.js.addon called on non-object:" },
|
||||
{ 5403, "cc.js.mixin: arguments must be type object:" },
|
||||
{ 5404, "The base class to extend from must be non-nil" },
|
||||
{ 5405, "The class to extend must be non-nil" },
|
||||
{ 5406, "Class should be extended before assigning any prototype members." },
|
||||
{ 5500, "'notify' can not be used in 'get/set' !" },
|
||||
{ 5501, "'notify' must be used with 'default' !" },
|
||||
{ 5507, "The 'default' attribute of '%s.%s' must be an array" },
|
||||
{ 5508, "Invalid type of %s.%s" },
|
||||
{ 5510, "The 'type' attribute of '%s.%s' can not be 'Number', use cc.Float or cc.Integer instead please." },
|
||||
{ 5511, "The 'type' attribute of '%s.%s' is undefined when loading script" },
|
||||
{ 5512, "Can not serialize '%s.%s' because the specified type is anonymous, please provide a class name or set the 'serializable' attribute of '%s.%s' to 'false'." },
|
||||
{ 5513, "The 'default' value of '%s.%s' should not be used with a 'get' function." },
|
||||
{ 5514, "The 'default' value of '%s.%s' should not be used with a 'set' function." },
|
||||
{ 5515, "The 'default' value of '%s.%s' can not be an constructor. Set default to null please." },
|
||||
{ 5517, "'%s.%s' hides inherited property '%s.%s'. To make the current property override that implementation, add the `override: true` attribute please." },
|
||||
{ 5601, "Can not get current scene." },
|
||||
{ 5602, "Scene is destroyed" },
|
||||
{ 5603, "reference node is destroyed" },
|
||||
{ 5700, "no %s or %s on %s" },
|
||||
{ 5800, "%s.lerp not yet implemented." },
|
||||
{ 5801, "%s.clone not yet implemented." },
|
||||
{ 5802, "%s.equals not yet implemented." },
|
||||
{ 5900, "MotionStreak only support WebGL mode." },
|
||||
{ 5901, "cc.MotionStreak.getOpacity has not been supported." },
|
||||
{ 5902, "cc.MotionStreak.setOpacity has not been supported." },
|
||||
{ 6000, "Custom should not be false if file is not specified." },
|
||||
{ 6001, "The new %s must not be NaN" },
|
||||
{ 6017, "Incomplete or corrupt PNG file" },
|
||||
{ 6018, "Invalid filter algorithm: %s" },
|
||||
{ 6019, "Invalid byte order value." },
|
||||
{ 6020, "You forgot your towel!" },
|
||||
{ 6021, "Unknown Field Tag: %s" },
|
||||
{ 6022, "Too many bits requested" },
|
||||
{ 6023, "No bits requested" },
|
||||
{ 6024, "Cannot recover from missing StripByteCounts" },
|
||||
{ 6025, "Cannot handle sub-byte bits per sample" },
|
||||
{ 6026, "Cannot handle sub-byte bits per pixel" },
|
||||
{ 6027, "Palette image missing color map" },
|
||||
{ 6028, "Unknown Photometric Interpretation: %s" },
|
||||
{ 6029, "Unkown error" },
|
||||
{ 6030, "cc.ParticleSystem: error decoding or ungzipping textureImageData" },
|
||||
{ 6031, "cc.ParticleSystem: unknown image format with Data" },
|
||||
{ 6032, "cc.ParticleSystem.initWithDictionary() : error loading the texture" },
|
||||
{ 6033, "cc.ParticleSystem: not allowing create to be invoked twice with different particle system" },
|
||||
{ 6034, "cc.ParticleSystem: shouldn't be initialized repetitively, otherwise there will be potential leak" },
|
||||
{ 6035, "cc.ParticleSystem: change material failed, please use proper particle material" },
|
||||
{ 6036, "cc.ParticleSystem: life time should bigger than 1 or buffer will be insufficient" },
|
||||
{ 6400, "asset.url is not usable in core process" },
|
||||
{ 6402, "AssetLibrary has already been initialized!" },
|
||||
{ 6500, "Widget target must be one of the parent nodes of it" },
|
||||
{ 6600, "collider not added or already removed" },
|
||||
{ 6601, "Can't find testFunc for (%s, $s)." },
|
||||
{ 6700, "Can't init canvas '%s' because it conflicts with the existing '%s', the scene should only have one active canvas at the same time." },
|
||||
{ 6705, "Argument must be non-nil" },
|
||||
{ 6706, "Priority can't be set in RenderRoot2D node" },
|
||||
{ 6800, "Callback of event must be non-nil" },
|
||||
{ 6801, "The message must be provided" },
|
||||
{ 6900, "The thing you want to instantiate must be an object" },
|
||||
{ 6901, "The thing you want to instantiate is nil" },
|
||||
{ 6902, "The thing you want to instantiate is destroyed" },
|
||||
{ 6903, "The instantiate method for given asset do not implemented" },
|
||||
{ 6904, "Can not instantiate array" },
|
||||
{ 6905, "Can not instantiate DOM element" },
|
||||
{ 7100, "%s already defined in Enum." },
|
||||
{ 7101, "Sorry, 'cc.Enum' not available on this platform, please report this error here: <https://github.com/cocos-creator/engine/issues/new>" },
|
||||
{ 7200, "Method 'initWithTMXFile' is no effect now, please set property 'tmxAsset' instead." },
|
||||
{ 7201, "Method 'initWithXML' is no effect now, please set property 'tmxAsset' instead." },
|
||||
{ 7202, "Add component TiledLayer into node failed." },
|
||||
{ 7203, "Property 'mapLoaded' is unused now. Please write the logic to the callback 'start'." },
|
||||
{ 7210, "TMX Hexa zOrder not supported" },
|
||||
{ 7211, "TMX invalid value" },
|
||||
{ 7215, "cocos2d: Warning: TMX Layer %s has no tiles" },
|
||||
{ 7216, "cocos2d: TMXFormat: Unsupported TMX version: %s" },
|
||||
{ 7217, "cocos2d: TMXFomat: Unsupported orientation: %s" },
|
||||
{ 7218, "cc.TMXMapInfo.parseXMLFile(): unsupported compression method" },
|
||||
{ 7219, "cc.TMXMapInfo.parseXMLFile(): Only base64 and/or gzip/zlib maps are supported" },
|
||||
{ 7221, "cc.TMXMapInfo.parseXMLFile(): Texture '%s' not found." },
|
||||
{ 7222, "Parse %s failed." },
|
||||
{ 7236, "cc.TMXLayer.getTileAt(): TMXLayer: the tiles map has been released" },
|
||||
{ 7237, "cc.TMXLayer.getTileGIDAt(): TMXLayer: the tiles map has been released" },
|
||||
{ 7238, "cc.TMXLayer.setTileGID(): TMXLayer: the tiles map has been released" },
|
||||
{ 7239, "cc.TMXLayer.setTileGID(): invalid gid: %s" },
|
||||
{ 7240, "cc.TMXLayer.getTileFlagsAt(): TMXLayer: the tiles map has been released" },
|
||||
{ 7241, "cc.TiledMap.initWithXML(): Map not found. Please check the filename." },
|
||||
{ 7401, "Failed to set _defaultArmatureIndex for '%s' because the index is out of range." },
|
||||
{ 7402, "Failed to set _animationIndex for '%s' because the index is out of range." },
|
||||
{ 7501, "Failed to set _defaultSkinIndex for '%s' because the index is out of range." },
|
||||
{ 7502, "Failed to set _animationIndex for '%s' because its skeletonData is invalid." },
|
||||
{ 7503, "Failed to set _animationIndex for '%s' because the index is out of range." },
|
||||
{ 7504, "Can not render dynamic created SkeletonData" },
|
||||
{ 7506, "Failed to load spine atlas '$s'" },
|
||||
{ 7507, "Please re-import '%s' because its textures is not initialized! (This workflow will be improved in the future.)" },
|
||||
{ 7508, "The atlas asset of '%s' is not exists!" },
|
||||
{ 7509, "Spine: Animation not found: %s" },
|
||||
{ 7510, "Spine: Animation not found: %s" },
|
||||
{ 7511, "Spine: Invalid input!" },
|
||||
{ 7600, "The context of RenderTexture is invalid." },
|
||||
{ 7601, "cc.RenderTexture._initWithWidthAndHeightForWebGL() : only RGB and RGBA formats are valid for a render texture;" },
|
||||
{ 7602, "Could not attach texture to the framebuffer" },
|
||||
{ 7603, "clearDepth isn't supported on Cocos2d-Html5" },
|
||||
{ 7604, "saveToFile isn't supported on Cocos2d-Html5" },
|
||||
{ 7605, "newCCImage isn't supported on Cocos2d-Html5" },
|
||||
{ 7606, "GFXTexture is null" },
|
||||
{ 7607, "readPixels buffer size smaller than %d" },
|
||||
{ 7700, "On the web is always keep the aspect ratio" },
|
||||
{ 7701, "Can't know status" },
|
||||
{ 7702, "Video player's duration is not ready to get now!" },
|
||||
{ 7703, "Video Downloader: video not supported on this browser!" },
|
||||
{ 7800, "Web does not support loading" },
|
||||
{ 7801, "Web does not support query history" },
|
||||
{ 7802, "Web does not support query history" },
|
||||
{ 7803, "The current browser does not support the GoBack" },
|
||||
{ 7804, "The current browser does not support the GoForward" },
|
||||
{ 7805, "Web does not support zoom" },
|
||||
{ 7900, "cc.math.Matrix3.assign(): current matrix equals matIn" },
|
||||
{ 7901, "cc.math.mat4Assign(): pOut equals pIn" },
|
||||
{ 7902, "cc.mat.Matrix4.assignFrom(): mat4 equals current matrix" },
|
||||
{ 7903, "cc.math.Matrix4 equal: pMat1 and pMat2 are same object." },
|
||||
{ 7904, "cc.math.Matrix4.extractPlane: Invalid plane index" },
|
||||
{ 7905, "cc.math.mat4Assign(): pOut equals pIn" },
|
||||
{ 7906, "cc.mat.Matrix4.assignFrom(): mat4 equals current matrix" },
|
||||
{ 7907, "cc.math.Matrix4 equals: pMat1 and pMat2 are same object." },
|
||||
{ 7908, "Invalid matrix mode specified" },
|
||||
{ 7909, "current quaternion is an invalid value" },
|
||||
{ 8000, "Can't handle this field type or size" },
|
||||
{ 8001, "No bytes requested" },
|
||||
{ 8002, "Too many bytes requested" },
|
||||
{ 8003, "Missing StripByteCounts!" },
|
||||
{ 8100, "cocos2d: ERROR: Failed to compile shader:\n %s" },
|
||||
{ 8101, "cocos2d: ERROR: Failed to compile vertex shader" },
|
||||
{ 8102, "cocos2d: ERROR: Failed to compile fragment shader" },
|
||||
{ 8103, "cc.GLProgram.link(): Cannot link invalid program" },
|
||||
{ 8104, "cocos2d: ERROR: Failed to link program: %s" },
|
||||
{ 8105, "cocos2d: cc.shaderCache._loadDefaultShader, error shader type" },
|
||||
{ 8106, "Please load the resource firset : %s" },
|
||||
{ 8107, "cc.GLProgram.getUniformLocationForName(): uniform name should be non-null" },
|
||||
{ 8108, "cc.GLProgram.getUniformLocationForName(): Invalid operation. Cannot get uniform location when program is not initialized" },
|
||||
{ 8109, "modelView matrix is undefined." },
|
||||
{ 8200, "Please set node's active instead of rigidbody's enabled." },
|
||||
{ 8300, "Should only one camera exists, please check your project." },
|
||||
{ 8301, "Camera does not support Canvas Mode." },
|
||||
{ 8302, "Camera.viewport is deprecated, please use setViewportInOrientedSpace instead." },
|
||||
{ 8400, "Wrong type arguments, 'filePath' must be a String." },
|
||||
{ 9000, "Stencil manager does not support level bigger than %d in this device." },
|
||||
{ 9001, "Stencil manager is already empty, cannot pop any mask" },
|
||||
{ 9002, "Failed to request any buffer from a mesh buffer without accessor" },
|
||||
{ 9003, "The internal state of LinearBufferAccessor have severe issue and irreversible, please check the reason" },
|
||||
{ 9004, "Failed to allocate chunk in StaticVBAccessor, the requested buffer might be too large: %d bytes" },
|
||||
{ 9005, "BATCHER2D_MEM_INCREMENT is too large, the Max value for BATCHER2D_MEM_INCREMENT is 2303KB (smaller than 65536 *9* 4 / 1024 = 2304KB)" },
|
||||
{ 9006, "QuadRenderData is removed, please use MeshRenderData instead." },
|
||||
{ 9007, "Since v3.6, Because mask changes the inheritance relationship, you can directly manipulate the rendering components under the same node to complete the operation." },
|
||||
{ 9100, "texture size exceeds current device limits %d/%d" },
|
||||
{ 9101, "The length of the TypedArrayBuffer must be an integer." },
|
||||
{ 9201, "Cannot access game frame or container." },
|
||||
{ 9202, "Setting window size is not supported." },
|
||||
{ 9300, "The current buffer beyond the limit in ui static component, please reduce the amount" },
|
||||
{ 9301, "The UI has not been initialized" },
|
||||
{ 9302, "Can't getGFXSampler with out device" },
|
||||
{ 9600, "[Physics]: please check to see if physics modules are included" },
|
||||
{ 9610, "[Physics]: cannon.js physics system doesn't support capsule collider" },
|
||||
{ 9611, "[Physics]: builtin physics system doesn't support mesh collider" },
|
||||
{ 9612, "[Physics]: builtin physics system doesn't support cylinder collider" },
|
||||
{ 9613, "[Physics]: cannon.js physics system doesn't support hinge drive and angular limit" },
|
||||
{ 9620, "[Physics][Ammo]: changing the mesh is not supported after the initialization is completed" },
|
||||
{ 9630, "[Physics]: A dynamic rigid body can not have the following collider shapes: Terrain, Plane and Non-convex Mesh. Node name: %s" },
|
||||
{ 9640, "[Physics][builtin]: sweep functions are not supported in builtin" },
|
||||
{ 9641, "[Physics][cannon.js]: sweep functions are not supported in cannon.js" },
|
||||
{ 10001, "The sub-mesh contains %d vertices, which beyonds the capability (%d vertices most) of renderer of your platform." },
|
||||
{ 10002, "Sub-mesh may include at most %d morph targets, but you specified %d." },
|
||||
{ 11000, "WebGL context lost." },
|
||||
{ 12001, "BlendFactors are disabled when using custom material, please modify the blend state in the material instead." },
|
||||
{ 12002, "Can't add renderable component to this node because it already have one." },
|
||||
{ 12004, "SubModel can only support %d passes." },
|
||||
{ 12005, "Material already initialized, request aborted." },
|
||||
{ 12006, "Pass already destroyed." },
|
||||
{ 12007, "This is old usage, please swap the parameters." },
|
||||
{ 12008, "GeometryRenderer: too many lines." },
|
||||
{ 12009, "GeometryRenderer: too many triangles." },
|
||||
{ 12010, "PassUtils: illegal uniform handle, accessing uniform at offset %d" },
|
||||
{ 12011, "Pass: setUniform is invoked with incompatible uniform data type for binding %d, expected type is %s" },
|
||||
{ 12012, "Can't set a material instance to a sharedMaterial slot" },
|
||||
{ 12100, "The font size is too big to be fitted into texture atlas. Please switch to other label cache modes or choose a smaller font size." },
|
||||
{ 12101, "The asset %s has been destroyed!" },
|
||||
{ 12102, "Base pass cannot override states, please use pass instance instead." },
|
||||
{ 12103, "Custom pipeline create shader %s failed. Please restart editor." },
|
||||
{ 12104, "Create shader %s failed." },
|
||||
{ 12105, "Pass resources incomplete." },
|
||||
{ 12106, "Cannot patch non-builtin macros." },
|
||||
{ 12107, "Custom pipeline invalid render pass, program: %s. Please restart editor." },
|
||||
{ 12108, "Custom pipeline invalid render phase, program: %s. Please restart editor." },
|
||||
{ 13100, "Incorrect CCON magic." },
|
||||
{ 13101, "Unknown CCON version number: %d." },
|
||||
{ 13102, "CCON Format error." },
|
||||
{ 13103, "Can not encode CCON binary: lack of text encoder." },
|
||||
{ 13104, "Can not decode CCON binary: lack of text decoder." },
|
||||
{ 14000, "State machine matched too many transitions(greater than %s) during this frame: %s." },
|
||||
{ 14100, "Pool.destroy no longer take a function as parameter, Please specify destruct function in the construction of Pool instead" },
|
||||
{ 14200, "Can not update a static mesh." },
|
||||
{ 14201, "The primitiveIndex is out of range." },
|
||||
{ 14202, "meshopt asm decoder initialized" },
|
||||
{ 14203, "meshopt wasm decoder initialized" },
|
||||
{ 14204, "meshopt decoder error: %d" },
|
||||
{ 14300, "Can not keep world transform due to the zero scaling of parent node" },
|
||||
{ 14400, "Spline error: less than 2 knots." },
|
||||
{ 14401, "Spline error: less than 4 knots or not a multiple of 4.\n\n<!-- Rendering algorithm reserved: 15000 - 16000 -->" },
|
||||
{ 15000, "Can not find corresponding diffuse map for environment lighting, use hemisphere diffuse instead, change environment lighting type to regenerate diffuse map" },
|
||||
{ 15001, "Can not find environment map, disable IBL lighting" },
|
||||
{ 15002, "Diffuse map resource is missing, please change environment lighting type to regenerate resource" },
|
||||
{ 15003, "The shadow visible distance is so small that CSM stratification is not effective, Please change the value of shadowDistance so that it is 10 times greater than 0.1" },
|
||||
{ 15004, "The native folder may be generated from older versions, please refer https://docs.cocos.com/creator/manual/en/release-notes/ to upgrade." },
|
||||
{ 15100, "Camera '%s' clear flag is skybox, but skybox is disabled, may cause strange background effect, please set camera clear flag to solid color." },
|
||||
{ 16000, "'%s' is deprecated since v%s." },
|
||||
{ 16001, "'%s' is deprecated since v%s, please use '%s' instead." },
|
||||
{ 16002, "'%s' is removed since v%s." },
|
||||
{ 16003, "'%s' is removed since v%s, please use '%s' instead." },
|
||||
{ 16101, "The effect('%s') you are looking for does not exist, please confirm the effect name in the editor. NOTE: Since 3.6, the name of the built-in effect has been changed to its name in the editor, please check it out. More information please refer to https://docs.cocos.com/creator/manual/en/shader/effect-inspector.html" },
|
||||
{ 16201, "The asset replacing failed, can not found override asset('%s') for '%s'" },
|
||||
{ 16301, "node '%s' doesn't have any ModelRenderer component, this component will not work. please add ModelRenderer component first" },
|
||||
{ 16302, "There is no reflection probe in the scene or no probe is near the current object. No reflection probe will take effect on this object. Please create a new reflection probe or move existing ones closer." },
|
||||
{ 16303, "Skin material needs floating-point render target, please check ENABLE_FLOAT_OUTPUT define in Project Settings--Macro" },
|
||||
{ 16304, "Skin material may need more accurate calculations, please select a head model of standard size, check the isGlobalStandardSkinObject option in the MeshRender component." },
|
||||
|
||||
};
|
||||
}//namespace cc
|
||||
33
cocos/core/builtin/DebugInfos.cpp.in
Normal file
33
cocos/core/builtin/DebugInfos.cpp.in
Normal file
@@ -0,0 +1,33 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
// clang-format off
|
||||
|
||||
#include "DebugInfos.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
ccstd::unordered_map<uint32_t, ccstd::string> debugInfos = {
|
||||
${PLACE_HOLDER}
|
||||
};
|
||||
}//namespace cc
|
||||
34
cocos/core/builtin/DebugInfos.h
Normal file
34
cocos/core/builtin/DebugInfos.h
Normal file
@@ -0,0 +1,34 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/std/container/string.h"
|
||||
#include "base/std/container/unordered_map.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
extern ccstd::unordered_map<uint32_t, ccstd::string> debugInfos;
|
||||
|
||||
}
|
||||
53
cocos/core/data/JSBNativeDataHolder.h
Normal file
53
cocos/core/data/JSBNativeDataHolder.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "base/Utils.h"
|
||||
|
||||
namespace cc {
|
||||
class JSBNativeDataHolder final {
|
||||
public:
|
||||
JSBNativeDataHolder() = default;
|
||||
explicit JSBNativeDataHolder(uint8_t* data) : _data(data){};
|
||||
|
||||
~JSBNativeDataHolder() {
|
||||
if (_data != nullptr) {
|
||||
free(_data); // Remove data in destructor
|
||||
}
|
||||
}
|
||||
|
||||
inline void setData(uint8_t* data) { _data = data; }
|
||||
inline uint8_t* getData() const { return _data; }
|
||||
|
||||
inline void destroy() { // Also support to invoke destroy method to free memory before garbage collection
|
||||
free(_data);
|
||||
_data = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t* _data{nullptr};
|
||||
};
|
||||
} // namespace cc
|
||||
137
cocos/core/data/Object.cpp
Normal file
137
cocos/core/data/Object.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/data/Object.h"
|
||||
#include "base/std/container/vector.h"
|
||||
#include "core/platform/Debug.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace {
|
||||
ccstd::vector<CCObject *> objectsToDestroy;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void CCObject::deferredDestroy() {
|
||||
if (objectsToDestroy.empty()) return;
|
||||
auto deleteCount = static_cast<int32_t>(objectsToDestroy.size());
|
||||
for (size_t i = 0; i < deleteCount; ++i) {
|
||||
CCObject *obj = objectsToDestroy[i];
|
||||
if (!(obj->_objFlags & Flags::DESTROYED)) {
|
||||
obj->destroyImmediate();
|
||||
obj->release();
|
||||
}
|
||||
}
|
||||
// if we called b.destory() in a.onDestroy(), objectsToDestroy will be resized,
|
||||
// but we only destroy the objects which called destory in this frame.
|
||||
if (deleteCount == objectsToDestroy.size()) {
|
||||
objectsToDestroy.clear();
|
||||
} else {
|
||||
objectsToDestroy.erase(objectsToDestroy.begin(), objectsToDestroy.begin() + deleteCount);
|
||||
}
|
||||
}
|
||||
|
||||
CCObject::CCObject(ccstd::string name /* = ""*/)
|
||||
: _name(std::move(name)) {
|
||||
}
|
||||
|
||||
CCObject::~CCObject() = default;
|
||||
|
||||
void CCObject::destruct() {
|
||||
_name.clear();
|
||||
}
|
||||
|
||||
bool CCObject::destroy() {
|
||||
//NOTE: _objFlags will be set to TO_DESTROY when destroy method in TS is triggered.
|
||||
// CCObject::destroy method will be invoked at the end. Refer to cocos/core/data/object.ts
|
||||
/*
|
||||
public destroy (): boolean {
|
||||
if (this._objFlags & Destroyed) {
|
||||
warnID(5000);
|
||||
return false;
|
||||
}
|
||||
... ...
|
||||
|
||||
if (JSB) {
|
||||
// @ts-ignore
|
||||
// _destroy is a JSB method
|
||||
this._destroy();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
if (static_cast<bool>(_objFlags & Flags::TO_DESTROY)) {
|
||||
//NOTE: Should not return false because _objFlags is already set to TO_DESTROY in TS.
|
||||
// And Scene::destroy depends on the return value. Refer to:
|
||||
/*
|
||||
bool Scene::destroy() {
|
||||
bool success = Super::destroy();
|
||||
if (success) {
|
||||
for (auto &child : _children) {
|
||||
child->setActive(false);
|
||||
}
|
||||
}
|
||||
......
|
||||
}
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
if (static_cast<bool>(_objFlags & Flags::DESTROYED)) {
|
||||
debug::warnID(5000);
|
||||
return false;
|
||||
}
|
||||
|
||||
_objFlags |= Flags::TO_DESTROY;
|
||||
addRef();
|
||||
objectsToDestroy.emplace_back(this);
|
||||
|
||||
//NOTE: EDITOR's deferredDestroyTimer trigger from ts
|
||||
return true;
|
||||
}
|
||||
|
||||
void CCObject::destroyImmediate() {
|
||||
if (static_cast<bool>(_objFlags & Flags::DESTROYED)) {
|
||||
debug::errorID(5000);
|
||||
return;
|
||||
}
|
||||
|
||||
onPreDestroy();
|
||||
|
||||
// NOTE: native has been use smart pointer, not needed to implement 'destruct' interface, remove 'destruct' reference code
|
||||
|
||||
_objFlags |= Flags::DESTROYED;
|
||||
}
|
||||
|
||||
bool isObjectValid(CCObject *value, bool strictMode /* = false*/) {
|
||||
if (value == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !(value->_objFlags & (strictMode ? (CCObject::Flags::DESTROYED | CCObject::Flags::TO_DESTROY) : CCObject::Flags::DESTROYED));
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
284
cocos/core/data/Object.h
Normal file
284
cocos/core/data/Object.h
Normal file
@@ -0,0 +1,284 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/std/container/string.h"
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "base/RefCounted.h"
|
||||
#include "base/TypeDef.h"
|
||||
|
||||
namespace se {
|
||||
class Object;
|
||||
}
|
||||
|
||||
namespace cc {
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The base class of most of all the objects in Cocos Creator.
|
||||
* @zh
|
||||
* 大部分对象的基类。
|
||||
* @private
|
||||
*/
|
||||
class CCObject : public RefCounted /*cjh implements EditorExtendableObject*/ {
|
||||
public:
|
||||
// definitions for CCObject.Flags
|
||||
enum class Flags : FlagBits {
|
||||
ZERO = 0,
|
||||
DESTROYED = 1 << 0,
|
||||
REAL_DESTROYED = 1 << 1,
|
||||
TO_DESTROY = 1 << 2,
|
||||
/**
|
||||
* @en The object will not be saved.
|
||||
* @zh 该对象将不会被保存。
|
||||
*/
|
||||
DONT_SAVE = 1 << 3,
|
||||
/**
|
||||
* @en The object will not be saved when building a player.
|
||||
* @zh 构建项目时,该对象将不会被保存。
|
||||
*/
|
||||
EDITOR_ONLY = 1 << 4,
|
||||
DIRTY = 1 << 5,
|
||||
/**
|
||||
* @en Dont destroy automatically when loading a new scene.
|
||||
* @zh 加载一个新场景时,不自动删除该对象。
|
||||
* @private
|
||||
*/
|
||||
DONT_DESTROY = 1 << 6,
|
||||
DESTROYING = 1 << 7,
|
||||
/**
|
||||
* @en The node is deactivating.
|
||||
* @zh 节点正在反激活的过程中。
|
||||
* @private
|
||||
*/
|
||||
DEACTIVATING = 1 << 8,
|
||||
/**
|
||||
* @en The lock node, when the node is locked, cannot be clicked in the scene.
|
||||
* @zh 锁定节点,锁定后场景内不能点击。
|
||||
* @private
|
||||
*/
|
||||
LOCKED_IN_EDITOR = 1 << 9,
|
||||
/**
|
||||
* @en Hide the object in editor.
|
||||
* @zh 在编辑器中隐藏该对象。
|
||||
*/
|
||||
HIDE_IN_HIERARCHY = 1 << 10,
|
||||
|
||||
IS_ON_ENABLE_CALLED = 1 << 11,
|
||||
IS_EDITOR_ON_ENABLE_CALLED = 1 << 12,
|
||||
IS_PRELOAD_STARTED = 1 << 13,
|
||||
IS_ON_LOAD_CALLED = 1 << 14,
|
||||
IS_ON_LOAD_STARTED = 1 << 15,
|
||||
IS_START_CALLED = 1 << 16,
|
||||
|
||||
IS_ROTATION_LOCKED = 1 << 17,
|
||||
IS_SCALE_LOCKED = 1 << 18,
|
||||
IS_ANCHOR_LOCKED = 1 << 19,
|
||||
IS_SIZE_LOCKED = 1 << 20,
|
||||
IS_POSITION_LOCKED = 1 << 21,
|
||||
|
||||
// Distributed
|
||||
IS_REPLICATED = 1 << 22,
|
||||
IS_CLIENT_LOAD = 1 << 23,
|
||||
|
||||
// var Hide = HideInGame | HideInEditor;
|
||||
// should not clone or serialize these flags
|
||||
PERSISTENT_MASK = ~(TO_DESTROY | DIRTY | DESTROYING | DONT_DESTROY | DEACTIVATING | IS_PRELOAD_STARTED | IS_ON_LOAD_STARTED | IS_ON_LOAD_CALLED | IS_START_CALLED | IS_ON_ENABLE_CALLED | IS_EDITOR_ON_ENABLE_CALLED | IS_ROTATION_LOCKED | IS_SCALE_LOCKED | IS_ANCHOR_LOCKED | IS_SIZE_LOCKED | IS_POSITION_LOCKED
|
||||
/* RegisteredInEditor */),
|
||||
|
||||
// all the hideFlags
|
||||
/**
|
||||
* @en The object will not be saved and hide the object in editor,and lock node, when the node is locked,
|
||||
* cannot be clicked in the scene,and The object will not be saved when building a player.
|
||||
* @zh 该对象将不会被保存,构建项目时,该对象将不会被保存, 锁定节点,锁定后场景内不能点击, 在编辑器中隐藏该对象。
|
||||
*/
|
||||
ALL_HIDE_MASKS = DONT_SAVE | EDITOR_ONLY | LOCKED_IN_EDITOR | HIDE_IN_HIERARCHY,
|
||||
};
|
||||
|
||||
static void deferredDestroy();
|
||||
|
||||
// cjh public declare [editorExtrasTag]: unknown;
|
||||
|
||||
Flags _objFlags{Flags::ZERO};
|
||||
ccstd::string _name;
|
||||
|
||||
explicit CCObject(ccstd::string name = "");
|
||||
~CCObject() override;
|
||||
|
||||
// MEMBER
|
||||
|
||||
/**
|
||||
* @en The name of the object.
|
||||
* @zh 该对象的名称。
|
||||
* @default ""
|
||||
* @example
|
||||
* ```
|
||||
* obj.name = "New Obj";
|
||||
* ```
|
||||
*/
|
||||
inline const ccstd::string& getName() const { return _name; }
|
||||
inline void setName(const ccstd::string& value) { _name = value; }
|
||||
|
||||
/**
|
||||
* @en After inheriting CCObject objects, control whether you need to hide, lock, serialize, and other functions.
|
||||
* @zh 在继承 CCObject 对象后,控制是否需要隐藏,锁定,序列化等功能。
|
||||
*/
|
||||
inline void setHideFlags(Flags hideFlags);
|
||||
inline Flags getHideFlags() const;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Indicates whether the object is not yet destroyed. (It will not be available after being destroyed)<br>
|
||||
* When an object's `destroy` is called, it is actually destroyed after the end of this frame.
|
||||
* So `isValid` will return false from the next frame, while `isValid` in the current frame will still be true.
|
||||
* If you want to determine whether the current frame has called `destroy`, use `isValid(obj, true)`,
|
||||
* but this is often caused by a particular logical requirements, which is not normally required.
|
||||
*
|
||||
* @zh
|
||||
* 表示该对象是否可用(被 destroy 后将不可用)。<br>
|
||||
* 当一个对象的 `destroy` 调用以后,会在这一帧结束后才真正销毁。<br>
|
||||
* 因此从下一帧开始 `isValid` 就会返回 false,而当前帧内 `isValid` 仍然会是 true。<br>
|
||||
* 如果希望判断当前帧是否调用过 `destroy`,请使用 `isValid(obj, true)`,不过这往往是特殊的业务需求引起的,通常情况下不需要这样。
|
||||
* @default true
|
||||
* @readOnly
|
||||
* @example
|
||||
* ```ts
|
||||
* import { Node, log } from 'cc';
|
||||
* const node = new Node();
|
||||
* log(node.isValid); // true
|
||||
* node.destroy();
|
||||
* log(node.isValid); // true, still valid in this frame
|
||||
* // after a frame...
|
||||
* log(node.isValid); // false, destroyed in the end of last frame
|
||||
* ```
|
||||
*/
|
||||
inline bool isValid() const;
|
||||
|
||||
virtual void destruct();
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Destroy this Object, and release all its own references to other objects.<br/>
|
||||
* Actual object destruction will delayed until before rendering.
|
||||
* From the next frame, this object is not usable any more.
|
||||
* You can use `isValid(obj)` to check whether the object is destroyed before accessing it.
|
||||
* @zh
|
||||
* 销毁该对象,并释放所有它对其它对象的引用。<br/>
|
||||
* 实际销毁操作会延迟到当前帧渲染前执行。从下一帧开始,该对象将不再可用。
|
||||
* 您可以在访问对象之前使用 `isValid(obj)` 来检查对象是否已被销毁。
|
||||
* @return whether it is the first time the destroy being called
|
||||
* @example
|
||||
* ```
|
||||
* obj.destroy();
|
||||
* ```
|
||||
*/
|
||||
virtual bool destroy();
|
||||
|
||||
/**
|
||||
* Clear all references in the instance.
|
||||
*
|
||||
* NOTE: this method will not clear the getter or setter functions which defined in the instance of CCObject.
|
||||
* You can override the _destruct method if you need, for example:
|
||||
* _destruct: function () {
|
||||
* for (var key in this) {
|
||||
* if (hasOwnProperty(key)) {
|
||||
* switch (typeof this[key]) {
|
||||
* case 'string':
|
||||
* this[key] = '';
|
||||
* break;
|
||||
* case 'object':
|
||||
* case 'function':
|
||||
* this[key] = null;
|
||||
* break;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
*/
|
||||
|
||||
void destroyImmediate();
|
||||
|
||||
virtual ccstd::string toString() const { return ""; };
|
||||
|
||||
inline void setScriptObject(se::Object* seObj) { _scriptObject = seObj; }
|
||||
inline se::Object* getScriptObject() const { return _scriptObject; }
|
||||
|
||||
protected:
|
||||
virtual bool onPreDestroy() {
|
||||
// FIXME: need reture value
|
||||
return true;
|
||||
}
|
||||
|
||||
se::Object* _scriptObject{nullptr}; // weak reference
|
||||
};
|
||||
|
||||
CC_ENUM_BITWISE_OPERATORS(CCObject::Flags);
|
||||
|
||||
inline bool CCObject::isValid() const {
|
||||
return !(_objFlags & Flags::DESTROYED);
|
||||
}
|
||||
|
||||
inline void CCObject::setHideFlags(Flags hideFlags) {
|
||||
Flags flags = hideFlags & Flags::ALL_HIDE_MASKS;
|
||||
_objFlags = (_objFlags & ~Flags::ALL_HIDE_MASKS) | flags;
|
||||
}
|
||||
|
||||
inline CCObject::Flags CCObject::getHideFlags() const {
|
||||
return _objFlags & Flags::ALL_HIDE_MASKS;
|
||||
}
|
||||
|
||||
/*
|
||||
* @en
|
||||
* Checks whether the object is non-nil and not yet destroyed.<br>
|
||||
* When an object's `destroy` is called, it is actually destroyed after the end of this frame.
|
||||
* So `isValid` will return false from the next frame, while `isValid` in the current frame will still be true.
|
||||
* If you want to determine whether the current frame has called `destroy`, use `isValid(obj, true)`,
|
||||
* but this is often caused by a particular logical requirements, which is not normally required.
|
||||
*
|
||||
* @zh
|
||||
* 检查该对象是否不为 null 并且尚未销毁。<br>
|
||||
* 当一个对象的 `destroy` 调用以后,会在这一帧结束后才真正销毁。<br>
|
||||
* 因此从下一帧开始 `isValid` 就会返回 false,而当前帧内 `isValid` 仍然会是 true。<br>
|
||||
* 如果希望判断当前帧是否调用过 `destroy`,请使用 `isValid(obj, true)`,不过这往往是特殊的业务需求引起的,通常情况下不需要这样。
|
||||
*
|
||||
* @method isValid
|
||||
* @param value
|
||||
* @param [strictMode=false] - If true, Object called destroy() in this frame will also treated as invalid.
|
||||
* @return whether is valid
|
||||
* @example
|
||||
* ```
|
||||
* import { Node, log } from 'cc';
|
||||
* var node = new Node();
|
||||
* log(isValid(node)); // true
|
||||
* node.destroy();
|
||||
* log(isValid(node)); // true, still valid in this frame
|
||||
* // after a frame...
|
||||
* log(isValid(node)); // false, destroyed in the end of last frame
|
||||
* ```
|
||||
*/
|
||||
bool isObjectValid(CCObject* value, bool strictMode = false);
|
||||
|
||||
} // namespace cc
|
||||
55
cocos/core/event/Event.h
Normal file
55
cocos/core/event/Event.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
#ifdef SWIGCOCOS
|
||||
#define IMPL_EVENT_TARGET_WITH_PARENT(...)
|
||||
#define IMPL_EVENT_TARGET(...)
|
||||
#define DECLARE_TARGET_EVENT_BEGIN(...)
|
||||
#define DECLARE_TARGET_EVENT_BEGIN_WITH_PARENTS(...)
|
||||
#define DECLARE_TARGET_EVENT_END(...)
|
||||
#define TARGET_EVENT_ARG0(...)
|
||||
#define TARGET_EVENT_ARG1(...)
|
||||
#define TARGET_EVENT_ARG2(...)
|
||||
#define TARGET_EVENT_ARG3(...)
|
||||
#define TARGET_EVENT_ARG4(...)
|
||||
#define TARGET_EVENT_ARG5(...)
|
||||
#define TARGET_EVENT_ARG6(...)
|
||||
#define TARGET_EVENT_ARG7(...)
|
||||
#define TARGET_EVENT_ARG8(...)
|
||||
#define TARGET_EVENT_ARG9(...)
|
||||
#define TARGET_EVENT_ARG10(...)
|
||||
#define TARGET_EVENT_ARG11(...)
|
||||
#define TARGET_EVENT_ARG12(...)
|
||||
#define TARGET_EVENT_ARG13(...)
|
||||
#define TARGET_EVENT_ARG14(...)
|
||||
#define TARGET_EVENT_ARG15(...)
|
||||
#define TARGET_EVENT_ARG16(...)
|
||||
#define TARGET_EVENT_ARG17(...)
|
||||
#define TARGET_EVENT_ARG18(...)
|
||||
#define TARGET_EVENT_ARG19(...)
|
||||
#define TARGET_EVENT_ARG20(...)
|
||||
#else
|
||||
#include "EventBus.h"
|
||||
#include "EventTarget.h"
|
||||
#endif
|
||||
62
cocos/core/event/EventBus.cpp
Normal file
62
cocos/core/event/EventBus.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#include "EventBus.h"
|
||||
#include <algorithm>
|
||||
#include "intl/List.h"
|
||||
|
||||
namespace cc {
|
||||
namespace event {
|
||||
|
||||
void BusEventListenerContainer::addListener(BusEventListenerBase *listener) {
|
||||
if (_isBroadcasting) {
|
||||
intl::listAppend(&_listenersToAdd, listener->entry);
|
||||
return;
|
||||
}
|
||||
intl::listAppend(&_listenerList, listener->entry);
|
||||
}
|
||||
|
||||
void BusEventListenerContainer::removeListener(BusEventListenerBase *listener) {
|
||||
if (_isBroadcasting) {
|
||||
_listenersToRemove.emplace_back(listener->entry);
|
||||
listener->entry->listener = nullptr;
|
||||
return;
|
||||
}
|
||||
intl::detachFromList(&_listenerList, listener->entry);
|
||||
delete listener->entry;
|
||||
}
|
||||
|
||||
void BusEventListenerContainer::addOrRemovePendingListeners() {
|
||||
for (auto &entry : _listenersToRemove) {
|
||||
intl::detachFromList(&_listenerList, entry);
|
||||
delete entry;
|
||||
}
|
||||
EVENT_LIST_LOOP_REV_BEGIN(curr, _listenersToAdd)
|
||||
intl::detachFromList(&_listenersToAdd, curr);
|
||||
intl::listAppend(&_listenerList, curr);
|
||||
EVENT_LIST_LOOP_REV_END(curr, _listenersToAdd)
|
||||
_listenersToAdd = nullptr;
|
||||
_listenersToRemove.clear();
|
||||
}
|
||||
} // namespace event
|
||||
} // namespace cc
|
||||
238
cocos/core/event/EventBus.h
Normal file
238
cocos/core/event/EventBus.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "base/std/container/vector.h"
|
||||
#include "core/memop/Pool.h"
|
||||
#include "intl/EventIntl.h"
|
||||
#include "intl/List.h"
|
||||
|
||||
namespace cc {
|
||||
namespace event {
|
||||
class BusEventListenerBase;
|
||||
|
||||
template <typename EHandler>
|
||||
class BusEventListenerDB;
|
||||
|
||||
template <typename EHandler, typename... ARGS>
|
||||
class BusEventBroadcaster;
|
||||
|
||||
class BusEventListenerContainer;
|
||||
struct BusEventListenerEntry {
|
||||
BusEventListenerEntry *next{nullptr};
|
||||
BusEventListenerEntry *prev{nullptr};
|
||||
BusEventListenerBase *listener{nullptr};
|
||||
};
|
||||
class BusEventListenerBase {
|
||||
protected:
|
||||
BusEventListenerEntry *entry{nullptr}; // NOLINT
|
||||
friend class BusEventListenerContainer;
|
||||
};
|
||||
|
||||
class BusEventListenerContainer {
|
||||
public:
|
||||
template <typename EHandler, typename... ARGS>
|
||||
bool broadcast(ARGS &&...args);
|
||||
|
||||
protected:
|
||||
BusEventListenerContainer() = default;
|
||||
virtual ~BusEventListenerContainer() = default;
|
||||
void addListener(BusEventListenerBase *);
|
||||
void removeListener(BusEventListenerBase *);
|
||||
|
||||
bool hasPendingListeners() const {
|
||||
return !_listenersToRemove.empty() || _listenersToAdd;
|
||||
}
|
||||
void addOrRemovePendingListeners();
|
||||
// fields
|
||||
BusEventListenerEntry *_listenerList{nullptr};
|
||||
BusEventListenerEntry *_listenersToAdd{nullptr};
|
||||
ccstd::vector<BusEventListenerEntry *> _listenersToRemove;
|
||||
int _isBroadcasting = 0;
|
||||
|
||||
template <typename T>
|
||||
friend class BusEventListenerDB;
|
||||
|
||||
template <typename EHandler, typename... ARGS>
|
||||
friend class BusEventBroadcaster;
|
||||
|
||||
friend class BusEventListenerBase;
|
||||
template <typename E>
|
||||
friend class Listener;
|
||||
};
|
||||
|
||||
template <typename EHandler, typename... ARGS>
|
||||
class BusEventBroadcaster final : public BusEventListenerContainer {
|
||||
public:
|
||||
bool doBroadcast(ARGS &&...args);
|
||||
};
|
||||
|
||||
template <typename EHandler, typename... ARGS>
|
||||
bool BusEventListenerContainer::broadcast(ARGS &&...args) {
|
||||
using BusType = BusEventBroadcaster<EHandler, ARGS...>;
|
||||
_isBroadcasting++;
|
||||
auto ret = static_cast<BusType *>(this)->doBroadcast(std::forward<ARGS>(args)...);
|
||||
_isBroadcasting--;
|
||||
if (!_isBroadcasting && hasPendingListeners()) {
|
||||
addOrRemovePendingListeners();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename EHandler>
|
||||
class BusEventListenerDB final {
|
||||
public:
|
||||
static BusEventListenerContainer *container() {
|
||||
if (ctn == nullptr) {
|
||||
ctn = new BusEventListenerContainer;
|
||||
}
|
||||
return ctn;
|
||||
}
|
||||
|
||||
private:
|
||||
static BusEventListenerContainer *ctn;
|
||||
};
|
||||
|
||||
template <typename EHandler>
|
||||
BusEventListenerContainer *BusEventListenerDB<EHandler>::ctn = nullptr;
|
||||
|
||||
template <typename BusType, typename R, typename... ARGS>
|
||||
struct BusEventTrait {
|
||||
using _bus_type = BusType;
|
||||
using _return_type = R;
|
||||
using _argument_tuple_types = std::tuple<ARGS...>;
|
||||
constexpr static int ARG_COUNT = sizeof...(ARGS);
|
||||
};
|
||||
/**
|
||||
* Bus Event Listener
|
||||
*/
|
||||
template <typename EHandler>
|
||||
class Listener : public BusEventListenerBase {
|
||||
public:
|
||||
using _agurment_tuple_types = typename EHandler::_argument_tuple_types;
|
||||
using _argument_wrapper = typename intl::TupleExtractor<_agurment_tuple_types>;
|
||||
// using func_type = typename _argument_wrapper::func_type;
|
||||
using _std_func_type = typename _argument_wrapper::std_func_type;
|
||||
|
||||
constexpr static const char *BUS_NAME = EHandler::BUS_NAME;
|
||||
constexpr static const char *HANDLE_CLASS = EHandler::HANDLE_CLASS;
|
||||
|
||||
Listener();
|
||||
~Listener();
|
||||
|
||||
inline bool isEnabled() const { return _enabled; }
|
||||
inline void enable() { _enabled = true; }
|
||||
inline void disable() { _enabled = false; }
|
||||
inline void reset() { _callback = nullptr; }
|
||||
|
||||
template <typename Fn>
|
||||
bool bind(Fn &&func) {
|
||||
_callback = intl::convertLambda(std::forward<Fn>(func));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename... ARGS>
|
||||
void invoke(ARGS &&...args) {
|
||||
if (_callback && _enabled) {
|
||||
_callback(std::forward<ARGS>(args)...);
|
||||
} else {
|
||||
CC_LOG_DEBUG("EventBus[%s] has no listener found!", BUS_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
const char *getBusName() const { return BUS_NAME; }
|
||||
const char *getHandlerName() const { return HANDLE_CLASS; }
|
||||
|
||||
private:
|
||||
bool _enabled{true};
|
||||
_std_func_type _callback;
|
||||
|
||||
friend class BusEventListenerContainer;
|
||||
};
|
||||
|
||||
template <typename EHandler>
|
||||
Listener<EHandler>::Listener() {
|
||||
entry = new BusEventListenerEntry;
|
||||
entry->listener = this;
|
||||
BusEventListenerDB<EHandler>::container()->addListener(this);
|
||||
}
|
||||
|
||||
template <typename EHandler>
|
||||
Listener<EHandler>::~Listener() {
|
||||
BusEventListenerDB<EHandler>::container()->removeListener(this);
|
||||
}
|
||||
|
||||
template <typename EHandler, typename... ARGS>
|
||||
bool BusEventBroadcaster<EHandler, ARGS...>::doBroadcast(ARGS &&...args) {
|
||||
// broadcast events to all listeners
|
||||
EVENT_LIST_LOOP_BEGIN(curr, _listenerList)
|
||||
if (curr->listener) {
|
||||
static_cast<Listener<EHandler> *>(curr->listener)->invoke(std::forward<ARGS>(args)...);
|
||||
}
|
||||
EVENT_LIST_LOOP_END(curr, _listenerList)
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename EHandler, typename... ARGS>
|
||||
void broadcast(ARGS &&...args) {
|
||||
static_assert(sizeof...(ARGS) == EHandler::ARG_COUNT, "parameter count incorrect");
|
||||
event::intl::validateParameters<0, EHandler, ARGS...>(std::forward<ARGS>(args)...);
|
||||
auto *listenerSet = BusEventListenerDB<EHandler>::container();
|
||||
listenerSet->template broadcast<EHandler, ARGS...>(std::forward<ARGS>(args)...);
|
||||
}
|
||||
|
||||
} // namespace event
|
||||
} // namespace cc
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
#define EventBusName_(n) n##_ebus
|
||||
|
||||
#define DECLARE_EVENT_BUS(EventBusClass) \
|
||||
struct EventBusClass##_ebus { \
|
||||
constexpr static const char *BUS_NAME = #EventBusClass; \
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
#define _DECLARE_BUS_EVENT_VA(BusEventClass, EventBusClass, ...) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, __VA_ARGS__> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = BusType::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
template <typename... ARGS> \
|
||||
static inline void emit(ARGS &&...args) { \
|
||||
cc::event::emit<BusEventClass>(std::forward<ARGS>(args)...); \
|
||||
} \
|
||||
};
|
||||
|
||||
#include "intl/EventBusMacros.h"
|
||||
715
cocos/core/event/EventTarget.h
Normal file
715
cocos/core/event/EventTarget.h
Normal file
@@ -0,0 +1,715 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include "base/Log.h"
|
||||
#include "base/Macros.h"
|
||||
#include "base/memory/Memory.h"
|
||||
#include "intl/EventIntl.h"
|
||||
#include "intl/List.h"
|
||||
|
||||
namespace cc {
|
||||
namespace event {
|
||||
|
||||
class TgtEventTraitClass {};
|
||||
|
||||
enum class EventPhaseType {
|
||||
CAPTUREING_PHASE = 1,
|
||||
AT_TARGET = 2,
|
||||
BUBBLING_PHASE = 3,
|
||||
UNKNOWN = 4,
|
||||
};
|
||||
|
||||
struct TgtEventInfo {
|
||||
EventPhaseType eventPhase{EventPhaseType::UNKNOWN};
|
||||
bool bubbles{true};
|
||||
bool cancelable{true};
|
||||
|
||||
void stopPropagation() {
|
||||
propagationStopped = true;
|
||||
}
|
||||
|
||||
void preventDefault() { /* TODO: */
|
||||
}
|
||||
|
||||
bool propagationStopped{false};
|
||||
};
|
||||
|
||||
template <typename TgtEvent>
|
||||
struct Event final : TgtEventInfo {
|
||||
using EmitterType = typename TgtEvent::_emitter_type;
|
||||
using _argument_tuple_types = typename TgtEvent::_argument_tuple_types;
|
||||
using _argument_local_types = typename TgtEvent::_argument_local_types;
|
||||
EmitterType *target{nullptr};
|
||||
EmitterType *currentTarget{nullptr};
|
||||
_argument_local_types args;
|
||||
|
||||
Event() = default;
|
||||
|
||||
explicit Event(const _argument_local_types &argsIn) : args(argsIn) {
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
auto get() const {
|
||||
return std::get<N>(args);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
auto get() {
|
||||
return std::get<N>(args);
|
||||
}
|
||||
|
||||
template <size_t N, typename A>
|
||||
void set(A &&value) {
|
||||
std::get<N>(args) = value;
|
||||
}
|
||||
|
||||
void initEvent(bool canBubbleArg, bool cancelableArg) {
|
||||
// TODO()
|
||||
}
|
||||
|
||||
template <typename... ARGS>
|
||||
void update(ARGS &&...values) {
|
||||
args = std::make_tuple<>(std::forward<ARGS>(values)...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename EmitterType, typename... ARGS>
|
||||
class TgtEventTrait : public TgtEventTraitClass {
|
||||
public:
|
||||
using _emitter_type = EmitterType;
|
||||
using _argument_tuple_types = std::tuple<ARGS...>;
|
||||
using _argument_local_types = std::tuple<std::remove_reference_t<std::remove_cv_t<ARGS>>...>;
|
||||
constexpr static int ARG_COUNT = sizeof...(ARGS);
|
||||
};
|
||||
|
||||
class TgtMemberFnCmp {
|
||||
public:
|
||||
virtual ~TgtMemberFnCmp() = default;
|
||||
|
||||
virtual void *getContext() = 0;
|
||||
|
||||
virtual bool equals(TgtMemberFnCmp *) const = 0;
|
||||
};
|
||||
|
||||
template <typename Fn>
|
||||
class TgtMemberHandleFn final : public TgtMemberFnCmp {
|
||||
public:
|
||||
~TgtMemberHandleFn() override = default;
|
||||
void *getContext() override { return context; }
|
||||
|
||||
bool equals(TgtMemberFnCmp *other) const override {
|
||||
auto *fake = reinterpret_cast<TgtMemberHandleFn *>(other);
|
||||
return context == fake->context && func == fake->func;
|
||||
}
|
||||
|
||||
Fn func;
|
||||
void *context;
|
||||
};
|
||||
|
||||
class TargetEventListenerBase {
|
||||
public:
|
||||
enum class RunState {
|
||||
NORMAL,
|
||||
PENDING_ONCE,
|
||||
ONCE_DONE,
|
||||
};
|
||||
|
||||
virtual ~TargetEventListenerBase() = default;
|
||||
|
||||
virtual void *getContext() const = 0;
|
||||
|
||||
virtual const char *getEventName() const { return nullptr; }
|
||||
|
||||
bool isEnabled() const { return _enabled; }
|
||||
|
||||
void setOnce() { _state = RunState::PENDING_ONCE; }
|
||||
|
||||
inline size_t getEventTypeID() const { return _eventTypeID; }
|
||||
|
||||
int32_t id{-1};
|
||||
|
||||
TargetEventListenerBase *next{nullptr};
|
||||
TargetEventListenerBase *prev{nullptr};
|
||||
|
||||
protected:
|
||||
bool _enabled = true;
|
||||
RunState _state{RunState::NORMAL};
|
||||
size_t _eventTypeID;
|
||||
};
|
||||
|
||||
template <typename TgtEvent>
|
||||
class TargetEventListener final : public TargetEventListenerBase {
|
||||
public:
|
||||
using _emitter_type = typename TgtEvent::_emitter_type;
|
||||
using EventType = typename TgtEvent::EventType;
|
||||
using _persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
|
||||
explicit TargetEventListener(_persist_function_type func) : _func(func) {
|
||||
_eventTypeID = TgtEvent::TYPE_ID;
|
||||
}
|
||||
|
||||
~TargetEventListener() override {
|
||||
delete _fnCmptor;
|
||||
}
|
||||
|
||||
template <typename Fn>
|
||||
void setMemberFuncAddr(Fn func, void *context) {
|
||||
auto fctx = new TgtMemberHandleFn<Fn>;
|
||||
fctx->func = func;
|
||||
fctx->context = context;
|
||||
_fnCmptor = fctx;
|
||||
}
|
||||
|
||||
void *getContext() const override {
|
||||
if (_fnCmptor) return _fnCmptor->getContext();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char *getEventName() const override {
|
||||
return TgtEvent::EVENT_NAME;
|
||||
}
|
||||
|
||||
void apply(_emitter_type *self, EventType *evobj) {
|
||||
switch (_state) {
|
||||
case RunState::ONCE_DONE:
|
||||
return;
|
||||
case RunState::PENDING_ONCE:
|
||||
_state = RunState::ONCE_DONE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
_func(self, evobj);
|
||||
}
|
||||
|
||||
protected:
|
||||
_persist_function_type _func;
|
||||
TgtMemberFnCmp *_fnCmptor{nullptr};
|
||||
};
|
||||
|
||||
using TargetEventIdType = int32_t;
|
||||
|
||||
template <typename TgtEvent>
|
||||
class TargetEventID final {
|
||||
public:
|
||||
using HandleType = TgtEvent;
|
||||
using IdType = TargetEventIdType;
|
||||
|
||||
TargetEventID() = default;
|
||||
|
||||
TargetEventID(IdType eventId) : _eventId(eventId) {} // NOLINT
|
||||
|
||||
TargetEventID(const TargetEventID &) = default;
|
||||
|
||||
TargetEventID(TargetEventID &&) noexcept = default;
|
||||
|
||||
TargetEventID &operator=(const TargetEventID &) = default;
|
||||
|
||||
TargetEventID &operator=(TargetEventID &&) noexcept = default;
|
||||
|
||||
IdType value() { return _eventId; }
|
||||
|
||||
private:
|
||||
IdType _eventId{};
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct TargetListenerContainer final {
|
||||
std::array<TargetEventListenerBase *, N> data{nullptr};
|
||||
|
||||
inline TargetEventListenerBase *&operator[](size_t index) { return data[index]; }
|
||||
|
||||
void clear() {
|
||||
for (size_t i = 0; i < N; i++) {
|
||||
auto &handlers = data[i];
|
||||
EVENT_LIST_LOOP_REV_BEGIN(handle, handlers)
|
||||
delete handle;
|
||||
EVENT_LIST_LOOP_REV_END(handle, handlers)
|
||||
data[i] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
~TargetListenerContainer() {
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Self, size_t EventCount, bool hasParent>
|
||||
class EventTargetImpl final {
|
||||
public:
|
||||
constexpr static bool HAS_PARENT = hasParent;
|
||||
|
||||
protected:
|
||||
template <typename TgtEvent, typename Fn>
|
||||
TargetEventID<TgtEvent> addEventListener(Fn &&func, bool useCapture, bool once) {
|
||||
/* CC_ASSERT(!_emittingEvent); */
|
||||
using func_type = std::conditional_t<intl::FunctionTrait<Fn>::IS_LAMBDA,
|
||||
typename intl::lambda_without_class_t<Fn>, Fn>;
|
||||
using wrap_type = intl::TgtEvtFnTrait<func_type>;
|
||||
auto stdfn = wrap_type::template wrap<TgtEvent>(intl::convertLambda(std::forward<Fn>(func)));
|
||||
auto *newHandler = new TargetEventListener<TgtEvent>(stdfn);
|
||||
auto newId = ++_handlerId;
|
||||
newHandler->id = newId;
|
||||
if (once) {
|
||||
newHandler->setOnce();
|
||||
}
|
||||
if constexpr (wrap_type::IS_MEMBER_FUNC) {
|
||||
newHandler->setMemberFuncAddr(std::forward<Fn>(func), nullptr);
|
||||
}
|
||||
if (useCapture) {
|
||||
intl::listAppend<TargetEventListenerBase>(&_capturingHandlers[TgtEvent::TYPE_ID], newHandler);
|
||||
} else {
|
||||
intl::listAppend<TargetEventListenerBase>(&_bubblingHandlers[TgtEvent::TYPE_ID], newHandler);
|
||||
}
|
||||
return TargetEventID<TgtEvent>(newId);
|
||||
}
|
||||
|
||||
template <typename TgtEvent, typename Fn, typename O>
|
||||
TargetEventID<TgtEvent> addEventListener(Fn &&func, O *ctx, bool useCapture, bool once) {
|
||||
/* CC_ASSERT(!_emittingEvent);*/
|
||||
using wrap_type = intl::TgtEvtFnTrait<Fn>;
|
||||
auto stdfn = wrap_type::template wrapWithContext<TgtEvent>(std::forward<Fn>(func), ctx);
|
||||
auto *newHandler = new TargetEventListener<TgtEvent>(stdfn);
|
||||
auto newId = ++_handlerId;
|
||||
newHandler->id = newId;
|
||||
if (once) {
|
||||
newHandler->setOnce();
|
||||
}
|
||||
if constexpr (wrap_type::IS_MEMBER_FUNC) {
|
||||
newHandler->setMemberFuncAddr(std::forward<Fn>(func), ctx);
|
||||
}
|
||||
if (useCapture) {
|
||||
intl::listAppend<TargetEventListenerBase>(&_capturingHandlers[TgtEvent::TYPE_ID], newHandler);
|
||||
} else {
|
||||
intl::listAppend<TargetEventListenerBase>(&_bubblingHandlers[TgtEvent::TYPE_ID], newHandler);
|
||||
}
|
||||
return TargetEventID<TgtEvent>(newId);
|
||||
}
|
||||
|
||||
public:
|
||||
template <typename TgtEvent, typename Fn>
|
||||
TargetEventID<TgtEvent> once(Fn &&func, bool useCapture) {
|
||||
return this->template addEventListener(std::forward<Fn>(func), useCapture, true);
|
||||
}
|
||||
|
||||
template <typename TgtEvent, typename Fn, typename O>
|
||||
TargetEventID<TgtEvent> once(Fn &&func, O *ctx) {
|
||||
return this->template addEventListener(std::forward<Fn>(func), ctx, true);
|
||||
}
|
||||
|
||||
template <typename TgtEvent, typename Fn>
|
||||
TargetEventID<TgtEvent> on(Fn &&func, bool useCapture = false) {
|
||||
static_assert(std::is_base_of<typename TgtEvent::_emitter_type, Self>::value, "mismatch target type");
|
||||
return this->template addEventListener<TgtEvent, Fn>(std::forward<Fn>(func), useCapture, false);
|
||||
}
|
||||
|
||||
template <typename TgtEvent, typename Fn, typename O>
|
||||
TargetEventID<TgtEvent> on(Fn &&func, O *ctx, bool useCapture = false) {
|
||||
return this->template addEventListener<TgtEvent, Fn, O>(std::forward<Fn>(func), ctx, useCapture, false);
|
||||
}
|
||||
|
||||
template <typename TgtEvent>
|
||||
bool off(TargetEventID<TgtEvent> eventId) {
|
||||
CC_ASSERT(!_emittingEvent[TgtEvent::TYPE_ID]);
|
||||
|
||||
TargetEventListenerBase *&bubblingHandlers = _bubblingHandlers[TgtEvent::TYPE_ID];
|
||||
|
||||
EVENT_LIST_LOOP_REV_BEGIN(handle, bubblingHandlers)
|
||||
if (handle && handle->id == eventId.value()) {
|
||||
CC_ASSERT(handle->getEventTypeID() == TgtEvent::TYPE_ID);
|
||||
intl::detachFromList(&bubblingHandlers, handle);
|
||||
delete handle;
|
||||
return true;
|
||||
}
|
||||
EVENT_LIST_LOOP_REV_END(handle, bubblingHandlers)
|
||||
TargetEventListenerBase *&capturingHandlers = _capturingHandlers[TgtEvent::TYPE_ID];
|
||||
EVENT_LIST_LOOP_REV_BEGIN(handle, capturingHandlers)
|
||||
if (handle && handle->id == eventId.value()) {
|
||||
CC_ASSERT(handle->getEventTypeID() == TgtEvent::TYPE_ID);
|
||||
intl::detachFromList(&capturingHandlers, handle);
|
||||
delete handle;
|
||||
return true;
|
||||
}
|
||||
EVENT_LIST_LOOP_REV_END(handle, capturingHandlers)
|
||||
return false;
|
||||
}
|
||||
|
||||
void offAll() {
|
||||
#if CC_DEBUG
|
||||
for (auto &itr : _emittingEvent) {
|
||||
CC_ASSERT(!itr);
|
||||
}
|
||||
#endif
|
||||
_bubblingHandlers.clear();
|
||||
_capturingHandlers.clear();
|
||||
}
|
||||
|
||||
template <typename TgtEvent>
|
||||
void off() {
|
||||
static_assert(std::is_base_of_v<TgtEventTraitClass, TgtEvent>, "incorrect template argument");
|
||||
CC_ASSERT(!_emittingEvent[TgtEvent::TYPE_ID]);
|
||||
TargetEventListenerBase *&bubblingHandlers = _bubblingHandlers[TgtEvent::TYPE_ID];
|
||||
|
||||
EVENT_LIST_LOOP_REV_BEGIN(handle, bubblingHandlers)
|
||||
if (handle) {
|
||||
intl::detachFromList(&bubblingHandlers, handle);
|
||||
delete handle;
|
||||
}
|
||||
EVENT_LIST_LOOP_REV_END(handle, bubblingHandlers)
|
||||
|
||||
TargetEventListenerBase *&capturingHandlers = _capturingHandlers[TgtEvent::TYPE_ID];
|
||||
EVENT_LIST_LOOP_REV_BEGIN(handle, capturingHandlers)
|
||||
if (handle) {
|
||||
intl::detachFromList(&capturingHandlers, handle);
|
||||
delete handle;
|
||||
}
|
||||
EVENT_LIST_LOOP_REV_END(handle, capturingHandlers)
|
||||
}
|
||||
|
||||
template <typename TgtEvent, typename... ARGS>
|
||||
void emit(Self *self, ARGS &&...args) { /* TODO() : statistics */
|
||||
using _handler_function_type = TargetEventListener<TgtEvent>;
|
||||
using EventType = typename TgtEvent::EventType;
|
||||
static_assert(sizeof...(ARGS) == TgtEvent::ARG_COUNT, "Parameter count incorrect for function EventTarget::emit");
|
||||
if (_bubblingHandlers[TgtEvent::TYPE_ID] == nullptr) return;
|
||||
intl::validateParameters<0, TgtEvent, ARGS...>(std::forward<ARGS>(args)...);
|
||||
EventType eventObj(std::make_tuple<ARGS...>(std::forward<ARGS>(args)...));
|
||||
eventObj.target = self;
|
||||
eventObj.currentTarget = self;
|
||||
|
||||
emitEvtObj<false, TgtEvent>(self, &eventObj);
|
||||
}
|
||||
|
||||
template <bool useCapture, typename TgtEvent, typename EvtObj>
|
||||
void emitEvtObj(Self *self, EvtObj *eventObj) {
|
||||
using EventType = typename TgtEvent::EventType;
|
||||
using _handler_function_type = TargetEventListener<TgtEvent>;
|
||||
static_assert(std::is_same_v<EventType, EvtObj>, "Event type mismatch");
|
||||
_emittingEvent[TgtEvent::TYPE_ID]++;
|
||||
if constexpr (useCapture) {
|
||||
TargetEventListenerBase *&handlers = _capturingHandlers[TgtEvent::TYPE_ID];
|
||||
EVENT_LIST_LOOP_BEGIN(handle, handlers)
|
||||
if (handle->isEnabled()) {
|
||||
#if CC_DEBUG
|
||||
bool sameAddr = handle->getEventName() == TgtEvent::EVENT_NAME;
|
||||
if (!sameAddr && strcmp(handle->getEventName(), TgtEvent::EVENT_NAME)) {
|
||||
// different event should not shared a same typeid.
|
||||
CC_LOG_ERROR("Event '%s' and '%s' shared the same TypeID(), for event declaration of subclasses, please use DECLARE_TARGET_EVENT_BEGIN_OFFSET()", TgtEvent::EVENT_NAME, handle->getEventName());
|
||||
CC_ABORT();
|
||||
}
|
||||
#endif
|
||||
static_cast<_handler_function_type *>(handle)->apply(self, eventObj);
|
||||
}
|
||||
EVENT_LIST_LOOP_END(handle, handlers);
|
||||
} else {
|
||||
TargetEventListenerBase *&handlers = _bubblingHandlers[TgtEvent::TYPE_ID];
|
||||
EVENT_LIST_LOOP_BEGIN(handle, handlers)
|
||||
if (handle->isEnabled()) {
|
||||
#if CC_DEBUG
|
||||
bool sameAddr = handle->getEventName() == TgtEvent::EVENT_NAME;
|
||||
if (!sameAddr && strcmp(handle->getEventName(), TgtEvent::EVENT_NAME)) {
|
||||
// different event should not shared a same typeid.
|
||||
CC_LOG_ERROR("Event '%s' and '%s' shared the same TypeID(), for event declaration of subclasses, please use DECLARE_TARGET_EVENT_BEGIN_OFFSET()", TgtEvent::EVENT_NAME, handle->getEventName());
|
||||
CC_ABORT();
|
||||
}
|
||||
#endif
|
||||
static_cast<_handler_function_type *>(handle)->apply(self, eventObj);
|
||||
}
|
||||
EVENT_LIST_LOOP_END(handle, handlers);
|
||||
}
|
||||
_emittingEvent[TgtEvent::TYPE_ID]--;
|
||||
}
|
||||
|
||||
template <typename TgtEvent, typename EvtType>
|
||||
std::enable_if_t<std::is_same_v<typename TgtEvent::EventType, std::decay_t<EvtType>>, void>
|
||||
dispatchEvent(Self *self, EvtType &eventObj) {
|
||||
if constexpr (HAS_PARENT) {
|
||||
std::vector<Self *> parents;
|
||||
Self *curr = self->evGetParent();
|
||||
while (curr) {
|
||||
if (curr->getEventTarget().template hasEventHandler<TgtEvent>()) {
|
||||
parents.emplace_back(curr);
|
||||
}
|
||||
curr = curr->evGetParent();
|
||||
}
|
||||
for (auto itr = parents.rbegin(); itr != parents.rend(); itr++) {
|
||||
eventObj.currentTarget = *itr;
|
||||
(*itr)->getEventTarget().template emitEvtObj<true, TgtEvent>(*itr, &eventObj);
|
||||
if (eventObj.propagationStopped) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eventObj.eventPhase = EventPhaseType::AT_TARGET;
|
||||
eventObj.currentTarget = self;
|
||||
|
||||
emitEvtObj<true, TgtEvent>(self, &eventObj);
|
||||
if (!eventObj.propagationStopped) {
|
||||
emitEvtObj<false, TgtEvent>(self, &eventObj);
|
||||
}
|
||||
|
||||
if constexpr (HAS_PARENT) {
|
||||
if (!eventObj.propagationStopped && eventObj.bubbles) {
|
||||
auto *curr = self->evGetParent();
|
||||
std::vector<Self *> parents;
|
||||
|
||||
while (curr) {
|
||||
if (curr->getEventTarget().template hasEventHandler<TgtEvent>()) {
|
||||
parents.emplace_back(curr);
|
||||
}
|
||||
curr = curr->evGetParent();
|
||||
}
|
||||
for (auto itr = parents.begin(); itr != parents.end(); itr++) {
|
||||
eventObj.currentTarget = *itr;
|
||||
(*itr)->getEventTarget().template emitEvtObj<false, TgtEvent>(*itr, &eventObj);
|
||||
if (eventObj.propagationStopped) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TgtEvent, typename... ARGS>
|
||||
std::enable_if_t<sizeof...(ARGS) != 1 ||
|
||||
(sizeof...(ARGS) == 1 &&
|
||||
!std::is_same_v<typename TgtEvent::EventType,
|
||||
std::remove_pointer_t<typename intl::HeadType<ARGS...>::head>>),
|
||||
void>
|
||||
dispatchEvent(Self *self, ARGS &&...args) {
|
||||
using _handler_function_type = TargetEventListener<TgtEvent>;
|
||||
using EventType = typename TgtEvent::EventType;
|
||||
static_assert(sizeof...(ARGS) == TgtEvent::ARG_COUNT, "Parameter count incorrect for function EventTarget::emit");
|
||||
intl::validateParameters<0, TgtEvent, ARGS...>(std::forward<ARGS>(args)...);
|
||||
EventType eventObj(std::make_tuple<ARGS...>(std::forward<ARGS>(args)...));
|
||||
eventObj.target = self;
|
||||
eventObj.currentTarget = self;
|
||||
eventObj.eventPhase = EventPhaseType::CAPTUREING_PHASE;
|
||||
dispatchEvent<TgtEvent, EventType>(self, eventObj);
|
||||
}
|
||||
|
||||
template <typename TgtEvent>
|
||||
void dispatchEvent(Self *self) {
|
||||
using _handler_function_type = TargetEventListener<TgtEvent>;
|
||||
using EventType = typename TgtEvent::EventType;
|
||||
static_assert(0 == TgtEvent::ARG_COUNT, "Parameter count incorrect for function EventTarget::emit");
|
||||
EventType eventObj;
|
||||
eventObj.target = self;
|
||||
eventObj.currentTarget = self;
|
||||
eventObj.eventPhase = EventPhaseType::CAPTUREING_PHASE;
|
||||
dispatchEvent<TgtEvent, EventType>(self, eventObj);
|
||||
}
|
||||
|
||||
template <typename TgtEvent>
|
||||
bool hasEventHandler() {
|
||||
TargetEventListenerBase *&bubblingHandlers = _bubblingHandlers[TgtEvent::TYPE_ID];
|
||||
EVENT_LIST_LOOP_BEGIN(handle, bubblingHandlers)
|
||||
if (handle->isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
EVENT_LIST_LOOP_END(handle, bubblingHandlers);
|
||||
TargetEventListenerBase *&capturingHandlers = _capturingHandlers[TgtEvent::TYPE_ID];
|
||||
EVENT_LIST_LOOP_BEGIN(handle, capturingHandlers)
|
||||
if (handle->isEnabled()) {
|
||||
return true;
|
||||
}
|
||||
EVENT_LIST_LOOP_END(handle, capturingHandlers);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename TgtEvent, typename Fn, typename C>
|
||||
bool hasEventHandler(Fn func, C *target) {
|
||||
using wrap_type = intl::TgtEvtFnTrait<Fn>;
|
||||
using _handler_function_type = event::TargetEventListener<TgtEvent>;
|
||||
static_assert(std::is_same<typename wrap_type::target_type, C>::value, "member function type mismatch");
|
||||
|
||||
TargetEventListenerBase *&bubblingHandlers = _bubblingHandlers[TgtEvent::TYPE_ID];
|
||||
EVENT_LIST_LOOP_BEGIN(handle, bubblingHandlers)
|
||||
if (handle->isEnabled() && handle->getContext() == target) {
|
||||
auto *ptr = static_cast<_handler_function_type *>(handle);
|
||||
return ptr->getMemberFuncAddr() == func;
|
||||
}
|
||||
EVENT_LIST_LOOP_END(handle, bubblingHandlers);
|
||||
TargetEventListenerBase *&capturingHandlers = _capturingHandlers[TgtEvent::TYPE_ID];
|
||||
EVENT_LIST_LOOP_BEGIN(handle, capturingHandlers)
|
||||
if (handle->isEnabled() && handle->getContext() == target) {
|
||||
auto *ptr = static_cast<_handler_function_type *>(handle);
|
||||
return ptr->getMemberFuncAddr() == func;
|
||||
}
|
||||
EVENT_LIST_LOOP_END(handle, capturingHandlers);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
TargetListenerContainer<EventCount> _bubblingHandlers;
|
||||
TargetListenerContainer<EventCount> _capturingHandlers;
|
||||
TargetEventIdType _handlerId{1};
|
||||
std::array<int, EventCount> _emittingEvent{0};
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class HeapObject final {
|
||||
public:
|
||||
HeapObject() {
|
||||
_data = ccnew T;
|
||||
}
|
||||
|
||||
~HeapObject() {
|
||||
delete _data;
|
||||
}
|
||||
|
||||
inline T &get() {
|
||||
return *_data;
|
||||
}
|
||||
|
||||
private:
|
||||
T *_data{nullptr};
|
||||
};
|
||||
|
||||
template <typename Self, size_t EventCnt, bool HAS_PARENT>
|
||||
using EventTargetGuard = HeapObject<EventTargetImpl<Self, EventCnt, HAS_PARENT>>;
|
||||
|
||||
} // namespace event
|
||||
} // namespace cc
|
||||
|
||||
#define TARGET_EVENT_ARG0(EventTypeClass) \
|
||||
class EventTypeClass final : public cc::event::TgtEventTrait<Self> { \
|
||||
public: \
|
||||
using BaseType = cc::event::TgtEventTrait<Self>; \
|
||||
using EventType = cc::event::Event<EventTypeClass>; \
|
||||
using EventID = cc::event::TargetEventID<EventTypeClass>; \
|
||||
using _persist_function_type = std::function<void(Self *, EventType *)>; \
|
||||
using _handler_function_type = std::function<void(EventType *)>; \
|
||||
constexpr static const char *EVENT_NAME = #EventTypeClass; \
|
||||
constexpr static size_t TYPE_ID = __COUNTER__ - __counter_start__ - 1 + __counter_offset__; \
|
||||
constexpr static size_t TypeHash() { \
|
||||
return cc::event::intl::hash(#EventTypeClass); \
|
||||
} \
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
#define _DECLARE_TARGET_EVENT_INTER(EventTypeClass, ...) \
|
||||
class EventTypeClass final : public cc::event::TgtEventTrait<Self, __VA_ARGS__> { \
|
||||
public: \
|
||||
using BaseType = cc::event::TgtEventTrait<Self, __VA_ARGS__>; \
|
||||
using EventType = cc::event::Event<EventTypeClass>; \
|
||||
using EventID = cc::event::TargetEventID<EventTypeClass>; \
|
||||
using _persist_function_type = std::function<void(Self *, EventType *)>; \
|
||||
using _handler_function_type = std::function<void(EventType *)>; \
|
||||
constexpr static const char *EVENT_NAME = #EventTypeClass; \
|
||||
constexpr static size_t TYPE_ID = __COUNTER__ - __counter_start__ - 1 + __counter_offset__; \
|
||||
constexpr static size_t TypeHash() { \
|
||||
return cc::event::intl::hash(#EventTypeClass); \
|
||||
} \
|
||||
};
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
#define _IMPL_EVENT_TARGET_(Self) \
|
||||
public: \
|
||||
template <typename TgtEvent, typename Fn> \
|
||||
cc::event::TargetEventID<TgtEvent> once(Fn &&func, bool useCapture) { \
|
||||
return _eventTargetImpl.get().once<TgtEvent>(std::forward<Fn>(func), useCapture); \
|
||||
} \
|
||||
\
|
||||
template <typename TgtEvent, typename Fn, typename O> \
|
||||
cc::event::TargetEventID<TgtEvent> once(Fn &&func, O *ctx) { \
|
||||
return _eventTargetImpl.get().once<TgtEvent>(std::forward<Fn>(func), ctx); \
|
||||
} \
|
||||
template <typename TgtEvent, typename Fn> \
|
||||
cc::event::TargetEventID<TgtEvent> on(Fn &&func, bool useCapture = false) { \
|
||||
static_assert(std::is_base_of<typename TgtEvent::_emitter_type, Self>::value, "mismatch target type"); \
|
||||
return _eventTargetImpl.get().on<TgtEvent, Fn>(std::forward<Fn>(func), useCapture); \
|
||||
} \
|
||||
template <typename TgtEvent, typename Fn, typename O> \
|
||||
cc::event::TargetEventID<TgtEvent> on(Fn &&func, O *ctx, bool useCapture = false) { \
|
||||
return _eventTargetImpl.get().on<TgtEvent, Fn, O>(std::forward<Fn>(func), ctx, useCapture); \
|
||||
} \
|
||||
template <typename TgtEvent> \
|
||||
bool off(cc::event::TargetEventID<TgtEvent> eventId) { \
|
||||
return _eventTargetImpl.get().off(eventId); \
|
||||
} \
|
||||
void offAll() { \
|
||||
_eventTargetImpl.get().offAll(); \
|
||||
} \
|
||||
template <typename TgtEvent> \
|
||||
void off() { \
|
||||
_eventTargetImpl.get().off<TgtEvent>(); \
|
||||
} \
|
||||
template <typename TgtEvent, typename... ARGS> \
|
||||
void emit(ARGS &&...args) { \
|
||||
_eventTargetImpl.get().emit<TgtEvent>(this, std::forward<ARGS>(args)...); \
|
||||
} \
|
||||
template <typename TgtEvent, typename... ARGS> \
|
||||
void dispatchEvent(ARGS &&...args) { \
|
||||
_eventTargetImpl.get().dispatchEvent<TgtEvent, ARGS...>(this, std::forward<ARGS>(args)...); \
|
||||
}
|
||||
|
||||
#define IMPL_EVENT_TARGET(TargetClass) \
|
||||
public: \
|
||||
static constexpr bool HAS_PARENT = false; \
|
||||
inline TargetClass *evGetParent() { return nullptr; } \
|
||||
_IMPL_EVENT_TARGET_(TargetClass)
|
||||
|
||||
#define IMPL_EVENT_TARGET_WITH_PARENT(TargetClass, getParentMethod) \
|
||||
public: \
|
||||
static constexpr bool HAS_PARENT = true; \
|
||||
inline auto evGetParent() { \
|
||||
return getParentMethod(); \
|
||||
} \
|
||||
_IMPL_EVENT_TARGET_(TargetClass)
|
||||
|
||||
// NOLINTNEXTLINE
|
||||
#define _DECLARE_TARGET_EVENT_BEGIN(TargetClass) \
|
||||
using Self = TargetClass; \
|
||||
\
|
||||
private: \
|
||||
constexpr static int __counter_start__ = __COUNTER__; \
|
||||
\
|
||||
public:
|
||||
|
||||
#define DECLARE_TARGET_EVENT_BEGIN(TargetClass) \
|
||||
constexpr static int __counter_offset__ = 0; \
|
||||
_DECLARE_TARGET_EVENT_BEGIN(TargetClass)
|
||||
|
||||
#define DECLARE_TARGET_EVENT_BEGIN_WITH_PARENTS(TargetClass, ...) \
|
||||
constexpr static int __counter_offset__ = cc::event::intl::TotalEvents<__VA_ARGS__>; \
|
||||
_DECLARE_TARGET_EVENT_BEGIN(TargetClass)
|
||||
|
||||
#define DECLARE_TARGET_EVENT_END() \
|
||||
private: \
|
||||
constexpr static int __counter_stop__ = __COUNTER__; \
|
||||
constexpr static int __event_count__ = __counter_stop__ - __counter_start__ + __counter_offset__; \
|
||||
cc::event::EventTargetGuard<Self, __event_count__, HAS_PARENT> _eventTargetImpl; \
|
||||
\
|
||||
public: \
|
||||
constexpr static int getEventCount() { return __event_count__; } \
|
||||
auto &getEventTarget() { return _eventTargetImpl.get(); }
|
||||
|
||||
#include "intl/EventTargetMacros.h"
|
||||
295
cocos/core/event/intl/EventBusMacros.h
Normal file
295
cocos/core/event/intl/EventBusMacros.h
Normal file
@@ -0,0 +1,295 @@
|
||||
// generated code
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG0(BusEventClass, EventBusClass) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast() { \
|
||||
cc::event::broadcast<BusEventClass>(); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG1(BusEventClass, EventBusClass, ArgType0) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG2(BusEventClass, EventBusClass, ArgType0, ArgType1) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG3(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG4(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG5(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG6(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG7(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG8(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG9(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG10(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG11(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG12(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG13(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG14(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12, ArgType13 arg13) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG15(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12, ArgType13 arg13, ArgType14 arg14) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG16(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12, ArgType13 arg13, ArgType14 arg14, ArgType15 arg15) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG17(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12, ArgType13 arg13, ArgType14 arg14, ArgType15 arg15, ArgType16 arg16) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG18(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12, ArgType13 arg13, ArgType14 arg14, ArgType15 arg15, ArgType16 arg16, ArgType17 arg17) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG19(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12, ArgType13 arg13, ArgType14 arg14, ArgType15 arg15, ArgType16 arg16, ArgType17 arg17, ArgType18 arg18) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18); \
|
||||
} \
|
||||
};
|
||||
|
||||
#define DECLARE_BUS_EVENT_ARG20(BusEventClass, EventBusClass, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18, ArgType19) \
|
||||
struct BusEventClass final : cc::event::BusEventTrait<EventBusName_(EventBusClass), void, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18, ArgType19> { \
|
||||
using BusType = EventBusName_(EventBusClass); \
|
||||
using Listener = cc::event::Listener<BusEventClass>; \
|
||||
constexpr static const char *BUS_NAME = EventBusName_(EventBusClass)::BUS_NAME; \
|
||||
constexpr static const char *HANDLE_CLASS = #BusEventClass; \
|
||||
constexpr static size_t TypeID() { \
|
||||
return cc::event::intl::hash(#BusEventClass); \
|
||||
} \
|
||||
static inline void broadcast(ArgType0 arg0, ArgType1 arg1, ArgType2 arg2, ArgType3 arg3, ArgType4 arg4, ArgType5 arg5, ArgType6 arg6, ArgType7 arg7, ArgType8 arg8, ArgType9 arg9, ArgType10 arg10, ArgType11 arg11, ArgType12 arg12, ArgType13 arg13, ArgType14 arg14, ArgType15 arg15, ArgType16 arg16, ArgType17 arg17, ArgType18 arg18, ArgType19 arg19) { \
|
||||
cc::event::broadcast<BusEventClass>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, arg16, arg17, arg18, arg19); \
|
||||
} \
|
||||
};
|
||||
481
cocos/core/event/intl/EventIntl.h
Normal file
481
cocos/core/event/intl/EventIntl.h
Normal file
@@ -0,0 +1,481 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
namespace cc {
|
||||
namespace event {
|
||||
namespace intl {
|
||||
template <size_t N, size_t I = 0>
|
||||
struct hash_calc { // NOLINT
|
||||
static constexpr size_t apply(const char (&str)[N]) {
|
||||
return (hash_calc<N, I + 1>::apply(str) ^ str[I]) * 16777619U;
|
||||
};
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
struct hash_calc<N, N> { // NOLINT
|
||||
static constexpr size_t apply(const char (&/*used*/)[N]) {
|
||||
return 2166136261U;
|
||||
};
|
||||
};
|
||||
|
||||
template <size_t N>
|
||||
constexpr size_t hash(const char (&str)[N]) {
|
||||
return hash_calc<N>::apply(str);
|
||||
}
|
||||
|
||||
template <typename... TYPES>
|
||||
struct HeadType;
|
||||
|
||||
template <typename Head, typename... Tails>
|
||||
struct HeadType<Head, Tails...> {
|
||||
using head = Head;
|
||||
using remain = HeadType<Tails...>;
|
||||
};
|
||||
|
||||
template <typename Head>
|
||||
struct HeadType<Head> {
|
||||
using head = Head;
|
||||
using remain = HeadType<>;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct HeadType<> {
|
||||
using head = void;
|
||||
using remain = HeadType<>;
|
||||
};
|
||||
|
||||
template <int idx, typename EHandler>
|
||||
constexpr bool validateParameters() {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <int idx, typename EHandler, typename Head>
|
||||
constexpr bool validateParameters(Head && /*unused*/) {
|
||||
using element_t = std::remove_reference_t<std::tuple_element_t<idx, typename EHandler::_argument_tuple_types>>;
|
||||
using head = std::remove_reference_t<Head>;
|
||||
constexpr bool assignable = std::is_assignable_v<head, element_t> || std::is_convertible_v<head, element_t>;
|
||||
constexpr bool ret = assignable;
|
||||
static_assert(ret, "Parameter type incorrect");
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <int idx, typename EHandler, typename Head, typename... ARGS>
|
||||
constexpr bool validateParameters(Head &&head, ARGS &&...remain) {
|
||||
return validateParameters<idx, EHandler, Head>(std::forward<Head>(head)) && validateParameters<idx + 1, EHandler, ARGS...>(std::forward<ARGS>(remain)...);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct TupleExtractor {
|
||||
using func_type = void();
|
||||
};
|
||||
|
||||
template <typename... ARGS>
|
||||
struct TupleExtractor<std::tuple<ARGS...>> {
|
||||
using func_type = void(ARGS...);
|
||||
using std_func_type = std::function<void(ARGS...)>;
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
struct FunctionTrait : public FunctionTrait<decltype(&F::operator())> {
|
||||
constexpr static bool IS_LAMBDA = true;
|
||||
};
|
||||
|
||||
template <typename R, typename C, typename... ARGS>
|
||||
struct FunctionTrait<R (C::*)(ARGS...)> {
|
||||
constexpr static bool IS_LAMBDA = false;
|
||||
using function_type = R (C::*)(ARGS...);
|
||||
};
|
||||
|
||||
template <typename R, typename C, typename... ARGS>
|
||||
struct FunctionTrait<R (C::*)(ARGS...) const> {
|
||||
constexpr static bool IS_LAMBDA = false;
|
||||
using function_type = R (C::*)(ARGS...) const;
|
||||
};
|
||||
|
||||
template <typename R, typename... ARGS>
|
||||
struct FunctionTrait<R (*)(ARGS...)> {
|
||||
using function_type = R (*)(ARGS...);
|
||||
constexpr static bool IS_LAMBDA = false;
|
||||
};
|
||||
|
||||
template <typename R, typename... ARGS>
|
||||
struct FunctionTrait<R(ARGS...)> {
|
||||
using function_type = R(ARGS...);
|
||||
constexpr static bool IS_LAMBDA = false;
|
||||
};
|
||||
template <typename R, typename... ARGS>
|
||||
struct FunctionTrait<std::function<R(ARGS...)>> {
|
||||
using function_type = std::function<R(ARGS...)>;
|
||||
constexpr static bool IS_LAMBDA = false;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveClass {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct RemoveClass<R (C::*)(ARGS...)> {
|
||||
using type = std::function<R(ARGS...)>;
|
||||
};
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct RemoveClass<R (C::*)(ARGS...) const> {
|
||||
using type = std::function<R(ARGS...)>;
|
||||
};
|
||||
|
||||
template <typename F>
|
||||
using function_type_t = typename FunctionTrait<F>::function_type;
|
||||
|
||||
template <typename F>
|
||||
using lambda_without_class_t = typename RemoveClass<function_type_t<F>>::type;
|
||||
|
||||
template <typename F>
|
||||
inline auto convertLambda(F &&lambda) {
|
||||
if constexpr (FunctionTrait<F>::IS_LAMBDA) {
|
||||
return static_cast<lambda_without_class_t<F>>(std::forward<F>(lambda));
|
||||
} else {
|
||||
return static_cast<function_type_t<F>>(std::forward<F>(lambda));
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
struct TgtEvtFnTrait;
|
||||
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct TgtEvtFnTrait<R(C *, ARGS...)> {
|
||||
using param0_type = C;
|
||||
using src_func_type = R(C *, ARGS...);
|
||||
constexpr static bool IS_MEMBER_FUNC = false;
|
||||
template <typename TgtEvent>
|
||||
static constexpr bool accept() {
|
||||
if constexpr (sizeof...(ARGS) == 0) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
return std::is_same_v<param0_type, event_type>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename TgtEvent>
|
||||
static auto wrap(src_func_type func) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
persist_function_type ret;
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
ret = [&func](emitter_type * /*self*/, event_type *event) {
|
||||
func(event);
|
||||
};
|
||||
} else {
|
||||
static_assert(std::is_same_v<param0_type, emitter_type>, "mismatch emitter type");
|
||||
ret = [func](emitter_type *self, event_type *event) {
|
||||
return std::apply([self, func](auto &&...args) { func(self, args...); }, event->args);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct TgtEvtFnTrait<R(const C *, ARGS...)> {
|
||||
using param0_type = C;
|
||||
using src_func_type = R(const C *, ARGS...);
|
||||
constexpr static bool IS_MEMBER_FUNC = false;
|
||||
template <typename TgtEvent>
|
||||
static constexpr bool accept() {
|
||||
if constexpr (sizeof...(ARGS) == 0) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
return std::is_same_v<param0_type, event_type>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename TgtEvent>
|
||||
static auto wrap(src_func_type func) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
persist_function_type ret;
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
ret = [func](emitter_type * /*self*/, event_type *event) {
|
||||
func(event);
|
||||
};
|
||||
} else {
|
||||
static_assert(std::is_same_v<param0_type, emitter_type>, "mismatch emitter type");
|
||||
ret = [func](emitter_type *self, event_type *event) { return std::apply([self, func](auto &&...args) { func(self, args...); }, event->args); };
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct TgtEvtFnTrait<R (*)(C *, ARGS...)> {
|
||||
using param0_type = C;
|
||||
using src_func_type = R (*)(C *, ARGS...);
|
||||
constexpr static bool IS_MEMBER_FUNC = false;
|
||||
template <typename TgtEvent>
|
||||
static constexpr bool accept() {
|
||||
if constexpr (sizeof...(ARGS) == 0) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
return std::is_same_v<param0_type, event_type>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename TgtEvent>
|
||||
static auto wrap(src_func_type func) {
|
||||
using EventType = typename TgtEvent::EventType;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
persist_function_type ret;
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
auto ret2 = [func](emitter_type * /*self*/, EventType *event) {
|
||||
func(event);
|
||||
};
|
||||
ret = ret2;
|
||||
} else {
|
||||
static_assert(std::is_same_v<emitter_type, param0_type>, "mismatch emitter type");
|
||||
ret = [func](emitter_type *self, EventType *event) {
|
||||
return std::apply([self, func](auto &&...args) { func(self, args...); }, event->args);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct TgtEvtFnTrait<R (*)(const C *, ARGS...)> {
|
||||
using src_func_type = R (*)(const C *, ARGS...);
|
||||
using param0_type = C;
|
||||
constexpr static bool IS_MEMBER_FUNC = false;
|
||||
template <typename TgtEvent>
|
||||
static constexpr bool accept() {
|
||||
if constexpr (sizeof...(ARGS) == 0) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
return std::is_same_v<param0_type, event_type>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename TgtEvent>
|
||||
static auto wrap(src_func_type func) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
persist_function_type ret;
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
ret = [&func](emitter_type * /*self*/, event_type *event) {
|
||||
func(event);
|
||||
};
|
||||
return ret;
|
||||
} else {
|
||||
static_assert(std::is_same_v<emitter_type, param0_type>, "mismatch emitter type");
|
||||
ret = [func](emitter_type *self, event_type *event) {
|
||||
return std::apply([self, func](auto &&...args) { func(self, args...); }, event->args);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct TgtEvtFnTrait<std::function<R(const C *, ARGS...)>> {
|
||||
using src_func_type = std::function<R(const C *, ARGS...)>;
|
||||
using param0_type = C;
|
||||
constexpr static bool IS_MEMBER_FUNC = false;
|
||||
template <typename TgtEvent>
|
||||
static constexpr bool accept() {
|
||||
if constexpr (sizeof...(ARGS) == 0) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
return std::is_same_v<param0_type, event_type>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename TgtEvent>
|
||||
static auto wrap(src_func_type func) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
persist_function_type ret;
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
ret = [&func](emitter_type * /*self*/, event_type *event) {
|
||||
func(event);
|
||||
};
|
||||
} else {
|
||||
static_assert(std::is_same_v<emitter_type, param0_type>, "mismatch emitter type");
|
||||
ret = [func](emitter_type *self, event_type *event) {
|
||||
return std::apply([self, func](auto &&...args) { func(self, args...); }, event->args);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct TgtEvtFnTrait<std::function<R(C *, ARGS...)>> {
|
||||
using param0_type = C;
|
||||
using src_func_type = std::function<R(C *, ARGS...)>;
|
||||
constexpr static bool IS_MEMBER_FUNC = false;
|
||||
template <typename TgtEvent>
|
||||
static constexpr bool accept() {
|
||||
if constexpr (sizeof...(ARGS) == 0) {
|
||||
using EventType = typename TgtEvent::EventType;
|
||||
return std::is_same_v<param0_type, EventType>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
template <typename TgtEvent>
|
||||
static auto wrap(src_func_type func) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
persist_function_type ret;
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
ret = [func](emitter_type * /*self*/, event_type *event) {
|
||||
func(event);
|
||||
};
|
||||
} else {
|
||||
static_assert(std::is_same_v<emitter_type, param0_type>, "mismatch emitter type");
|
||||
ret = [func](emitter_type *self, event_type *event) {
|
||||
return std::apply([self, func](auto &&...args) { func(self, args...); }, event->args);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct TgtEvtFnTrait<R (C::*)(ARGS...)> {
|
||||
using src_func_type = R (C::*)(ARGS...);
|
||||
using context_type = C;
|
||||
using param0_type = typename intl::HeadType<ARGS...>::head;
|
||||
constexpr static bool IS_MEMBER_FUNC = true;
|
||||
template <typename TgtEvent>
|
||||
static constexpr bool accept() {
|
||||
if constexpr (sizeof...(ARGS) == 1) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
return std::is_same_v<param0_type, event_type *>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TgtEvent>
|
||||
static auto wrap(src_func_type func) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
persist_function_type ret;
|
||||
static_assert(std::is_same_v<emitter_type, context_type>, "mismatch emitter type");
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
ret = [&func](emitter_type *self, event_type *event) {
|
||||
(self->*func)(event);
|
||||
};
|
||||
} else {
|
||||
ret = [func](emitter_type *self, event_type *event) {
|
||||
return std::apply([&self, func](auto &&...args) { (self->*func)(args...); }, event->args);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
template <typename TgtEvent>
|
||||
static auto wrapWithContext(src_func_type func, context_type *ctx) {
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
persist_function_type ret;
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
ret = [func, ctx](emitter_type * /*self*/, event_type *event) {
|
||||
(ctx->*func)(event);
|
||||
};
|
||||
} else {
|
||||
ret = [func, ctx](emitter_type * /*self*/, event_type *event) {
|
||||
return std::apply([ctx, func](auto... args) { (ctx->*func)(args...); }, event->args);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
template <typename C, typename R, typename... ARGS>
|
||||
struct TgtEvtFnTrait<R (C::*)(ARGS...) const> {
|
||||
using src_func_type = R (C::*)(ARGS...) const;
|
||||
using context_type = C;
|
||||
using param0_type = typename intl::HeadType<ARGS...>::head;
|
||||
constexpr static bool IS_MEMBER_FUNC = true;
|
||||
|
||||
template <typename TgtEvent>
|
||||
static constexpr bool accept() {
|
||||
if constexpr (sizeof...(ARGS) == 1) {
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
return std::is_same_v<param0_type, event_type *>;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TgtEvent>
|
||||
static auto wrap(src_func_type func) {
|
||||
using EventType = typename TgtEvent::EventType;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
persist_function_type ret;
|
||||
static_assert(std::is_same_v<emitter_type, context_type>, "mismatch emitter type");
|
||||
if constexpr (accept<TgtEvent>()) {
|
||||
ret = [&func](context_type *self, EventType *event) {
|
||||
(self->*func)(event);
|
||||
};
|
||||
} else {
|
||||
ret = [&func](context_type *self, EventType *event) {
|
||||
return std::apply([self, func](auto &&...args) { (self->*func)(args...); }, event->args);
|
||||
};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename TgtEvent>
|
||||
static auto wrapWithContext(src_func_type func, context_type *ctx) {
|
||||
using emitter_type = typename TgtEvent::_emitter_type;
|
||||
using event_type = typename TgtEvent::EventType;
|
||||
using persist_function_type = typename TgtEvent::_persist_function_type;
|
||||
persist_function_type ret = [func, ctx](emitter_type * /*self*/, event_type *event) {
|
||||
return std::apply([ctx, func](auto &&...args) { (ctx->*func)(args...); }, event->args);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
constexpr T addAll(T first) {
|
||||
return first;
|
||||
}
|
||||
template <typename T, typename... Others>
|
||||
constexpr T addAll(T first, Others... others) {
|
||||
return first + addAll(others...);
|
||||
}
|
||||
|
||||
template <typename... Parents>
|
||||
constexpr int TotalEvents = addAll(Parents::getEventCount()...); // NOLINT
|
||||
|
||||
} // namespace intl
|
||||
} // namespace event
|
||||
} // namespace cc
|
||||
64
cocos/core/event/intl/EventTargetMacros.h
Normal file
64
cocos/core/event/intl/EventTargetMacros.h
Normal file
@@ -0,0 +1,64 @@
|
||||
// generated code
|
||||
|
||||
#define TARGET_EVENT_ARG1(EventType, ArgType0) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0)
|
||||
|
||||
#define TARGET_EVENT_ARG2(EventType, ArgType0, ArgType1) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1)
|
||||
|
||||
#define TARGET_EVENT_ARG3(EventType, ArgType0, ArgType1, ArgType2) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2)
|
||||
|
||||
#define TARGET_EVENT_ARG4(EventType, ArgType0, ArgType1, ArgType2, ArgType3) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3)
|
||||
|
||||
#define TARGET_EVENT_ARG5(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4)
|
||||
|
||||
#define TARGET_EVENT_ARG6(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5)
|
||||
|
||||
#define TARGET_EVENT_ARG7(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6)
|
||||
|
||||
#define TARGET_EVENT_ARG8(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7)
|
||||
|
||||
#define TARGET_EVENT_ARG9(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8)
|
||||
|
||||
#define TARGET_EVENT_ARG10(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9)
|
||||
|
||||
#define TARGET_EVENT_ARG11(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10)
|
||||
|
||||
#define TARGET_EVENT_ARG12(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11)
|
||||
|
||||
#define TARGET_EVENT_ARG13(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12)
|
||||
|
||||
#define TARGET_EVENT_ARG14(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13)
|
||||
|
||||
#define TARGET_EVENT_ARG15(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14)
|
||||
|
||||
#define TARGET_EVENT_ARG16(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15)
|
||||
|
||||
#define TARGET_EVENT_ARG17(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16)
|
||||
|
||||
#define TARGET_EVENT_ARG18(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17)
|
||||
|
||||
#define TARGET_EVENT_ARG19(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18)
|
||||
|
||||
#define TARGET_EVENT_ARG20(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18, ArgType19) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18, ArgType19)
|
||||
|
||||
#define TARGET_EVENT_ARG21(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18, ArgType19, ArgType20) \
|
||||
_DECLARE_TARGET_EVENT_INTER(EventType, ArgType0, ArgType1, ArgType2, ArgType3, ArgType4, ArgType5, ArgType6, ArgType7, ArgType8, ArgType9, ArgType10, ArgType11, ArgType12, ArgType13, ArgType14, ArgType15, ArgType16, ArgType17, ArgType18, ArgType19, ArgType20)
|
||||
105
cocos/core/event/intl/List.h
Normal file
105
cocos/core/event/intl/List.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include "base/Macros.h"
|
||||
namespace cc {
|
||||
namespace event {
|
||||
namespace intl {
|
||||
|
||||
template <typename ListNode>
|
||||
bool listAppend(ListNode **head, ListNode *newNode) {
|
||||
if (newNode->next != nullptr || newNode->prev != nullptr) {
|
||||
CC_ABORT();
|
||||
return false;
|
||||
}
|
||||
if (*head == nullptr) {
|
||||
newNode->next = newNode;
|
||||
newNode->prev = newNode;
|
||||
*head = newNode;
|
||||
} else {
|
||||
auto *first = *head;
|
||||
auto *last = (*head)->prev;
|
||||
newNode->prev = last;
|
||||
newNode->next = first;
|
||||
first->prev = newNode;
|
||||
last->next = newNode;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename ListNode>
|
||||
bool detachFromList(ListNode **head, ListNode *node) {
|
||||
if (*head == nullptr || node->prev == nullptr || node->next == nullptr) {
|
||||
CC_ABORT();
|
||||
return false;
|
||||
}
|
||||
if (node->prev == node && node->next == node) { // the only node
|
||||
CC_ASSERT(node == *head); // should be the first
|
||||
*head = nullptr;
|
||||
} else {
|
||||
auto *nextNode = node->next;
|
||||
auto *prevNode = node->prev;
|
||||
nextNode->prev = prevNode;
|
||||
prevNode->next = nextNode;
|
||||
if (node == *head) {
|
||||
*head = nextNode;
|
||||
}
|
||||
}
|
||||
node->prev = nullptr;
|
||||
node->next = nullptr;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace intl
|
||||
} // namespace event
|
||||
} // namespace cc
|
||||
|
||||
#define EVENT_LIST_LOOP_BEGIN(tempVar, list) \
|
||||
if (list) { \
|
||||
auto *tempVar = list; \
|
||||
do { \
|
||||
auto *nextCopy = tempVar->next;
|
||||
|
||||
#define EVENT_LIST_LOOP_END(tempVar, list) \
|
||||
tempVar = nextCopy; \
|
||||
} \
|
||||
while (tempVar != list) \
|
||||
; \
|
||||
}
|
||||
|
||||
#define EVENT_LIST_LOOP_REV_BEGIN(tempVar, list) \
|
||||
if (list) { \
|
||||
auto *tempVar = list->prev; \
|
||||
bool isLastListNode = false; \
|
||||
do { \
|
||||
auto *nextCopy = tempVar->prev; \
|
||||
isLastListNode = tempVar == list;
|
||||
|
||||
#define EVENT_LIST_LOOP_REV_END(tempVar, list) \
|
||||
tempVar = nextCopy; \
|
||||
} \
|
||||
while (!isLastListNode) \
|
||||
; \
|
||||
}
|
||||
181
cocos/core/geometry/AABB.cpp
Normal file
181
cocos/core/geometry/AABB.cpp
Normal file
@@ -0,0 +1,181 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "AABB.h"
|
||||
#include "base/Macros.h"
|
||||
#include "cocos/core/geometry/Enums.h"
|
||||
#include "cocos/core/geometry/Sphere.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
Sphere *AABB::toBoundingSphere(Sphere *out, const AABB &a) {
|
||||
out->setCenter(a.getCenter());
|
||||
out->setRadius(a.getHalfExtents().length());
|
||||
return out;
|
||||
}
|
||||
|
||||
AABB *AABB::fromPoints(const Vec3 &minPos, const Vec3 &maxPos, AABB *dst) {
|
||||
Vec3 center{(minPos + maxPos) * 0.5F};
|
||||
Vec3 halfExtents{(maxPos - minPos) * 0.5F};
|
||||
dst->setCenter(center);
|
||||
dst->setHalfExtents(halfExtents);
|
||||
return dst;
|
||||
}
|
||||
|
||||
AABB *AABB::merge(AABB *out, const AABB &a, const AABB &b) {
|
||||
Vec3 minCornor;
|
||||
Vec3 maxCorner;
|
||||
Vec3::max(a.getCenter() + a.getHalfExtents(), b.getCenter() + b.getHalfExtents(), &maxCorner);
|
||||
Vec3::min(a.getCenter() - a.getHalfExtents(), b.getCenter() - b.getHalfExtents(), &minCornor);
|
||||
return AABB::fromPoints(minCornor, maxCorner, out);
|
||||
}
|
||||
|
||||
void AABB::merge(const cc::Vec3 &point) {
|
||||
cc::Vec3 minPos = getCenter() - getHalfExtents();
|
||||
cc::Vec3 maxPos = getCenter() + getHalfExtents();
|
||||
if (point.x < minPos.x) {
|
||||
minPos.x = point.x;
|
||||
}
|
||||
if (point.y < minPos.y) {
|
||||
minPos.y = point.y;
|
||||
}
|
||||
if (point.z < minPos.z) {
|
||||
minPos.z = point.z;
|
||||
}
|
||||
if (point.x > maxPos.x) {
|
||||
maxPos.x = point.x;
|
||||
}
|
||||
if (point.y > maxPos.y) {
|
||||
maxPos.y = point.y;
|
||||
}
|
||||
if (point.z > maxPos.z) {
|
||||
maxPos.z = point.z;
|
||||
}
|
||||
|
||||
const Vec3 center = (minPos + maxPos) * 0.5F;
|
||||
setCenter(center);
|
||||
setHalfExtents(maxPos.x - center.x, maxPos.y - center.y, maxPos.z - center.z);
|
||||
}
|
||||
|
||||
void AABB::merge(const ccstd::vector<cc::Vec3> &points) {
|
||||
for (const auto &p : points) {
|
||||
merge(p);
|
||||
}
|
||||
}
|
||||
|
||||
void AABB::merge(const Frustum &frustum) {
|
||||
const ccstd::array<Vec3, 8> &vertices = frustum.vertices;
|
||||
for (size_t i = 0; i < vertices.max_size(); ++i) {
|
||||
merge(vertices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool AABB::aabbAabb(const AABB &aabb) const {
|
||||
Vec3 aMin;
|
||||
Vec3 aMax;
|
||||
Vec3 bMin;
|
||||
Vec3 bMax;
|
||||
Vec3::subtract(getCenter(), getHalfExtents(), &aMin);
|
||||
Vec3::add(getCenter(), getHalfExtents(), &aMax);
|
||||
Vec3::subtract(aabb.getCenter(), aabb.getHalfExtents(), &bMin);
|
||||
Vec3::add(aabb.getCenter(), aabb.getHalfExtents(), &bMax);
|
||||
return (aMin.x <= bMax.x && aMax.x >= bMin.x) &&
|
||||
(aMin.y <= bMax.y && aMax.y >= bMin.y) &&
|
||||
(aMin.z <= bMax.z && aMax.z >= bMin.z);
|
||||
}
|
||||
|
||||
int AABB::aabbPlane(const Plane &plane) const {
|
||||
auto r = getHalfExtents().x * std::abs(plane.n.x) +
|
||||
getHalfExtents().y * std::abs(plane.n.y) +
|
||||
getHalfExtents().z * std::abs(plane.n.z);
|
||||
auto dot = Vec3::dot(plane.n, getCenter());
|
||||
if (dot + r < plane.d) {
|
||||
return -1;
|
||||
}
|
||||
if (dot - r > plane.d) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool AABB::aabbFrustum(const Frustum &frustum) const {
|
||||
const auto &planes = frustum.planes;
|
||||
const auto *self = this;
|
||||
return std::all_of(planes.begin(),
|
||||
planes.end(),
|
||||
// frustum plane normal points to the inside
|
||||
[self](const Plane *plane) { return self->aabbPlane(*plane) != -1; });
|
||||
}
|
||||
|
||||
void AABB::getBoundary(cc::Vec3 *minPos, cc::Vec3 *maxPos) const {
|
||||
*maxPos = getCenter() + getHalfExtents();
|
||||
*minPos = getCenter() - getHalfExtents();
|
||||
}
|
||||
|
||||
void AABB::merge(const AABB &aabb) {
|
||||
AABB::merge(this, aabb, *this);
|
||||
}
|
||||
|
||||
void AABB::set(const cc::Vec3 ¢erVal, const cc::Vec3 &halfExtentVal) {
|
||||
setCenter(centerVal);
|
||||
setHalfExtents(halfExtentVal);
|
||||
}
|
||||
|
||||
void AABB::transform(const Mat4 &m, AABB *out) const {
|
||||
Vec3::transformMat4(center, m, &out->center);
|
||||
transformExtentM4(&out->halfExtents, getHalfExtents(), m);
|
||||
}
|
||||
|
||||
bool AABB::contain(const cc::Vec3 &point) const {
|
||||
cc::Vec3 minPos = getCenter() - getHalfExtents();
|
||||
cc::Vec3 maxPos = getCenter() + getHalfExtents();
|
||||
|
||||
return !(point.x > maxPos.x || point.x < minPos.x ||
|
||||
point.y > maxPos.y || point.y < minPos.y ||
|
||||
point.z > maxPos.z || point.z < minPos.z);
|
||||
}
|
||||
|
||||
// https://zeuxcg.org/2010/10/17/aabb-from-obb-with-component-wise-abs/
|
||||
void AABB::transformExtentM4(Vec3 *out, const Vec3 &extent, const Mat4 &m4) {
|
||||
Mat3 m3Tmp;
|
||||
m3Tmp.m[0] = std::abs(m4.m[0]);
|
||||
m3Tmp.m[1] = std::abs(m4.m[1]);
|
||||
m3Tmp.m[2] = std::abs(m4.m[2]);
|
||||
m3Tmp.m[3] = std::abs(m4.m[4]);
|
||||
m3Tmp.m[4] = std::abs(m4.m[5]);
|
||||
m3Tmp.m[5] = std::abs(m4.m[6]);
|
||||
m3Tmp.m[6] = std::abs(m4.m[8]);
|
||||
m3Tmp.m[7] = std::abs(m4.m[9]);
|
||||
m3Tmp.m[8] = std::abs(m4.m[10]);
|
||||
out->transformMat3(extent, m3Tmp);
|
||||
}
|
||||
|
||||
AABB::AABB(float px, float py, float pz, float hw, float hh, float hl) : AABB() {
|
||||
setCenter(px, py, pz);
|
||||
setHalfExtents(hw, hh, hl);
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
164
cocos/core/geometry/AABB.h
Normal file
164
cocos/core/geometry/AABB.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include "base/memory/Memory.h"
|
||||
#include "base/std/container/vector.h"
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "math/Mat3.h"
|
||||
#include "math/Quaternion.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
class Sphere;
|
||||
class Frustum;
|
||||
class Plane;
|
||||
|
||||
class AABB final : public ShapeBase {
|
||||
public:
|
||||
/**
|
||||
* @en
|
||||
* create a new AABB
|
||||
* @zh
|
||||
* 创建一个新的 AABB 实例。
|
||||
* @param px - AABB 的原点的 X 坐标。
|
||||
* @param py - AABB 的原点的 Y 坐标。
|
||||
* @param pz - AABB 的原点的 Z 坐标。
|
||||
* @param hw - AABB 宽度的一半。
|
||||
* @param hh - AABB 高度的一半。
|
||||
* @param hl - AABB 长度的一半。
|
||||
* @returns 返回新创建的 AABB 实例。
|
||||
*/
|
||||
static AABB *create(float px, float py, float pz, float hw, float hh, float hl) {
|
||||
return ccnew AABB(px, py, pz, hw, hh, hl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set the components of a AABB to the given values
|
||||
* @zh
|
||||
* 将 AABB 的属性设置为给定的值。
|
||||
* @param {AABB} out 接受操作的 AABB。
|
||||
* @param px - AABB 的原点的 X 坐标。
|
||||
* @param py - AABB 的原点的 Y 坐标。
|
||||
* @param pz - AABB 的原点的 Z 坐标。
|
||||
* @param hw - AABB 宽度的一半。
|
||||
* @param hh - AABB 高度的一半。
|
||||
* @param hl - AABB 长度度的一半。
|
||||
* @return {AABB} out 接受操作的 AABB。
|
||||
*/
|
||||
|
||||
static AABB *set(AABB *out, float px, float py,
|
||||
float pz,
|
||||
float hw,
|
||||
float hh,
|
||||
float hl) {
|
||||
out->setCenter(px, py, pz);
|
||||
out->setHalfExtents(hw, hh, hl);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Merge tow AABB.
|
||||
* @zh
|
||||
* 合并两个 AABB 到 out。
|
||||
* @param out 接受操作的 AABB。
|
||||
* @param a 输入的 AABB。
|
||||
* @param b 输入的 AABB。
|
||||
* @returns {AABB} out 接受操作的 AABB。
|
||||
*/
|
||||
static AABB *merge(AABB *out, const AABB &a, const AABB &b);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* AABB to sphere
|
||||
* @zh
|
||||
* 包围盒转包围球
|
||||
* @param out 接受操作的 sphere。
|
||||
* @param a 输入的 AABB。
|
||||
*/
|
||||
|
||||
static Sphere *toBoundingSphere(Sphere *out, const AABB &a);
|
||||
|
||||
static AABB *fromPoints(const Vec3 &minPos, const Vec3 &maxPos, AABB *dst);
|
||||
static void transformExtentM4(Vec3 *out, const Vec3 &extent, const Mat4 &m4);
|
||||
|
||||
AABB(float px, float py, float pz, float hw, float hh, float hl);
|
||||
AABB() : ShapeBase(ShapeEnum::SHAPE_AABB) {}
|
||||
~AABB() override = default;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* aabb-plane intersect detect.
|
||||
* @zh
|
||||
* 轴对齐包围盒和平面的相交性检测。
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @param {Plane} plane 平面
|
||||
* @return {number} inside(back) = -1, outside(front) = 0, intersect = 1
|
||||
*/
|
||||
bool aabbAabb(const AABB &aabb) const;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* aabb-frustum intersect detect, faster but has false positive corner cases.
|
||||
* @zh
|
||||
* 轴对齐包围盒和锥台相交性检测,速度快,但有错误情况。
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @param {Frustum} frustum 锥台
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
bool aabbFrustum(const Frustum &) const;
|
||||
|
||||
int aabbPlane(const Plane &) const;
|
||||
void getBoundary(cc::Vec3 *minPos, cc::Vec3 *maxPos) const;
|
||||
void merge(const AABB &aabb);
|
||||
void merge(const cc::Vec3 &point);
|
||||
void merge(const ccstd::vector<cc::Vec3> &points);
|
||||
void merge(const Frustum &frustum);
|
||||
void set(const cc::Vec3 ¢erVal, const cc::Vec3 &halfExtentVal);
|
||||
void transform(const Mat4 &m, AABB *out) const;
|
||||
bool contain(const cc::Vec3 &point) const;
|
||||
inline void setCenter(float x, float y, float z) { center.set(x, y, z); }
|
||||
inline void setCenter(const Vec3 ¢er) { this->center.set(center); }
|
||||
inline void setValid(bool isValid) { _isValid = isValid; }
|
||||
inline const Vec3 &getCenter() const { return center; }
|
||||
inline bool isValid() const { return _isValid; }
|
||||
inline void setHalfExtents(float x, float y, float z) { halfExtents.set(x, y, z); }
|
||||
inline void setHalfExtents(const Vec3 &halfExtents) { this->halfExtents.set(halfExtents); }
|
||||
inline const Vec3 &getHalfExtents() const { return halfExtents; }
|
||||
|
||||
cc::Vec3 center;
|
||||
cc::Vec3 halfExtents{1, 1, 1};
|
||||
|
||||
private:
|
||||
bool _isValid{true};
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
71
cocos/core/geometry/Capsule.cpp
Normal file
71
cocos/core/geometry/Capsule.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "cocos/core/geometry/Capsule.h"
|
||||
#include "cocos/math/Vec3.h"
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
void Capsule::transform(const Mat4 &m, const Vec3 & /*pos*/, const Quaternion &rot, const Vec3 &scale, Capsule *out) const {
|
||||
const auto maxComponent = mathutils::absMaxComponent(scale);
|
||||
out->radius = this->radius * std::abs(maxComponent);
|
||||
|
||||
const auto halfTotalWorldHeight = (this->halfHeight + this->radius) * std::abs(scale.y);
|
||||
auto halfWorldHeight = halfTotalWorldHeight - out->radius;
|
||||
if (halfWorldHeight < 0) halfWorldHeight = 0;
|
||||
out->halfHeight = halfWorldHeight;
|
||||
|
||||
out->center.transformMat4(this->center, m);
|
||||
Quaternion::multiply(this->rotation, rot, &out->rotation);
|
||||
out->updateCache();
|
||||
}
|
||||
|
||||
void Capsule::updateCache() {
|
||||
updateLocalCenter();
|
||||
ellipseCenter0.transformQuat(rotation);
|
||||
ellipseCenter1.transformQuat(rotation);
|
||||
ellipseCenter0 += center;
|
||||
ellipseCenter1 += center;
|
||||
}
|
||||
|
||||
void Capsule::updateLocalCenter() {
|
||||
switch (axis) {
|
||||
case CenterEnum::X:
|
||||
ellipseCenter0 = {halfHeight, 0, 0};
|
||||
ellipseCenter1 = {-halfHeight, 0, 0};
|
||||
break;
|
||||
case CenterEnum::Y:
|
||||
ellipseCenter0 = {0, halfHeight, 0};
|
||||
ellipseCenter1 = {0, -halfHeight, 0};
|
||||
break;
|
||||
case CenterEnum::Z:
|
||||
ellipseCenter0 = {0, 0, halfHeight};
|
||||
ellipseCenter1 = {0, 0, -halfHeight};
|
||||
break;
|
||||
default:
|
||||
CC_ABORT();
|
||||
}
|
||||
}
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
130
cocos/core/geometry/Capsule.h
Normal file
130
cocos/core/geometry/Capsule.h
Normal file
@@ -0,0 +1,130 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "math/Mat4.h"
|
||||
#include "math/Quaternion.h"
|
||||
#include "math/Utils.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Basic Geometry: capsule.
|
||||
* @zh
|
||||
* 基础几何,胶囊体。
|
||||
*/
|
||||
class Capsule final : public ShapeBase {
|
||||
/**
|
||||
* @en
|
||||
* Gets the type of the shape.
|
||||
* @zh
|
||||
* 获取形状的类型。
|
||||
*/
|
||||
public:
|
||||
enum class CenterEnum {
|
||||
X = 0,
|
||||
Y = 1,
|
||||
Z = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Capsule sphere radius.
|
||||
* @zh
|
||||
* 胶囊体球部半径。
|
||||
*/
|
||||
float radius{0.0F};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The distance between the center point of the capsule and the center of the sphere.
|
||||
* @zh
|
||||
* 胶囊体中心点和球部圆心的距离。
|
||||
*/
|
||||
float halfHeight{0.0F};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Local orientation of capsule [0,1,2] => [x,y,z].
|
||||
* @zh
|
||||
* 胶囊体的本地朝向,映射关系 [0,1,2] => [x,y,z]。
|
||||
*/
|
||||
CenterEnum axis;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The origin of the capsule.
|
||||
* @zh
|
||||
* 胶囊体的原点。
|
||||
*/
|
||||
Vec3 center;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The rotation of the capsule.
|
||||
* @zh
|
||||
* 胶囊体的旋转。
|
||||
*/
|
||||
Quaternion rotation;
|
||||
|
||||
/** cache, local center of ellipse */
|
||||
Vec3 ellipseCenter0;
|
||||
Vec3 ellipseCenter1;
|
||||
|
||||
explicit Capsule(float radius = 0.5, float halfHeight = 0.5, CenterEnum axis = CenterEnum::Y) : ShapeBase(ShapeEnum::SHAPE_CAPSULE) {
|
||||
this->radius = radius;
|
||||
this->halfHeight = halfHeight;
|
||||
this->axis = axis;
|
||||
this->center = {};
|
||||
this->rotation = {};
|
||||
ellipseCenter0 = {0, halfHeight, 0};
|
||||
ellipseCenter1 = {0, -halfHeight, 0};
|
||||
updateCache();
|
||||
}
|
||||
|
||||
Capsule(const Capsule &other) = default;
|
||||
Capsule(Capsule &&other) = default;
|
||||
Capsule &operator=(const Capsule &other) = default;
|
||||
Capsule &operator=(Capsule &&other) = default;
|
||||
~Capsule() override = default;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Transform this capsule.
|
||||
* @zh
|
||||
* 变换此胶囊体。
|
||||
*/
|
||||
void transform(const Mat4 &m, const Vec3 &pos, const Quaternion &rot, const Vec3 &scale, Capsule *out) const;
|
||||
|
||||
private:
|
||||
void updateCache();
|
||||
void updateLocalCenter();
|
||||
};
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
38
cocos/core/geometry/Curve.cpp
Normal file
38
cocos/core/geometry/Curve.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "cocos/core/geometry/Curve.h"
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
float OptimizedKey::evaluate(float tt) {
|
||||
const t = tt - time;
|
||||
return evalOptCurve(t, coefficient);
|
||||
}
|
||||
|
||||
float evalOptCurve(float t, const ccstd::vector<float> &coefs) {
|
||||
return (t * (t * (t * coefs[0] + coefs[1]) + coefs[2])) + coefs[3];
|
||||
}
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
386
cocos/core/geometry/Curve.h
Normal file
386
cocos/core/geometry/Curve.h
Normal file
@@ -0,0 +1,386 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
constexpr auto LOOK_FORWARD = 3;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* A key frame in the curve.
|
||||
* @zh
|
||||
* 曲线中的一个关键帧。
|
||||
*/
|
||||
struct Keyframe {
|
||||
/**
|
||||
* @en Current frame time.
|
||||
* @zh 当前帧时间。
|
||||
*/
|
||||
float time = 0;
|
||||
|
||||
/**
|
||||
* @en Current frame value.
|
||||
* @zh 当前帧的值。
|
||||
*/
|
||||
float value = 0;
|
||||
|
||||
/**
|
||||
* @en In tangent value.
|
||||
* @zh 左切线。
|
||||
*/
|
||||
float inTangent = 0;
|
||||
|
||||
/**
|
||||
* @en Out tangent value.
|
||||
* @zh 右切线。
|
||||
*/
|
||||
float outTangent = 0;
|
||||
};
|
||||
|
||||
float evalOptCurve(float t, const ccstd::vector<float> &coefs);
|
||||
|
||||
struct OptimizedKey {
|
||||
float index;
|
||||
float time;
|
||||
float endTime;
|
||||
ccstd::vector<float> coefficient;
|
||||
OptimizedKey() {
|
||||
index = -1;
|
||||
time = 0;
|
||||
endTime = 0;
|
||||
coefficient.resize(4);
|
||||
}
|
||||
static float evaluate(float t);
|
||||
};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Describe a curve in which three times Hermite interpolation is used for each adjacent key frame.
|
||||
* @zh
|
||||
* 描述一条曲线,其中每个相邻关键帧采用三次hermite插值计算。
|
||||
*/
|
||||
class AnimationCurve {
|
||||
// @serializable
|
||||
private:
|
||||
// _curve ! : RealCurve;
|
||||
|
||||
public:
|
||||
static ccstd::vector<KeyFrame> defaultKF = [ {
|
||||
time : 0,
|
||||
value : 1,
|
||||
inTangent : 0,
|
||||
outTangent : 0,
|
||||
},
|
||||
{
|
||||
time : 1,
|
||||
value : 1,
|
||||
inTangent : 0,
|
||||
outTangent : 0,
|
||||
} ];
|
||||
|
||||
/**
|
||||
* For internal usage only.
|
||||
* @internal
|
||||
*/
|
||||
get _internalCurve() {
|
||||
return this._curve;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The key frame of the curve.
|
||||
* @zh
|
||||
* 曲线的关键帧。
|
||||
*/
|
||||
auto getKeyFrames() {
|
||||
return Array.from(this._curve.keyframes()).map(([ time, value ]) = > {
|
||||
const legacyKeyframe = ccnew Keyframe();
|
||||
legacyKeyframe.time = time;
|
||||
legacyKeyframe.value = value.value;
|
||||
legacyKeyframe.inTangent = value.leftTangent;
|
||||
legacyKeyframe.outTangent = value.rightTangent;
|
||||
return legacyKeyframe;
|
||||
});
|
||||
}
|
||||
|
||||
void setKeyFrames(value) {
|
||||
this._curve.assignSorted(value.map((legacyCurve) = > [
|
||||
legacyCurve.time,
|
||||
{
|
||||
interpolationMode : RealInterpolationMode.CUBIC,
|
||||
value : legacyCurve.value,
|
||||
leftTangent : legacyCurve.inTangent,
|
||||
rightTangent : legacyCurve.outTangent,
|
||||
},
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Loop mode [[WrapMode]] when the sampling time exceeds the left end.
|
||||
* @zh
|
||||
* 当采样时间超出左端时采用的循环模式[[WrapMode]]。
|
||||
*/
|
||||
auto getPreWrapMode() {
|
||||
return toLegacyWrapMode(this._curve.preExtrapolation);
|
||||
}
|
||||
|
||||
void sPreWrapMode(value) {
|
||||
this._curve.preExtrapolation = fromLegacyWrapMode(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Cycle mode [[WrapMode]] when the sampling time exceeds the right end.
|
||||
* @zh
|
||||
* 当采样时间超出右端时采用的循环模式[[WrapMode]]。
|
||||
*/
|
||||
get postWrapMode() {
|
||||
return toLegacyWrapMode(this._curve.postExtrapolation);
|
||||
}
|
||||
|
||||
set postWrapMode(value) {
|
||||
this._curve.postExtrapolation = fromLegacyWrapMode(value);
|
||||
}
|
||||
|
||||
private
|
||||
cachedKey : OptimizedKey;
|
||||
|
||||
/**
|
||||
* 构造函数。
|
||||
* @param keyFrames 关键帧。
|
||||
*/
|
||||
constructor(keyFrames
|
||||
: Keyframe[] | null | RealCurve = null) {
|
||||
if (keyFrames instanceof RealCurve) {
|
||||
this._curve = keyFrames;
|
||||
} else {
|
||||
const curve = ccnew RealCurve();
|
||||
this._curve = curve;
|
||||
curve.preExtrapolation = ExtrapolationMode.LOOP;
|
||||
curve.postExtrapolation = ExtrapolationMode.CLAMP;
|
||||
if (!keyFrames) {
|
||||
curve.assignSorted([
|
||||
[ 0.0, {interpolationMode : RealInterpolationMode.CUBIC, value : 1.0} ],
|
||||
[ 1.0, {interpolationMode : RealInterpolationMode.CUBIC, value : 1.0} ],
|
||||
]);
|
||||
} else {
|
||||
curve.assignSorted(keyFrames.map((legacyKeyframe) = > [ legacyKeyframe.time, {
|
||||
interpolationMode : RealInterpolationMode.CUBIC,
|
||||
value : legacyKeyframe.value,
|
||||
leftTangent : legacyKeyframe.inTangent,
|
||||
rightTangent : legacyKeyframe.outTangent,
|
||||
} ]));
|
||||
}
|
||||
}
|
||||
this.cachedKey = ccnew OptimizedKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Add a keyframe.
|
||||
* @zh
|
||||
* 添加一个关键帧。
|
||||
* @param keyFrame 关键帧。
|
||||
*/
|
||||
public
|
||||
addKey(keyFrame
|
||||
: Keyframe | null) {
|
||||
if (!keyFrame) {
|
||||
this._curve.clear();
|
||||
} else {
|
||||
this._curve.addKeyFrame(keyFrame.time, {
|
||||
interpolationMode : RealInterpolationMode.CUBIC,
|
||||
value : keyFrame.value,
|
||||
leftTangent : keyFrame.inTangent,
|
||||
rightTangent : keyFrame.outTangent,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @param time
|
||||
*/
|
||||
public
|
||||
evaluate_slow(time
|
||||
: number) {
|
||||
return this._curve.evaluate(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Calculate the curve interpolation at a given point in time.
|
||||
* @zh
|
||||
* 计算给定时间点的曲线插值。
|
||||
* @param time 时间。
|
||||
*/
|
||||
public
|
||||
evaluate(time
|
||||
: number) {
|
||||
const {cachedKey, _curve : curve} = this;
|
||||
const nKeyframes = curve.keyFramesCount;
|
||||
const lastKeyframeIndex = nKeyframes - 1;
|
||||
let wrappedTime = time;
|
||||
const extrapolationMode = time < 0 ? curve.preExtrapolation : curve.postExtrapolation;
|
||||
const startTime = curve.getKeyframeTime(0);
|
||||
const endTime = curve.getKeyframeTime(lastKeyframeIndex);
|
||||
switch (extrapolationMode) {
|
||||
case ExtrapolationMode.LOOP:
|
||||
wrappedTime = repeat(time - startTime, endTime - startTime) + startTime;
|
||||
break;
|
||||
case ExtrapolationMode.PING_PONG:
|
||||
wrappedTime = pingPong(time - startTime, endTime - startTime) + startTime;
|
||||
break;
|
||||
case ExtrapolationMode.CLAMP:
|
||||
default:
|
||||
wrappedTime = clamp(time, startTime, endTime);
|
||||
break;
|
||||
}
|
||||
if (wrappedTime >= cachedKey.time && wrappedTime < cachedKey.endTime) {
|
||||
return cachedKey.evaluate(wrappedTime);
|
||||
}
|
||||
const leftIndex = this.findIndex(cachedKey, wrappedTime);
|
||||
const rightIndex = Math.min(leftIndex + 1, lastKeyframeIndex);
|
||||
this.calcOptimizedKey(cachedKey, leftIndex, rightIndex);
|
||||
return cachedKey.evaluate(wrappedTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @param optKey
|
||||
* @param leftIndex
|
||||
* @param rightIndex
|
||||
*/
|
||||
public
|
||||
calcOptimizedKey(optKey
|
||||
: OptimizedKey, leftIndex
|
||||
: number, rightIndex
|
||||
: number) {
|
||||
const lhsTime = this._curve.getKeyframeTime(leftIndex);
|
||||
const rhsTime = this._curve.getKeyframeTime(rightIndex);
|
||||
const {value : lhsValue, leftTangent : lhsOutTangent} = this._curve.getKeyframeValue(leftIndex);
|
||||
const {value : rhsValue, rightTangent : rhsInTangent} = this._curve.getKeyframeValue(rightIndex);
|
||||
optKey.index = leftIndex;
|
||||
optKey.time = lhsTime;
|
||||
optKey.endTime = rhsTime;
|
||||
|
||||
const dx = rhsTime - lhsTime;
|
||||
const dy = rhsValue - lhsValue;
|
||||
const length = 1 / (dx * dx);
|
||||
const d1 = lhsOutTangent * dx;
|
||||
const d2 = rhsInTangent * dx;
|
||||
|
||||
optKey.coefficient[0] = (d1 + d2 - dy - dy) * length / dx;
|
||||
optKey.coefficient[1] = (dy + dy + dy - d1 - d1 - d2) * length;
|
||||
optKey.coefficient[2] = lhsOutTangent;
|
||||
optKey.coefficient[3] = lhsValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* @param optKey
|
||||
* @param t
|
||||
*/
|
||||
private
|
||||
findIndex(optKey
|
||||
: OptimizedKey, t
|
||||
: number) {
|
||||
const {_curve : curve} = this;
|
||||
const nKeyframes = curve.keyFramesCount;
|
||||
const cachedIndex = optKey.index;
|
||||
if (cachedIndex != = -1) {
|
||||
const cachedTime = curve.getKeyframeTime(cachedIndex);
|
||||
if (t > cachedTime) {
|
||||
for (let i = 0; i < LOOK_FORWARD; i++) {
|
||||
const currIndex = cachedIndex + i;
|
||||
if (currIndex + 1 < nKeyframes && curve.getKeyframeTime(currIndex + 1) > t) {
|
||||
return currIndex;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < LOOK_FORWARD; i++) {
|
||||
const currIndex = cachedIndex - i;
|
||||
if (currIndex >= 0 && curve.getKeyframeTime(currIndex - 1) <= t) {
|
||||
return currIndex - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let left = 0;
|
||||
let right = nKeyframes;
|
||||
let mid;
|
||||
while (right - left > 1) {
|
||||
mid = Math.floor((left + right) / 2);
|
||||
if (curve.getKeyframeTime(mid) >= t) {
|
||||
right = mid;
|
||||
} else {
|
||||
left = mid;
|
||||
}
|
||||
}
|
||||
return left;
|
||||
}
|
||||
}
|
||||
|
||||
function
|
||||
fromLegacyWrapMode(legacyWrapMode
|
||||
: WrapModeMask) : ExtrapolationMode {
|
||||
switch (legacyWrapMode) {
|
||||
default:
|
||||
case WrapModeMask.Default:
|
||||
case WrapModeMask.Normal:
|
||||
case WrapModeMask.Clamp: return ExtrapolationMode.CLAMP;
|
||||
case WrapModeMask.PingPong: return ExtrapolationMode.PING_PONG;
|
||||
case WrapModeMask.Loop: return ExtrapolationMode.LOOP;
|
||||
}
|
||||
}
|
||||
|
||||
function toLegacyWrapMode(extrapolationMode
|
||||
: ExtrapolationMode) : WrapModeMask {
|
||||
switch (extrapolationMode) {
|
||||
default:
|
||||
case ExtrapolationMode.LINEAR:
|
||||
case ExtrapolationMode.CLAMP: return WrapModeMask.Clamp;
|
||||
case ExtrapolationMode.PING_PONG: return WrapModeMask.PingPong;
|
||||
case ExtrapolationMode.LOOP: return WrapModeMask.Loop;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as but more effective than `new LegacyCurve()._internalCurve`.
|
||||
*/
|
||||
export function constructLegacyCurveAndConvert() {
|
||||
const curve = ccnew RealCurve();
|
||||
curve.assignSorted([
|
||||
[ 0.0, {interpolationMode : RealInterpolationMode.CUBIC, value : 1.0} ],
|
||||
[ 1.0, {interpolationMode : RealInterpolationMode.CUBIC, value : 1.0} ],
|
||||
]);
|
||||
return curve;
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
104
cocos/core/geometry/Distance.cpp
Normal file
104
cocos/core/geometry/Distance.cpp
Normal file
@@ -0,0 +1,104 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "cocos/core/geometry/Distance.h"
|
||||
|
||||
#include "cocos/core/geometry/AABB.h"
|
||||
#include "cocos/core/geometry/Obb.h"
|
||||
#include "cocos/core/geometry/Plane.h"
|
||||
#include "cocos/math/Mat4.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include "base/std/container/array.h"
|
||||
#include "cocos/math/Utils.h"
|
||||
#include "cocos/math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
float pointPlane(const Vec3 &point, const Plane &plane) {
|
||||
return Vec3::dot(plane.n, point) - plane.d;
|
||||
}
|
||||
|
||||
Vec3 *ptPointPlane(Vec3 *out, const Vec3 &point, const Plane &plane) {
|
||||
auto t = pointPlane(point, plane);
|
||||
*out = point - t * plane.n;
|
||||
return out;
|
||||
}
|
||||
|
||||
Vec3 *ptPointAabb(Vec3 *out, const Vec3 &point, const AABB &aabb) {
|
||||
auto min = aabb.getCenter() - aabb.getHalfExtents();
|
||||
auto max = aabb.getCenter() + aabb.getHalfExtents();
|
||||
*out = {cc::mathutils::clamp(point.x, min.x, max.x),
|
||||
cc::mathutils::clamp(point.y, min.y, max.y),
|
||||
cc::mathutils::clamp(point.z, min.z, max.z)};
|
||||
return out;
|
||||
}
|
||||
|
||||
Vec3 *ptPointObb(Vec3 *out, const Vec3 &point, const OBB &obb) {
|
||||
ccstd::array<Vec3, 3> u = {
|
||||
Vec3{obb.orientation.m[0], obb.orientation.m[1], obb.orientation.m[2]},
|
||||
Vec3{obb.orientation.m[3], obb.orientation.m[4], obb.orientation.m[5]},
|
||||
Vec3{obb.orientation.m[6], obb.orientation.m[7], obb.orientation.m[8]},
|
||||
};
|
||||
ccstd::array<float, 3> e = {obb.halfExtents.x, obb.halfExtents.y, obb.halfExtents.z};
|
||||
|
||||
auto d = point - obb.center;
|
||||
float dist = 0.0F;
|
||||
|
||||
// Start result at center of obb; make steps from there
|
||||
*out = obb.center;
|
||||
|
||||
// For each OBB axis...
|
||||
for (int i = 0; i < 3; i++) {
|
||||
// ...project d onto that axis to get the distance
|
||||
// along the axis of d from the obb center
|
||||
dist = Vec3::dot(d, u[i]);
|
||||
// if distance farther than the obb extents, clamp to the obb
|
||||
dist = cc::mathutils::clamp(dist, -e[i], e[i]);
|
||||
|
||||
// Step that distance along the axis to get world coordinate
|
||||
*out += (dist * u[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Vec3 *ptPointLine(Vec3 *out, const Vec3 &point, const Vec3 &linePointA, const Vec3 &linePointB) {
|
||||
auto dir = linePointA - linePointB;
|
||||
auto dirSquared = dir.lengthSquared();
|
||||
|
||||
if (dirSquared == 0.0F) {
|
||||
// The point is at the segment start.
|
||||
*out = linePointA;
|
||||
} else {
|
||||
// Calculate the projection of the point onto the line extending through the segment.
|
||||
auto ap = point - linePointA;
|
||||
auto t = Vec3::dot(ap, dir) / dirSquared;
|
||||
*out = linePointA + cc::mathutils::clamp(t, 0.0F, 1.0F) * dir;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
96
cocos/core/geometry/Distance.h
Normal file
96
cocos/core/geometry/Distance.h
Normal file
@@ -0,0 +1,96 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Mat4;
|
||||
class Vec3;
|
||||
namespace geometry {
|
||||
|
||||
class Plane;
|
||||
class OBB;
|
||||
class AABB;
|
||||
/**
|
||||
* @en
|
||||
* the distance between a point and a plane
|
||||
* @zh
|
||||
* 计算点和平面之间的距离。
|
||||
* @param {Vec3} point 点。
|
||||
* @param {Plane} plane 平面。
|
||||
* @return 距离。
|
||||
*/
|
||||
float pointPlane(const Vec3 &point, const Plane &plane);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* the closest point on plane to a given point
|
||||
* @zh
|
||||
* 计算平面上最接近给定点的点。
|
||||
* @param out 最近点。
|
||||
* @param point 给定点。
|
||||
* @param plane 平面。
|
||||
* @return 最近点。
|
||||
*/
|
||||
Vec3 *ptPointPlane(Vec3 *out, const Vec3 &point, const Plane &plane);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* the closest point on aabb to a given point
|
||||
* @zh
|
||||
* 计算 aabb 上最接近给定点的点。
|
||||
* @param {Vec3} out 最近点。
|
||||
* @param {Vec3} point 给定点。
|
||||
* @param {AABB} aabb 轴对齐包围盒。
|
||||
* @return {Vec3} 最近点。
|
||||
*/
|
||||
Vec3 *ptPointAabb(Vec3 *out, const Vec3 &point, const AABB &aabb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* the closest point on obb to a given point
|
||||
* @zh
|
||||
* 计算 obb 上最接近给定点的点。
|
||||
* @param {Vec3} out 最近点。
|
||||
* @param {Vec3} point 给定点。
|
||||
* @param {OBB} obb 方向包围盒。
|
||||
* @return {Vec3} 最近点。
|
||||
*/
|
||||
Vec3 *ptPointObb(Vec3 *out, const Vec3 &point, const OBB &obb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Calculate the nearest point on the line to the given point.
|
||||
* @zh
|
||||
* 计算给定点距离直线上最近的一点。
|
||||
* @param out 最近点
|
||||
* @param point 给定点
|
||||
* @param linePointA 线上的某点 A
|
||||
* @param linePointB 线上的某点 B
|
||||
*/
|
||||
Vec3 *ptPointLine(Vec3 *out, const Vec3 &point, const Vec3 &linePointA, const Vec3 &linePointB);
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
69
cocos/core/geometry/Enums.h
Normal file
69
cocos/core/geometry/Enums.h
Normal file
@@ -0,0 +1,69 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "base/RefCounted.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
enum class ShapeEnum {
|
||||
SHAPE_RAY = (1 << 0),
|
||||
SHAPE_LINE = (1 << 1),
|
||||
SHAPE_SPHERE = (1 << 2),
|
||||
SHAPE_AABB = (1 << 3),
|
||||
SHAPE_OBB = (1 << 4),
|
||||
SHAPE_PLANE = (1 << 5),
|
||||
SHAPE_TRIANGLE = (1 << 6),
|
||||
SHAPE_FRUSTUM = (1 << 7),
|
||||
SHAPE_FRUSTUM_ACCURATE = (1 << 8),
|
||||
SHAPE_CAPSULE = (1 << 9),
|
||||
SHAPE_SPLINE = (1 << 10),
|
||||
SHAPE_BAD = (1 << 11),
|
||||
};
|
||||
|
||||
class ShapeBase : public RefCounted {
|
||||
public:
|
||||
ShapeBase(ShapeEnum type) : _type(type) {}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Gets the type of the shape.
|
||||
* @zh
|
||||
* 获取形状的类型。
|
||||
*/
|
||||
inline ShapeEnum getType() const {
|
||||
CC_ASSERT_NE(_type, ShapeEnum::SHAPE_BAD); // shape is not initialized
|
||||
return _type;
|
||||
}
|
||||
inline void setType(ShapeEnum type) { _type = type; }
|
||||
|
||||
private:
|
||||
ShapeEnum _type = ShapeEnum::SHAPE_BAD;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
215
cocos/core/geometry/Frustum.cpp
Normal file
215
cocos/core/geometry/Frustum.cpp
Normal file
@@ -0,0 +1,215 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/geometry/Frustum.h"
|
||||
#include <cmath>
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "scene/Define.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
namespace {
|
||||
const ccstd::vector<cc::Vec3> VEC_VALS{
|
||||
{1, 1, 1},
|
||||
{-1, 1, 1},
|
||||
{-1, -1, 1},
|
||||
{1, -1, 1},
|
||||
{1, 1, -1},
|
||||
{-1, 1, -1},
|
||||
{-1, -1, -1},
|
||||
{1, -1, -1}};
|
||||
} // namespace
|
||||
|
||||
void Frustum::createOrtho(Frustum *out, float width,
|
||||
float height,
|
||||
float near,
|
||||
float far,
|
||||
const Mat4 &transform) {
|
||||
createOrthographic(out, width, height, near, far, transform);
|
||||
}
|
||||
|
||||
void Frustum::createOrthographic(Frustum *out, float width,
|
||||
float height,
|
||||
float near,
|
||||
float far,
|
||||
const Mat4 &transform) {
|
||||
auto halfWidth = width / 2.0F;
|
||||
auto halfHeight = height / 2.0F;
|
||||
Vec3::transformMat4({halfWidth, halfHeight, -near}, transform, &out->vertices[0]);
|
||||
Vec3::transformMat4({-halfWidth, halfHeight, -near}, transform, &out->vertices[1]);
|
||||
Vec3::transformMat4({-halfWidth, -halfHeight, -near}, transform, &out->vertices[2]);
|
||||
Vec3::transformMat4({halfWidth, -halfHeight, -near}, transform, &out->vertices[3]);
|
||||
Vec3::transformMat4({halfWidth, halfHeight, -far}, transform, &out->vertices[4]);
|
||||
Vec3::transformMat4({-halfWidth, halfHeight, -far}, transform, &out->vertices[5]);
|
||||
Vec3::transformMat4({-halfWidth, -halfHeight, -far}, transform, &out->vertices[6]);
|
||||
Vec3::transformMat4({halfWidth, -halfHeight, -far}, transform, &out->vertices[7]);
|
||||
|
||||
out->updatePlanes();
|
||||
}
|
||||
|
||||
Frustum *Frustum::createFromAABB(Frustum *out, const AABB &aabb) {
|
||||
Vec3 minPos;
|
||||
Vec3 maxPos;
|
||||
aabb.getBoundary(&minPos, &maxPos);
|
||||
|
||||
out->vertices[0].set(maxPos.x, maxPos.y, -minPos.z);
|
||||
out->vertices[1].set(minPos.x, maxPos.y, -minPos.z);
|
||||
out->vertices[2].set(minPos.x, minPos.y, -minPos.z);
|
||||
out->vertices[3].set(maxPos.x, minPos.y, -minPos.z);
|
||||
out->vertices[4].set(maxPos.x, maxPos.y, -maxPos.z);
|
||||
out->vertices[5].set(minPos.x, maxPos.y, -maxPos.z);
|
||||
out->vertices[6].set(minPos.x, minPos.y, -maxPos.z);
|
||||
out->vertices[7].set(maxPos.x, minPos.y, -maxPos.z);
|
||||
|
||||
out->updatePlanes();
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void Frustum::createPerspective(Frustum *out, float fov,
|
||||
float aspect,
|
||||
float near,
|
||||
float far,
|
||||
const Mat4 &transform) {
|
||||
const float h = tanf(fov * 0.5F);
|
||||
const float w = h * aspect;
|
||||
const Vec3 nearTemp(near * w, near * h, near);
|
||||
const Vec3 farTemp(far * w, far * h, far);
|
||||
|
||||
out->vertices[0].transformMat4(Vec3(nearTemp.x, nearTemp.y, -nearTemp.z), transform);
|
||||
out->vertices[1].transformMat4(Vec3(-nearTemp.x, nearTemp.y, -nearTemp.z), transform);
|
||||
out->vertices[2].transformMat4(Vec3(-nearTemp.x, -nearTemp.y, -nearTemp.z), transform);
|
||||
out->vertices[3].transformMat4(Vec3(nearTemp.x, -nearTemp.y, -nearTemp.z), transform);
|
||||
out->vertices[4].transformMat4(Vec3(farTemp.x, farTemp.y, -farTemp.z), transform);
|
||||
out->vertices[5].transformMat4(Vec3(-farTemp.x, farTemp.y, -farTemp.z), transform);
|
||||
out->vertices[6].transformMat4(Vec3(-farTemp.x, -farTemp.y, -farTemp.z), transform);
|
||||
out->vertices[7].transformMat4(Vec3(farTemp.x, -farTemp.y, -farTemp.z), transform);
|
||||
|
||||
out->updatePlanes();
|
||||
}
|
||||
|
||||
void Frustum::update(const Mat4 &m, const Mat4 &inv) {
|
||||
// left plane
|
||||
planes[0]->n.set(m.m[3] + m.m[0], m.m[7] + m.m[4], m.m[11] + m.m[8]);
|
||||
planes[0]->d = -(m.m[15] + m.m[12]);
|
||||
// right plane
|
||||
planes[1]->n.set(m.m[3] - m.m[0], m.m[7] - m.m[4], m.m[11] - m.m[8]);
|
||||
planes[1]->d = -(m.m[15] - m.m[12]);
|
||||
// bottom plane
|
||||
planes[2]->n.set(m.m[3] + m.m[1], m.m[7] + m.m[5], m.m[11] + m.m[9]);
|
||||
planes[2]->d = -(m.m[15] + m.m[13]);
|
||||
// top plane
|
||||
planes[3]->n.set(m.m[3] - m.m[1], m.m[7] - m.m[5], m.m[11] - m.m[9]);
|
||||
planes[3]->d = -(m.m[15] - m.m[13]);
|
||||
// near plane
|
||||
planes[4]->n.set(m.m[3] + m.m[2], m.m[7] + m.m[6], m.m[11] + m.m[10]);
|
||||
planes[4]->d = -(m.m[15] + m.m[14]);
|
||||
// far plane
|
||||
planes[5]->n.set(m.m[3] - m.m[2], m.m[7] - m.m[6], m.m[11] - m.m[10]);
|
||||
planes[5]->d = -(m.m[15] - m.m[14]);
|
||||
|
||||
for (Plane *plane : planes) {
|
||||
float invDist = 1 / plane->n.length();
|
||||
plane->n *= invDist;
|
||||
plane->d *= invDist;
|
||||
}
|
||||
uint32_t i = 0;
|
||||
for (const Vec3 &vec : VEC_VALS) {
|
||||
vertices[i].transformMat4(vec, inv);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void Frustum::transform(const Mat4 &mat) {
|
||||
for (auto i = 0; i < 8; i++) {
|
||||
vertices[i].transformMat4(vertices[i], mat);
|
||||
}
|
||||
updatePlanes();
|
||||
}
|
||||
|
||||
void Frustum::createOrthographic(float width, float height, float near, float far, const Mat4 &transform) {
|
||||
createOrthographic(this, width, height, near, far, transform);
|
||||
}
|
||||
|
||||
void Frustum::createOrtho(const float width, const float height, const float near, const float far, const Mat4 &transform) {
|
||||
createOrthographic(width, height, near, far, transform);
|
||||
}
|
||||
|
||||
void Frustum::split(float near, float far, float aspect, float fov, const Mat4 &transform) {
|
||||
createPerspective(this, fov, aspect, near, far, transform);
|
||||
}
|
||||
|
||||
void Frustum::updatePlanes() {
|
||||
// left plane
|
||||
planes[0]->define(vertices[1], vertices[6], vertices[5]);
|
||||
// right plane
|
||||
planes[1]->define(vertices[3], vertices[4], vertices[7]);
|
||||
// bottom plane
|
||||
planes[2]->define(vertices[6], vertices[3], vertices[7]);
|
||||
// top plane
|
||||
planes[3]->define(vertices[0], vertices[5], vertices[4]);
|
||||
// near plane
|
||||
planes[4]->define(vertices[2], vertices[0], vertices[3]);
|
||||
// far plane
|
||||
planes[5]->define(vertices[7], vertices[5], vertices[6]);
|
||||
}
|
||||
|
||||
Frustum::Frustum() : ShapeBase(ShapeEnum::SHAPE_FRUSTUM) {
|
||||
init();
|
||||
}
|
||||
|
||||
Frustum::Frustum(const Frustum &rhs) : ShapeBase(rhs) {
|
||||
init();
|
||||
*this = rhs;
|
||||
}
|
||||
|
||||
Frustum::~Frustum() {
|
||||
for (auto *plane : planes) {
|
||||
plane->release();
|
||||
}
|
||||
}
|
||||
|
||||
Frustum &Frustum::operator=(const Frustum &rhs) {
|
||||
if (this == &rhs) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
vertices = rhs.vertices;
|
||||
|
||||
for (size_t i = 0; i < planes.size(); ++i) { // NOLINT(modernize-loop-convert)
|
||||
Plane::copy(planes[i], *rhs.planes[i]);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Frustum::init() {
|
||||
for (size_t i = 0; i < planes.size(); ++i) { // NOLINT(modernize-loop-convert)
|
||||
planes[i] = ccnew Plane();
|
||||
planes[i]->addRef();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
207
cocos/core/geometry/Frustum.h
Normal file
207
cocos/core/geometry/Frustum.h
Normal file
@@ -0,0 +1,207 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/memory/Memory.h"
|
||||
#include "base/std/container/array.h"
|
||||
#include "core/geometry/AABB.h"
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "core/geometry/Plane.h"
|
||||
#include "math/Mat4.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
class Frustum final : public ShapeBase {
|
||||
public:
|
||||
/**
|
||||
* @en
|
||||
* Create a ortho frustum.
|
||||
* @zh
|
||||
* 创建一个正交视锥体。
|
||||
* @param out @en The result orthographic frustum. @zh 输出的正交视锥体。
|
||||
* @param width @en The width of the frustum. @zh 正交视锥体的宽度。
|
||||
* @param height @en The height of the frustum. @zh 正交视锥体的高度。
|
||||
* @param near @en The near plane of the frustum. @zh 正交视锥体的近平面值。
|
||||
* @param far @en The far plane of the frustum. @zh 正交视锥体的远平面值。
|
||||
* @param transform @en The transform matrix of the frustum. @zh 正交视锥体的变换矩阵。
|
||||
*
|
||||
* @deprecated since 3.8.0, please use [createOrthographic] instead of it.
|
||||
*/
|
||||
static void createOrtho(Frustum *out, float width,
|
||||
float height,
|
||||
float near,
|
||||
float far,
|
||||
const Mat4 &transform);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Create a ortho frustum.
|
||||
* @zh
|
||||
* 创建一个正交视锥体。
|
||||
* @param out @en The result orthographic frustum. @zh 输出的正交视锥体。
|
||||
* @param width @en The width of the frustum. @zh 正交视锥体的宽度。
|
||||
* @param height @en The height of the frustum. @zh 正交视锥体的高度。
|
||||
* @param near @en The near plane of the frustum. @zh 正交视锥体的近平面值。
|
||||
* @param far @en The far plane of the frustum. @zh 正交视锥体的远平面值。
|
||||
* @param transform @en The transform matrix of the frustum. @zh 正交视锥体的变换矩阵。
|
||||
*/
|
||||
static void createOrthographic(Frustum *out, float width,
|
||||
float height,
|
||||
float near,
|
||||
float far,
|
||||
const Mat4 &transform);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Create a perspective frustum.
|
||||
* @zh
|
||||
* 创建一个透视视锥体。
|
||||
* @param out @en The result perspective frustum. @zh 输出的透视视锥体。
|
||||
* @param fov @en The field of view of the frustum. @zh 视锥体的视野。
|
||||
* @param aspect @en The aspect ratio of the frustum. @zh 视锥体的宽高比。
|
||||
* @param near @en The near plane of the frustum. @zh 视锥体的近平面值。
|
||||
* @param far @en The far plane of the frustum. @zh 视锥体的远平面值。
|
||||
* @param transform @en The transform matrix of the frustum. @zh 视锥体的变换矩阵。
|
||||
*/
|
||||
static void createPerspective(Frustum *out, float fov,
|
||||
float aspect,
|
||||
float near,
|
||||
float far,
|
||||
const Mat4 &transform);
|
||||
|
||||
/**
|
||||
* @en Create a frustum from an AABB box.
|
||||
* @zh 从 AABB 包围盒中创建一个视锥体。
|
||||
* @param out @en The result frustum @zh 输出的视锥体对象。
|
||||
* @param aabb @en The AABB bounding box of the frustum @zh AABB 包围盒。
|
||||
* @return @en The out object @zh 返回视锥体.
|
||||
*
|
||||
* @deprecated since 3.8.0, please use [createOrthographic] instead of it.
|
||||
*/
|
||||
static Frustum *createFromAABB(Frustum *out, const AABB &aabb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Create a ccnew frustum.
|
||||
* @zh
|
||||
* 创建一个新的截锥体。
|
||||
* @return @en An empty frustum. @zh 一个空截椎体
|
||||
*/
|
||||
static Frustum *create() {
|
||||
return ccnew Frustum();
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Clone a frustum.
|
||||
* @zh
|
||||
* 克隆一个截锥体。
|
||||
* @param f @en The frustum to clone from @zh 用于克隆的截锥体
|
||||
* @return @en The cloned frustum @zh 克隆出的新截锥体
|
||||
*/
|
||||
static Frustum *clone(const Frustum &f) {
|
||||
return Frustum::copy(ccnew Frustum(), f);
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Copy the values from one frustum to another.
|
||||
* @zh
|
||||
* 从一个视锥体拷贝到另一个视锥体。
|
||||
* @param out @en The result frustum @zh 用于存储拷贝数据的截锥体
|
||||
* @param f @en The frustum to copy from @zh 用于克隆的截锥体
|
||||
* @return @en The out object @zh 传入的 out 对象
|
||||
|
||||
*/
|
||||
static Frustum *copy(Frustum *out, const Frustum &f) {
|
||||
out->setType(f.getType());
|
||||
for (size_t i = 0; i < 6; ++i) { // NOLINT(modernize-loop-convert)
|
||||
Plane::copy(out->planes[i], *(f.planes[i]));
|
||||
}
|
||||
out->vertices = f.vertices;
|
||||
return out;
|
||||
}
|
||||
|
||||
Frustum();
|
||||
Frustum(const Frustum &rhs);
|
||||
Frustum(Frustum &&rhs) = delete;
|
||||
~Frustum() override;
|
||||
|
||||
// Can remove these operator override functions if not using Plane* in planes array.
|
||||
Frustum &operator=(const Frustum &rhs);
|
||||
Frustum &operator=(Frustum &&rhs) = delete;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Transform this frustum.
|
||||
* @zh
|
||||
* 变换此截锥体。
|
||||
* @param mat 变换矩阵。
|
||||
*/
|
||||
void transform(const Mat4 &);
|
||||
|
||||
void createOrtho(float width, float height, float near, float far, const Mat4 &transform);
|
||||
void createOrthographic(float width, float height, float near, float far, const Mat4 &transform);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set as a perspective frustum.
|
||||
* @zh
|
||||
* 设置为一个透视视锥体。
|
||||
* @param near @en The near plane of the frustum. @zh 视锥体的近平面值。
|
||||
* @param far @en The far plane of the frustum. @zh 视锥体的远平面值。
|
||||
* @param fov @en The field of view of the frustum. @zh 视锥体的视野。
|
||||
* @param aspect @en The aspect ratio of the frustum. @zh 视锥体的宽高比。
|
||||
* @param transform @en The transform matrix of the frustum. @zh 视锥体的变换矩阵。
|
||||
*
|
||||
* @deprecated since 3.8.0, please use [createPerspective] instead of it.
|
||||
*/
|
||||
void split(float near, float far, float aspect, float fov, const Mat4 &transform);
|
||||
void updatePlanes();
|
||||
void update(const Mat4 &m, const Mat4 &inv);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set whether to use accurate intersection testing function on this frustum.
|
||||
* @zh
|
||||
* 设置是否在此截锥体上使用精确的相交测试函数。
|
||||
*
|
||||
* @deprecated since v3.8.0 no need to set accurate flag since it doesn't affect the calculation at all.
|
||||
*/
|
||||
inline void setAccurate(bool accurate) {
|
||||
setType(accurate ? ShapeEnum::SHAPE_FRUSTUM_ACCURATE : ShapeEnum::SHAPE_FRUSTUM);
|
||||
}
|
||||
|
||||
ccstd::array<Vec3, 8> vertices;
|
||||
ccstd::array<Plane *, 6> planes;
|
||||
|
||||
private:
|
||||
void init();
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
41
cocos/core/geometry/Geometry.h
Normal file
41
cocos/core/geometry/Geometry.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AABB.h"
|
||||
#include "Capsule.h"
|
||||
// #include "Curve.h"
|
||||
#include "Distance.h"
|
||||
#include "Enums.h"
|
||||
#include "Frustum.h"
|
||||
#include "Intersect.h"
|
||||
#include "Line.h"
|
||||
#include "Obb.h"
|
||||
#include "Plane.h"
|
||||
#include "Ray.h"
|
||||
#include "Spec.h"
|
||||
#include "Sphere.h"
|
||||
#include "Spline.h"
|
||||
#include "Triangle.h"
|
||||
1100
cocos/core/geometry/Intersect.cpp
Normal file
1100
cocos/core/geometry/Intersect.cpp
Normal file
File diff suppressed because it is too large
Load Diff
498
cocos/core/geometry/Intersect.h
Normal file
498
cocos/core/geometry/Intersect.h
Normal file
@@ -0,0 +1,498 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Macros.h"
|
||||
|
||||
#include "core/assets/RenderingSubMesh.h"
|
||||
#include "core/geometry/Distance.h"
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "core/geometry/Frustum.h"
|
||||
#include "core/geometry/Spec.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace cc {
|
||||
|
||||
class Vec3;
|
||||
class Mat3;
|
||||
|
||||
namespace scene {
|
||||
class Model;
|
||||
}
|
||||
|
||||
namespace geometry {
|
||||
|
||||
class Ray;
|
||||
class Plane;
|
||||
class OBB;
|
||||
class AABB;
|
||||
class Line;
|
||||
class Frustum;
|
||||
class Sphere;
|
||||
class Triangle;
|
||||
class Capsule;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* ray-plane intersect detect.
|
||||
* @zh
|
||||
* 射线与平面的相交性检测。
|
||||
* @param {Ray} ray 射线
|
||||
* @param {Plane} plane 平面
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float rayPlane(const Ray &ray, const Plane &plane);
|
||||
|
||||
// based on http://fileadmin.cs.lth.se/cs/Personal/Tomas_Akenine-Moller/raytri/
|
||||
/**
|
||||
* @en
|
||||
* ray-triangle intersect detect.
|
||||
* @zh
|
||||
* 射线与三角形的相交性检测。
|
||||
* @param {Ray} ray 射线
|
||||
* @param {Triangle} triangle 三角形
|
||||
* @param {boolean} doubleSided 三角形是否为双面
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float rayTriangle(const Ray &ray, const Triangle &triangle, bool doubleSided = false);
|
||||
/**
|
||||
* @en
|
||||
* ray-sphere intersect detect.
|
||||
* @zh
|
||||
* 射线和球的相交性检测。
|
||||
* @param {Ray} ray 射线
|
||||
* @param {Sphere} sphere 球
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float raySphere(const Ray &ray, const Sphere &sphere);
|
||||
|
||||
float rayAABB2(const Ray &ray, const Vec3 &min, const Vec3 &max);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* ray-aabb intersect detect.
|
||||
* @zh
|
||||
* 射线和轴对齐包围盒的相交性检测。
|
||||
* @param {Ray} ray 射线
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float rayAABB(const Ray &ray, const AABB &aabb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* ray-obb intersect detect.
|
||||
* @zh
|
||||
* 射线和方向包围盒的相交性检测。
|
||||
* @param {Ray} ray 射线
|
||||
* @param {OBB} obb 方向包围盒
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float rayOBB(const Ray &ray, const OBB &obb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* ray-capsule intersect detect.
|
||||
* @zh
|
||||
* 射线和胶囊体的相交性检测。
|
||||
* @param {Ray} ray 射线
|
||||
* @param {Capsule} capsule 胶囊体
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float rayCapsule(const Ray &ray, const Capsule &capsule);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* ray-subMesh intersect detect, in model space.
|
||||
* @zh
|
||||
* 在模型空间中,射线和子三角网格的相交性检测。
|
||||
* @param {Ray} ray
|
||||
* @param {RenderingSubMesh} subMesh
|
||||
* @param {IRaySubMeshOptions} options
|
||||
* @return {number} 0 or !0
|
||||
*/
|
||||
float raySubMesh(const Ray &ray, const RenderingSubMesh &submesh, IRaySubMeshOptions *options = nullptr);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* ray-mesh intersect detect, in model space.
|
||||
* @zh
|
||||
* 在模型空间中,射线和三角网格资源的相交性检测。
|
||||
* @param {Ray} ray
|
||||
* @param {Mesh} mesh
|
||||
* @param {IRayMeshOptions} options
|
||||
* @return {number} 0 or !0
|
||||
*/
|
||||
float rayMesh(const Ray &ray, const Mesh &mesh, IRayMeshOptions *option);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* ray-model intersect detect, in world space.
|
||||
* @zh
|
||||
* 在世界空间中,射线和渲染模型的相交性检测。
|
||||
* @param ray
|
||||
* @param model
|
||||
* @param options
|
||||
* @return 0 or !0
|
||||
*/
|
||||
float rayModel(const Ray &ray, const scene::Model &model, IRayModelOptions *option);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* line-plane intersect detect.
|
||||
* @zh
|
||||
* 线段与平面的相交性检测。
|
||||
* @param {line} line 线段
|
||||
* @param {Plane} plane 平面
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float linePlane(const Line &line, const Plane &plane);
|
||||
/**
|
||||
* @en
|
||||
* line-triangle intersect detect.
|
||||
* @zh
|
||||
* 线段与三角形的相交性检测。
|
||||
* @param {line} line 线段
|
||||
* @param {Triangle} triangle 三角形
|
||||
* @param {Vec3} outPt 可选,相交点
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
int lineTriangle(const Line &line, const Triangle &triangle, Vec3 *outPt = nullptr);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* line-aabb intersect detect.
|
||||
* @zh
|
||||
* 线段与轴对齐包围盒的相交性检测
|
||||
* @param line 线段
|
||||
* @param aabb 轴对齐包围盒
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float lineAABB(const Line &line, const AABB &aabb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* line-obb intersect detect.
|
||||
* @zh
|
||||
* 线段与方向包围盒的相交性检测
|
||||
* @param line 线段
|
||||
* @param obb 方向包围盒
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float lineOBB(const Line &line, const OBB &obb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* line-sphere intersect detect.
|
||||
* @zh
|
||||
* 线段与球的相交性检测
|
||||
* @param line 线段
|
||||
* @param sphere 球
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
float lineSphere(const Line &line, const Sphere &sphere);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* aabb-aabb intersect detect.
|
||||
* @zh
|
||||
* 轴对齐包围盒和轴对齐包围盒的相交性检测。
|
||||
* @param {AABB} aabb1 轴对齐包围盒1
|
||||
* @param {AABB} aabb2 轴对齐包围盒2
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
bool aabbWithAABB(const AABB &aabb1, const AABB &aabb2);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* aabb-obb intersect detect.
|
||||
* @zh
|
||||
* 轴对齐包围盒和方向包围盒的相交性检测。
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @param {OBB} obb 方向包围盒
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
int aabbWithOBB(const AABB &aabb, const OBB &obb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* aabb-plane intersect detect.
|
||||
* @zh
|
||||
* 轴对齐包围盒和平面的相交性检测。
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @param {Plane} plane 平面
|
||||
* @return {number} inside(back) = -1, outside(front) = 0, intersect = 1
|
||||
*/
|
||||
|
||||
int aabbPlane(const AABB &aabb, const Plane &plane);
|
||||
/**
|
||||
* @en
|
||||
* aabb-frustum intersect detect, faster but has false positive corner cases.
|
||||
* @zh
|
||||
* 轴对齐包围盒和锥台相交性检测,速度快,但有错误情况。
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @param {Frustum} frustum 锥台
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
|
||||
int aabbFrustum(const AABB &aabb, const Frustum &frustum);
|
||||
/**
|
||||
* @en
|
||||
* aabb-frustum intersect detect, faster but false while frustum is completely inside the aabb.
|
||||
* @zh
|
||||
* 轴对齐包围盒和锥台的相交性检测。速度快,但是当锥台完全在aabb中时就会判断出错。
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @param {Frustum} frustum 锥台
|
||||
* @return {number} aabb completely inside the frustum = 1, otherwise = 0
|
||||
*/
|
||||
int aabbFrustumCompletelyInside(const AABB &aabb, const Frustum &frustum);
|
||||
|
||||
// https://cesium.com/blog/2017/02/02/tighter-frustum-culling-and-why-you-may-want-to-disregard-it/
|
||||
/**
|
||||
* @en
|
||||
* aabb-frustum intersect, handles most of the false positives correctly.
|
||||
* @zh
|
||||
* 轴对齐包围盒和锥台相交性检测,正确处理大多数错误情况。
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @param {Frustum} frustum 锥台
|
||||
* @return {number}
|
||||
*/
|
||||
int aabbFrustumAccurate(const AABB &aabb, const Frustum &frustum);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* obb contains the point.
|
||||
* @zh
|
||||
* 方向包围盒和点的相交性检测。
|
||||
* @param {OBB} obb 方向包围盒
|
||||
* @param {Vec3} point 点
|
||||
* @return {boolean} true or false
|
||||
*/
|
||||
bool obbPoint(const OBB &obb, const Vec3 &point);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* obb-plane intersect detect.
|
||||
* @zh
|
||||
* 方向包围盒和平面的相交性检测。
|
||||
* @param {OBB} obb 方向包围盒
|
||||
* @param {Plane} plane 平面
|
||||
* @return {number} inside(back) = -1, outside(front) = 0, intersect = 1
|
||||
*/
|
||||
int obbPlane(const OBB &obb, const Plane &plane);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* obb-frustum intersect, faster but has false positive corner cases.
|
||||
* @zh
|
||||
* 方向包围盒和锥台相交性检测,速度快,但有错误情况。
|
||||
* @param {OBB} obb 方向包围盒
|
||||
* @param {Frustum} frustum 锥台
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
int obbFrustum(const OBB &obb, const Frustum &frustum);
|
||||
|
||||
// https://cesium.com/blog/2017/02/02/tighter-frustum-culling-and-why-you-may-want-to-disregard-it/
|
||||
/**
|
||||
* @en
|
||||
* obb-frustum intersect, handles most of the false positives correctly.
|
||||
* @zh
|
||||
* 方向包围盒和锥台相交性检测,正确处理大多数错误情况。
|
||||
* @param {OBB} obb 方向包围盒
|
||||
* @param {Frustum} frustum 锥台
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
int obbFrustumAccurate(const OBB &obb, const Frustum &frustum);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* obb-obb intersect detect.
|
||||
* @zh
|
||||
* 方向包围盒和方向包围盒的相交性检测。
|
||||
* @param {OBB} obb1 方向包围盒1
|
||||
* @param {OBB} obb2 方向包围盒2
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
int obbWithOBB(const OBB &obb1, const OBB &obb2);
|
||||
|
||||
// https://github.com/diku-dk/bvh-tvcg18/blob/1fd3348c17bc8cf3da0b4ae60fdb8f2aa90a6ff0/FOUNDATION/GEOMETRY/GEOMETRY/include/overlap/geometry_overlap_obb_capsule.h
|
||||
/**
|
||||
* @en
|
||||
* obb-capsule intersect detect.
|
||||
* @zh
|
||||
* 方向包围盒和胶囊体的相交性检测。
|
||||
* @param obb 方向包围盒
|
||||
* @param capsule 胶囊体
|
||||
*/
|
||||
int obbCapsule(const OBB &obb, const Capsule &capsule);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* sphere-plane intersect, not necessarily faster than obb-plane,due to the length calculation of the
|
||||
* plane normal to factor out the unnomalized plane distance.
|
||||
* @zh
|
||||
* 球与平面的相交性检测。
|
||||
* @param {Sphere} sphere 球
|
||||
* @param {Plane} plane 平面
|
||||
* @return {number} inside(back) = -1, outside(front) = 0, intersect = 1
|
||||
*/
|
||||
int spherePlane(const Sphere &sphere, const Plane &plane);
|
||||
/**
|
||||
* @en
|
||||
* sphere-frustum intersect, faster but has false positive corner cases.
|
||||
* @zh
|
||||
* 球和锥台的相交性检测,速度快,但有错误情况。
|
||||
* @param {Sphere} sphere 球
|
||||
* @param {Frustum} frustum 锥台
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
int sphereFrustum(const Sphere &sphere, const Frustum &frustum);
|
||||
|
||||
// https://stackoverflow.com/questions/20912692/view-frustum-culling-corner-cases
|
||||
/**
|
||||
* @en
|
||||
* sphere-frustum intersect, handles the false positives correctly.
|
||||
* @zh
|
||||
* 球和锥台的相交性检测,正确处理大多数错误情况。
|
||||
* @param {Sphere} sphere 球
|
||||
* @param {Frustum} frustum 锥台
|
||||
* @return {number} 0 或 非0
|
||||
*/
|
||||
int sphereFrustumAccurate(const Sphere &sphere, const Frustum &frustum);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* sphere-sphere intersect detect.
|
||||
* @zh
|
||||
* 球和球的相交性检测。
|
||||
* @param {Sphere} sphere0 球0
|
||||
* @param {Sphere} sphere1 球1
|
||||
* @return {boolean} true or false
|
||||
*/
|
||||
bool sphereWithSphere(const Sphere &sphere0, const Sphere &sphere1);
|
||||
/**
|
||||
* @en
|
||||
* sphere-aabb intersect detect.
|
||||
* @zh
|
||||
* 球和轴对齐包围盒的相交性检测。
|
||||
* @param {Sphere} sphere 球
|
||||
* @param {AABB} aabb 轴对齐包围盒
|
||||
* @return {boolean} true or false
|
||||
*/
|
||||
bool sphereAABB(const Sphere &sphere, const AABB &aabb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* sphere-obb intersect detect.
|
||||
* @zh
|
||||
* 球和方向包围盒的相交性检测。
|
||||
* @param {Sphere} sphere 球
|
||||
* @param {OBB} obb 方向包围盒
|
||||
* @return {boolean} true or false
|
||||
*/
|
||||
bool sphereOBB(const Sphere &sphere, const OBB &obb);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* sphere-capsule intersect detect.
|
||||
* @zh
|
||||
* 球和胶囊体的相交性检测。
|
||||
*/
|
||||
bool sphereCapsule(const Sphere &sphere, const Capsule &capsule);
|
||||
|
||||
// http://www.geomalgorithms.com/a07-_distance.html
|
||||
/**
|
||||
* @en
|
||||
* capsule-capsule intersect detect.
|
||||
* @zh
|
||||
* 胶囊体和胶囊体的相交性检测。
|
||||
*/
|
||||
bool capsuleWithCapsule(const Capsule &capsuleA, const Capsule &capsuleB);
|
||||
|
||||
template <typename T1, typename T2>
|
||||
auto intersects(const T1 & /*a*/, const T2 & /*b*/) {
|
||||
static_assert(std::is_base_of<T1, ShapeBase>::value, "type is not base of ShapeBase");
|
||||
static_assert(std::is_base_of<T2, ShapeBase>::value, "type is not base of ShapeBase");
|
||||
CC_ABORT(); // mismatch
|
||||
}
|
||||
|
||||
#define DECLARE_EXCHANGABLE_INTERSECT(TYPE1, TYPE2, FN) \
|
||||
template <> \
|
||||
inline auto intersects(const TYPE1 &arg1, const TYPE2 &arg2) { \
|
||||
return FN(arg1, arg2); \
|
||||
} \
|
||||
template <> \
|
||||
inline auto intersects(const TYPE2 &arg2, const TYPE1 &arg1) { \
|
||||
return FN(arg1, arg2); \
|
||||
}
|
||||
|
||||
#define DECLARE_SELF_INTERSECT(TYPE, FN) \
|
||||
template <> \
|
||||
inline auto intersects(const TYPE &arg1, const TYPE &arg2) { \
|
||||
return FN(arg1, arg2); \
|
||||
}
|
||||
|
||||
int dynObbFrustum(const OBB &obb, const Frustum &frustum);
|
||||
int dynSphereFrustum(const Sphere &sphere, const Frustum &frustum);
|
||||
int dynAabbFrustum(const AABB &aabb, const Frustum &frustum);
|
||||
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Ray, Sphere, raySphere)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Ray, AABB, rayAABB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Ray, OBB, rayOBB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Ray, Plane, rayPlane)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Ray, Triangle, rayTriangle)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Ray, Capsule, rayCapsule)
|
||||
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Line, Sphere, lineSphere)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Line, AABB, lineAABB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Line, OBB, lineOBB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Line, Plane, linePlane)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Line, Triangle, lineTriangle)
|
||||
|
||||
DECLARE_SELF_INTERSECT(Sphere, sphereWithSphere)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Sphere, AABB, sphereAABB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Sphere, OBB, sphereOBB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Sphere, Plane, spherePlane)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Sphere, Frustum, dynSphereFrustum)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(Sphere, Capsule, sphereCapsule)
|
||||
|
||||
DECLARE_SELF_INTERSECT(AABB, aabbWithAABB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(AABB, OBB, aabbWithOBB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(AABB, Plane, aabbPlane)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(AABB, Frustum, dynAabbFrustum)
|
||||
|
||||
DECLARE_SELF_INTERSECT(OBB, obbWithOBB)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(OBB, Plane, obbPlane)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(OBB, Frustum, dynObbFrustum)
|
||||
DECLARE_EXCHANGABLE_INTERSECT(OBB, Capsule, obbCapsule)
|
||||
|
||||
DECLARE_SELF_INTERSECT(Capsule, capsuleWithCapsule)
|
||||
|
||||
#undef DECLARE_SELF_INTERSECT
|
||||
#undef DECLARE_EXCHANGABLE_INTERSECT
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
81
cocos/core/geometry/Line.cpp
Normal file
81
cocos/core/geometry/Line.cpp
Normal file
@@ -0,0 +1,81 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/geometry/Line.h"
|
||||
#include "base/memory/Memory.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
Line *Line::create(float sx,
|
||||
float sy,
|
||||
float sz,
|
||||
float ex,
|
||||
float ey,
|
||||
float ez) {
|
||||
return ccnew Line(sx, sy, sz, ex, ey, ez);
|
||||
}
|
||||
|
||||
Line *Line::clone(const Line &a) {
|
||||
return ccnew Line(
|
||||
a.s.x, a.s.y, a.s.z,
|
||||
a.e.x, a.e.y, a.e.z);
|
||||
}
|
||||
|
||||
Line *Line::copy(Line *out, const Line &a) {
|
||||
out->s = a.s;
|
||||
out->e = a.e;
|
||||
return out;
|
||||
}
|
||||
|
||||
Line *Line::fromPoints(Line *out, const Vec3 &start, const Vec3 &end) {
|
||||
out->s = start;
|
||||
out->e = end;
|
||||
return out;
|
||||
}
|
||||
|
||||
Line *Line::set(Line *out,
|
||||
float sx,
|
||||
float sy,
|
||||
float sz,
|
||||
float ex,
|
||||
float ey,
|
||||
float ez) {
|
||||
out->s.x = sx;
|
||||
out->s.y = sy;
|
||||
out->s.z = sz;
|
||||
out->e.x = ex;
|
||||
out->e.y = ey;
|
||||
out->e.z = ez;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Line::Line(float sx, float sy, float sz, float ex, float ey, float ez) : ShapeBase(ShapeEnum::SHAPE_LINE) {
|
||||
s = {sx, sy, sz};
|
||||
e = {ex, ey, ez};
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
171
cocos/core/geometry/Line.h
Normal file
171
cocos/core/geometry/Line.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "math/Vec3.h"
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Basic Geometry: Line.
|
||||
* @zh
|
||||
* 基础几何 line。
|
||||
*/
|
||||
|
||||
class Line final : public ShapeBase {
|
||||
public:
|
||||
/**
|
||||
* @en
|
||||
* create a new line
|
||||
* @zh
|
||||
* 创建一个新的 line。
|
||||
* @param sx 起点的 x 部分。
|
||||
* @param sy 起点的 y 部分。
|
||||
* @param sz 起点的 z 部分。
|
||||
* @param ex 终点的 x 部分。
|
||||
* @param ey 终点的 y 部分。
|
||||
* @param ez 终点的 z 部分。
|
||||
* @return
|
||||
*/
|
||||
|
||||
static Line *create(float sx,
|
||||
float sy,
|
||||
float sz,
|
||||
float ex,
|
||||
float ey,
|
||||
float ez);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Creates a new Line initialized with values from an existing Line
|
||||
* @zh
|
||||
* 克隆一个新的 line。
|
||||
* @param a 克隆的来源。
|
||||
* @return 克隆出的对象。
|
||||
*/
|
||||
|
||||
static Line *clone(const Line &a);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Copy the values from one Line to another
|
||||
* @zh
|
||||
* 复制一个线的值到另一个。
|
||||
* @param out 接受操作的对象。
|
||||
* @param a 复制的来源。
|
||||
* @return 接受操作的对象。
|
||||
*/
|
||||
static Line *copy(Line *out, const Line &a);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* create a line from two points
|
||||
* @zh
|
||||
* 用两个点创建一个线。
|
||||
* @param out 接受操作的对象。
|
||||
* @param start 起点。
|
||||
* @param end 终点。
|
||||
* @return out 接受操作的对象。
|
||||
*/
|
||||
|
||||
static Line *fromPoints(Line *out, const Vec3 &start, const Vec3 &end);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set the components of a Vec3 to the given values
|
||||
* @zh
|
||||
* 将给定线的属性设置为给定值。
|
||||
* @param out 接受操作的对象。
|
||||
* @param sx 起点的 x 部分。
|
||||
* @param sy 起点的 y 部分。
|
||||
* @param sz 起点的 z 部分。
|
||||
* @param ex 终点的 x 部分。
|
||||
* @param ey 终点的 y 部分。
|
||||
* @param ez 终点的 z 部分。
|
||||
* @return out 接受操作的对象。
|
||||
*/
|
||||
static Line *set(Line *out,
|
||||
float sx,
|
||||
float sy,
|
||||
float sz,
|
||||
float ex,
|
||||
float ey,
|
||||
float ez);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 计算线的长度。
|
||||
* @param a 要计算的线。
|
||||
* @return 长度。
|
||||
*/
|
||||
static inline float len(const Line &a) {
|
||||
return a.s.distance(a.e);
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 起点。
|
||||
*/
|
||||
Vec3 s;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 终点。
|
||||
*/
|
||||
Vec3 e;
|
||||
|
||||
/**
|
||||
* 构造一条线。
|
||||
* @param sx 起点的 x 部分。
|
||||
* @param sy 起点的 y 部分。
|
||||
* @param sz 起点的 z 部分。
|
||||
* @param ex 终点的 x 部分。
|
||||
* @param ey 终点的 y 部分。
|
||||
* @param ez 终点的 z 部分。
|
||||
*/
|
||||
explicit Line(float sx = 0, float sy = 0, float sz = 0, float ex = 0, float ey = 0, float ez = -1);
|
||||
|
||||
Line(const Line &) = default;
|
||||
Line &operator=(const Line &) = default;
|
||||
Line &operator=(Line &&) = default;
|
||||
Line(Line &&) = default;
|
||||
~Line() override = default;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 计算线的长度。
|
||||
* @param a 要计算的线。
|
||||
* @return 长度。
|
||||
*/
|
||||
|
||||
inline float length() const {
|
||||
return s.distance(e);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
128
cocos/core/geometry/Obb.cpp
Normal file
128
cocos/core/geometry/Obb.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "cocos/core/geometry/Obb.h"
|
||||
#include "base/memory/Memory.h"
|
||||
|
||||
namespace {
|
||||
void transformExtentM3(cc::Vec3 *out, const cc::Vec3 &extent, const cc::Mat3 &m3) {
|
||||
cc::Mat3 m3Tmp;
|
||||
m3Tmp.m[0] = std::abs(m3.m[0]);
|
||||
m3Tmp.m[1] = std::abs(m3.m[1]);
|
||||
m3Tmp.m[2] = std::abs(m3.m[2]);
|
||||
m3Tmp.m[3] = std::abs(m3.m[3]);
|
||||
m3Tmp.m[4] = std::abs(m3.m[4]);
|
||||
m3Tmp.m[5] = std::abs(m3.m[5]);
|
||||
m3Tmp.m[6] = std::abs(m3.m[6]);
|
||||
m3Tmp.m[7] = std::abs(m3.m[7]);
|
||||
m3Tmp.m[8] = std::abs(m3.m[8]);
|
||||
out->transformMat3(extent, m3Tmp);
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
OBB *OBB::create(
|
||||
float cx, float cy, float cz,
|
||||
float hw, float hh, float hl,
|
||||
float ox1, float ox2, float ox3,
|
||||
float oy1, float oy2, float oy3,
|
||||
float oz1, float oz2, float oz3) {
|
||||
return ccnew OBB(cx, cy, cz, hw, hh, hl,
|
||||
ox1, ox2, ox3,
|
||||
oy1, oy2, oy3,
|
||||
oz1, oz2, oz3);
|
||||
}
|
||||
|
||||
OBB *OBB::clone(const OBB &a) {
|
||||
return ccnew OBB(a.center.x, a.center.y, a.center.z,
|
||||
a.halfExtents.x, a.halfExtents.y, a.halfExtents.z,
|
||||
a.orientation.m[0], a.orientation.m[1], a.orientation.m[2],
|
||||
a.orientation.m[3], a.orientation.m[4], a.orientation.m[5],
|
||||
a.orientation.m[6], a.orientation.m[7], a.orientation.m[8]);
|
||||
}
|
||||
|
||||
OBB *OBB::copy(OBB *out, const OBB &a) {
|
||||
out->center = a.center;
|
||||
out->halfExtents = a.halfExtents;
|
||||
out->orientation = a.orientation;
|
||||
return out;
|
||||
}
|
||||
|
||||
OBB *OBB::fromPoints(OBB *out, const Vec3 &minPos, const Vec3 &maxPos) {
|
||||
out->center = 0.5F * (minPos + maxPos);
|
||||
out->halfExtents = 0.5F * (maxPos - minPos);
|
||||
Mat3::identity(out->orientation);
|
||||
return out;
|
||||
}
|
||||
|
||||
OBB *OBB::set(OBB *out,
|
||||
float cx, float cy, float cz,
|
||||
float hw, float hh, float hl,
|
||||
float ox1, float ox2, float ox3,
|
||||
float oy1, float oy2, float oy3,
|
||||
float oz1, float oz2, float oz3) {
|
||||
out->center = {cx, cy, cz};
|
||||
out->halfExtents = {hw, hh, hl};
|
||||
out->orientation = {ox1, ox2, ox3, oy1, oy2, oy3, oz1, oz2, oz3};
|
||||
return out;
|
||||
}
|
||||
|
||||
OBB::OBB(float cx, float cy, float cz,
|
||||
float hw, float hh, float hl,
|
||||
float ox1, float ox2, float ox3,
|
||||
float oy1, float oy2, float oy3,
|
||||
float oz1, float oz2, float oz3) : ShapeBase(ShapeEnum::SHAPE_OBB) {
|
||||
center = {cx, cy, cz};
|
||||
halfExtents = {hw, hh, hl};
|
||||
orientation = {ox1, ox2, ox3, oy1, oy2, oy3, oz1, oz2, oz3};
|
||||
}
|
||||
|
||||
void OBB::getBoundary(Vec3 *minPos, Vec3 *maxPos) const {
|
||||
Vec3 v3Tmp;
|
||||
transformExtentM3(&v3Tmp, halfExtents, orientation);
|
||||
*minPos = center - v3Tmp;
|
||||
*maxPos = center + v3Tmp;
|
||||
}
|
||||
|
||||
void OBB::transform(const Mat4 &m, const Vec3 & /*pos*/, const Quaternion &rot, const Vec3 &scale, OBB *out) const {
|
||||
Vec3::transformMat4(center, m, &out->center);
|
||||
// parent shape doesn't contain rotations for now
|
||||
Mat3::fromQuat(rot, &out->orientation);
|
||||
Vec3::multiply(halfExtents, scale, &out->halfExtents);
|
||||
}
|
||||
|
||||
void OBB::translateAndRotate(const Mat4 &m, const Quaternion &rot, OBB *out) const {
|
||||
Vec3::transformMat4(center, m, &out->center);
|
||||
// parent shape doesn't contain rotations for now
|
||||
Mat3::fromQuat(rot, &out->orientation);
|
||||
}
|
||||
|
||||
void OBB::setScale(const Vec3 &scale, OBB *out) const {
|
||||
Vec3::multiply(halfExtents, scale, &out->halfExtents);
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
192
cocos/core/geometry/Obb.h
Normal file
192
cocos/core/geometry/Obb.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cocos/core/geometry/Enums.h"
|
||||
#include "cocos/math/Mat3.h"
|
||||
#include "cocos/math/Quaternion.h"
|
||||
#include "cocos/math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
class OBB final : public ShapeBase {
|
||||
public:
|
||||
/**
|
||||
* @en
|
||||
* create a new obb
|
||||
* @zh
|
||||
* 创建一个新的 obb 实例。
|
||||
* @param cx 形状的相对于原点的 X 坐标。
|
||||
* @param cy 形状的相对于原点的 Y 坐标。
|
||||
* @param cz 形状的相对于原点的 Z 坐标。
|
||||
* @param hw - obb 宽度的一半。
|
||||
* @param hh - obb 高度的一半。
|
||||
* @param hl - obb 长度的一半。
|
||||
* @param ox1 方向矩阵参数。
|
||||
* @param ox2 方向矩阵参数。
|
||||
* @param ox3 方向矩阵参数。
|
||||
* @param oy1 方向矩阵参数。
|
||||
* @param oy2 方向矩阵参数。
|
||||
* @param oy3 方向矩阵参数。
|
||||
* @param oz1 方向矩阵参数。
|
||||
* @param oz2 方向矩阵参数。
|
||||
* @param oz3 方向矩阵参数。
|
||||
* @return 返回一个 obb。
|
||||
*/
|
||||
static OBB *create(
|
||||
float cx, float cy, float cz,
|
||||
float hw, float hh, float hl,
|
||||
float ox1, float ox2, float ox3,
|
||||
float oy1, float oy2, float oy3,
|
||||
float oz1, float oz2, float oz3);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* clone a new obb
|
||||
* @zh
|
||||
* 克隆一个 obb。
|
||||
* @param a 克隆的目标。
|
||||
* @returns 克隆出的新对象。
|
||||
*/
|
||||
static OBB *clone(const OBB &a);
|
||||
/**
|
||||
* @en
|
||||
* copy the values from one obb to another
|
||||
* @zh
|
||||
* 将从一个 obb 的值复制到另一个 obb。
|
||||
* @param {OBB} out 接受操作的 obb。
|
||||
* @param {OBB} a 被复制的 obb。
|
||||
* @return {OBB} out 接受操作的 obb。
|
||||
*/
|
||||
static OBB *copy(OBB *out, const OBB &a);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* create a new obb from two corner points
|
||||
* @zh
|
||||
* 用两个点创建一个新的 obb。
|
||||
* @param out - 接受操作的 obb。
|
||||
* @param minPos - obb 的最小点。
|
||||
* @param maxPos - obb 的最大点。
|
||||
* @returns {OBB} out 接受操作的 obb。
|
||||
*/
|
||||
static OBB *fromPoints(OBB *out, const Vec3 &minPos, const Vec3 &maxPos);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set the components of a obb to the given values
|
||||
* @zh
|
||||
* 将给定 obb 的属性设置为给定的值。
|
||||
* @param cx - obb 的原点的 X 坐标。
|
||||
* @param cy - obb 的原点的 Y 坐标。
|
||||
* @param cz - obb 的原点的 Z 坐标。
|
||||
* @param hw - obb 宽度的一半。
|
||||
* @param hh - obb 高度的一半。
|
||||
* @param hl - obb 长度的一半。
|
||||
* @param ox1 方向矩阵参数。
|
||||
* @param ox2 方向矩阵参数。
|
||||
* @param ox3 方向矩阵参数。
|
||||
* @param oy1 方向矩阵参数。
|
||||
* @param oy2 方向矩阵参数。
|
||||
* @param oy3 方向矩阵参数。
|
||||
* @param oz1 方向矩阵参数。
|
||||
* @param oz2 方向矩阵参数。
|
||||
* @param oz3 方向矩阵参数。
|
||||
* @return {OBB} out
|
||||
*/
|
||||
|
||||
static OBB *set(OBB *out,
|
||||
float cx, float cy, float cz,
|
||||
float hw, float hh, float hl,
|
||||
float ox1, float ox2, float ox3,
|
||||
float oy1, float oy2, float oy3,
|
||||
float oz1, float oz2, float oz3);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 本地坐标的中心点。
|
||||
*/
|
||||
Vec3 center;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 长宽高的一半。
|
||||
*/
|
||||
Vec3 halfExtents;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 方向矩阵。
|
||||
*/
|
||||
|
||||
Mat3 orientation;
|
||||
|
||||
explicit OBB(float cx = 0, float cy = 0, float cz = 0,
|
||||
float hw = 1, float hh = 1, float hl = 1,
|
||||
float ox1 = 1, float ox2 = 0, float ox3 = 0,
|
||||
float oy1 = 0, float oy2 = 1, float oy3 = 0,
|
||||
float oz1 = 0, float oz2 = 0, float oz3 = 1);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Get the bounding points of this shape
|
||||
* @zh
|
||||
* 获取 obb 的最小点和最大点。
|
||||
* @param {Vec3} minPos 最小点。
|
||||
* @param {Vec3} maxPos 最大点。
|
||||
*/
|
||||
void getBoundary(Vec3 *minPos, Vec3 *maxPos) const;
|
||||
/**
|
||||
* Transform this shape
|
||||
* @zh
|
||||
* 将 out 根据这个 obb 的数据进行变换。
|
||||
* @param m 变换的矩阵。
|
||||
* @param pos 变换的位置部分。
|
||||
* @param rot 变换的旋转部分。
|
||||
* @param scale 变换的缩放部分。
|
||||
* @param out 变换的目标。
|
||||
*/
|
||||
void transform(const Mat4 &m, const Vec3 &pos, const Quaternion &rot, const Vec3 &scale, OBB *out) const;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 将 out 根据这个 obb 的数据进行变换。
|
||||
* @param m 变换的矩阵。
|
||||
* @param rot 变换的旋转部分。
|
||||
* @param out 变换的目标。
|
||||
*/
|
||||
void translateAndRotate(const Mat4 &m, const Quaternion &rot, OBB *out) const;
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 将 out 根据这个 obb 的数据进行缩放。
|
||||
* @param scale 缩放值。
|
||||
* @param out 缩放的目标。
|
||||
*/
|
||||
void setScale(const Vec3 &scale, OBB *out) const;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
118
cocos/core/geometry/Plane.cpp
Normal file
118
cocos/core/geometry/Plane.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "cocos/core/geometry/Plane.h"
|
||||
#include "base/memory/Memory.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
Plane *Plane::create(float nx, float ny, float nz, float d) {
|
||||
return ccnew Plane{nx, ny, nz, d};
|
||||
}
|
||||
|
||||
Plane *Plane::clone(const Plane &p) {
|
||||
return ccnew Plane{p.n.x, p.n.y, p.n.z, p.d};
|
||||
}
|
||||
|
||||
Plane *Plane::copy(Plane *out, const Plane &p) {
|
||||
out->n = p.n;
|
||||
out->d = p.d;
|
||||
return out;
|
||||
}
|
||||
|
||||
Plane *Plane::fromPoints(Plane *out,
|
||||
const Vec3 &a,
|
||||
const Vec3 &b,
|
||||
const Vec3 &c) {
|
||||
Vec3::cross(b - a, c - a, &out->n);
|
||||
out->n.normalize();
|
||||
out->d = Vec3::dot(out->n, a);
|
||||
return out;
|
||||
}
|
||||
|
||||
Plane *Plane::fromNormalAndPoint(Plane *out, const Vec3 &normal, const Vec3 &point) {
|
||||
out->n = normal;
|
||||
out->d = Vec3::dot(normal, point);
|
||||
return out;
|
||||
}
|
||||
|
||||
Plane *Plane::normalize(Plane *out, const Plane &a) {
|
||||
const auto len = a.n.length();
|
||||
out->n = a.n.getNormalized();
|
||||
if (len > 0) {
|
||||
out->d = a.d / len;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
Plane *Plane::set(Plane *out, float nx, float ny, float nz, float d) {
|
||||
out->n = {nx, ny, nz};
|
||||
out->d = d;
|
||||
return out;
|
||||
}
|
||||
|
||||
Plane::Plane(float nx, float ny, float nz, float d) : Plane() {
|
||||
n = {nx, ny, nz};
|
||||
this->d = d;
|
||||
}
|
||||
|
||||
void Plane::transform(const Mat4 &mat) {
|
||||
Mat4 tempMat = mat.getInversed();
|
||||
tempMat.transpose();
|
||||
Vec4 tempVec4 = {n.x, n.y, n.z, -d};
|
||||
tempMat.transformVector(&tempVec4);
|
||||
n.set(tempVec4.x, tempVec4.y, tempVec4.z);
|
||||
d = -tempVec4.w;
|
||||
}
|
||||
|
||||
// Define from 3 vertices.
|
||||
void Plane::define(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2) {
|
||||
const Vec3 dist1 = v1 - v0;
|
||||
const Vec3 dist2 = v2 - v0;
|
||||
|
||||
Vec3 dist;
|
||||
Vec3::cross(dist1, dist2, &dist);
|
||||
define(dist, v0);
|
||||
}
|
||||
// Define from a normal vector and a point on the plane.
|
||||
void Plane::define(const Vec3 &normal, const Vec3 &point) {
|
||||
n = normal.getNormalized();
|
||||
d = n.dot(point);
|
||||
}
|
||||
|
||||
// Return signed distance to a point.
|
||||
float Plane::distance(const Vec3 &point) const {
|
||||
return n.dot(point) - d;
|
||||
}
|
||||
|
||||
Plane Plane::clone() const {
|
||||
Plane plane;
|
||||
plane.n.set(n);
|
||||
plane.d = d;
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
191
cocos/core/geometry/Plane.h
Normal file
191
cocos/core/geometry/Plane.h
Normal file
@@ -0,0 +1,191 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cocos/core/geometry/Enums.h"
|
||||
#include "cocos/math/Mat4.h"
|
||||
#include "cocos/math/Vec3.h"
|
||||
#include "cocos/math/Vec4.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
/**
|
||||
* @en
|
||||
* Basic Geometry: Plane.
|
||||
* @zh
|
||||
* 基础几何 Plane。
|
||||
*/
|
||||
class Plane final : public ShapeBase {
|
||||
/**
|
||||
* @en
|
||||
* create a new plane
|
||||
* @zh
|
||||
* 创建一个新的 plane。
|
||||
* @param nx 法向分量的 x 部分。
|
||||
* @param ny 法向分量的 y 部分。
|
||||
* @param nz 法向分量的 z 部分。
|
||||
* @param d 与原点的距离。
|
||||
* @return
|
||||
*/
|
||||
public:
|
||||
static Plane *create(float nx, float ny, float nz, float d);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* clone a new plane
|
||||
* @zh
|
||||
* 克隆一个新的 plane。
|
||||
* @param p 克隆的来源。
|
||||
* @return 克隆出的对象。
|
||||
*/
|
||||
static Plane *clone(const Plane &p);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* copy the values from one plane to another
|
||||
* @zh
|
||||
* 复制一个平面的值到另一个。
|
||||
* @param out 接受操作的对象。
|
||||
* @param p 复制的来源。
|
||||
* @return 接受操作的对象。
|
||||
*/
|
||||
|
||||
static Plane *copy(Plane *out, const Plane &p);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* create a plane from three points
|
||||
* @zh
|
||||
* 用三个点创建一个平面。
|
||||
* @param out 接受操作的对象。
|
||||
* @param a 点 a。
|
||||
* @param b 点 b。
|
||||
* @param c 点 c。
|
||||
* @return out 接受操作的对象。
|
||||
*/
|
||||
static Plane *fromPoints(Plane *out,
|
||||
const Vec3 &a,
|
||||
const Vec3 &b,
|
||||
const Vec3 &c);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set the components of a plane to the given values
|
||||
* @zh
|
||||
* 将给定平面的属性设置为给定值。
|
||||
* @param out 接受操作的对象。
|
||||
* @param nx 法向分量的 x 部分。
|
||||
* @param ny 法向分量的 y 部分。
|
||||
* @param nz 法向分量的 z 部分。
|
||||
* @param d 与原点的距离。
|
||||
* @return out 接受操作的对象。
|
||||
*/
|
||||
static Plane *set(Plane *out, float nx, float ny, float nz, float d);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* create plane from normal and point
|
||||
* @zh
|
||||
* 用一条法线和一个点创建平面。
|
||||
* @param out 接受操作的对象。
|
||||
* @param normal 平面的法线。
|
||||
* @param point 平面上的一点。
|
||||
* @return out 接受操作的对象。
|
||||
*/
|
||||
static Plane *fromNormalAndPoint(Plane *out, const Vec3 &normal, const Vec3 &point);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* normalize a plane
|
||||
* @zh
|
||||
* 归一化一个平面。
|
||||
* @param out 接受操作的对象。
|
||||
* @param a 操作的源数据。
|
||||
* @return out 接受操作的对象。
|
||||
*/
|
||||
static Plane *normalize(Plane *out, const Plane &a);
|
||||
|
||||
// compatibility with vector interfaces
|
||||
inline void setX(float val) { n.x = val; }
|
||||
inline float getX() const { return n.x; }
|
||||
inline void setY(float val) { n.y = val; }
|
||||
inline float getY() const { return n.y; }
|
||||
inline void setZ(float val) { n.z = val; }
|
||||
inline float getZ() const { return n.z; }
|
||||
inline void setW(float val) { d = val; }
|
||||
inline float getW() const { return d; }
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Construct a plane.
|
||||
* @zh
|
||||
* 构造一个平面。
|
||||
* @param nx 法向分量的 x 部分。
|
||||
* @param ny 法向分量的 y 部分。
|
||||
* @param nz 法向分量的 z 部分。
|
||||
* @param d 与原点的距离。
|
||||
*/
|
||||
explicit Plane(float nx, float ny, float nz, float d);
|
||||
|
||||
Plane() : ShapeBase(ShapeEnum::SHAPE_PLANE) {}
|
||||
// Plane(const Plane& other) = default;
|
||||
// Plane(Plane&& other) = default;
|
||||
// Plane& operator=(const Plane& other) = default;
|
||||
// Plane& operator=(Plane&& other) = default;
|
||||
// ~Plane() = default;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* transform this plane.
|
||||
* @zh
|
||||
* 变换一个平面。
|
||||
* @param mat
|
||||
*/
|
||||
void transform(const Mat4 &mat);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The normal of the plane.
|
||||
* @zh
|
||||
* 法线向量。
|
||||
*/
|
||||
Vec3 n{0.0F, 1.0F, 0.0F};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The distance from the origin to the plane.
|
||||
* @zh
|
||||
* 原点到平面的距离。
|
||||
*/
|
||||
float d{0.0F};
|
||||
|
||||
void define(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2);
|
||||
void define(const Vec3 &normal, const Vec3 &point);
|
||||
float distance(const Vec3 &point) const;
|
||||
Plane clone() const;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
76
cocos/core/geometry/Ray.cpp
Normal file
76
cocos/core/geometry/Ray.cpp
Normal file
@@ -0,0 +1,76 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/geometry/Ray.h"
|
||||
#include "base/memory/Memory.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
Ray *Ray::create(float ox, float oy, float oz, float dx, float dy, float dz) {
|
||||
return ccnew Ray{ox, oy, oz, dx, dy, dz};
|
||||
}
|
||||
|
||||
Ray *Ray::clone(const Ray &a) {
|
||||
return ccnew Ray{
|
||||
a.o.x, a.o.y, a.o.z,
|
||||
a.d.x, a.d.y, a.d.z};
|
||||
}
|
||||
|
||||
Ray *Ray::copy(Ray *out, const Ray &a) {
|
||||
out->o = a.o;
|
||||
out->d = a.d;
|
||||
return out;
|
||||
}
|
||||
|
||||
Ray *Ray::fromPoints(Ray *out, const Vec3 &origin, const Vec3 &target) {
|
||||
out->o = origin;
|
||||
out->d = (target - origin).getNormalized();
|
||||
return out;
|
||||
}
|
||||
|
||||
Ray *Ray::set(Ray *out, float ox, float oy,
|
||||
float oz,
|
||||
float dx,
|
||||
float dy,
|
||||
float dz) {
|
||||
out->o.x = ox;
|
||||
out->o.y = oy;
|
||||
out->o.z = oz;
|
||||
out->d.x = dx;
|
||||
out->d.y = dy;
|
||||
out->d.z = dz;
|
||||
return out;
|
||||
}
|
||||
|
||||
Ray::Ray(float ox, float oy, float oz,
|
||||
float dx, float dy, float dz) : ShapeBase(ShapeEnum::SHAPE_RAY) {
|
||||
o = {ox, oy, oz};
|
||||
d = {dx, dy, dz};
|
||||
}
|
||||
|
||||
void Ray::computeHit(Vec3 *out, float distance) const {
|
||||
*out = o + d.getNormalized() * distance;
|
||||
}
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
160
cocos/core/geometry/Ray.h
Normal file
160
cocos/core/geometry/Ray.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Basic Geometry: ray.
|
||||
* @zh
|
||||
* 基础几何 射线。
|
||||
*/
|
||||
|
||||
class Ray final : public ShapeBase {
|
||||
public:
|
||||
/**
|
||||
* @en
|
||||
* create a new ray
|
||||
* @zh
|
||||
* 创建一条射线。
|
||||
* @param {number} ox 起点的 x 部分。
|
||||
* @param {number} oy 起点的 y 部分。
|
||||
* @param {number} oz 起点的 z 部分。
|
||||
* @param {number} dx 方向的 x 部分。
|
||||
* @param {number} dy 方向的 y 部分。
|
||||
* @param {number} dz 方向的 z 部分。
|
||||
* @return {Ray} 射线。
|
||||
*/
|
||||
static Ray *create(float ox = 0, float oy = 0, float oz = 0, float dx = 0, float dy = 0, float dz = 1);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Creates a new ray initialized with values from an existing ray
|
||||
* @zh
|
||||
* 从一条射线克隆出一条新的射线。
|
||||
* @param {Ray} a 克隆的目标。
|
||||
* @return {Ray} 克隆出的新对象。
|
||||
*/
|
||||
static Ray *clone(const Ray &a);
|
||||
/**
|
||||
* @en
|
||||
* Copy the values from one ray to another
|
||||
* @zh
|
||||
* 将从一个 ray 的值复制到另一个 ray。
|
||||
* @param {Ray} out 接受操作的 ray。
|
||||
* @param {Ray} a 被复制的 ray。
|
||||
* @return {Ray} out 接受操作的 ray。
|
||||
*/
|
||||
static Ray *copy(Ray *out, const Ray &a);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* create a ray from two points
|
||||
* @zh
|
||||
* 用两个点创建一条射线。
|
||||
* @param {Ray} out 接受操作的射线。
|
||||
* @param {Vec3} origin 射线的起点。
|
||||
* @param {Vec3} target 射线上的一点。
|
||||
* @return {Ray} out 接受操作的射线。
|
||||
*/
|
||||
static Ray *fromPoints(Ray *out, const Vec3 &origin, const Vec3 &target);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set the components of a ray to the given values
|
||||
* @zh
|
||||
* 将给定射线的属性设置为给定的值。
|
||||
* @param {Ray} out 接受操作的射线。
|
||||
* @param {number} ox 起点的 x 部分。
|
||||
* @param {number} oy 起点的 y 部分。
|
||||
* @param {number} oz 起点的 z 部分。
|
||||
* @param {number} dx 方向的 x 部分。
|
||||
* @param {number} dy 方向的 y 部分。
|
||||
* @param {number} dz 方向的 z 部分。
|
||||
* @return {Ray} out 接受操作的射线。
|
||||
*/
|
||||
|
||||
static Ray *set(Ray *out, float ox, float oy,
|
||||
float oz,
|
||||
float dx,
|
||||
float dy,
|
||||
float dz);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The origin of the ray.
|
||||
* @zh
|
||||
* 起点。
|
||||
*/
|
||||
Vec3 o;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The direction of the ray.
|
||||
* @zh
|
||||
* 方向。
|
||||
*/
|
||||
Vec3 d;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Construct a ray;
|
||||
* @zh
|
||||
* 构造一条射线。
|
||||
* @param {number} ox 起点的 x 部分。
|
||||
* @param {number} oy 起点的 y 部分。
|
||||
* @param {number} oz 起点的 z 部分。
|
||||
* @param {number} dx 方向的 x 部分。
|
||||
* @param {number} dy 方向的 y 部分。
|
||||
* @param {number} dz 方向的 z 部分。
|
||||
*/
|
||||
explicit Ray(float ox = 0, float oy = 0, float oz = 0,
|
||||
float dx = 0, float dy = 0, float dz = -1);
|
||||
|
||||
Ray(const Ray &) = default;
|
||||
Ray &operator=(const Ray &) = default;
|
||||
Ray &operator=(Ray &&) = default;
|
||||
Ray(Ray &&) = default;
|
||||
~Ray() override = default;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Compute a point with the distance between the origin.
|
||||
* @zh
|
||||
* 根据给定距离计算出射线上的一点。
|
||||
* @param out 射线上的另一点。
|
||||
* @param distance 给定距离。
|
||||
*/
|
||||
|
||||
void computeHit(Vec3 *out, float distance) const;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
23
cocos/core/geometry/Spec.cpp
Normal file
23
cocos/core/geometry/Spec.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
174
cocos/core/geometry/Spec.h
Normal file
174
cocos/core/geometry/Spec.h
Normal file
@@ -0,0 +1,174 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cfloat>
|
||||
#include <cstdint>
|
||||
|
||||
#include "base/std/container/vector.h"
|
||||
#include "base/std/optional.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The raycast mode.
|
||||
* @zh
|
||||
* 射线检测模式。
|
||||
*/
|
||||
enum class ERaycastMode {
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Detect and record all data.
|
||||
* @zh
|
||||
* 检测并记录所有的数据。
|
||||
*/
|
||||
ALL,
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Detect all, but record only the most recent data.
|
||||
* @zh
|
||||
* 检测所有,但只记录最近的数据。
|
||||
*/
|
||||
CLOSEST,
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Once the test is successful, the test is stopped and the data is recorded only once.
|
||||
* @zh
|
||||
* 一旦检测成功就停止检测,只会记录一次数据。
|
||||
*/
|
||||
ANY,
|
||||
};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The storage structure of the raycast results.
|
||||
* @zh
|
||||
* 射线检测结果的存储结构。
|
||||
*/
|
||||
struct IRaySubMeshResult {
|
||||
/**
|
||||
* @en
|
||||
* The distance between the hit point and the ray.
|
||||
* @zh
|
||||
* 击中点和射线的距离。
|
||||
*/
|
||||
float distance{0.0F};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The index of the triangle vertex 0。
|
||||
* @zh
|
||||
* 三角形顶点0的索引。
|
||||
*/
|
||||
uint32_t vertexIndex0{0};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The index of the triangle vertex 1。
|
||||
* @zh
|
||||
* 三角形顶点1的索引
|
||||
*/
|
||||
uint32_t vertexIndex1{0};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The index of the triangle vertex 2。
|
||||
* @zh
|
||||
* 三角形顶点2的索引
|
||||
*/
|
||||
uint32_t vertexIndex2{0};
|
||||
};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The optional param structure of the `raySubMesh`.
|
||||
* @zh
|
||||
* `raySubMesh`的可选参数结构。
|
||||
*/
|
||||
struct IRaySubMeshOptions {
|
||||
/**
|
||||
* @en
|
||||
* The raycast mode,`ANY` by default.
|
||||
* @zh
|
||||
* 射线检测模式:[0, 1, 2]=>[`ALL`, `CLOSEST`, `ANY`]
|
||||
*/
|
||||
ERaycastMode mode;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The maximum distance of the raycast, `Infinity` by default.
|
||||
* @zh
|
||||
* 射线检测的最大距离,默认为`Infinity`。
|
||||
*/
|
||||
float distance = FLT_MAX;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* An array used to store the results of a ray detection.
|
||||
* @zh
|
||||
* 用于存储射线检测结果的数组。
|
||||
*/
|
||||
ccstd::optional<ccstd::vector<IRaySubMeshResult>> result{};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Whether to detect the double-sided or not,`false` by default.
|
||||
* @zh
|
||||
* 是否检测双面,默认为`false`。
|
||||
*/
|
||||
bool doubleSided{false};
|
||||
};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The optional param structure of the `rayMesh`.
|
||||
* @zh
|
||||
* `rayMesh`的可选参数结构。
|
||||
*/
|
||||
struct IRayMeshOptions : public IRaySubMeshOptions {
|
||||
/**
|
||||
* @en
|
||||
* The index of the sub mesh.
|
||||
* @zh
|
||||
* 子网格的索引。
|
||||
*/
|
||||
ccstd::optional<ccstd::vector<uint32_t>> subIndices{};
|
||||
};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The optional param structure of the `rayModel`.
|
||||
* @zh
|
||||
* `rayModel`的可选参数结构。
|
||||
*/
|
||||
using IRayModelOptions = IRayMeshOptions;
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
202
cocos/core/geometry/Sphere.cpp
Normal file
202
cocos/core/geometry/Sphere.cpp
Normal file
@@ -0,0 +1,202 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/geometry/Sphere.h"
|
||||
#include <algorithm>
|
||||
#include "core/geometry/AABB.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
Sphere *Sphere::create(float cx, float cy, float cz, float radius) {
|
||||
return ccnew Sphere(cx, cy, cz, radius);
|
||||
}
|
||||
|
||||
Sphere *Sphere::clone(const Sphere &p) {
|
||||
return ccnew Sphere(p._center.x, p._center.y, p._center.z, p._radius);
|
||||
}
|
||||
|
||||
Sphere *Sphere::copy(Sphere *out, const Sphere &p) {
|
||||
out->_center = p._center;
|
||||
out->_radius = p._radius;
|
||||
return out;
|
||||
}
|
||||
|
||||
Sphere *Sphere::fromPoints(Sphere *out, const Vec3 &minPos, const Vec3 &maxPos) {
|
||||
out->_center = 0.5F * (minPos + maxPos);
|
||||
out->_radius = 0.5F * (maxPos - minPos).length();
|
||||
return out;
|
||||
}
|
||||
|
||||
Sphere *Sphere::set(Sphere *out, float cx, float cy, float cz, float r) {
|
||||
out->_center = {cx, cy, cz};
|
||||
out->_radius = r;
|
||||
return out;
|
||||
}
|
||||
|
||||
Sphere *Sphere::mergePoint(Sphere *out, const Sphere &s, const Vec3 &point) {
|
||||
// if sphere.radius Less than 0,
|
||||
// Set this point as anchor,
|
||||
// And set radius to 0.
|
||||
if (s._radius < 0.0) {
|
||||
out->_center = point;
|
||||
out->_radius = 0.0F;
|
||||
return out;
|
||||
}
|
||||
|
||||
auto offset = point - s._center;
|
||||
auto dist = offset.length();
|
||||
|
||||
if (dist > s._radius) {
|
||||
auto half = (dist - s._radius) * 0.5F;
|
||||
out->_radius += half;
|
||||
offset.scale(half / dist);
|
||||
out->_center = out->_center + offset;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void Sphere::merge(const ccstd::vector<cc::Vec3> &points) {
|
||||
if (points.empty()) return;
|
||||
_radius = -1.0F;
|
||||
for (const auto &p : points) {
|
||||
merge(p);
|
||||
}
|
||||
}
|
||||
|
||||
Sphere *Sphere::mergeAABB(Sphere *out, const Sphere &s, const AABB &a) {
|
||||
Vec3 aabbMin;
|
||||
Vec3 aabbMax;
|
||||
a.getBoundary(&aabbMin, &aabbMax);
|
||||
Sphere::mergePoint(out, s, aabbMin);
|
||||
Sphere::mergePoint(out, s, aabbMax);
|
||||
return out;
|
||||
}
|
||||
|
||||
Sphere::Sphere(float cx, float cy, float cz, float radius) : ShapeBase(ShapeEnum::SHAPE_SPHERE) {
|
||||
_center = {cx, cy, cz};
|
||||
_radius = radius;
|
||||
}
|
||||
|
||||
void Sphere::getBoundary(Vec3 *minPos, Vec3 *maxPos) const {
|
||||
Vec3 half = {_radius, _radius, _radius};
|
||||
*minPos = _center - half;
|
||||
*maxPos = _center + half;
|
||||
}
|
||||
|
||||
void Sphere::transform(const Mat4 &m,
|
||||
const Vec3 & /*pos*/,
|
||||
const Quaternion & /*rot*/,
|
||||
const Vec3 &scale,
|
||||
Sphere *out) const {
|
||||
Vec3::transformMat4(_center, m, &out->_center);
|
||||
out->_radius = _radius * mathutils::maxComponent(scale);
|
||||
}
|
||||
|
||||
int Sphere::intersect(const Plane &plane) const {
|
||||
const float dot = plane.n.dot(_center);
|
||||
const float r = _radius * plane.n.length();
|
||||
if (dot + r < plane.d) {
|
||||
return -1; // Sphere is on the back of the plane
|
||||
}
|
||||
|
||||
if (dot - r > plane.d) {
|
||||
return 0; // Sphere is on the front of the plane
|
||||
}
|
||||
|
||||
return 1; // intersect
|
||||
}
|
||||
|
||||
bool Sphere::intersect(const Frustum &frustum) const {
|
||||
const auto &planes = frustum.planes;
|
||||
const auto *self = this;
|
||||
return std::all_of(planes.begin(),
|
||||
planes.end(),
|
||||
// frustum plane normal points to the inside
|
||||
[self](const Plane *plane) { return self->intersect(*plane) != -1; });
|
||||
}
|
||||
|
||||
void Sphere::mergePoint(const Vec3 &point) {
|
||||
if (_radius < 0.0F) {
|
||||
_center = point;
|
||||
_radius = 0.0F;
|
||||
return;
|
||||
}
|
||||
|
||||
auto offset = point - _center;
|
||||
auto distance = offset.length();
|
||||
|
||||
if (distance > _radius) {
|
||||
auto half = (distance - _radius) * 0.5F;
|
||||
_radius += half;
|
||||
offset.scale(half / distance);
|
||||
_center += offset;
|
||||
}
|
||||
}
|
||||
|
||||
void Sphere::define(const AABB &aabb) {
|
||||
cc::Vec3 minPos;
|
||||
cc::Vec3 maxPos;
|
||||
aabb.getBoundary(&minPos, &maxPos);
|
||||
|
||||
// Initialize sphere
|
||||
_center.set(minPos);
|
||||
_radius = 0.0F;
|
||||
|
||||
// Calculate sphere
|
||||
const cc::Vec3 offset = maxPos - _center;
|
||||
const float dist = offset.length();
|
||||
|
||||
const float half = dist * 0.5F;
|
||||
_radius += dist * 0.5F;
|
||||
_center += (half / dist) * offset;
|
||||
}
|
||||
|
||||
void Sphere::mergeAABB(const AABB *aabb) {
|
||||
cc::Vec3 minPos;
|
||||
cc::Vec3 maxPos;
|
||||
aabb->getBoundary(&minPos, &maxPos);
|
||||
mergePoint(minPos);
|
||||
mergePoint(maxPos);
|
||||
}
|
||||
|
||||
int Sphere::spherePlane(const Plane &plane) const {
|
||||
return intersect(plane);
|
||||
}
|
||||
|
||||
bool Sphere::sphereFrustum(const Frustum &frustum) const {
|
||||
return intersect(frustum);
|
||||
}
|
||||
|
||||
void Sphere::mergeFrustum(const Frustum &frustum) {
|
||||
const ccstd::array<Vec3, 8> &vertices = frustum.vertices;
|
||||
for (size_t i = 0; i < vertices.max_size(); ++i) {
|
||||
merge(vertices[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
201
cocos/core/geometry/Sphere.h
Normal file
201
cocos/core/geometry/Sphere.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "core/geometry/Frustum.h"
|
||||
#include "math/Utils.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
class AABB;
|
||||
|
||||
class Sphere final : public ShapeBase {
|
||||
public:
|
||||
/**
|
||||
* @en
|
||||
* create a new sphere
|
||||
* @zh
|
||||
* 创建一个新的 sphere 实例。
|
||||
* @param cx 形状的相对于原点的 X 坐标。
|
||||
* @param cy 形状的相对于原点的 Y 坐标。
|
||||
* @param cz 形状的相对于原点的 Z 坐标。
|
||||
* @param r 球体的半径
|
||||
* @return {Sphere} 返回一个 sphere。
|
||||
*/
|
||||
static Sphere *create(float cx, float cy, float cz, float radius);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* clone a new sphere
|
||||
* @zh
|
||||
* 克隆一个新的 sphere 实例。
|
||||
* @param {Sphere} p 克隆的目标。
|
||||
* @return {Sphere} 克隆出的示例。
|
||||
*/
|
||||
static Sphere *clone(const Sphere &p);
|
||||
/**
|
||||
* @en
|
||||
* copy the values from one sphere to another
|
||||
* @zh
|
||||
* 将从一个 sphere 的值复制到另一个 sphere。
|
||||
* @param {Sphere} out 接受操作的 sphere。
|
||||
* @param {Sphere} a 被复制的 sphere。
|
||||
* @return {Sphere} out 接受操作的 sphere。
|
||||
*/
|
||||
static Sphere *copy(Sphere *out, const Sphere &p);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* create a new bounding sphere from two corner points
|
||||
* @zh
|
||||
* 从两个点创建一个新的 sphere。
|
||||
* @param out - 接受操作的 sphere。
|
||||
* @param minPos - sphere 的最小点。
|
||||
* @param maxPos - sphere 的最大点。
|
||||
* @returns {Sphere} out 接受操作的 sphere。
|
||||
*/
|
||||
static Sphere *fromPoints(Sphere *out, const Vec3 &minPos, const Vec3 &maxPos);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set the components of a sphere to the given values
|
||||
* @zh
|
||||
* 将球体的属性设置为给定的值。
|
||||
* @param {Sphere} out 接受操作的 sphere。
|
||||
* @param cx 形状的相对于原点的 X 坐标。
|
||||
* @param cy 形状的相对于原点的 Y 坐标。
|
||||
* @param cz 形状的相对于原点的 Z 坐标。
|
||||
* @param {number} r 半径。
|
||||
* @return {Sphere} out 接受操作的 sphere。
|
||||
* @function
|
||||
*/
|
||||
static Sphere *set(Sphere *out, float cx, float cy, float cz, float r);
|
||||
/**
|
||||
* @zh
|
||||
* 球跟点合并
|
||||
*/
|
||||
static Sphere *mergePoint(Sphere *out, const Sphere &s, const Vec3 &point);
|
||||
|
||||
/**
|
||||
* @zh
|
||||
* 球跟立方体合并
|
||||
*/
|
||||
static Sphere *mergeAABB(Sphere *out, const Sphere &s, const AABB &a);
|
||||
explicit Sphere(float cx = 0, float cy = 0, float cz = 0, float radius = 1.0F);
|
||||
|
||||
Sphere(const Sphere &) = default;
|
||||
Sphere(Sphere &&) = delete;
|
||||
~Sphere() override = default;
|
||||
Sphere &operator=(const Sphere &) = default;
|
||||
Sphere &operator=(Sphere &&) = delete;
|
||||
|
||||
inline float getRadius() const { return _radius; }
|
||||
inline const Vec3 &getCenter() const { return _center; }
|
||||
inline void setCenter(const Vec3 &val) { _center = val; }
|
||||
inline void setRadius(float val) { _radius = val; }
|
||||
|
||||
inline Sphere *clone() const {
|
||||
return Sphere::clone(*this);
|
||||
}
|
||||
|
||||
inline Sphere *copy(Sphere *out) const {
|
||||
return Sphere::copy(out, *this);
|
||||
}
|
||||
|
||||
void define(const AABB &aabb);
|
||||
void mergeAABB(const AABB *aabb);
|
||||
void mergePoint(const Vec3 &point);
|
||||
void mergeFrustum(const Frustum &frustum);
|
||||
inline void merge(const AABB *aabb) { mergeAABB(aabb); }
|
||||
inline void merge(const Vec3 &point) { mergePoint(point); }
|
||||
void merge(const ccstd::vector<Vec3> &points);
|
||||
inline void merge(const Frustum &frustum) { mergeFrustum(frustum); }
|
||||
bool intersect(const Frustum &frustum) const;
|
||||
int intersect(const Plane &plane) const;
|
||||
int spherePlane(const Plane &plane) const;
|
||||
bool sphereFrustum(const Frustum &frustum) const;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Get the bounding points of this shape
|
||||
* @zh
|
||||
* 获取此形状的边界点。
|
||||
* @param {Vec3} minPos 最小点。
|
||||
* @param {Vec3} maxPos 最大点。
|
||||
*/
|
||||
void getBoundary(Vec3 *minPos, Vec3 *maxPos) const;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Transform this shape
|
||||
* @zh
|
||||
* 将 out 根据这个 sphere 的数据进行变换。
|
||||
* @param m 变换的矩阵。
|
||||
* @param pos 变换的位置部分。
|
||||
* @param rot 变换的旋转部分。
|
||||
* @param scale 变换的缩放部分。
|
||||
* @param out 变换的目标。
|
||||
*/
|
||||
void transform(const Mat4 &m,
|
||||
const Vec3 & /*pos*/,
|
||||
const Quaternion & /*rot*/,
|
||||
const Vec3 &scale,
|
||||
Sphere *out) const;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Translate and rotate this sphere.
|
||||
* @zh
|
||||
* 将 out 根据这个 sphere 的数据进行变换。
|
||||
* @param m 变换的矩阵。
|
||||
* @param rot 变换的旋转部分。
|
||||
* @param out 变换的目标。
|
||||
*/
|
||||
inline void translateAndRotate(const Mat4 &m, const Quaternion & /*rot*/, Sphere *out) const {
|
||||
Vec3::transformMat4(_center, m, &out->_center);
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Scaling this sphere.
|
||||
* @zh
|
||||
* 将 out 根据这个 sphere 的数据进行缩放。
|
||||
* @param scale 缩放值。
|
||||
* @param out 缩放的目标。
|
||||
*/
|
||||
inline void setScale(const Vec3 &scale, Sphere *out) const {
|
||||
out->_radius = _radius * mathutils::maxComponent(scale);
|
||||
}
|
||||
|
||||
// private: // make public for js bindings
|
||||
float _radius{-1.0};
|
||||
Vec3 _center;
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
200
cocos/core/geometry/Spline.cpp
Normal file
200
cocos/core/geometry/Spline.cpp
Normal file
@@ -0,0 +1,200 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/geometry/Spline.h"
|
||||
#include <cmath>
|
||||
#include "base/Log.h"
|
||||
#include "base/Macros.h"
|
||||
#include "base/memory/Memory.h"
|
||||
#include "math/Utils.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
Spline::Spline(SplineMode mode /*= SplineMode::CATMULL_ROM*/, ccstd::vector<Vec3> knots /*= {}*/)
|
||||
: ShapeBase(ShapeEnum::SHAPE_SPLINE), _mode(mode), _knots(std::move(knots)) {
|
||||
}
|
||||
|
||||
Spline *Spline::create(SplineMode mode, const ccstd::vector<Vec3> &knots /*= {}*/) {
|
||||
return ccnew Spline(mode, knots);
|
||||
}
|
||||
|
||||
Spline *Spline::clone(const Spline &s) {
|
||||
return ccnew Spline(s._mode, s._knots);
|
||||
}
|
||||
|
||||
Spline *Spline::copy(Spline *out, const Spline &s) {
|
||||
out->_mode = s._mode;
|
||||
out->_knots = s._knots;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void Spline::setModeAndKnots(SplineMode mode, const ccstd::vector<Vec3> &knots) {
|
||||
_mode = mode;
|
||||
_knots = knots;
|
||||
}
|
||||
|
||||
void Spline::insertKnot(uint32_t index, const Vec3 &knot) {
|
||||
if (index >= static_cast<uint32_t>(_knots.size())) {
|
||||
_knots.push_back(knot);
|
||||
return;
|
||||
}
|
||||
|
||||
_knots.insert(_knots.begin() + index, knot);
|
||||
}
|
||||
|
||||
void Spline::removeKnot(uint32_t index) {
|
||||
CC_ASSERT(index < static_cast<uint32_t>(_knots.size()));
|
||||
|
||||
_knots.erase(_knots.begin() + index);
|
||||
}
|
||||
|
||||
void Spline::setKnot(uint32_t index, const Vec3 &knot) {
|
||||
CC_ASSERT(index < static_cast<uint32_t>(_knots.size()));
|
||||
|
||||
_knots[index] = knot;
|
||||
}
|
||||
|
||||
const Vec3 &Spline::getKnot(uint32_t index) const {
|
||||
CC_ASSERT(index < static_cast<uint32_t>(_knots.size()));
|
||||
|
||||
return _knots[index];
|
||||
}
|
||||
Vec3 &Spline::getKnot(uint32_t index) {
|
||||
CC_ASSERT(index < static_cast<uint32_t>(_knots.size()));
|
||||
|
||||
return _knots[index];
|
||||
}
|
||||
|
||||
Vec3 Spline::getPoint(float t, uint32_t index /*= SPLINE_WHOLE_INDEX*/) const {
|
||||
t = mathutils::clamp(t, 0.0F, 1.0F);
|
||||
|
||||
const auto segments = getSegments();
|
||||
if (segments == 0) {
|
||||
return Vec3(0.0F, 0.0F, 0.0F);
|
||||
}
|
||||
|
||||
if (index == SPLINE_WHOLE_INDEX) {
|
||||
const auto deltaT = 1.0F / static_cast<float>(segments);
|
||||
|
||||
index = static_cast<uint32_t>(t / deltaT);
|
||||
t = std::fmod(t, deltaT) / deltaT;
|
||||
}
|
||||
|
||||
if (index >= segments) {
|
||||
return _knots.back();
|
||||
}
|
||||
|
||||
switch (_mode) {
|
||||
case SplineMode::LINEAR:
|
||||
return calcLinear(_knots[index], _knots[index + 1], t);
|
||||
case SplineMode::BEZIER:
|
||||
return calcBezier(_knots[index * 4], _knots[index * 4 + 1], _knots[index * 4 + 2], _knots[index * 4 + 3], t);
|
||||
case SplineMode::CATMULL_ROM: {
|
||||
const auto v0 = index > 0 ? _knots[index - 1] : _knots[index];
|
||||
const auto v3 = index + 2 < static_cast<uint32_t>(_knots.size()) ? _knots[index + 2] : _knots[index + 1];
|
||||
return calcCatmullRom(v0, _knots[index], _knots[index + 1], v3, t);
|
||||
}
|
||||
default:
|
||||
return Vec3(0.0F, 0.0F, 0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
ccstd::vector<Vec3> Spline::getPoints(uint32_t num, uint32_t index /*= SPLINE_WHOLE_INDEX*/) const {
|
||||
if (num == 0U) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (num == 1U) {
|
||||
auto point = getPoint(0.0F, index);
|
||||
return {point};
|
||||
}
|
||||
|
||||
ccstd::vector<Vec3> points;
|
||||
const float deltaT = 1.0F / (static_cast<float>(num) - 1.0F);
|
||||
|
||||
for (auto i = 0; i < num; i++) {
|
||||
const auto t = static_cast<float>(i) * deltaT;
|
||||
const auto point = getPoint(t, index);
|
||||
|
||||
points.push_back(point);
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
uint32_t Spline::getSegments() const {
|
||||
const auto count = static_cast<uint32_t>(_knots.size());
|
||||
switch (_mode) {
|
||||
case SplineMode::LINEAR:
|
||||
case SplineMode::CATMULL_ROM:
|
||||
if (count < 2) {
|
||||
CC_LOG_WARNING("Spline error: less than 2 knots.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return count - 1;
|
||||
case SplineMode::BEZIER:
|
||||
if (count < 4 || count % 4 != 0) {
|
||||
CC_LOG_WARNING("Spline error: less than 4 knots or not a multiple of 4.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return count / 4;
|
||||
default:
|
||||
CC_ABORT();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 Spline::calcLinear(const Vec3 &v0, const Vec3 &v1, float t) {
|
||||
const auto result = v0 * (1.0F - t) + v1 * t;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec3 Spline::calcBezier(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, float t) {
|
||||
const auto s = 1.0F - t;
|
||||
const auto result = v0 * s * s * s +
|
||||
v1 * 3.0F * t * s * s +
|
||||
v2 * 3.0F * t * t * s +
|
||||
v3 * t * t * t;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Vec3 Spline::calcCatmullRom(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, float t) {
|
||||
const auto t2 = t * t;
|
||||
const auto t3 = t2 * t;
|
||||
const auto result = v0 * (-0.5F * t3 + t2 - 0.5F * t) +
|
||||
v1 * (1.5F * t3 - 2.5F * t2 + 1.0F) +
|
||||
v2 * (-1.5F * t3 + 2.0F * t2 + 0.5F * t) +
|
||||
v3 * (0.5F * t3 - 0.5F * t2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
115
cocos/core/geometry/Spline.h
Normal file
115
cocos/core/geometry/Spline.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/std/container/vector.h"
|
||||
#include "core/geometry/Enums.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
enum class SplineMode {
|
||||
/**
|
||||
* Broken line:
|
||||
* Each knot is connected with a straight line from the beginning to the end to form a curve. At least two knots.
|
||||
*/
|
||||
LINEAR = 0,
|
||||
|
||||
/**
|
||||
* Piecewise Bezier curve:
|
||||
* Every four knots form a curve. Total knots number must be a multiple of 4.
|
||||
* Each curve passes only the first and fourth knots, and does not pass through the middle two control knots.
|
||||
*
|
||||
* If you need a whole continuous curve:
|
||||
* (1) Suppose the four knots of the previous curve are A, B, C, D
|
||||
* (2) The four knots of the next curve must be D, E, F, G
|
||||
* (3) C and E need to be symmetrical about D
|
||||
*/
|
||||
BEZIER = 1,
|
||||
|
||||
/**
|
||||
* Catmull Rom curve:
|
||||
* All knots(including start & end knots) form a whole continuous curve. At least two knots.
|
||||
* The whole curve passes through all knots.
|
||||
*/
|
||||
CATMULL_ROM = 2
|
||||
};
|
||||
|
||||
constexpr uint32_t SPLINE_WHOLE_INDEX = 0xffffffff;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Basic Geometry: Spline.
|
||||
* @zh
|
||||
* 基础几何 Spline。
|
||||
*/
|
||||
|
||||
class Spline final : public ShapeBase {
|
||||
public:
|
||||
explicit Spline(SplineMode mode = SplineMode::CATMULL_ROM, ccstd::vector<Vec3> knots = {});
|
||||
|
||||
Spline(const Spline &) = default;
|
||||
Spline(Spline &&) = default;
|
||||
~Spline() override = default;
|
||||
Spline &operator=(const Spline &) = default;
|
||||
Spline &operator=(Spline &&) = default;
|
||||
|
||||
static Spline *create(SplineMode mode, const ccstd::vector<Vec3> &knots = {});
|
||||
static Spline *clone(const Spline &s);
|
||||
static Spline *copy(Spline *out, const Spline &s);
|
||||
|
||||
inline void setMode(SplineMode mode) { _mode = mode; }
|
||||
inline SplineMode getMode() const { return _mode; }
|
||||
inline void setKnots(const ccstd::vector<Vec3> &knots) { _knots = knots; }
|
||||
inline const ccstd::vector<Vec3> &getKnots() const { return _knots; }
|
||||
inline void clearKnots() { _knots.clear(); }
|
||||
inline uint32_t getKnotCount() const { return static_cast<uint32_t>(_knots.size()); }
|
||||
inline void addKnot(const Vec3 &knot) { _knots.push_back(knot); }
|
||||
void setModeAndKnots(SplineMode mode, const ccstd::vector<Vec3> &knots);
|
||||
void insertKnot(uint32_t index, const Vec3 &knot);
|
||||
void removeKnot(uint32_t index);
|
||||
void setKnot(uint32_t index, const Vec3 &knot);
|
||||
const Vec3 &getKnot(uint32_t index) const;
|
||||
Vec3 &getKnot(uint32_t index);
|
||||
|
||||
// get a point at t with repect to the `index` segment of curve or the whole curve.
|
||||
Vec3 getPoint(float t, uint32_t index = SPLINE_WHOLE_INDEX) const;
|
||||
|
||||
// get num points from 0 to 1 uniformly with repect to the `index` segment of curve or the whole curve
|
||||
ccstd::vector<Vec3> getPoints(uint32_t num, uint32_t index = SPLINE_WHOLE_INDEX) const;
|
||||
|
||||
private:
|
||||
uint32_t getSegments() const;
|
||||
static Vec3 calcLinear(const Vec3 &v0, const Vec3 &v1, float t);
|
||||
static Vec3 calcBezier(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, float t);
|
||||
static Vec3 calcCatmullRom(const Vec3 &v0, const Vec3 &v1, const Vec3 &v2, const Vec3 &v3, float t);
|
||||
|
||||
SplineMode _mode{SplineMode::CATMULL_ROM};
|
||||
ccstd::vector<Vec3> _knots; // control points of the curve.
|
||||
};
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
87
cocos/core/geometry/Triangle.cpp
Normal file
87
cocos/core/geometry/Triangle.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/geometry/Triangle.h"
|
||||
#include "base/memory/Memory.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
Triangle *Triangle::create(float ax, float ay, float az,
|
||||
float bx, float by, float bz,
|
||||
float cx, float cy, float cz) {
|
||||
return ccnew Triangle(ax, ay, az, bx, by, bz, cx, cy, cz);
|
||||
}
|
||||
|
||||
Triangle *Triangle::clone(const Triangle &t) {
|
||||
return ccnew Triangle(
|
||||
t.a.x, t.a.y, t.a.z,
|
||||
t.b.x, t.b.y, t.b.z,
|
||||
t.c.x, t.c.y, t.c.z);
|
||||
}
|
||||
|
||||
Triangle *Triangle::copy(Triangle *out, const Triangle &t) {
|
||||
out->a = t.a;
|
||||
out->b = t.b;
|
||||
out->c = t.c;
|
||||
return out;
|
||||
}
|
||||
|
||||
Triangle *Triangle::fromPoints(Triangle *out, const Vec3 &a,
|
||||
const Vec3 &b,
|
||||
const Vec3 &c) {
|
||||
out->a = a;
|
||||
out->b = b;
|
||||
out->c = c;
|
||||
return out;
|
||||
}
|
||||
|
||||
Triangle *Triangle::set(Triangle *out,
|
||||
float ax, float ay, float az,
|
||||
float bx, float by, float bz,
|
||||
float cx, float cy, float cz) {
|
||||
out->a.x = ax;
|
||||
out->a.y = ay;
|
||||
out->a.z = az;
|
||||
|
||||
out->b.x = bx;
|
||||
out->b.y = by;
|
||||
out->b.z = bz;
|
||||
|
||||
out->c.x = cx;
|
||||
out->c.y = cy;
|
||||
out->c.z = cz;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Triangle::Triangle(float ax, float ay, float az,
|
||||
float bx, float by, float bz,
|
||||
float cx, float cy, float cz) : ShapeBase(ShapeEnum::SHAPE_TRIANGLE) {
|
||||
a = {ax, ay, az};
|
||||
b = {bx, by, bz};
|
||||
c = {cx, cy, cz};
|
||||
}
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
175
cocos/core/geometry/Triangle.h
Normal file
175
cocos/core/geometry/Triangle.h
Normal file
@@ -0,0 +1,175 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
#include "core/geometry/Enums.h"
|
||||
|
||||
#include "math/Vec3.h"
|
||||
|
||||
namespace cc {
|
||||
namespace geometry {
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Basic Geometry: Triangle.
|
||||
* @zh
|
||||
* 基础几何 三角形。
|
||||
*/
|
||||
|
||||
class Triangle final : public ShapeBase {
|
||||
public:
|
||||
/**
|
||||
* @en
|
||||
* create a new triangle
|
||||
* @zh
|
||||
* 创建一个新的 triangle。
|
||||
* @param {number} ax a 点的 x 部分。
|
||||
* @param {number} ay a 点的 y 部分。
|
||||
* @param {number} az a 点的 z 部分。
|
||||
* @param {number} bx b 点的 x 部分。
|
||||
* @param {number} by b 点的 y 部分。
|
||||
* @param {number} bz b 点的 z 部分。
|
||||
* @param {number} cx c 点的 x 部分。
|
||||
* @param {number} cy c 点的 y 部分。
|
||||
* @param {number} cz c 点的 z 部分。
|
||||
* @return {Triangle} 一个新的 triangle。
|
||||
*/
|
||||
static Triangle *create(float ax = 1, float ay = 0, float az = 0,
|
||||
float bx = 0, float by = 0, float bz = 0,
|
||||
float cx = 0, float cy = 0, float cz = 1);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* clone a new triangle
|
||||
* @zh
|
||||
* 克隆一个新的 triangle。
|
||||
* @param {Triangle} t 克隆的目标。
|
||||
* @return {Triangle} 克隆出的新对象。
|
||||
*/
|
||||
|
||||
static Triangle *clone(const Triangle &t);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* copy the values from one triangle to another
|
||||
* @zh
|
||||
* 将一个 triangle 的值复制到另一个 triangle。
|
||||
* @param {Triangle} out 接受操作的 triangle。
|
||||
* @param {Triangle} t 被复制的 triangle。
|
||||
* @return {Triangle} out 接受操作的 triangle。
|
||||
*/
|
||||
|
||||
static Triangle *copy(Triangle *out, const Triangle &t);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Create a triangle from three points
|
||||
* @zh
|
||||
* 用三个点创建一个 triangle。
|
||||
* @param {Triangle} out 接受操作的 triangle。
|
||||
* @param {Vec3} a a 点。
|
||||
* @param {Vec3} b b 点。
|
||||
* @param {Vec3} c c 点。
|
||||
* @return {Triangle} out 接受操作的 triangle。
|
||||
*/
|
||||
static Triangle *fromPoints(Triangle *out, const Vec3 &a,
|
||||
const Vec3 &b,
|
||||
const Vec3 &c);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Set the components of a triangle to the given values
|
||||
* @zh
|
||||
* 将给定三角形的属性设置为给定值。
|
||||
* @param {Triangle} out 给定的三角形。
|
||||
* @param {number} ax a 点的 x 部分。
|
||||
* @param {number} ay a 点的 y 部分。
|
||||
* @param {number} az a 点的 z 部分。
|
||||
* @param {number} bx b 点的 x 部分。
|
||||
* @param {number} by b 点的 y 部分。
|
||||
* @param {number} bz b 点的 z 部分。
|
||||
* @param {number} cx c 点的 x 部分。
|
||||
* @param {number} cy c 点的 y 部分。
|
||||
* @param {number} cz c 点的 z 部分。
|
||||
* @return {Triangle}
|
||||
* @function
|
||||
*/
|
||||
static Triangle *set(Triangle *out,
|
||||
float ax, float ay, float az,
|
||||
float bx, float by, float bz,
|
||||
float cx, float cy, float cz);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Point a.
|
||||
* @zh
|
||||
* 点 a。
|
||||
*/
|
||||
|
||||
Vec3 a;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Point b.
|
||||
* @zh
|
||||
* 点 b。
|
||||
*/
|
||||
Vec3 b;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Point c.
|
||||
* @zh
|
||||
* 点 c。
|
||||
*/
|
||||
Vec3 c;
|
||||
/**
|
||||
* @en
|
||||
* Construct a triangle.
|
||||
* @zh
|
||||
* 构造一个三角形。
|
||||
* @param {number} ax a 点的 x 部分。
|
||||
* @param {number} ay a 点的 y 部分。
|
||||
* @param {number} az a 点的 z 部分。
|
||||
* @param {number} bx b 点的 x 部分。
|
||||
* @param {number} by b 点的 y 部分。
|
||||
* @param {number} bz b 点的 z 部分。
|
||||
* @param {number} cx c 点的 x 部分。
|
||||
* @param {number} cy c 点的 y 部分。
|
||||
* @param {number} cz c 点的 z 部分。
|
||||
*/
|
||||
explicit Triangle(float ax = 0, float ay = 0, float az = 0,
|
||||
float bx = 1, float by = 0, float bz = 0,
|
||||
float cx = 0, float cy = 1, float cz = 0);
|
||||
|
||||
Triangle(const Triangle &) = default;
|
||||
Triangle(Triangle &&) = default;
|
||||
~Triangle() override = default;
|
||||
Triangle &operator=(const Triangle &) = default;
|
||||
Triangle &operator=(Triangle &&) = default;
|
||||
|
||||
}; // namespace geometry
|
||||
|
||||
} // namespace geometry
|
||||
} // namespace cc
|
||||
166
cocos/core/memop/CachedArray.h
Normal file
166
cocos/core/memop/CachedArray.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
#include <climits>
|
||||
#include "base/Object.h"
|
||||
#include "base/TypeDef.h"
|
||||
#include "base/memory/Memory.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
template <typename T>
|
||||
class CachedArray final {
|
||||
public:
|
||||
explicit CachedArray(uint size = 1U) {
|
||||
_size = 0;
|
||||
_capacity = std::max(size, 1U);
|
||||
_array = ccnew T[_capacity];
|
||||
}
|
||||
|
||||
// The rule of five applies here
|
||||
~CachedArray() {
|
||||
CC_SAFE_DELETE_ARRAY(_array);
|
||||
}
|
||||
|
||||
CachedArray(const CachedArray &other)
|
||||
: _size(other._size), _capacity(other._capacity), _array(ccnew T[other._capacity]) {
|
||||
memcpy(_array, other._array, _size * sizeof(T));
|
||||
}
|
||||
|
||||
CachedArray &operator=(const CachedArray &other) {
|
||||
if (this != &other) {
|
||||
delete[] _array;
|
||||
_size = other._size;
|
||||
_capacity = other._capacity;
|
||||
_array = ccnew T[_capacity];
|
||||
memcpy(_array, other._array, _size * sizeof(T));
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
CachedArray(CachedArray &&other) noexcept : _size(other._size), _capacity(other._capacity), _array(other._array) {
|
||||
other._size = 0;
|
||||
other._capacity = 0;
|
||||
other._array = nullptr;
|
||||
}
|
||||
|
||||
CachedArray &operator=(CachedArray &&other) noexcept {
|
||||
if (this != &other) {
|
||||
delete[] _array;
|
||||
_size = other._size;
|
||||
_capacity = other._capacity;
|
||||
_array = other._array;
|
||||
other._size = 0;
|
||||
other._capacity = 0;
|
||||
other._array = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Subscription operators
|
||||
T &operator[](uint index) {
|
||||
return _array[index];
|
||||
}
|
||||
|
||||
const T &operator[](uint index) const {
|
||||
return _array[index];
|
||||
}
|
||||
|
||||
inline void clear() { _size = 0; }
|
||||
inline uint size() const { return _size; }
|
||||
inline T pop() { return _array[--_size]; }
|
||||
|
||||
void reserve(uint size) {
|
||||
if (size > _capacity) {
|
||||
T *temp = _array;
|
||||
_array = ccnew T[size];
|
||||
memcpy(_array, temp, _capacity * sizeof(T));
|
||||
_capacity = size;
|
||||
delete[] temp;
|
||||
}
|
||||
}
|
||||
|
||||
void push(T item) {
|
||||
if (_size >= _capacity) {
|
||||
T *temp = _array;
|
||||
_array = ccnew T[_capacity * 2];
|
||||
memcpy(_array, temp, _capacity * sizeof(T));
|
||||
_capacity *= 2;
|
||||
delete[] temp;
|
||||
}
|
||||
_array[_size++] = item;
|
||||
}
|
||||
|
||||
void concat(const CachedArray<T> &array) {
|
||||
if (_size + array._size > _capacity) {
|
||||
T *temp = _array;
|
||||
uint size = std::max(_capacity * 2, _size + array._size);
|
||||
_array = ccnew T[size];
|
||||
memcpy(_array, temp, _size * sizeof(T));
|
||||
_capacity = size;
|
||||
delete[] temp;
|
||||
}
|
||||
memcpy(_array + _size, array._array, array._size * sizeof(T));
|
||||
_size += array._size;
|
||||
}
|
||||
|
||||
void concat(T *array, uint count) {
|
||||
if (_size + count > _capacity) {
|
||||
T *temp = _array;
|
||||
uint size = std::max(_capacity * 2, _size + count);
|
||||
_array = ccnew T[size];
|
||||
memcpy(_array, temp, _size * sizeof(T));
|
||||
_capacity = size;
|
||||
delete[] temp;
|
||||
}
|
||||
memcpy(_array + _size, array, count * sizeof(T));
|
||||
_size += count;
|
||||
}
|
||||
|
||||
void fastRemove(uint idx) {
|
||||
if (idx >= _size) {
|
||||
return;
|
||||
}
|
||||
_array[idx] = _array[--_size];
|
||||
}
|
||||
|
||||
uint indexOf(T item) {
|
||||
for (uint i = 0; i < _size; ++i) {
|
||||
if (_array[i] == item) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return UINT_MAX;
|
||||
}
|
||||
|
||||
private:
|
||||
uint _size = 0;
|
||||
uint _capacity = 0;
|
||||
T *_array = nullptr;
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
133
cocos/core/memop/Pool.h
Normal file
133
cocos/core/memop/Pool.h
Normal file
@@ -0,0 +1,133 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include "base/TypeDef.h"
|
||||
#include "base/std/container/vector.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace memop {
|
||||
|
||||
template <typename T>
|
||||
class Pool final {
|
||||
public:
|
||||
using CtorFunc = std::function<T *()>;
|
||||
using DtorFunc = std::function<void(T *)>;
|
||||
/**
|
||||
* @en Constructor with the allocator of elements and initial pool size
|
||||
* @zh 使用元素的构造器和初始大小的构造函数
|
||||
* @param ctor The allocator of elements in pool, it's invoked directly without `new`
|
||||
* @param elementsPerBatch Initial pool size, this size will also be the incremental size when the pool is overloaded
|
||||
*/
|
||||
Pool(const CtorFunc &ctor, const DtorFunc &dtor, uint32_t elementsPerBatch)
|
||||
: _ctor(ctor),
|
||||
_dtor(dtor),
|
||||
_elementsPerBatch(std::max(elementsPerBatch, static_cast<uint32_t>(1))) {
|
||||
CC_ASSERT(_ctor);
|
||||
CC_ASSERT(_dtor);
|
||||
_nextAvail = static_cast<index_t>(_elementsPerBatch - 1);
|
||||
|
||||
for (uint32_t i = 0; i < _elementsPerBatch; ++i) {
|
||||
_freepool.push_back(ctor());
|
||||
}
|
||||
}
|
||||
|
||||
Pool(const Pool &) = delete;
|
||||
Pool(Pool &&) = delete;
|
||||
~Pool() = default;
|
||||
Pool &operator=(const Pool &) = delete;
|
||||
Pool &operator=(Pool &&) = delete;
|
||||
|
||||
/**
|
||||
* @en Take an object out of the object pool.
|
||||
* @zh 从对象池中取出一个对象。
|
||||
* @return An object ready for use. This function always return an object.
|
||||
*/
|
||||
T *alloc() {
|
||||
if (_nextAvail < 0) {
|
||||
_freepool.resize(_elementsPerBatch);
|
||||
for (uint32_t i = 0; i < _elementsPerBatch; ++i) {
|
||||
_freepool[i] = _ctor();
|
||||
}
|
||||
_nextAvail = static_cast<index_t>(_elementsPerBatch - 1);
|
||||
}
|
||||
|
||||
return _freepool[_nextAvail--];
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Put an object back into the object pool.
|
||||
* @zh 将一个对象放回对象池中。
|
||||
* @param obj The object to be put back into the pool
|
||||
*/
|
||||
void free(T *obj) {
|
||||
++_nextAvail;
|
||||
if (_nextAvail >= _freepool.size()) {
|
||||
_freepool.resize(_freepool.size() + 1);
|
||||
}
|
||||
_freepool[_nextAvail] = obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Put multiple objects back into the object pool.
|
||||
* @zh 将一组对象放回对象池中。
|
||||
* @param objs An array of objects to be put back into the pool
|
||||
*/
|
||||
void freeArray(const ccstd::vector<T *> &objs) {
|
||||
_freepool.reserve(_nextAvail + 1 + objs.size());
|
||||
_freepool.insert(_freepool.begin() + _nextAvail + 1,
|
||||
objs.begin(), objs.end());
|
||||
_nextAvail += static_cast<index_t>(objs.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @en Destroy all elements and clear the pool.
|
||||
* @zh 释放对象池中所有资源并清空缓存池。
|
||||
* @param dtor The destructor function, it will be invoked for all elements in the pool
|
||||
*/
|
||||
void destroy() {
|
||||
for (int i = 0; i <= _nextAvail; ++i) {
|
||||
_dtor(_freepool[i]);
|
||||
}
|
||||
_nextAvail = -1;
|
||||
_freepool.clear();
|
||||
_freepool.shrink_to_fit();
|
||||
}
|
||||
|
||||
private:
|
||||
CtorFunc _ctor{nullptr};
|
||||
DtorFunc _dtor{nullptr};
|
||||
uint32_t _elementsPerBatch{0};
|
||||
index_t _nextAvail{-1};
|
||||
ccstd::vector<T *> _freepool;
|
||||
};
|
||||
|
||||
} // namespace memop
|
||||
|
||||
} // namespace cc
|
||||
105
cocos/core/memop/RecyclePool.h
Normal file
105
cocos/core/memop/RecyclePool.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include "base/std/container/vector.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
/**
|
||||
* @en Recyclable object pool. It's designed to be entirely reused each time.
|
||||
* There is no put and get method, each time you get the [[data]], you can use all elements as new.
|
||||
* You shouldn't simultaneously use the same RecyclePool in more than two overlapped logic.
|
||||
* Its size can be automatically incremented or manually resized.
|
||||
* @zh 循环对象池。这种池子被设计为每次使用都完整复用。
|
||||
* 它没有回收和提取的函数,通过获取 [[data]] 可以获取池子中所有元素,全部都应该被当做新对象来使用。
|
||||
* 开发者不应该在相互交叉的不同逻辑中同时使用同一个循环对象池。
|
||||
* 池子尺寸可以在池子满时自动扩充,也可以手动调整。
|
||||
* @see [[Pool]]
|
||||
*/
|
||||
template <typename T>
|
||||
class RecyclePool final {
|
||||
public:
|
||||
/**
|
||||
* @en Constructor with the allocator of elements and initial pool size, all elements will be pre-allocated.
|
||||
* @zh 使用元素的构造器和初始大小的构造函数,所有元素都会被预创建。
|
||||
* @param fn The allocator of elements in pool, it's invoked directly without `new`
|
||||
* @param size Initial pool size
|
||||
*/
|
||||
RecyclePool(const std::function<T *()> &fn, uint32_t size);
|
||||
|
||||
RecyclePool(const RecyclePool &) = delete;
|
||||
RecyclePool(RecyclePool &&) = delete;
|
||||
~RecyclePool() = default;
|
||||
RecyclePool &operator=(const RecyclePool &) = delete;
|
||||
RecyclePool &operator=(RecyclePool &&) = delete;
|
||||
|
||||
/**
|
||||
* @en The length of the object pool.
|
||||
* @zh 对象池大小。
|
||||
*/
|
||||
inline uint32_t getLength() const { return _count; }
|
||||
|
||||
/**
|
||||
* @en The underlying array of all pool elements.
|
||||
* @zh 实际对象池数组。
|
||||
*/
|
||||
inline const ccstd::vector<T *> &getData() const { return _data; }
|
||||
|
||||
/**
|
||||
* @en Resets the object pool. Only changes the length to 0
|
||||
* @zh 清空对象池。目前仅仅会设置尺寸为 0
|
||||
*/
|
||||
inline void reset() { _count = 0; }
|
||||
|
||||
/**
|
||||
* @en Resize the object poo, and fills with new created elements.
|
||||
* @zh 设置对象池大小,并填充新的元素。
|
||||
* @param size The new size of the pool
|
||||
*/
|
||||
void resize(uint32_t size);
|
||||
|
||||
/**
|
||||
* @en Expand the object pool, the size will be increment to current size times two, and fills with new created elements.
|
||||
* @zh 扩充对象池容量,会自动扩充尺寸到两倍,并填充新的元素。
|
||||
* @param idx
|
||||
*/
|
||||
void add();
|
||||
|
||||
/**
|
||||
* @en Remove an element of the object pool. This will also decrease size of the pool
|
||||
* @zh 移除对象池中的一个元素,同时会减小池子尺寸。
|
||||
* @param idx The index of the element to be removed
|
||||
*/
|
||||
void removeAt(uint32_t idx);
|
||||
|
||||
private:
|
||||
uint32_t _count{0};
|
||||
ccstd::vector<T *> _data;
|
||||
};
|
||||
|
||||
} // namespace cc
|
||||
145
cocos/core/platform/Debug.cpp
Normal file
145
cocos/core/platform/Debug.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http =//www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "Debug.h"
|
||||
|
||||
namespace cc {
|
||||
namespace debug {
|
||||
const ccstd::string CONSOLE_LOG = "log";
|
||||
const ccstd::string CONSOLE_WARN = "warn";
|
||||
const ccstd::string CONSOLE_ERROR = "error";
|
||||
const ccstd::string CONSOLE_ASSET = "assert";
|
||||
|
||||
const ccstd::string &getPrefixTag(DebugMode mode) {
|
||||
switch (mode) {
|
||||
case DebugMode::VERBOSE:
|
||||
return CONSOLE_LOG;
|
||||
case DebugMode::WARN:
|
||||
return CONSOLE_WARN;
|
||||
case DebugMode::ERROR_MODE:
|
||||
return CONSOLE_ERROR;
|
||||
default:
|
||||
return CONSOLE_ASSET;
|
||||
}
|
||||
}
|
||||
|
||||
LogLevel getLogLevel(DebugMode mode) {
|
||||
switch (mode) {
|
||||
case DebugMode::VERBOSE:
|
||||
return LogLevel::LEVEL_DEBUG;
|
||||
case DebugMode::WARN:
|
||||
return LogLevel::WARN;
|
||||
case DebugMode::ERROR_MODE:
|
||||
return LogLevel::ERR;
|
||||
default:
|
||||
return LogLevel::FATAL;
|
||||
}
|
||||
}
|
||||
|
||||
ccstd::string getTypedFormatter(DebugMode mode, uint32_t id) {
|
||||
const ccstd::string &tag = getPrefixTag(mode);
|
||||
ccstd::string msg;
|
||||
#if CC_DEBUG > 0
|
||||
if (debugInfos.find(id) == debugInfos.end()) {
|
||||
msg = "unknown id";
|
||||
} else {
|
||||
msg = debugInfos[id];
|
||||
}
|
||||
#else
|
||||
char szTmp[1024] = {0};
|
||||
snprintf(szTmp, sizeof(szTmp), "%s %d, please go to %s#%d to see details.", tag.c_str(), id, ERROR_MAP_URL.c_str(), id);
|
||||
msg = szTmp;
|
||||
#endif
|
||||
|
||||
return msg;
|
||||
}
|
||||
|
||||
void printLog(DebugMode mode, const ccstd::string &fmt, ccstd::any *arr, int paramsLength) {
|
||||
ccstd::string msg = fmt;
|
||||
const ccstd::string &prefix = getPrefixTag(mode);
|
||||
LogLevel logLevel = getLogLevel(mode);
|
||||
|
||||
size_t pos;
|
||||
for (int i = 1; i <= paramsLength; i++) {
|
||||
pos = msg.find('%');
|
||||
bool needToReplace = false;
|
||||
if (pos != ccstd::string::npos && pos != (msg.length() - 1) && (msg[pos + 1] == 'd' || msg[pos + 1] == 's' || msg[pos + 1] == 'f')) {
|
||||
needToReplace = true;
|
||||
}
|
||||
const auto &elemTypeId = arr[i].type();
|
||||
if (elemTypeId == typeid(const ccstd::string)) {
|
||||
const auto s = ccstd::any_cast<const ccstd::string>(arr[i]);
|
||||
if (needToReplace) {
|
||||
msg.replace(pos, 2, s);
|
||||
} else {
|
||||
msg += " " + s;
|
||||
}
|
||||
} else if (elemTypeId == typeid(ccstd::string)) {
|
||||
auto s = ccstd::any_cast<ccstd::string>(arr[i]);
|
||||
if (needToReplace) {
|
||||
msg.replace(pos, 2, s);
|
||||
} else {
|
||||
msg += " " + s;
|
||||
}
|
||||
} else if (elemTypeId == typeid(int)) {
|
||||
int value = ccstd::any_cast<int>(arr[i]);
|
||||
if (needToReplace) {
|
||||
msg.replace(pos, 2, std::to_string(value));
|
||||
} else {
|
||||
msg += " " + std::to_string(value);
|
||||
}
|
||||
} else if (elemTypeId == typeid(unsigned int)) {
|
||||
auto value = ccstd::any_cast<unsigned int>(arr[i]);
|
||||
if (needToReplace) {
|
||||
msg.replace(pos, 2, std::to_string(value));
|
||||
} else {
|
||||
msg += " " + std::to_string(value);
|
||||
}
|
||||
|
||||
} else if (elemTypeId == typeid(float)) {
|
||||
auto value = ccstd::any_cast<float>(arr[i]);
|
||||
if (needToReplace) {
|
||||
msg.replace(pos, 2, std::to_string(value));
|
||||
} else {
|
||||
msg += " " + std::to_string(value);
|
||||
}
|
||||
} else if (elemTypeId == typeid(const char *)) {
|
||||
ccstd::string s = ccstd::any_cast<const char *>(arr[i]);
|
||||
if (needToReplace) {
|
||||
msg.replace(pos, 2, s);
|
||||
} else {
|
||||
msg += " " + s;
|
||||
}
|
||||
} else {
|
||||
CC_LOG_ERROR("DebugInfos: unsupport params data type: '%s'", elemTypeId.name());
|
||||
CC_LOG_ERROR(" fmt: \"%s\", parameter index: %d", fmt.c_str(), i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cc::Log::logMessage(cc::LogType::KERNEL, logLevel, "%s %s", prefix.c_str(), msg.c_str());
|
||||
}
|
||||
|
||||
} // namespace debug
|
||||
} // namespace cc
|
||||
226
cocos/core/platform/Debug.h
Normal file
226
cocos/core/platform/Debug.h
Normal file
@@ -0,0 +1,226 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http =//www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Log.h"
|
||||
#include "base/std/any.h"
|
||||
#include "base/std/container/string.h"
|
||||
#include "core/builtin/DebugInfos.h"
|
||||
|
||||
namespace cc {
|
||||
namespace debug {
|
||||
|
||||
const ccstd::string ERROR_MAP_URL{"https://github.com/cocos-creator/engine/blob/3d/EngineErrorMap.md"};
|
||||
|
||||
enum class DebugMode {
|
||||
|
||||
/**
|
||||
* @en The debug mode none.
|
||||
* @zh 禁止模式,禁止显示任何日志消息。
|
||||
*/
|
||||
NONE = 0,
|
||||
|
||||
/**
|
||||
* @en The debug mode none.
|
||||
* @zh 调试模式,显示所有日志消息。
|
||||
*/
|
||||
VERBOSE = 1,
|
||||
|
||||
/**
|
||||
* @en Information mode, which display messages with level higher than "information" level.
|
||||
* @zh 信息模式,显示“信息”级别以上的日志消息。
|
||||
*/
|
||||
INFO = 2,
|
||||
|
||||
/**
|
||||
* @en Information mode, which display messages with level higher than "warning" level.
|
||||
* @zh 警告模式,显示“警告”级别以上的日志消息。
|
||||
*/
|
||||
WARN = 3,
|
||||
|
||||
/**
|
||||
* @en Information mode, which display only messages with "error" level.
|
||||
* @zh 错误模式,仅显示“错误”级别的日志消息。
|
||||
*/
|
||||
ERROR_MODE = 4, // ERROR has been defined by MACRO
|
||||
|
||||
/**
|
||||
* @en The debug mode info for web page.
|
||||
* @zh 信息模式(仅 WEB 端有效),在画面上输出所有信息。
|
||||
*/
|
||||
INFO_FOR_WEB_PAGE = 5,
|
||||
|
||||
/**
|
||||
* @en The debug mode warn for web page.
|
||||
* @zh 警告模式(仅 WEB 端有效),在画面上输出 warn 级别以上的(包含 error)信息。
|
||||
*/
|
||||
WARN_FOR_WEB_PAGE = 6,
|
||||
|
||||
/**
|
||||
* @en The debug mode error for web page.
|
||||
* @zh 错误模式(仅 WEB 端有效),在画面上输出 error 信息。
|
||||
*/
|
||||
ERROR_FOR_WEB_PAGE = 7,
|
||||
};
|
||||
|
||||
/**
|
||||
* @en Outputs a message to the Cocos Creator Console (editor) or Web Console (runtime).
|
||||
* @zh 输出一条消息到 Cocos Creator 编辑器的 Console 或运行时 Web 端的 Console 中。
|
||||
* @param message - A JavaScript string containing zero or more substitution strings.
|
||||
* @param optionalParams - JavaScript objects with which to replace substitution strings within msg.
|
||||
* This gives you additional control over the format of the output.
|
||||
*/
|
||||
|
||||
template <typename... Args>
|
||||
void log(ccstd::any message, Args... optionalParams);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Outputs a warning message to the Cocos Creator Console (editor) or Web Console (runtime).
|
||||
* - In Cocos Creator, warning is yellow.
|
||||
* - In Chrome, warning have a yellow warning icon with the message text.
|
||||
* @zh
|
||||
* 输出警告消息到 Cocos Creator 编辑器的 Console 或运行时 Web 端的 Console 中。<br/>
|
||||
* - 在 Cocos Creator 中,警告信息显示是黄色的。<br/>
|
||||
* - 在 Chrome 中,警告信息有着黄色的图标以及黄色的消息文本。<br/>
|
||||
* @param message - A JavaScript string containing zero or more substitution strings.
|
||||
* @param optionalParams - JavaScript objects with which to replace substitution strings within msg.
|
||||
* This gives you additional control over the format of the output.
|
||||
*/
|
||||
template <typename... Args>
|
||||
void warn(ccstd::any message, Args... optionalParams);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Outputs an error message to the Cocos Creator Console (editor) or Web Console (runtime).<br/>
|
||||
* - In Cocos Creator, error is red.<br/>
|
||||
* - In Chrome, error have a red icon along with red message text.<br/>
|
||||
* @zh
|
||||
* 输出错误消息到 Cocos Creator 编辑器的 Console 或运行时页面端的 Console 中。<br/>
|
||||
* - 在 Cocos Creator 中,错误信息显示是红色的。<br/>
|
||||
* - 在 Chrome 中,错误信息有红色的图标以及红色的消息文本。<br/>
|
||||
* @param message - A JavaScript string containing zero or more substitution strings.
|
||||
* @param optionalParams - JavaScript objects with which to replace substitution strings within msg.
|
||||
* This gives you additional control over the format of the output.
|
||||
*/
|
||||
template <typename... Args>
|
||||
void error(ccstd::any message, Args... optionalParams);
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Assert the condition and output error messages if the condition is not true.
|
||||
* @zh
|
||||
* 对检查测试条件进行检查,如果条件不为 true 则输出错误消息
|
||||
* @param value - The condition to check on
|
||||
* @param message - A JavaScript string containing zero or more substitution strings.
|
||||
* @param optionalParams - JavaScript objects with which to replace substitution strings within msg.
|
||||
* This gives you additional control over the format of the output.
|
||||
*/
|
||||
|
||||
template <typename... Args>
|
||||
void _assert(ccstd::any value, ccstd::string message, Args... optionalParams); // NOLINT //assert is a reserved word
|
||||
|
||||
/**
|
||||
* @en Outputs a message at the "debug" log level.
|
||||
* @zh 输出一条“调试”日志等级的消息。
|
||||
*/
|
||||
template <typename... Args>
|
||||
void debug(Args... data);
|
||||
|
||||
void resetDebugSetting(DebugMode mode);
|
||||
|
||||
/**
|
||||
* @en Gets error message with the error id and possible parameters.
|
||||
* @zh 通过 error id 和必要的参数来获取错误信息。
|
||||
*/
|
||||
template <typename... Args>
|
||||
ccstd::string getError(uint32_t errorId, Args... param);
|
||||
|
||||
/**
|
||||
* @en Returns whether or not to display the FPS and debug information.
|
||||
* @zh 是否显示 FPS 信息和部分调试信息。
|
||||
*/
|
||||
bool isDisplayStats();
|
||||
|
||||
/**
|
||||
* @en Sets whether display the FPS and debug informations on the bottom-left corner.
|
||||
* @zh 设置是否在左下角显示 FPS 和部分调试。
|
||||
*/
|
||||
|
||||
void setDisplayStats(bool displayStats);
|
||||
|
||||
ccstd::string getTypedFormatter(DebugMode mode, uint32_t id);
|
||||
|
||||
const ccstd::string &getPrefixTag(DebugMode mode);
|
||||
|
||||
LogLevel getLogLevel(DebugMode mode);
|
||||
|
||||
template <typename T>
|
||||
T unpackParams(T value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
void printLog(DebugMode mode, const ccstd::string &fmt, ccstd::any *arr, int paramsLength);
|
||||
|
||||
template <typename... Args>
|
||||
void logID(uint32_t id, Args... optionalParams) {
|
||||
ccstd::string msg = getTypedFormatter(DebugMode::VERBOSE, id);
|
||||
int size = sizeof...(optionalParams);
|
||||
ccstd::any arr[] = {0, unpackParams(optionalParams)...};
|
||||
printLog(DebugMode::VERBOSE, msg, arr, size);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void warnID(uint32_t id, Args... optionalParams) {
|
||||
ccstd::string msg = getTypedFormatter(DebugMode::WARN, id);
|
||||
int size = sizeof...(optionalParams);
|
||||
ccstd::any arr[] = {0, unpackParams(optionalParams)...};
|
||||
printLog(DebugMode::WARN, msg, arr, size);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void errorID(uint32_t id, Args... optionalParams) {
|
||||
ccstd::string msg = getTypedFormatter(DebugMode::ERROR_MODE, id);
|
||||
int size = sizeof...(optionalParams);
|
||||
ccstd::any arr[] = {0, unpackParams(optionalParams)...};
|
||||
printLog(DebugMode::ERROR_MODE, msg, arr, size);
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
void assertID(bool condition, uint32_t id, Args... optionalParams) {
|
||||
if (condition) {
|
||||
return;
|
||||
}
|
||||
ccstd::string msg = getTypedFormatter(DebugMode::INFO, id);
|
||||
int size = sizeof...(optionalParams);
|
||||
ccstd::any arr[] = {0, unpackParams(optionalParams)...};
|
||||
printLog(DebugMode::INFO, msg, arr, size);
|
||||
CC_ABORT();
|
||||
}
|
||||
|
||||
void _throw(); // NOLINT // throw is a reserved word
|
||||
} // namespace debug
|
||||
|
||||
} // namespace cc
|
||||
34
cocos/core/platform/Macro.cpp
Normal file
34
cocos/core/platform/Macro.cpp
Normal file
@@ -0,0 +1,34 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http =//www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#include "core/platform/Macro.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
namespace macro {
|
||||
const ccstd::vector<ccstd::string> SUPPORT_TEXTURE_FORMATS = {
|
||||
".astc", ".pkm", ".pvr", ".webp", ".jpg", ".jpeg", ".bmp", ".png"};
|
||||
|
||||
}
|
||||
} // namespace cc
|
||||
898
cocos/core/platform/Macro.h
Normal file
898
cocos/core/platform/Macro.h
Normal file
@@ -0,0 +1,898 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/std/container/string.h"
|
||||
#include "base/std/container/vector.h"
|
||||
#include "math/Math.h"
|
||||
|
||||
namespace cc {
|
||||
namespace macro {
|
||||
/**
|
||||
* @en
|
||||
* The image format supported by the engine defaults, and the supported formats may differ in different build platforms and device types.
|
||||
* Currently all platform and device support ['.webp', '.jpg', '.jpeg', '.bmp', '.png'], ios mobile platform
|
||||
* @zh
|
||||
* 引擎默认支持的图片格式,支持的格式可能在不同的构建平台和设备类型上有所差别。
|
||||
* 目前所有平台和设备支持的格式有 ['.webp', '.jpg', '.jpeg', '.bmp', '.png']. The iOS mobile platform also supports the PVR format。
|
||||
*/
|
||||
extern const ccstd::vector<ccstd::string> SUPPORT_TEXTURE_FORMATS;
|
||||
/**
|
||||
* @en Key map for keyboard event
|
||||
* @zh 键盘事件的按键值。
|
||||
* @example {@link cocos/core/platform/CCCommon/KEY.js}
|
||||
* @deprecated since v3.3 please use KeyCode instead
|
||||
*/
|
||||
enum class KEY {
|
||||
/**
|
||||
* @en None
|
||||
* @zh 没有分配
|
||||
* @readonly
|
||||
*/
|
||||
NONE = 0,
|
||||
|
||||
// android
|
||||
/**
|
||||
* @en The back key on mobile phone
|
||||
* @zh 移动端返回键
|
||||
* @readonly
|
||||
* @deprecated since v3.3
|
||||
*/
|
||||
BACK = 6,
|
||||
/**
|
||||
* @en The menu key on mobile phone
|
||||
* @zh 移动端菜单键
|
||||
* @readonly
|
||||
* @deprecated since v3.3
|
||||
*/
|
||||
MENU = 18,
|
||||
|
||||
/**
|
||||
* @en The backspace key
|
||||
* @zh 退格键
|
||||
* @readonly
|
||||
*/
|
||||
BACKSPACE = 8,
|
||||
|
||||
/**
|
||||
* @en The tab key
|
||||
* @zh Tab 键
|
||||
* @readonly
|
||||
*/
|
||||
TAB = 9,
|
||||
|
||||
/**
|
||||
* @en The enter key
|
||||
* @zh 回车键
|
||||
* @readonly
|
||||
*/
|
||||
ENTER = 13,
|
||||
|
||||
/**
|
||||
* @en The shift key
|
||||
* @zh Shift 键
|
||||
* @readonly
|
||||
* @deprecated since v3.3, please use KeyCode.SHIFT_LEFT instead.
|
||||
*/
|
||||
SHIFT = 16, // should use shiftkey instead
|
||||
|
||||
/**
|
||||
* @en The ctrl key
|
||||
* @zh Ctrl 键
|
||||
* @readonly
|
||||
* @deprecated since v3.3, please use KeyCode.CTRL_LEFT instead.
|
||||
*/
|
||||
CTRL = 17, // should use ctrlkey
|
||||
|
||||
/**
|
||||
* @en The alt key
|
||||
* @zh Alt 键
|
||||
* @readonly
|
||||
* @deprecated since v3.3, please use KeyCode.ALT_LEFT instead.
|
||||
*/
|
||||
ALT = 18, // should use altkey
|
||||
|
||||
/**
|
||||
* @en The pause key
|
||||
* @zh 暂停键
|
||||
* @readonly
|
||||
*/
|
||||
PAUSE = 19,
|
||||
|
||||
/**
|
||||
* @en The caps lock key
|
||||
* @zh 大写锁定键
|
||||
* @readonly
|
||||
*/
|
||||
CAPSLOCK = 20,
|
||||
|
||||
/**
|
||||
* @en The esc key
|
||||
* @zh ESC 键
|
||||
* @readonly
|
||||
*/
|
||||
ESCAPE = 27,
|
||||
|
||||
/**
|
||||
* @en The space key
|
||||
* @zh 空格键
|
||||
* @readonly
|
||||
*/
|
||||
SPACE = 32,
|
||||
|
||||
/**
|
||||
* @en The page up key
|
||||
* @zh 向上翻页键
|
||||
* @readonly
|
||||
*/
|
||||
PAGEUP = 33,
|
||||
|
||||
/**
|
||||
* @en The page down key
|
||||
* @zh 向下翻页键
|
||||
* @readonly
|
||||
*/
|
||||
PAGEDOWN = 34,
|
||||
|
||||
/**
|
||||
* @en The end key
|
||||
* @zh 结束键
|
||||
* @readonly
|
||||
*/
|
||||
END = 35,
|
||||
|
||||
/**
|
||||
* @en The home key
|
||||
* @zh 主菜单键
|
||||
* @readonly
|
||||
*/
|
||||
HOME = 36,
|
||||
|
||||
/**
|
||||
* @en The left key
|
||||
* @zh 向左箭头键
|
||||
* @readonly
|
||||
*/
|
||||
LEFT = 37,
|
||||
|
||||
/**
|
||||
* @en The up key
|
||||
* @zh 向上箭头键
|
||||
* @readonly
|
||||
*/
|
||||
UP = 38,
|
||||
|
||||
/**
|
||||
* @en The right key
|
||||
* @zh 向右箭头键
|
||||
* @readonly
|
||||
*/
|
||||
RIGHT = 39,
|
||||
|
||||
/**
|
||||
* @en The down key
|
||||
* @zh 向下箭头键
|
||||
* @readonly
|
||||
*/
|
||||
DOWN = 40,
|
||||
|
||||
/**
|
||||
* @en The select key
|
||||
* @zh Select 键
|
||||
* @readonly
|
||||
* @deprecated since v3.3
|
||||
*/
|
||||
SELECT = 41,
|
||||
|
||||
/**
|
||||
* @en The insert key
|
||||
* @zh 插入键
|
||||
* @readonly
|
||||
*/
|
||||
INSERT = 45,
|
||||
|
||||
/**
|
||||
* @en The Delete key
|
||||
* @zh 删除键
|
||||
* @readonly
|
||||
* DELETE may be used as platform's macro, such as winnt.h,thus use DELETE_ instead here.
|
||||
*/
|
||||
DELETE_ = 46, // NOLINT(readability-identifier-naming)
|
||||
|
||||
/**
|
||||
* @en The a key
|
||||
* @zh A 键
|
||||
* @readonly
|
||||
*/
|
||||
A = 65,
|
||||
|
||||
/**
|
||||
* @en The b key
|
||||
* @zh B 键
|
||||
* @readonly
|
||||
*/
|
||||
B = 66,
|
||||
|
||||
/**
|
||||
* @en The c key
|
||||
* @zh C 键
|
||||
* @readonly
|
||||
*/
|
||||
C = 67,
|
||||
|
||||
/**
|
||||
* @en The d key
|
||||
* @zh D 键
|
||||
* @readonly
|
||||
*/
|
||||
D = 68,
|
||||
|
||||
/**
|
||||
* @en The e key
|
||||
* @zh E 键
|
||||
* @readonly
|
||||
*/
|
||||
E = 69,
|
||||
|
||||
/**
|
||||
* @en The f key
|
||||
* @zh F 键
|
||||
* @readonly
|
||||
*/
|
||||
F = 70,
|
||||
|
||||
/**
|
||||
* @en The g key
|
||||
* @zh G 键
|
||||
* @readonly
|
||||
*/
|
||||
G = 71,
|
||||
|
||||
/**
|
||||
* @en The h key
|
||||
* @zh H 键
|
||||
* @readonly
|
||||
*/
|
||||
H = 72,
|
||||
|
||||
/**
|
||||
* @en The i key
|
||||
* @zh I 键
|
||||
* @readonly
|
||||
*/
|
||||
I = 73,
|
||||
|
||||
/**
|
||||
* @en The j key
|
||||
* @zh J 键
|
||||
* @readonly
|
||||
*/
|
||||
J = 74,
|
||||
|
||||
/**
|
||||
* @en The k key
|
||||
* @zh K 键
|
||||
* @readonly
|
||||
*/
|
||||
K = 75,
|
||||
|
||||
/**
|
||||
* @en The l key
|
||||
* @zh L 键
|
||||
* @readonly
|
||||
*/
|
||||
L = 76,
|
||||
|
||||
/**
|
||||
* @en The m key
|
||||
* @zh M 键
|
||||
* @readonly
|
||||
*/
|
||||
M = 77,
|
||||
|
||||
/**
|
||||
* @en The n key
|
||||
* @zh N 键
|
||||
* @readonly
|
||||
*/
|
||||
N = 78,
|
||||
|
||||
/**
|
||||
* @en The o key
|
||||
* @zh O 键
|
||||
* @readonly
|
||||
*/
|
||||
O = 79,
|
||||
|
||||
/**
|
||||
* @en The p key
|
||||
* @zh P 键
|
||||
* @readonly
|
||||
*/
|
||||
P = 80,
|
||||
|
||||
/**
|
||||
* @en The q key
|
||||
* @zh Q 键
|
||||
* @readonly
|
||||
*/
|
||||
Q = 81,
|
||||
|
||||
/**
|
||||
* @en The r key
|
||||
* @zh R 键
|
||||
* @readonly
|
||||
*/
|
||||
R = 82,
|
||||
|
||||
/**
|
||||
* @en The s key
|
||||
* @zh S 键
|
||||
* @readonly
|
||||
*/
|
||||
S = 83,
|
||||
|
||||
/**
|
||||
* @en The t key
|
||||
* @zh T 键
|
||||
* @readonly
|
||||
*/
|
||||
T = 84,
|
||||
|
||||
/**
|
||||
* @en The u key
|
||||
* @zh U 键
|
||||
* @readonly
|
||||
*/
|
||||
U = 85,
|
||||
|
||||
/**
|
||||
* @en The v key
|
||||
* @zh V 键
|
||||
* @readonly
|
||||
*/
|
||||
V = 86,
|
||||
|
||||
/**
|
||||
* @en The w key
|
||||
* @zh W 键
|
||||
* @readonly
|
||||
*/
|
||||
W = 87,
|
||||
|
||||
/**
|
||||
* @en The x key
|
||||
* @zh X 键
|
||||
* @readonly
|
||||
*/
|
||||
X = 88,
|
||||
|
||||
/**
|
||||
* @en The y key
|
||||
* @zh Y 键
|
||||
* @readonly
|
||||
*/
|
||||
Y = 89,
|
||||
|
||||
/**
|
||||
* @en The z key
|
||||
* @zh Z 键
|
||||
* @readonly
|
||||
*/
|
||||
Z = 90,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 0
|
||||
* @zh 数字键盘 0
|
||||
* @readonly
|
||||
*/
|
||||
NUM0 = 96,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 1
|
||||
* @zh 数字键盘 1
|
||||
* @readonly
|
||||
*/
|
||||
NUM1 = 97,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 2
|
||||
* @zh 数字键盘 2
|
||||
* @readonly
|
||||
*/
|
||||
NUM2 = 98,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 3
|
||||
* @zh 数字键盘 3
|
||||
* @readonly
|
||||
*/
|
||||
NUM3 = 99,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 4
|
||||
* @zh 数字键盘 4
|
||||
* @readonly
|
||||
*/
|
||||
NUM4 = 100,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 5
|
||||
* @zh 数字键盘 5
|
||||
* @readonly
|
||||
*/
|
||||
NUM5 = 101,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 6
|
||||
* @zh 数字键盘 6
|
||||
* @readonly
|
||||
*/
|
||||
NUM6 = 102,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 7
|
||||
* @zh 数字键盘 7
|
||||
* @readonly
|
||||
*/
|
||||
NUM7 = 103,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 8
|
||||
* @zh 数字键盘 8
|
||||
* @readonly
|
||||
*/
|
||||
NUM8 = 104,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 9
|
||||
* @zh 数字键盘 9
|
||||
* @readonly
|
||||
*/
|
||||
NUM9 = 105,
|
||||
|
||||
/**
|
||||
* @en The numeric keypad 'delete'
|
||||
* @zh 数字键盘删除键
|
||||
* @readonly
|
||||
*/
|
||||
NUMDEL = 110,
|
||||
|
||||
/**
|
||||
* @en The F1 function key
|
||||
* @zh F1 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F1 = 112, // f1-f12 dont work on ie
|
||||
|
||||
/**
|
||||
* @en The F2 function key
|
||||
* @zh F2 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F2 = 113,
|
||||
|
||||
/**
|
||||
* @en The F3 function key
|
||||
* @zh F3 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F3 = 114,
|
||||
|
||||
/**
|
||||
* @en The F4 function key
|
||||
* @zh F4 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F4 = 115,
|
||||
|
||||
/**
|
||||
* @en The F5 function key
|
||||
* @zh F5 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F5 = 116,
|
||||
|
||||
/**
|
||||
* @en The F6 function key
|
||||
* @zh F6 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F6 = 117,
|
||||
|
||||
/**
|
||||
* @en The F7 function key
|
||||
* @zh F7 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F7 = 118,
|
||||
|
||||
/**
|
||||
* @en The F8 function key
|
||||
* @zh F8 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F8 = 119,
|
||||
|
||||
/**
|
||||
* @en The F9 function key
|
||||
* @zh F9 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F9 = 120,
|
||||
|
||||
/**
|
||||
* @en The F10 function key
|
||||
* @zh F10 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F10 = 121,
|
||||
|
||||
/**
|
||||
* @en The F11 function key
|
||||
* @zh F11 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F11 = 122,
|
||||
|
||||
/**
|
||||
* @en The F12 function key
|
||||
* @zh F12 功能键
|
||||
* @readonly
|
||||
*/
|
||||
F12 = 123,
|
||||
|
||||
/**
|
||||
* @en The numlock key
|
||||
* @zh 数字锁定键
|
||||
* @readonly
|
||||
*/
|
||||
NUMLOCK = 144,
|
||||
|
||||
/**
|
||||
* @en The scroll lock key
|
||||
* @zh 滚动锁定键
|
||||
* @readonly
|
||||
*/
|
||||
SCROLLLOCK = 145,
|
||||
|
||||
/**
|
||||
* @en The ';' key.
|
||||
* @zh 分号键
|
||||
* @readonly
|
||||
*/
|
||||
SEMICOLON = 186,
|
||||
|
||||
/**
|
||||
* @en The '=' key.
|
||||
* @zh 等于号键
|
||||
* @readonly
|
||||
*/
|
||||
EQUAL = 187,
|
||||
|
||||
/**
|
||||
* @en The ',' key.
|
||||
* @zh 逗号键
|
||||
* @readonly
|
||||
*/
|
||||
COMMA = 188,
|
||||
|
||||
/**
|
||||
* @en The dash '-' key.
|
||||
* @zh 中划线键
|
||||
* @readonly
|
||||
*/
|
||||
DASH = 189,
|
||||
|
||||
/**
|
||||
* @en The '.' key
|
||||
* @zh 句号键
|
||||
* @readonly
|
||||
*/
|
||||
PERIOD = 190,
|
||||
|
||||
/**
|
||||
* @en The forward slash key
|
||||
* @zh 正斜杠键
|
||||
* @readonly
|
||||
*/
|
||||
FORWARDSLASH = 191,
|
||||
|
||||
/**
|
||||
* @en The grave key
|
||||
* @zh 按键 `
|
||||
* @readonly
|
||||
*/
|
||||
GRAVE = 192,
|
||||
|
||||
/**
|
||||
* @en The '[' key
|
||||
* @zh 按键 [
|
||||
* @readonly
|
||||
*/
|
||||
OPENBRACKET = 219,
|
||||
|
||||
/**
|
||||
* @en The '\' key
|
||||
* @zh 反斜杠键
|
||||
* @readonly
|
||||
*/
|
||||
BACKSLASH = 220,
|
||||
|
||||
/**
|
||||
* @en The ']' key
|
||||
* @zh 按键 ]
|
||||
* @readonly
|
||||
*/
|
||||
CLOSEBRACKET = 221,
|
||||
|
||||
/**
|
||||
* @en The quote key
|
||||
* @zh 单引号键
|
||||
* @readonly
|
||||
*/
|
||||
QUOTE = 222,
|
||||
|
||||
/**
|
||||
* @en The dpad left key
|
||||
* @zh 导航键 向左
|
||||
* @readonly
|
||||
* @deprecated since v3.3
|
||||
*/
|
||||
DPAD_LEFT = 1000,
|
||||
|
||||
/**
|
||||
* @en The dpad right key
|
||||
* @zh 导航键 向右
|
||||
* @readonly
|
||||
* @deprecated since v3.3
|
||||
*/
|
||||
DPAD_RIGHT = 1001,
|
||||
|
||||
/**
|
||||
* @en The dpad up key
|
||||
* @zh 导航键 向上
|
||||
* @readonly
|
||||
* @deprecated since v3.3
|
||||
*/
|
||||
DPAD_UP = 1003,
|
||||
|
||||
/**
|
||||
* @en The dpad down key
|
||||
* @zh 导航键 向下
|
||||
* @readonly
|
||||
* @deprecated since v3.3
|
||||
*/
|
||||
DPAD_DOWN = 1004,
|
||||
|
||||
/**
|
||||
* @en The dpad center key
|
||||
* @zh 导航键 确定键
|
||||
* @readonly
|
||||
* @deprecated since v3.3
|
||||
*/
|
||||
DPAD_CENTER = 1005,
|
||||
};
|
||||
|
||||
/**
|
||||
* PI / 180
|
||||
*/
|
||||
static const float RAD{math::PI / 180};
|
||||
|
||||
/**
|
||||
* One degree
|
||||
*/
|
||||
// static const float DEG;
|
||||
static const float DEG{math::PI / 180};
|
||||
|
||||
/**
|
||||
* A maximum value of number
|
||||
*/
|
||||
static const uint32_t REPEAT_FOREVER{UINT32_MAX};
|
||||
|
||||
/**
|
||||
* A minimal float value
|
||||
*/
|
||||
// FLT_EPSILON: 0.0000001192092896,
|
||||
|
||||
// static const float FLTEPSILON {0.0000001192092896}; //FLT_EPSILON is keyword in cpp
|
||||
// Possible device orientations
|
||||
/**
|
||||
* @en Oriented vertically
|
||||
* @zh 竖屏朝向
|
||||
*/
|
||||
static const int32_t ORIENTATION_PORTRAIT{1};
|
||||
|
||||
/**
|
||||
* @en Oriented horizontally
|
||||
* @zh 横屏朝向
|
||||
*/
|
||||
static const int32_t ORIENTATION_LANDSCAPE{2};
|
||||
|
||||
/**
|
||||
* @en Oriented automatically
|
||||
* @zh 自动适配朝向
|
||||
*/
|
||||
static const int32_t ORIENTATION_AUTO{3};
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* If enabled, the texture coordinates will be calculated by using this formula: <br/>
|
||||
* - texCoord.left = (rect.x*2+1) / (texture.wide*2); <br/>
|
||||
* - texCoord.right = texCoord.left + (rect.width*2-2)/(texture.wide*2); <br/>
|
||||
* <br/>
|
||||
* The same for bottom and top. <br/>
|
||||
* <br/>
|
||||
* This formula prevents artifacts by using 99% of the texture. <br/>
|
||||
* The "correct" way to prevent artifacts is by expand the texture's border with the same color by 1 pixel<br/>
|
||||
* <br/>
|
||||
* Affected component: <br/>
|
||||
* - TMXLayer <br/>
|
||||
* <br/>
|
||||
* Enabled by default. To disabled set it to 0. <br/>
|
||||
* To modify it, in Web engine please refer to CCMacro.js, in JSB please refer to CCConfig.h
|
||||
* </p>
|
||||
* Currently not useful in 3D engine
|
||||
*/
|
||||
// FIX_ARTIFACTS_BY_STRECHING_TEXEL_TMX: true,
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Whether or not enabled tiled map auto culling. If you set the TiledMap skew or rotation,
|
||||
* then need to manually disable this, otherwise, the rendering will be wrong.
|
||||
* Currently not useful in 3D engine
|
||||
* @zh
|
||||
* 是否开启瓦片地图的自动裁减功能。瓦片地图如果设置了 skew, rotation 的话,需要手动关闭,否则渲染会出错。
|
||||
* 在 3D 引擎中暂时无效。
|
||||
* @default true
|
||||
*/
|
||||
static const bool ENABLE_TILEDMAP_CULLING{true};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The timeout to determine whether a touch is no longer active and should be removed.
|
||||
* The reason to add this timeout is due to an issue in X5 browser core,
|
||||
* when X5 is presented in wechat on Android, if a touch is glissed from the bottom up, and leave the page area,
|
||||
* no touch cancel event is triggered, and the touch will be considered active forever.
|
||||
* After multiple times of this action, our maximum touches number will be reached and all new touches will be ignored.
|
||||
* So this new mechanism can remove the touch that should be inactive if it's not updated during the last 5000 milliseconds.
|
||||
* Though it might remove a real touch if it's just not moving for the last 5 seconds which is not easy with the sensibility of mobile touch screen.
|
||||
* You can modify this value to have a better behavior if you find it's not enough.
|
||||
* @zh
|
||||
* 用于甄别一个触点对象是否已经失效并且可以被移除的延时时长
|
||||
* 添加这个时长的原因是 X5 内核在微信浏览器中出现的一个 bug。
|
||||
* 在这个环境下,如果用户将一个触点从底向上移出页面区域,将不会触发任何 touch cancel 或 touch end 事件,而这个触点会被永远当作停留在页面上的有效触点。
|
||||
* 重复这样操作几次之后,屏幕上的触点数量将达到我们的事件系统所支持的最高触点数量,之后所有的触摸事件都将被忽略。
|
||||
* 所以这个新的机制可以在触点在一定时间内没有任何更新的情况下视为失效触点并从事件系统中移除。
|
||||
* 当然,这也可能移除一个真实的触点,如果用户的触点真的在一定时间段内完全没有移动(这在当前手机屏幕的灵敏度下会很难)。
|
||||
* 你可以修改这个值来获得你需要的效果,默认值是 5000 毫秒。
|
||||
* @default 5000
|
||||
*/
|
||||
static const uint32_t TOUCH_TIMEOUT{5000};
|
||||
/**
|
||||
* @en
|
||||
* Boolean that indicates if the canvas contains an alpha channel, default sets to false for better performance.
|
||||
* Though if you want to make your canvas background transparent and show other dom elements at the background,
|
||||
* you can set it to true before {{game.init}}.
|
||||
* Web only.
|
||||
* @zh
|
||||
* 用于设置 Canvas 背景是否支持 alpha 通道,默认为 false,这样可以有更高的性能表现。
|
||||
* 如果你希望 Canvas 背景是透明的,并显示背后的其他 DOM 元素,你可以在 {{game.init}} 之前将这个值设为 true。
|
||||
* 仅支持 Web
|
||||
* @default false
|
||||
*/
|
||||
static const bool ENABLE_TRANSPARENT_CANVAS{false};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Boolean that indicates if the WebGL context is created with `antialias` option turned on, default value is false.
|
||||
* Set it to true could make your game graphics slightly smoother, like texture hard edges when rotated.
|
||||
* Whether to use this really depend on your game design and targeted platform,
|
||||
* device with retina display usually have good detail on graphics with or without this option,
|
||||
* you probably don't want antialias if your game style is pixel art based.
|
||||
* Also, it could have great performance impact with some browser / device using software MSAA.
|
||||
* You can set it to true before {{game.init}}.
|
||||
* Web only.
|
||||
* @zh
|
||||
* 用于设置在创建 WebGL Context 时是否开启抗锯齿选项,默认值是 false。
|
||||
* 将这个选项设置为 true 会让你的游戏画面稍稍平滑一些,比如旋转硬边贴图时的锯齿。是否开启这个选项很大程度上取决于你的游戏和面向的平台。
|
||||
* 在大多数拥有 retina 级别屏幕的设备上用户往往无法区分这个选项带来的变化;如果你的游戏选择像素艺术风格,你也多半不会想开启这个选项。
|
||||
* 同时,在少部分使用软件级别抗锯齿算法的设备或浏览器上,这个选项会对性能产生比较大的影响。
|
||||
* 你可以在 {{game.init}} 之前设置这个值,否则它不会生效。
|
||||
* 仅支持 Web
|
||||
* @default true
|
||||
*/
|
||||
static const bool ENABLE_WEBGL_ANTIALIAS{true};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Whether to clear the original image cache after uploaded a texture to GPU.
|
||||
* If cleared, [Dynamic Atlas](https://docs.cocos.com/creator/manual/en/advanced-topics/dynamic-atlas.html) will not be supported.
|
||||
* Normally you don't need to enable this option on the web platform, because Image object doesn't consume too much memory.
|
||||
* But on Wechat Game platform, the current version cache decoded data in Image object, which has high memory usage.
|
||||
* So we enabled this option by default on Wechat, so that we can release Image cache immediately after uploaded to GPU.
|
||||
* Currently not useful in 3D engine
|
||||
* @zh
|
||||
* 是否在将贴图上传至 GPU 之后删除原始图片缓存,删除之后图片将无法进行 [动态合图](https://docs.cocos.com/creator/manual/zh/advanced-topics/dynamic-atlas.html)。
|
||||
* 在 Web 平台,你通常不需要开启这个选项,因为在 Web 平台 Image 对象所占用的内存很小。
|
||||
* 但是在微信小游戏平台的当前版本,Image 对象会缓存解码后的图片数据,它所占用的内存空间很大。
|
||||
* 所以我们在微信平台默认开启了这个选项,这样我们就可以在上传 GL 贴图之后立即释放 Image 对象的内存,避免过高的内存占用。
|
||||
* 在 3D 引擎中暂时无效。
|
||||
* @default false
|
||||
*/
|
||||
static const bool CLEANUP_IMAGE_CACHE{false};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Whether to enable multi-touch.
|
||||
* @zh
|
||||
* 是否开启多点触摸
|
||||
* @default true
|
||||
*/
|
||||
static const bool ENABLE_MULTI_TOUCH{true};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* The maximum size of the canvas pool used by Label, please adjust according to the number of label component in the same scene of the project
|
||||
* @zh
|
||||
* Label 使用的 canvas pool 的最大大小,请根据项目同场景的 label 数量进行调整
|
||||
* @default 20
|
||||
*/
|
||||
static const uint32_t MAX_LABEL_CANVAS_POOL_SIZE{20};
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Boolean that indicates if enable highp precision data in structure with fragment shader.
|
||||
* Enable this option will make the variables defined by the HIGHP_VALUE_STRUCT_DEFINE macro in the shader more accurate, such as position.
|
||||
* Enable this option can avoid some distorted lighting effects. That depends on whether your game has abnormal lighting effects on this platform.
|
||||
* There will be a slight performance loss if enable this option, but the impact is not significant.
|
||||
* Only affect WebGL backend
|
||||
* @zh
|
||||
* 用于设置是否在片元着色器中使用结构体的时候,允许其中的数据使用highp精度
|
||||
* 将这个选项设置为 true 会让shader中使用HIGHP_VALUE_STRUCT_DEFINE宏定义的变量精度更高,比如位置信息等,避免出现一些失真的光照效果。是否开启这个选项很大程度上取决于你的游戏在此平台上是否出现了异常的表现。
|
||||
* 开启后会有轻微的性能损失,但影响不大。
|
||||
* 仅影响 WebGL 后端
|
||||
* @default false
|
||||
*/
|
||||
static const bool ENABLE_WEBGL_HIGHP_STRUCT_VALUES{false};
|
||||
|
||||
/**
|
||||
* @zh Batcher2D 中内存增量的大小(KB)
|
||||
* 这个值决定了当场景中存在的 2d 渲染组件的顶点数量超过当前 batcher2D 中可容纳的顶点数量时,内存扩充的增加量
|
||||
* 这个值越大,共用同一个 meshBuffer 的 2d 渲染组件数量会更多,但每次扩充所占用的内存也会更大
|
||||
* 默认值在标准格式([[vfmtPosUvColor]])下可容纳 4096 个顶点(4096*9*4/1024),你可以增加容量来提升每个批次可容纳的元素数量
|
||||
* @en The MeshBuffer chunk size in Batcher2D (KB)
|
||||
* This value determines the increase in memory expansion,
|
||||
* when the number of vertices of 2d rendering components present in the scene exceeds the number of vertices,
|
||||
* that can be accommodated in the current batcher2D.
|
||||
* The larger this value is, the more 2d rendering components will share the same meshBuffer, but the more memory will be used for each expansion
|
||||
* The default size can contain 4096 standard vertex ([[vfmtPosUvColor]]) in one buffer,
|
||||
* you can user larger buffer size to increase the elements count per 2d draw batch.
|
||||
* @default 144 KB
|
||||
*/
|
||||
static const uint32_t BATCHER2D_MEM_INCREMENT{144};
|
||||
} // namespace macro
|
||||
|
||||
} // namespace cc
|
||||
23
cocos/core/scene-graph/Layers.cpp
Normal file
23
cocos/core/scene-graph/Layers.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2022-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
121
cocos/core/scene-graph/Layers.h
Normal file
121
cocos/core/scene-graph/Layers.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2021-2023 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "base/Macros.h"
|
||||
#include "base/std/container/vector.h"
|
||||
|
||||
namespace cc {
|
||||
|
||||
/**
|
||||
* @zh 节点层管理器,层数据是以掩码数据方式存储在 [[Node.layer]] 中,用于射线检测、物理碰撞和用户自定义脚本逻辑。
|
||||
* 每个节点可属于一个或多个层,可通过 “包含式” 或 “排除式” 两种检测器进行层检测。
|
||||
* @en Node's layer manager, it's stored as bit mask data in [[Node.layer]].
|
||||
* Layer information is widely used in raycast, physics and user logic.
|
||||
* Every node can be assigned to multiple layers with different bit masks, you can setup layer with inclusive or exclusive operation.
|
||||
*/
|
||||
class Layers final {
|
||||
public:
|
||||
Layers() = delete;
|
||||
~Layers() = delete;
|
||||
|
||||
// built-in layers, users can use 0~19 bits, 20~31 are system preserve bits.
|
||||
enum class LayerList : uint32_t {
|
||||
NONE = 0,
|
||||
IGNORE_RAYCAST = (1 << 20),
|
||||
GIZMOS = (1 << 21),
|
||||
EDITOR = (1 << 22),
|
||||
UI_3D = (1 << 23),
|
||||
SCENE_GIZMO = (1 << 24),
|
||||
UI_2D = (1 << 25),
|
||||
|
||||
PROFILER = (1 << 28),
|
||||
DEFAULT = (1 << 30),
|
||||
ALL = 0xffffffff,
|
||||
};
|
||||
|
||||
using Enum = LayerList;
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Make a layer mask accepting nothing but the listed layers
|
||||
* @zh
|
||||
* 创建一个包含式层检测器,只接受列表中的层
|
||||
* @param includes All accepted layers
|
||||
* @return A filter which can detect all accepted layers
|
||||
*/
|
||||
static uint32_t makeMaskInclude(const ccstd::vector<uint32_t> &includes) {
|
||||
uint32_t mask = 0;
|
||||
for (uint32_t inc : includes) {
|
||||
mask |= inc;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @en
|
||||
* Make a layer mask accepting everything but the listed layers
|
||||
* @zh
|
||||
* 创建一个排除式层检测器,只拒绝列表中的层
|
||||
* @param excludes All excluded layers
|
||||
* @return A filter which can detect for excluded layers
|
||||
*/
|
||||
static uint32_t makeMaskExclude(const ccstd::vector<uint32_t> &excludes) {
|
||||
return ~makeMaskInclude(excludes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @zh 添加一个新层,用户可编辑 0 - 19 位为用户自定义层
|
||||
* @en Add a new layer, user can use layers from bit position 0 to 19, other bits are reserved.
|
||||
* @param name Layer's name
|
||||
* @param bitNum Layer's bit position
|
||||
*/
|
||||
static void addLayer(const std::string &name, uint32_t bitNum);
|
||||
|
||||
/**
|
||||
* @en Remove a layer, user can remove layers from bit position 0 to 19, other bits are reserved.
|
||||
* @zh 移除一个层,用户可编辑 0 - 19 位为用户自定义层
|
||||
* @param bitNum Layer's bit position
|
||||
*/
|
||||
static void deleteLayer(uint32_t bitNum);
|
||||
|
||||
/**
|
||||
* @en Given a layer name, returns the layer index as defined by either a Builtin or a User Layer in the Tags and Layers manager.
|
||||
* @zh 给定层名称,返回由标记和层管理器中的内置层或用户层定义的层索引。
|
||||
* @param name layer's name
|
||||
*/
|
||||
static uint32_t nameToLayer(const std::string &name);
|
||||
|
||||
/**
|
||||
* @en Given a layer number, returns the name of the layer as defined in either a Builtin or a User Layer in the Tags and Layers manager.
|
||||
* @zh 给定层数,返回在标记和层管理器中的内置层或用户层中定义的层名称。
|
||||
* @param bitNum layer's value
|
||||
*/
|
||||
static std::string layerToName(uint32_t bitNum);
|
||||
};
|
||||
|
||||
CC_ENUM_BITWISE_OPERATORS(Layers::LayerList);
|
||||
|
||||
} // namespace cc
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user