mirror of https://github.com/zeldaret/botw.git
ksys/phys: Add MaterialMask
This commit is contained in:
parent
75a270118a
commit
eb16cbaf55
|
@ -79484,20 +79484,20 @@ Address,Quality,Size,Name
|
||||||
0x0000007100e9d484,U,000092,
|
0x0000007100e9d484,U,000092,
|
||||||
0x0000007100e9d4e0,U,000004,nullsub_4024
|
0x0000007100e9d4e0,U,000004,nullsub_4024
|
||||||
0x0000007100e9d4e4,U,000004,nullsub_4025
|
0x0000007100e9d4e4,U,000004,nullsub_4025
|
||||||
0x0000007100e9d4e8,U,000028,Struct9::ctor
|
0x0000007100e9d4e8,O,000028,_ZN4ksys4phys12MaterialMaskC1Ev
|
||||||
0x0000007100e9d504,U,000028,
|
0x0000007100e9d504,O,000028,_ZN4ksys4phys12MaterialMaskC1ENS0_16MaterialMaskDataE
|
||||||
0x0000007100e9d520,U,000080,
|
0x0000007100e9d520,O,000080,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialENS0_9FloorCodeENS0_8WallCodeEb
|
||||||
0x0000007100e9d570,U,000176,
|
0x0000007100e9d570,O,000176,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialEPKcNS0_9FloorCodeENS0_8WallCodeEb
|
||||||
0x0000007100e9d620,U,000032,
|
0x0000007100e9d620,O,000032,_ZN4ksys4phys12MaterialMask17getSubMaterialIdxENS0_8MaterialERKN4sead14SafeStringBaseIcEE
|
||||||
0x0000007100e9d640,U,000172,
|
0x0000007100e9d640,O,000172,_ZN4ksys4phys12MaterialMaskC1ENS0_8MaterialEiNS0_9FloorCodeENS0_8WallCodeEb
|
||||||
0x0000007100e9d6ec,U,000048,
|
0x0000007100e9d6ec,O,000048,_ZN4ksys4phys12MaterialMask18getSubMaterialNameENS0_8MaterialEi
|
||||||
0x0000007100e9d71c,U,000004,nullsub_4026
|
0x0000007100e9d71c,O,000004,_ZN4ksys4phys12MaterialMaskD1Ev
|
||||||
0x0000007100e9d720,U,000004,j__ZdlPv_942
|
0x0000007100e9d720,O,000004,_ZN4ksys4phys12MaterialMaskD0Ev
|
||||||
0x0000007100e9d724,U,000032,
|
0x0000007100e9d724,O,000032,_ZNK4ksys4phys12MaterialMask15getMaterialNameEv
|
||||||
0x0000007100e9d744,U,000092,getLastSurface
|
0x0000007100e9d744,O,000092,_ZNK4ksys4phys12MaterialMask18getSubMaterialNameEv
|
||||||
0x0000007100e9d7a0,U,000028,
|
0x0000007100e9d7a0,O,000028,_ZN4ksys4phys12MaterialMask18getNumSubMaterialsENS0_8MaterialE
|
||||||
0x0000007100e9d7bc,U,000048,
|
0x0000007100e9d7bc,O,000048,_ZN4ksys4phys12MaterialMask18getSubMaterialNameEii
|
||||||
0x0000007100e9d7ec,U,000036,
|
0x0000007100e9d7ec,O,000036,_ZN4ksys4phys12MaterialMask11setMaterialENS0_8MaterialE
|
||||||
0x0000007100e9d810,U,000160,
|
0x0000007100e9d810,U,000160,
|
||||||
0x0000007100e9d8b0,U,000536,
|
0x0000007100e9d8b0,U,000536,
|
||||||
0x0000007100e9dac8,U,000296,
|
0x0000007100e9dac8,U,000296,
|
||||||
|
|
Can't render this file because it is too large.
|
|
@ -48,6 +48,8 @@ target_sources(uking PRIVATE
|
||||||
System/physGroupFilter.h
|
System/physGroupFilter.h
|
||||||
System/physInstanceSet.cpp
|
System/physInstanceSet.cpp
|
||||||
System/physInstanceSet.h
|
System/physInstanceSet.h
|
||||||
|
System/physMaterialMask.cpp
|
||||||
|
System/physMaterialMask.h
|
||||||
System/physMaterialTable.cpp
|
System/physMaterialTable.cpp
|
||||||
System/physMaterialTable.h
|
System/physMaterialTable.h
|
||||||
System/physMemSystem.cpp
|
System/physMemSystem.cpp
|
||||||
|
|
|
@ -13,32 +13,26 @@ CapsuleBody* CapsuleShape::init(sead::Heap* heap) {
|
||||||
auto* hk_shape =
|
auto* hk_shape =
|
||||||
new (ptr) hkpCapsuleShape(hkVector4(vertex_a.x, vertex_a.y, vertex_a.z),
|
new (ptr) hkpCapsuleShape(hkVector4(vertex_a.x, vertex_a.y, vertex_a.z),
|
||||||
hkVector4(vertex_b.x, vertex_b.y, vertex_b.z), radius);
|
hkVector4(vertex_b.x, vertex_b.y, vertex_b.z), radius);
|
||||||
auto* body = new (heap) CapsuleBody(vertex_a, vertex_b, radius, _20, _28, _30, _34, hk_shape);
|
auto* body = new (heap) CapsuleBody(vertex_a, vertex_b, radius, material, sub_material,
|
||||||
|
floor_code, wall_code, hk_shape);
|
||||||
if (_38) {
|
if (_38) {
|
||||||
body->unk.shape_type = 1 << 23;
|
body->material_mask.getData().flag_23 = true;
|
||||||
}
|
}
|
||||||
body->unk._10 = nullptr;
|
body->material_mask.clearSubMaterialNameCache();
|
||||||
hk_shape->setUserData(body->unk.shape_type);
|
hk_shape->setUserData(body->material_mask.getRawData());
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
CapsuleBody* CapsuleBody::clone(sead::Heap* heap) {
|
CapsuleBody* CapsuleBody::clone(sead::Heap* heap) {
|
||||||
CapsuleShape shape;
|
CapsuleShape shape;
|
||||||
|
|
||||||
shape._20 = 0;
|
|
||||||
shape._28 = sead::SafeString::cEmptyString.cstr();
|
|
||||||
shape._30 = 0;
|
|
||||||
shape._34 = 0;
|
|
||||||
shape._38 = false;
|
|
||||||
shape.radius = radius;
|
shape.radius = radius;
|
||||||
shape.vertex_a = vertex_a;
|
shape.vertex_a = vertex_a;
|
||||||
shape.vertex_b = vertex_b;
|
shape.vertex_b = vertex_b;
|
||||||
|
|
||||||
CapsuleBody* body = shape.init(heap);
|
CapsuleBody* body = shape.init(heap);
|
||||||
body->unk.shape_type = unk.shape_type;
|
body->material_mask = material_mask;
|
||||||
body->unk._10 = nullptr;
|
|
||||||
if (body->shape != nullptr)
|
if (body->shape != nullptr)
|
||||||
body->shape->setUserData(unk.shape_type);
|
body->shape->setUserData(material_mask.getRawData());
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
#include <prim/seadTypedBitFlag.h>
|
#include <prim/seadTypedBitFlag.h>
|
||||||
#include <thread/seadAtomic.h>
|
#include <thread/seadAtomic.h>
|
||||||
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
|
#include "KingSystem/Physics/RigidBody/physRigidBody.h"
|
||||||
|
#include "KingSystem/Physics/System/physDefines.h"
|
||||||
|
#include "KingSystem/Physics/System/physMaterialMask.h"
|
||||||
|
|
||||||
class hkpShape;
|
class hkpShape;
|
||||||
|
|
||||||
|
@ -18,17 +20,11 @@ struct CapsuleBody {
|
||||||
Modified = 1 << 0,
|
Modified = 1 << 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Unk {
|
CapsuleBody(const sead::Vector3f& va, const sead::Vector3f& vb, f32 r, Material material,
|
||||||
Unk(u32 a1, const char* a2, u32 a3, u32 a4, u32 a5);
|
const char* sub_material, FloorCode floor_code, WallCode wall_code,
|
||||||
virtual ~Unk();
|
hkpShape* shape_)
|
||||||
|
: vertex_a(va), vertex_b(vb), radius(r),
|
||||||
u32 shape_type = 0;
|
material_mask(material, sub_material, floor_code, wall_code, false), shape(shape_) {}
|
||||||
const char* _10;
|
|
||||||
};
|
|
||||||
|
|
||||||
CapsuleBody(const sead::Vector3f& va, const sead::Vector3f& vb, f32 r, u32 a4, const char* a5,
|
|
||||||
u32 a6, u32 a7, hkpShape* a8)
|
|
||||||
: vertex_a(va), vertex_b(vb), radius(r), unk(a4, a5, a6, a7, 0), shape(a8) {}
|
|
||||||
virtual ~CapsuleBody();
|
virtual ~CapsuleBody();
|
||||||
|
|
||||||
virtual hkpShape* getShape();
|
virtual hkpShape* getShape();
|
||||||
|
@ -49,7 +45,7 @@ struct CapsuleBody {
|
||||||
sead::TypedBitFlag<Flag, sead::Atomic<u32>> flags{};
|
sead::TypedBitFlag<Flag, sead::Atomic<u32>> flags{};
|
||||||
sead::Vector3f vertex_b;
|
sead::Vector3f vertex_b;
|
||||||
f32 radius;
|
f32 radius;
|
||||||
Unk unk;
|
MaterialMask material_mask;
|
||||||
hkpShape* shape;
|
hkpShape* shape;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -60,11 +56,11 @@ struct CapsuleShape {
|
||||||
sead::Vector3f vertex_b;
|
sead::Vector3f vertex_b;
|
||||||
f32 radius;
|
f32 radius;
|
||||||
u32 _1c;
|
u32 _1c;
|
||||||
u32 _20;
|
Material material;
|
||||||
const char* _28;
|
const char* sub_material = sead::SafeString::cEmptyString.cstr();
|
||||||
u32 _30;
|
FloorCode floor_code;
|
||||||
u32 _34;
|
WallCode wall_code;
|
||||||
bool _38;
|
bool _38 = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CapsuleView : public RigidBodyParamView {
|
class CapsuleView : public RigidBodyParamView {
|
||||||
|
|
|
@ -113,6 +113,10 @@ Misc,\
|
||||||
GrudgeSlow
|
GrudgeSlow
|
||||||
)
|
)
|
||||||
|
|
||||||
|
constexpr bool isInvalidMaterial(Material::ValueType mat) {
|
||||||
|
return mat >= Material::size();
|
||||||
|
}
|
||||||
|
|
||||||
SEAD_ENUM(GroundHit,
|
SEAD_ENUM(GroundHit,
|
||||||
Player,\
|
Player,\
|
||||||
Animal,\
|
Animal,\
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
#include "KingSystem/Physics/System/physMaterialMask.h"
|
||||||
|
#include "KingSystem/Physics/System/physMaterialTable.h"
|
||||||
|
#include "KingSystem/Physics/System/physMemSystem.h"
|
||||||
|
|
||||||
|
namespace ksys::phys {
|
||||||
|
|
||||||
|
MaterialMask::MaterialMask() = default;
|
||||||
|
|
||||||
|
MaterialMask::MaterialMask(MaterialMaskData data) : mData(data) {}
|
||||||
|
|
||||||
|
MaterialMask::MaterialMask(Material mat, FloorCode floor, WallCode wall, bool flag) {
|
||||||
|
mData.material.Init(mat);
|
||||||
|
mData.floor.Init(floor);
|
||||||
|
mData.wall.Init(wall);
|
||||||
|
mData.setFlag(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialMask::MaterialMask(Material mat, const char* submat_name, FloorCode floor, WallCode wall,
|
||||||
|
bool flag)
|
||||||
|
: mSubMaterialNameCache(submat_name) {
|
||||||
|
auto submat_idx = getSubMaterialIdx(mat, submat_name);
|
||||||
|
if (!MaterialMaskData::isValidSubMaterialIdx(submat_idx))
|
||||||
|
submat_idx = 0;
|
||||||
|
mData.raw = {};
|
||||||
|
mData.material.Init(mat);
|
||||||
|
mData.sub_material.Init(submat_idx);
|
||||||
|
mData.floor.Init(floor);
|
||||||
|
mData.wall.Init(wall);
|
||||||
|
mData.setFlag(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialMask::MaterialMask(Material mat, int submat_idx, FloorCode floor, WallCode wall, bool flag)
|
||||||
|
: mSubMaterialNameCache(getSubMaterialName(mat, submat_idx).cstr()) {
|
||||||
|
mData.raw = {};
|
||||||
|
mData.material.Init(mat);
|
||||||
|
mData.sub_material.Init(submat_idx);
|
||||||
|
mData.floor.Init(floor);
|
||||||
|
mData.wall.Init(wall);
|
||||||
|
mData.setFlag(flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialMask::~MaterialMask() = default;
|
||||||
|
|
||||||
|
const char* MaterialMask::getMaterialName() const {
|
||||||
|
const Material material = getMaterial();
|
||||||
|
if (isInvalidMaterial(material.value()))
|
||||||
|
return "Incorrent"; // sic
|
||||||
|
return materialToText(material);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* MaterialMask::getSubMaterialName() const {
|
||||||
|
if (mSubMaterialNameCache != nullptr)
|
||||||
|
return mSubMaterialNameCache;
|
||||||
|
|
||||||
|
mSubMaterialNameCache = getSubMaterialName(getMaterial(), getSubMaterialIdx()).cstr();
|
||||||
|
return mSubMaterialNameCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MaterialMask::getSubMaterialIdx(Material mat, const sead::SafeString& submat_name) {
|
||||||
|
return MemSystem::instance()->getMaterialTable()->getSubMaterialIdx(mat, submat_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sead::SafeString& MaterialMask::getSubMaterialName(Material mat, int submat_idx) {
|
||||||
|
return MemSystem::instance()->getMaterialTable()->getSubMaterial(mat, submat_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MaterialMask::getNumSubMaterials(Material mat) {
|
||||||
|
return MemSystem::instance()->getMaterialTable()->getNumSubMaterials(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
const sead::SafeString& MaterialMask::getSubMaterialName(int mat, int submat_idx) {
|
||||||
|
return getSubMaterialName(Material(mat), submat_idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MaterialMask::setMaterial(Material mat) {
|
||||||
|
mData.material = {};
|
||||||
|
mData.material.SetUnsafe(mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ksys::phys
|
|
@ -0,0 +1,85 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <basis/seadTypes.h>
|
||||||
|
#include <prim/seadSafeString.h>
|
||||||
|
#include "KingSystem/Physics/System/physDefines.h"
|
||||||
|
#include "KingSystem/Utils/BitField.h"
|
||||||
|
|
||||||
|
namespace ksys::phys {
|
||||||
|
|
||||||
|
union MaterialMaskData {
|
||||||
|
constexpr explicit MaterialMaskData(u32 raw_ = 0) : raw(raw_) {}
|
||||||
|
constexpr MaterialMaskData(const MaterialMaskData&) = default;
|
||||||
|
constexpr MaterialMaskData& operator=(const MaterialMaskData& other) {
|
||||||
|
raw = other.raw;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr bool isValidSubMaterialIdx(int idx) {
|
||||||
|
return u32(idx) < (1 << decltype(sub_material)::NumBits());
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFlag(bool b) {
|
||||||
|
if (!b)
|
||||||
|
clearFlag();
|
||||||
|
else
|
||||||
|
setFlag();
|
||||||
|
}
|
||||||
|
void setFlag() { flag = 1; }
|
||||||
|
void clearFlag() { flag = 0; }
|
||||||
|
|
||||||
|
u32 raw;
|
||||||
|
util::BitField<0, 6, u32> material;
|
||||||
|
util::BitField<6, 4, int, u32> sub_material;
|
||||||
|
util::BitField<10, 5, u32> floor;
|
||||||
|
util::BitField<15, 5, u32> wall;
|
||||||
|
// TODO: rename
|
||||||
|
util::BitField<23, 1, u32> flag_23;
|
||||||
|
// TODO: rename once we figure out what this flag is
|
||||||
|
util::BitField<31, 1, u32> flag;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(MaterialMaskData) == sizeof(u32));
|
||||||
|
|
||||||
|
class MaterialMask {
|
||||||
|
public:
|
||||||
|
MaterialMask();
|
||||||
|
explicit MaterialMask(MaterialMaskData data);
|
||||||
|
MaterialMask(Material mat, FloorCode floor, WallCode wall, bool flag);
|
||||||
|
MaterialMask(Material mat, const char* submat_name, FloorCode floor, WallCode wall, bool flag);
|
||||||
|
MaterialMask(Material mat, int submat_idx, FloorCode floor, WallCode wall, bool flag);
|
||||||
|
MaterialMask(const MaterialMask& other) : mData(other.mData) {}
|
||||||
|
|
||||||
|
// XXX: this doesn't need to be virtual.
|
||||||
|
virtual ~MaterialMask();
|
||||||
|
|
||||||
|
MaterialMask& operator=(const MaterialMask& other) {
|
||||||
|
mData = other.mData;
|
||||||
|
mSubMaterialNameCache = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaterialMaskData& getData() { return mData; }
|
||||||
|
const MaterialMaskData& getData() const { return mData; }
|
||||||
|
u32 getRawData() const { return mData.raw; }
|
||||||
|
Material getMaterial() const { return Material::ValueType(mData.material.Value()); }
|
||||||
|
int getSubMaterialIdx() const { return mData.sub_material; }
|
||||||
|
|
||||||
|
const char* getMaterialName() const;
|
||||||
|
const char* getSubMaterialName() const;
|
||||||
|
|
||||||
|
void setMaterial(Material mat);
|
||||||
|
void clearSubMaterialNameCache() { mSubMaterialNameCache = nullptr; }
|
||||||
|
|
||||||
|
static int getSubMaterialIdx(Material mat, const sead::SafeString& submat_name);
|
||||||
|
static const sead::SafeString& getSubMaterialName(Material mat, int submat_idx);
|
||||||
|
static int getNumSubMaterials(Material mat);
|
||||||
|
static const sead::SafeString& getSubMaterialName(int mat, int submat_idx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MaterialMaskData mData{};
|
||||||
|
/// Fetching the name of a sub-material from the MaterialTable is an expensive operation,
|
||||||
|
/// so it is only done once and the result is cached.
|
||||||
|
mutable const char* mSubMaterialNameCache{};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ksys::phys
|
|
@ -9,9 +9,11 @@ namespace ksys::phys {
|
||||||
|
|
||||||
class ContactMgr;
|
class ContactMgr;
|
||||||
class GroupFilter;
|
class GroupFilter;
|
||||||
|
class MaterialTable;
|
||||||
class RigidBody;
|
class RigidBody;
|
||||||
class RigidContactPoints;
|
class RigidContactPoints;
|
||||||
class RigidContactPointsEx;
|
class RigidContactPointsEx;
|
||||||
|
class SystemData;
|
||||||
class SystemGroupHandler;
|
class SystemGroupHandler;
|
||||||
|
|
||||||
// FIXME: obviously incomplete. Also this should be moved to its own header
|
// FIXME: obviously incomplete. Also this should be moved to its own header
|
||||||
|
@ -28,6 +30,8 @@ public:
|
||||||
GroupFilter* getGroupFilter(ContactLayerType type) const;
|
GroupFilter* getGroupFilter(ContactLayerType type) const;
|
||||||
ContactMgr* getContactMgr() const { return mContactMgr; }
|
ContactMgr* getContactMgr() const { return mContactMgr; }
|
||||||
RigidBodyRequestMgr* getRigidBodyRequestMgr() const { return mRigidBodyRequestMgr; }
|
RigidBodyRequestMgr* getRigidBodyRequestMgr() const { return mRigidBodyRequestMgr; }
|
||||||
|
SystemData* getSystemData() const { return mSystemData; }
|
||||||
|
MaterialTable* getMaterialTable() const { return mMaterialTable; }
|
||||||
|
|
||||||
RigidContactPoints* allocContactPoints(sead::Heap* heap, int num, const sead::SafeString& name,
|
RigidContactPoints* allocContactPoints(sead::Heap* heap, int num, const sead::SafeString& name,
|
||||||
int a, int b, int c) const;
|
int a, int b, int c) const;
|
||||||
|
@ -48,7 +52,11 @@ private:
|
||||||
void* _150;
|
void* _150;
|
||||||
void* _158;
|
void* _158;
|
||||||
RigidBodyRequestMgr* mRigidBodyRequestMgr;
|
RigidBodyRequestMgr* mRigidBodyRequestMgr;
|
||||||
u8 _168[0x480 - 0x168];
|
void* _168;
|
||||||
|
void* mRigidBodyDividedMeshShapeMgr;
|
||||||
|
SystemData* mSystemData;
|
||||||
|
MaterialTable* mMaterialTable;
|
||||||
|
u8 _188[0x480 - 0x188];
|
||||||
};
|
};
|
||||||
KSYS_CHECK_SIZE_NX150(MemSystem, 0x480);
|
KSYS_CHECK_SIZE_NX150(MemSystem, 0x480);
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,10 @@ struct BitField {
|
||||||
// so that we can use this within unions
|
// so that we can use this within unions
|
||||||
constexpr BitField() = default;
|
constexpr BitField() = default;
|
||||||
|
|
||||||
|
// We declare a user-defined copy assignment operator, so the default copy constructor
|
||||||
|
// must be defaulted explicitly to avoid a deprecation warning.
|
||||||
|
constexpr BitField(const BitField&) = default;
|
||||||
|
|
||||||
// This constructor might be considered ambiguous:
|
// This constructor might be considered ambiguous:
|
||||||
// Would it initialize the storage or just the bitfield?
|
// Would it initialize the storage or just the bitfield?
|
||||||
// Hence, delete it. Use the assignment operator to set bitfield values!
|
// Hence, delete it. Use the assignment operator to set bitfield values!
|
||||||
|
@ -132,6 +136,11 @@ struct BitField {
|
||||||
storage = (storage & ~GetMask()) | (static_cast<StorageType>(val) << position);
|
storage = (storage & ~GetMask()) | (static_cast<StorageType>(val) << position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @warning Same as SetUnsafe, but assumes this bitfield's bits are zero.
|
||||||
|
/// This is intended to be called only once to efficiently initialise a bitfield,
|
||||||
|
/// and will break very badly if called more than once. Using Set() is preferred.
|
||||||
|
inline constexpr void Init(T val) { storage |= static_cast<StorageType>(val) << position; }
|
||||||
|
|
||||||
inline constexpr BitField& operator=(const BitField& other) {
|
inline constexpr BitField& operator=(const BitField& other) {
|
||||||
Set(other.Value());
|
Set(other.Value());
|
||||||
return *this;
|
return *this;
|
||||||
|
|
Loading…
Reference in New Issue