fix most warnings with -pendantic
parent
48a772b20b
commit
6c5f9ecb06
|
@ -273,8 +273,8 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
|
||||||
void * GetBufferPointer() { return buffer; };
|
void * GetBufferPointer() { return buffer; };
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
virtual size_t Read(void* pvBuffer, size_t pSize, size_t pCount) { return 0; };
|
virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; };
|
||||||
virtual aiReturn Seek(size_t pOffset, aiOrigin pOrigin) { return aiReturn_FAILURE; };
|
virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; };
|
||||||
virtual size_t Tell() const { return cursor; };
|
virtual size_t Tell() const { return cursor; };
|
||||||
virtual void Flush() { };
|
virtual void Flush() { };
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ const aiImporterDesc* AssbinImporter::GetInfo() const
|
||||||
return &desc;
|
return &desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const
|
bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const
|
||||||
{
|
{
|
||||||
IOStream * in = pIOHandler->Open(pFile);
|
IOStream * in = pIOHandler->Open(pFile);
|
||||||
if (!in)
|
if (!in)
|
||||||
|
@ -186,7 +186,7 @@ void ReadArray(IOStream * stream, T * out, unsigned int size)
|
||||||
for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream);
|
for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> void ReadBounds( IOStream * stream, T* p, unsigned int n )
|
template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n )
|
||||||
{
|
{
|
||||||
// not sure what to do here, the data isn't really useful.
|
// not sure what to do here, the data isn't really useful.
|
||||||
stream->Seek( sizeof(T) * n, aiOrigin_CUR );
|
stream->Seek( sizeof(T) * n, aiOrigin_CUR );
|
||||||
|
|
|
@ -999,7 +999,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
|
aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* /*camera*/, ConversionData& /*conv_data*/)
|
||||||
{
|
{
|
||||||
ScopeGuard<aiCamera> out(new aiCamera());
|
ScopeGuard<aiCamera> out(new aiCamera());
|
||||||
out->mName = obj->id.name+2;
|
out->mName = obj->id.name+2;
|
||||||
|
@ -1010,7 +1010,7 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
|
aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
|
||||||
{
|
{
|
||||||
ScopeGuard<aiLight> out(new aiLight());
|
ScopeGuard<aiLight> out(new aiLight());
|
||||||
out->mName = obj->id.name+2;
|
out->mName = obj->id.name+2;
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace boost {
|
||||||
};
|
};
|
||||||
|
|
||||||
// dummy
|
// dummy
|
||||||
list_elem& operator = (const list_elem& other) {
|
list_elem& operator = (const list_elem& /*other*/) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ namespace boost {
|
||||||
return me.me;
|
return me.me;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|
||||||
// A very minimal implementation for up to 5 elements
|
// A very minimal implementation for up to 5 elements
|
||||||
template <typename T0 = detail::nulltype,
|
template <typename T0 = detail::nulltype,
|
||||||
|
@ -278,6 +278,6 @@ namespace boost {
|
||||||
tuple <> t;
|
tuple <> t;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
#endif // !! BOOST_TUPLE_INCLUDED
|
#endif // !! BOOST_TUPLE_INCLUDED
|
||||||
|
|
|
@ -59,7 +59,7 @@ namespace FBX {
|
||||||
using namespace Util;
|
using namespace Util;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc)
|
AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
|
||||||
: Object(id, element, name)
|
: Object(id, element, name)
|
||||||
{
|
{
|
||||||
const Scope& sc = GetRequiredScope(element);
|
const Scope& sc = GetRequiredScope(element);
|
||||||
|
|
|
@ -1319,7 +1319,7 @@ private:
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertCluster(std::vector<aiBone*>& bones, const Model& model, const Cluster& cl,
|
void ConvertCluster(std::vector<aiBone*>& bones, const Model& /*model*/, const Cluster& cl,
|
||||||
std::vector<size_t>& out_indices,
|
std::vector<size_t>& out_indices,
|
||||||
std::vector<size_t>& index_out_indices,
|
std::vector<size_t>& index_out_indices,
|
||||||
std::vector<size_t>& count_out_indices,
|
std::vector<size_t>& count_out_indices,
|
||||||
|
@ -2347,7 +2347,7 @@ private:
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
|
aiNodeAnim* GenerateScalingNodeAnim(const std::string& name,
|
||||||
const Model& target,
|
const Model& /*target*/,
|
||||||
const std::vector<const AnimationCurveNode*>& curves,
|
const std::vector<const AnimationCurveNode*>& curves,
|
||||||
const LayerMap& layer_map,
|
const LayerMap& layer_map,
|
||||||
double& max_time,
|
double& max_time,
|
||||||
|
@ -2378,7 +2378,7 @@ private:
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
|
aiNodeAnim* GenerateTranslationNodeAnim(const std::string& name,
|
||||||
const Model& target,
|
const Model& /*target*/,
|
||||||
const std::vector<const AnimationCurveNode*>& curves,
|
const std::vector<const AnimationCurveNode*>& curves,
|
||||||
const LayerMap& layer_map,
|
const LayerMap& layer_map,
|
||||||
double& max_time,
|
double& max_time,
|
||||||
|
@ -2830,7 +2830,7 @@ private:
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& layers,
|
void ConvertScaleKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes, const LayerMap& /*layers*/,
|
||||||
double& maxTime,
|
double& maxTime,
|
||||||
double& minTime)
|
double& minTime)
|
||||||
{
|
{
|
||||||
|
@ -2851,7 +2851,7 @@ private:
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
void ConvertTranslationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
||||||
const LayerMap& layers,
|
const LayerMap& /*layers*/,
|
||||||
double& maxTime,
|
double& maxTime,
|
||||||
double& minTime)
|
double& minTime)
|
||||||
{
|
{
|
||||||
|
@ -2869,7 +2869,7 @@ private:
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
void ConvertRotationKeys(aiNodeAnim* na, const std::vector<const AnimationCurveNode*>& nodes,
|
||||||
const LayerMap& layers,
|
const LayerMap& /*layers*/,
|
||||||
double& maxTime,
|
double& maxTime,
|
||||||
double& minTime,
|
double& minTime,
|
||||||
Model::RotOrder order)
|
Model::RotOrder order)
|
||||||
|
|
|
@ -696,7 +696,7 @@ public:
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/** Get the Skin attached to this geometry or NULL */
|
/** Get the Skin attached to this geometry or NULL */
|
||||||
const Skin* const DeformerSkin() const {
|
const Skin* DeformerSkin() const {
|
||||||
return skin;
|
return skin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1096,7 +1096,7 @@ public:
|
||||||
return transformLink;
|
return transformLink;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Model* const TargetNode() const {
|
const Model* TargetNode() const {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ Texture::~Texture()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& doc, const std::string& name)
|
LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name)
|
||||||
: Object(id,element,name)
|
: Object(id,element,name)
|
||||||
,texture(0)
|
,texture(0)
|
||||||
,blendMode(BlendMode_Modulate)
|
,blendMode(BlendMode_Modulate)
|
||||||
|
|
|
@ -506,7 +506,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
|
||||||
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
|
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
|
||||||
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
|
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
|
||||||
std::vector<char>& buff,
|
std::vector<char>& buff,
|
||||||
const Element& el)
|
const Element& /*el*/)
|
||||||
{
|
{
|
||||||
ai_assert(static_cast<size_t>(end-data) >= 4); // runtime check for this happens at tokenization stage
|
ai_assert(static_cast<size_t>(end-data) >= 4); // runtime check for this happens at tokenization stage
|
||||||
|
|
||||||
|
|
|
@ -143,8 +143,7 @@ private:
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T PropertyGet(const PropertyTable& in, const std::string& name,
|
inline T PropertyGet(const PropertyTable& in, const std::string& name,
|
||||||
const T& defaultValue,
|
const T& defaultValue)
|
||||||
bool ignoreTemplate = false)
|
|
||||||
{
|
{
|
||||||
const Property* const prop = in.Get(name);
|
const Property* const prop = in.Get(name);
|
||||||
if(!prop) {
|
if(!prop) {
|
||||||
|
@ -164,8 +163,7 @@ inline T PropertyGet(const PropertyTable& in, const std::string& name,
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T PropertyGet(const PropertyTable& in, const std::string& name,
|
inline T PropertyGet(const PropertyTable& in, const std::string& name,
|
||||||
bool& result,
|
bool& result)
|
||||||
bool ignoreTemplate = false)
|
|
||||||
{
|
{
|
||||||
const Property* const prop = in.Get(name);
|
const Property* const prop = in.Get(name);
|
||||||
if(!prop) {
|
if(!prop) {
|
||||||
|
|
|
@ -85,7 +85,7 @@ Intersect IntersectSegmentPlane(const IfcVector3& p,const IfcVector3& n, const I
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
|
void ProcessBooleanHalfSpaceDifference(const IfcHalfSpaceSolid* hs, TempMesh& result,
|
||||||
const TempMesh& first_operand,
|
const TempMesh& first_operand,
|
||||||
ConversionData& conv)
|
ConversionData& /*conv*/)
|
||||||
{
|
{
|
||||||
ai_assert(hs != NULL);
|
ai_assert(hs != NULL);
|
||||||
|
|
||||||
|
|
|
@ -259,7 +259,7 @@ BoundingBox GetBoundingBox(const ClipperLib::Polygon& poly)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void InsertWindowContours(const ContourVector& contours,
|
void InsertWindowContours(const ContourVector& contours,
|
||||||
const std::vector<TempOpening>& openings,
|
const std::vector<TempOpening>& /*openings*/,
|
||||||
TempMesh& curmesh)
|
TempMesh& curmesh)
|
||||||
{
|
{
|
||||||
// fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
|
// fix windows - we need to insert the real, polygonal shapes into the quadratic holes that we have now
|
||||||
|
|
|
@ -101,7 +101,7 @@ void ProcessOpenProfile(const IfcArbitraryOpenProfileDef& def, TempMesh& meshout
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& conv)
|
void ProcessParametrizedProfile(const IfcParameterizedProfileDef& def, TempMesh& meshout, ConversionData& /*conv*/)
|
||||||
{
|
{
|
||||||
if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
|
if(const IfcRectangleProfileDef* const cprofile = def.ToPtr<IfcRectangleProfileDef>()) {
|
||||||
const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
|
const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
|
||||||
|
|
|
@ -1045,7 +1045,7 @@ void IFC::GetSchema(EXPRESS::ConversionSchema& out)
|
||||||
namespace STEP {
|
namespace STEP {
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------
|
||||||
template <> size_t GenericFill<NotImplemented>(const STEP::DB& db, const LIST& params, NotImplemented* in)
|
template <> size_t GenericFill<NotImplemented>(const STEP::DB& /*db*/, const LIST& /*params*/, NotImplemented* /*in*/)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1253,7 +1253,7 @@ template <> size_t GenericFill<IfcPerformanceHistory>(const DB& db, const LIST&
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------
|
||||||
template <> size_t GenericFill<IfcRepresentationItem>(const DB& db, const LIST& params, IfcRepresentationItem* in)
|
template <> size_t GenericFill<IfcRepresentationItem>(const DB& /*db*/, const LIST& /*params*/, IfcRepresentationItem* /*in*/)
|
||||||
{
|
{
|
||||||
size_t base = 0;
|
size_t base = 0;
|
||||||
return base;
|
return base;
|
||||||
|
@ -1715,7 +1715,7 @@ template <> size_t GenericFill<IfcPlateType>(const DB& db, const LIST& params, I
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
// -----------------------------------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------------------------------
|
||||||
template <> size_t GenericFill<IfcObjectPlacement>(const DB& db, const LIST& params, IfcObjectPlacement* in)
|
template <> size_t GenericFill<IfcObjectPlacement>(const DB& /*db*/, const LIST& /*params*/, IfcObjectPlacement* /*in*/)
|
||||||
{
|
{
|
||||||
size_t base = 0;
|
size_t base = 0;
|
||||||
return base;
|
return base;
|
||||||
|
|
|
@ -376,14 +376,14 @@ void OgreBinarySerializer::ReadMeshSkeletonLink(Mesh *mesh)
|
||||||
mesh->skeletonRef = ReadLine();
|
mesh->skeletonRef = ReadLine();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreBinarySerializer::ReadMeshBounds(Mesh *mesh)
|
void OgreBinarySerializer::ReadMeshBounds(Mesh * /*mesh*/)
|
||||||
{
|
{
|
||||||
// Skip bounds, not compatible with Assimp.
|
// Skip bounds, not compatible with Assimp.
|
||||||
// 2x float vec3 + 1x float sphere radius
|
// 2x float vec3 + 1x float sphere radius
|
||||||
SkipBytes(sizeof(float) * 7);
|
SkipBytes(sizeof(float) * 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreBinarySerializer::ReadMeshExtremes(Mesh *mesh)
|
void OgreBinarySerializer::ReadMeshExtremes(Mesh * /*mesh*/)
|
||||||
{
|
{
|
||||||
// Skip extremes, not compatible with Assimp.
|
// Skip extremes, not compatible with Assimp.
|
||||||
size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
|
size_t numBytes = m_currentLen - MSTREAM_OVERHEAD_SIZE;
|
||||||
|
@ -643,7 +643,7 @@ void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest)
|
||||||
DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
|
DefaultLogger::get()->debug(Formatter::format() << " - Read vertex buffer for source " << bindIndex << " of " << numBytes << " bytes");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreBinarySerializer::ReadEdgeList(Mesh *mesh)
|
void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/)
|
||||||
{
|
{
|
||||||
// Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
|
// Assimp does not acknowledge LOD levels as far as I can see it. This info is just skipped.
|
||||||
|
|
||||||
|
@ -1054,7 +1054,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton)
|
||||||
DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
|
DefaultLogger::get()->debug(Formatter::format() << " " << anim->name << " (" << anim->length << " sec, " << anim->tracks.size() << " tracks)");
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton *skeleton, Animation *dest)
|
void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest)
|
||||||
{
|
{
|
||||||
uint16_t boneId = Read<uint16_t>();
|
uint16_t boneId = Read<uint16_t>();
|
||||||
Bone *bone = dest->parentSkeleton->BoneById(boneId);
|
Bone *bone = dest->parentSkeleton->BoneById(boneId);
|
||||||
|
@ -1096,7 +1096,7 @@ void OgreBinarySerializer::ReadSkeletonAnimationKeyFrame(VertexAnimationTrack *d
|
||||||
dest->transformKeyFrames.push_back(keyframe);
|
dest->transformKeyFrames.push_back(keyframe);
|
||||||
}
|
}
|
||||||
|
|
||||||
void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton *skeleton)
|
void OgreBinarySerializer::ReadSkeletonAnimationLink(Skeleton * /*skeleton*/)
|
||||||
{
|
{
|
||||||
// Skip bounds, not compatible with Assimp.
|
// Skip bounds, not compatible with Assimp.
|
||||||
ReadLine(); // skeleton name
|
ReadLine(); // skeleton name
|
||||||
|
|
|
@ -301,7 +301,7 @@ enum MeshChunkId
|
||||||
// unsigned short poseIndex
|
// unsigned short poseIndex
|
||||||
// float influence
|
// float influence
|
||||||
// Optional submesh extreme vertex list chink
|
// Optional submesh extreme vertex list chink
|
||||||
M_TABLE_EXTREMES = 0xE000,
|
M_TABLE_EXTREMES = 0xE000
|
||||||
// unsigned short submesh_index;
|
// unsigned short submesh_index;
|
||||||
// float extremes [n_extremes][3];
|
// float extremes [n_extremes][3];
|
||||||
};
|
};
|
||||||
|
|
|
@ -1105,7 +1105,7 @@ aiNode *Bone::ConvertToAssimpNode(Skeleton *skeleton, aiNode *parentNode)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
aiBone *Bone::ConvertToAssimpBone(Skeleton *parent, const std::vector<aiVertexWeight> &boneWeights)
|
aiBone *Bone::ConvertToAssimpBone(Skeleton * /*parent*/, const std::vector<aiVertexWeight> &boneWeights)
|
||||||
{
|
{
|
||||||
aiBone *bone = new aiBone();
|
aiBone *bone = new aiBone();
|
||||||
bone->mName = name;
|
bone->mName = name;
|
||||||
|
|
|
@ -68,25 +68,25 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
|
||||||
return (voidpf) io_system->Open(filename, mode_fopen);
|
return (voidpf) io_system->Open(filename, mode_fopen);
|
||||||
}
|
}
|
||||||
|
|
||||||
uLong IOSystem2Unzip::read(voidpf opaque, voidpf stream, void* buf, uLong size) {
|
uLong IOSystem2Unzip::read(voidpf /*opaque*/, voidpf stream, void* buf, uLong size) {
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
IOStream* io_stream = (IOStream*) stream;
|
||||||
|
|
||||||
return io_stream->Read(buf, 1, size);
|
return io_stream->Read(buf, 1, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
uLong IOSystem2Unzip::write(voidpf opaque, voidpf stream, const void* buf, uLong size) {
|
uLong IOSystem2Unzip::write(voidpf /*opaque*/, voidpf stream, const void* buf, uLong size) {
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
IOStream* io_stream = (IOStream*) stream;
|
||||||
|
|
||||||
return io_stream->Write(buf, 1, size);
|
return io_stream->Write(buf, 1, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
long IOSystem2Unzip::tell(voidpf opaque, voidpf stream) {
|
long IOSystem2Unzip::tell(voidpf /*opaque*/, voidpf stream) {
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
IOStream* io_stream = (IOStream*) stream;
|
||||||
|
|
||||||
return io_stream->Tell();
|
return io_stream->Tell();
|
||||||
}
|
}
|
||||||
|
|
||||||
long IOSystem2Unzip::seek(voidpf opaque, voidpf stream, uLong offset, int origin) {
|
long IOSystem2Unzip::seek(voidpf /*opaque*/, voidpf stream, uLong offset, int origin) {
|
||||||
IOStream* io_stream = (IOStream*) stream;
|
IOStream* io_stream = (IOStream*) stream;
|
||||||
|
|
||||||
aiOrigin assimp_origin;
|
aiOrigin assimp_origin;
|
||||||
|
@ -115,7 +115,7 @@ int IOSystem2Unzip::close(voidpf opaque, voidpf stream) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IOSystem2Unzip::testerror(voidpf opaque, voidpf stream) {
|
int IOSystem2Unzip::testerror(voidpf /*opaque*/, voidpf /*stream*/) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ enum aiImporterFlags
|
||||||
* should be used with care. This only happens for trunk
|
* should be used with care. This only happens for trunk
|
||||||
* (i.e. SVN) versions, experimental code is not included
|
* (i.e. SVN) versions, experimental code is not included
|
||||||
* in releases. */
|
* in releases. */
|
||||||
aiImporterFlags_Experimental = 0x10,
|
aiImporterFlags_Experimental = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
// Simple sample to prove that Assimp is easy to use with OpenGL.
|
// Simple sample to prove that Assimp is easy to use with OpenGL.
|
||||||
// It takes a file name as command line parameter, loads it using standard
|
// It takes a file name as command line parameter, loads it using standard
|
||||||
// settings and displays it.
|
// settings and displays it.
|
||||||
|
@ -9,29 +9,30 @@
|
||||||
// The vc8 solution links against assimp-release-dll_win32 - be sure to
|
// The vc8 solution links against assimp-release-dll_win32 - be sure to
|
||||||
// have this configuration built.
|
// have this configuration built.
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <GL/glut.h>
|
#include <GL/glut.h>
|
||||||
|
|
||||||
// assimp include files. These three are usually needed.
|
/* assimp include files. These three are usually needed. */
|
||||||
#include <assimp/cimport.h>
|
#include <assimp/cimport.h>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
|
|
||||||
// the global Assimp scene object
|
/* the global Assimp scene object */
|
||||||
const struct aiScene* scene = NULL;
|
const struct aiScene* scene = NULL;
|
||||||
GLuint scene_list = 0;
|
GLuint scene_list = 0;
|
||||||
struct aiVector3D scene_min, scene_max, scene_center;
|
struct aiVector3D scene_min, scene_max, scene_center;
|
||||||
|
|
||||||
// current rotation angle
|
/* current rotation angle */
|
||||||
static float angle = 0.f;
|
static float angle = 0.f;
|
||||||
|
|
||||||
#define aisgl_min(x,y) (x<y?x:y)
|
#define aisgl_min(x,y) (x<y?x:y)
|
||||||
#define aisgl_max(x,y) (y>x?y:x)
|
#define aisgl_max(x,y) (y>x?y:x)
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void reshape(int width, int height)
|
void reshape(int width, int height)
|
||||||
{
|
{
|
||||||
const double aspectRatio = (float) width / height, fieldOfView = 45.0;
|
const double aspectRatio = (float) width / height, fieldOfView = 45.0;
|
||||||
|
@ -43,7 +44,7 @@ void reshape(int width, int height)
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void get_bounding_box_for_node (const struct aiNode* nd,
|
void get_bounding_box_for_node (const struct aiNode* nd,
|
||||||
struct aiVector3D* min,
|
struct aiVector3D* min,
|
||||||
struct aiVector3D* max,
|
struct aiVector3D* max,
|
||||||
|
@ -78,7 +79,7 @@ void get_bounding_box_for_node (const struct aiNode* nd,
|
||||||
*trafo = prev;
|
*trafo = prev;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max)
|
void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max)
|
||||||
{
|
{
|
||||||
struct aiMatrix4x4 trafo;
|
struct aiMatrix4x4 trafo;
|
||||||
|
@ -89,7 +90,7 @@ void get_bounding_box (struct aiVector3D* min, struct aiVector3D* max)
|
||||||
get_bounding_box_for_node(scene->mRootNode,min,max,&trafo);
|
get_bounding_box_for_node(scene->mRootNode,min,max,&trafo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void color4_to_float4(const struct aiColor4D *c, float f[4])
|
void color4_to_float4(const struct aiColor4D *c, float f[4])
|
||||||
{
|
{
|
||||||
f[0] = c->r;
|
f[0] = c->r;
|
||||||
|
@ -98,7 +99,7 @@ void color4_to_float4(const struct aiColor4D *c, float f[4])
|
||||||
f[3] = c->a;
|
f[3] = c->a;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void set_float4(float f[4], float a, float b, float c, float d)
|
void set_float4(float f[4], float a, float b, float c, float d)
|
||||||
{
|
{
|
||||||
f[0] = a;
|
f[0] = a;
|
||||||
|
@ -107,7 +108,7 @@ void set_float4(float f[4], float a, float b, float c, float d)
|
||||||
f[3] = d;
|
f[3] = d;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void apply_material(const struct aiMaterial *mtl)
|
void apply_material(const struct aiMaterial *mtl)
|
||||||
{
|
{
|
||||||
float c[4];
|
float c[4];
|
||||||
|
@ -173,19 +174,19 @@ void apply_material(const struct aiMaterial *mtl)
|
||||||
glEnable(GL_CULL_FACE);
|
glEnable(GL_CULL_FACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
|
void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned int n = 0, t;
|
unsigned int n = 0, t;
|
||||||
struct aiMatrix4x4 m = nd->mTransformation;
|
struct aiMatrix4x4 m = nd->mTransformation;
|
||||||
|
|
||||||
// update transform
|
/* update transform */
|
||||||
aiTransposeMatrix4(&m);
|
aiTransposeMatrix4(&m);
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glMultMatrixf((float*)&m);
|
glMultMatrixf((float*)&m);
|
||||||
|
|
||||||
// draw all meshes assigned to this node
|
/* draw all meshes assigned to this node */
|
||||||
for (; n < nd->mNumMeshes; ++n) {
|
for (; n < nd->mNumMeshes; ++n) {
|
||||||
const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
|
const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
|
||||||
|
|
||||||
|
@ -224,7 +225,7 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// draw all children
|
/* draw all children */
|
||||||
for (n = 0; n < nd->mNumChildren; ++n) {
|
for (n = 0; n < nd->mNumChildren; ++n) {
|
||||||
recursive_render(sc, nd->mChildren[n]);
|
recursive_render(sc, nd->mChildren[n]);
|
||||||
}
|
}
|
||||||
|
@ -232,7 +233,7 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd)
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void do_motion (void)
|
void do_motion (void)
|
||||||
{
|
{
|
||||||
static GLint prev_time = 0;
|
static GLint prev_time = 0;
|
||||||
|
@ -244,7 +245,7 @@ void do_motion (void)
|
||||||
prev_time = time;
|
prev_time = time;
|
||||||
|
|
||||||
frames += 1;
|
frames += 1;
|
||||||
if ((time - prev_fps_time) > 1000) // update every seconds
|
if ((time - prev_fps_time) > 1000) /* update every seconds */
|
||||||
{
|
{
|
||||||
int current_fps = frames * 1000 / (time - prev_fps_time);
|
int current_fps = frames * 1000 / (time - prev_fps_time);
|
||||||
printf("%d fps\n", current_fps);
|
printf("%d fps\n", current_fps);
|
||||||
|
@ -256,7 +257,7 @@ void do_motion (void)
|
||||||
glutPostRedisplay ();
|
glutPostRedisplay ();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
void display(void)
|
void display(void)
|
||||||
{
|
{
|
||||||
float tmp;
|
float tmp;
|
||||||
|
@ -267,27 +268,27 @@ void display(void)
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f);
|
gluLookAt(0.f,0.f,3.f,0.f,0.f,-5.f,0.f,1.f,0.f);
|
||||||
|
|
||||||
// rotate it around the y axis
|
/* rotate it around the y axis */
|
||||||
glRotatef(angle,0.f,1.f,0.f);
|
glRotatef(angle,0.f,1.f,0.f);
|
||||||
|
|
||||||
// scale the whole asset to fit into our view frustum
|
/* scale the whole asset to fit into our view frustum */
|
||||||
tmp = scene_max.x-scene_min.x;
|
tmp = scene_max.x-scene_min.x;
|
||||||
tmp = aisgl_max(scene_max.y - scene_min.y,tmp);
|
tmp = aisgl_max(scene_max.y - scene_min.y,tmp);
|
||||||
tmp = aisgl_max(scene_max.z - scene_min.z,tmp);
|
tmp = aisgl_max(scene_max.z - scene_min.z,tmp);
|
||||||
tmp = 1.f / tmp;
|
tmp = 1.f / tmp;
|
||||||
glScalef(tmp, tmp, tmp);
|
glScalef(tmp, tmp, tmp);
|
||||||
|
|
||||||
// center the model
|
/* center the model */
|
||||||
glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z );
|
glTranslatef( -scene_center.x, -scene_center.y, -scene_center.z );
|
||||||
|
|
||||||
// if the display list has not been made yet, create a new one and
|
/* if the display list has not been made yet, create a new one and
|
||||||
// fill it with scene contents
|
fill it with scene contents */
|
||||||
if(scene_list == 0) {
|
if(scene_list == 0) {
|
||||||
scene_list = glGenLists(1);
|
scene_list = glGenLists(1);
|
||||||
glNewList(scene_list, GL_COMPILE);
|
glNewList(scene_list, GL_COMPILE);
|
||||||
// now begin at the root node of the imported data and traverse
|
/* now begin at the root node of the imported data and traverse
|
||||||
// the scenegraph by multiplying subsequent local transforms
|
the scenegraph by multiplying subsequent local transforms
|
||||||
// together on GL's matrix stack.
|
together on GL's matrix stack. */
|
||||||
recursive_render(scene, scene->mRootNode);
|
recursive_render(scene, scene->mRootNode);
|
||||||
glEndList();
|
glEndList();
|
||||||
}
|
}
|
||||||
|
@ -299,11 +300,11 @@ void display(void)
|
||||||
do_motion();
|
do_motion();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
int loadasset (const char* path)
|
int loadasset (const char* path)
|
||||||
{
|
{
|
||||||
// we are taking one of the postprocessing presets to avoid
|
/* we are taking one of the postprocessing presets to avoid
|
||||||
// spelling out 20+ single postprocessing flags here.
|
spelling out 20+ single postprocessing flags here. */
|
||||||
scene = aiImportFile(path,aiProcessPreset_TargetRealtime_MaxQuality);
|
scene = aiImportFile(path,aiProcessPreset_TargetRealtime_MaxQuality);
|
||||||
|
|
||||||
if (scene) {
|
if (scene) {
|
||||||
|
@ -316,7 +317,7 @@ int loadasset (const char* path)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
/* ---------------------------------------------------------------------------- */
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
struct aiLogStream stream;
|
struct aiLogStream stream;
|
||||||
|
@ -330,21 +331,21 @@ int main(int argc, char **argv)
|
||||||
glutDisplayFunc(display);
|
glutDisplayFunc(display);
|
||||||
glutReshapeFunc(reshape);
|
glutReshapeFunc(reshape);
|
||||||
|
|
||||||
// get a handle to the predefined STDOUT log stream and attach
|
/* get a handle to the predefined STDOUT log stream and attach
|
||||||
// it to the logging system. It remains active for all further
|
it to the logging system. It remains active for all further
|
||||||
// calls to aiImportFile(Ex) and aiApplyPostProcessing.
|
calls to aiImportFile(Ex) and aiApplyPostProcessing. */
|
||||||
stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
|
stream = aiGetPredefinedLogStream(aiDefaultLogStream_STDOUT,NULL);
|
||||||
aiAttachLogStream(&stream);
|
aiAttachLogStream(&stream);
|
||||||
|
|
||||||
// ... same procedure, but this stream now writes the
|
/* ... same procedure, but this stream now writes the
|
||||||
// log messages to assimp_log.txt
|
log messages to assimp_log.txt */
|
||||||
stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt");
|
stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt");
|
||||||
aiAttachLogStream(&stream);
|
aiAttachLogStream(&stream);
|
||||||
|
|
||||||
// the model name can be specified on the command line. If none
|
/* the model name can be specified on the command line. If none
|
||||||
// is specified, we try to locate one of the more expressive test
|
is specified, we try to locate one of the more expressive test
|
||||||
// models from the repository (/models-nonbsd may be missing in
|
models from the repository (/models-nonbsd may be missing in
|
||||||
// some distributions so we need a fallback from /models!).
|
some distributions so we need a fallback from /models!). */
|
||||||
if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) {
|
if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) {
|
||||||
if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) {
|
if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -354,14 +355,14 @@ int main(int argc, char **argv)
|
||||||
glClearColor(0.1f,0.1f,0.1f,1.f);
|
glClearColor(0.1f,0.1f,0.1f,1.f);
|
||||||
|
|
||||||
glEnable(GL_LIGHTING);
|
glEnable(GL_LIGHTING);
|
||||||
glEnable(GL_LIGHT0); // Uses default lighting parameters
|
glEnable(GL_LIGHT0); /* Uses default lighting parameters */
|
||||||
|
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
|
||||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
||||||
glEnable(GL_NORMALIZE);
|
glEnable(GL_NORMALIZE);
|
||||||
|
|
||||||
// XXX docs say all polygons are emitted CCW, but tests show that some aren't.
|
/* XXX docs say all polygons are emitted CCW, but tests show that some aren't. */
|
||||||
if(getenv("MODEL_IS_BROKEN"))
|
if(getenv("MODEL_IS_BROKEN"))
|
||||||
glFrontFace(GL_CW);
|
glFrontFace(GL_CW);
|
||||||
|
|
||||||
|
@ -370,14 +371,15 @@ int main(int argc, char **argv)
|
||||||
glutGet(GLUT_ELAPSED_TIME);
|
glutGet(GLUT_ELAPSED_TIME);
|
||||||
glutMainLoop();
|
glutMainLoop();
|
||||||
|
|
||||||
// cleanup - calling 'aiReleaseImport' is important, as the library
|
/* cleanup - calling 'aiReleaseImport' is important, as the library
|
||||||
// keeps internal resources until the scene is freed again. Not
|
keeps internal resources until the scene is freed again. Not
|
||||||
// doing so can cause severe resource leaking.
|
doing so can cause severe resource leaking. */
|
||||||
aiReleaseImport(scene);
|
aiReleaseImport(scene);
|
||||||
|
|
||||||
// We added a log stream to the library, it's our job to disable it
|
/* We added a log stream to the library, it's our job to disable it
|
||||||
// again. This will definitely release the last resources allocated
|
again. This will definitely release the last resources allocated
|
||||||
// by Assimp.
|
by Assimp.*/
|
||||||
aiDetachAllLogStreams();
|
aiDetachAllLogStreams();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
// This is just a small test to check whether Assimp's API compiles from C
|
/* This is just a small test to check whether Assimp's API compiles from C */
|
||||||
|
|
||||||
#include <assimp/postprocess.h>
|
#include <assimp/postprocess.h>
|
||||||
#include <assimp/scene.h>
|
#include <assimp/scene.h>
|
||||||
|
|
|
@ -72,7 +72,7 @@ static const aiImporterDesc desc = {
|
||||||
|
|
||||||
|
|
||||||
bool TestPlugin :: CanRead( const std::string& pFile,
|
bool TestPlugin :: CanRead( const std::string& pFile,
|
||||||
IOSystem* pIOHandler, bool test) const
|
IOSystem* /*pIOHandler*/, bool /*test*/) const
|
||||||
{
|
{
|
||||||
std::string::size_type pos = pFile.find_last_of('.');
|
std::string::size_type pos = pFile.find_last_of('.');
|
||||||
// no file extension - can't read
|
// no file extension - can't read
|
||||||
|
@ -90,8 +90,8 @@ const aiImporterDesc* TestPlugin :: GetInfo() const
|
||||||
return & desc;
|
return & desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestPlugin :: InternReadFile( const std::string& pFile,
|
void TestPlugin :: InternReadFile( const std::string& /*pFile*/,
|
||||||
aiScene* pScene, IOSystem* pIOHandler)
|
aiScene* /*pScene*/, IOSystem* /*pIOHandler*/)
|
||||||
{
|
{
|
||||||
throw DeadlyImportError(AIUT_DEF_ERROR_TEXT);
|
throw DeadlyImportError(AIUT_DEF_ERROR_TEXT);
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,7 +656,7 @@ uint32_t WriteBinaryScene(const aiScene* scene)
|
||||||
// -----------------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------------
|
||||||
// Write a binary model dump
|
// Write a binary model dump
|
||||||
void WriteBinaryDump(const aiScene* scene, FILE* _out, const char* src, const char* cmd,
|
void WriteBinaryDump(const aiScene* scene, FILE* _out, const char* src, const char* cmd,
|
||||||
bool _shortened, bool compressed, ImportData& imp)
|
bool _shortened, bool compressed, ImportData& /*imp*/)
|
||||||
{
|
{
|
||||||
out = _out;
|
out = _out;
|
||||||
shortened = _shortened;
|
shortened = _shortened;
|
||||||
|
|
Loading…
Reference in New Issue