- FooArchive : 디렉토리 처리? 뭐 그런거라고 보자
- FooArchiveFactory : 보일러플레이트
- FooDataStream : 파일스트림 처리? 그렇게 생각하면 굳
리소스매니저를 통해 리소스에 접근이 가능하다.
아직 파일포맷에 대해서 생각하지는 않았지만 위와 같은 과정을 테스트해보기 위한 코드를 만들어보고 적어둔다.
fooarchive.hpp 는 위 세 클래스의 선언을 모두 담았다.
펼쳐두기..
[code cpp]
// 예를들어 foo 타입의 아카이브를 지원하려면
// 아래 세개의 클래스를 만들고
// 1. FooArchive
// 2. FooArchiveFactory
// 3. FooDataStream
//
// FooArchiveFactory 를 ArchiveManager 에 등록한후
// 리소스매니저를 통해 쓰면 된다.
#pragma once
#ifndef _FOOARCHIVE_H_
#define _FOOARCHIVE_H_
#include <OgrePrerequisites.h>
#include <OgreArchive.h>
#include <OgreArchiveFactory.h>
class FooArchive : public Ogre::Archive
{
public:
FooArchive(const Ogre::String name, const Ogre::String& archType);
~FooArchive();
bool isCaseSensitive() const { return true; }
void load();
void unload();
bool isReadOnly() const { return true; }
Ogre::DataStreamPtr open(const Ogre::String& filename) const;
Ogre::StringVectorPtr list(bool recursive=true, bool dirs=false);
Ogre::FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false);
Ogre::StringVectorPtr find(const Ogre::String& pattern, bool recursive = true, bool dirs = false);
Ogre::FileInfoListPtr findFileInfo(const Ogre::String& pattern, bool recursive = true, bool dirs = false);
bool exists(const Ogre::String& filename);
time_t getModifiedTime(const Ogre::String& filename);
};
class FooArchiveFactory : public Ogre::ArchiveFactory
{
public:
virtual ~FooArchiveFactory();
const Ogre::String& getType() const;
Ogre::Archive *createInstance(const Ogre::String& name);
void destroyInstance(Ogre::Archive* arch);
};
class FooDataStream : public Ogre::DataStream
{
public:
FooDataStream(const Ogre::String& name);
size_t read(void* buf, size_t count);
void skip(long count);
void seek(size_t pos);
size_t tell() const;
bool eof() const;
void close();
private:
size_t idx_;
char buf_[26];
};
#endif /* _FOOARCHIVE_H_ */
[/code]
// 예를들어 foo 타입의 아카이브를 지원하려면
// 아래 세개의 클래스를 만들고
// 1. FooArchive
// 2. FooArchiveFactory
// 3. FooDataStream
//
// FooArchiveFactory 를 ArchiveManager 에 등록한후
// 리소스매니저를 통해 쓰면 된다.
#pragma once
#ifndef _FOOARCHIVE_H_
#define _FOOARCHIVE_H_
#include <OgrePrerequisites.h>
#include <OgreArchive.h>
#include <OgreArchiveFactory.h>
class FooArchive : public Ogre::Archive
{
public:
FooArchive(const Ogre::String name, const Ogre::String& archType);
~FooArchive();
bool isCaseSensitive() const { return true; }
void load();
void unload();
bool isReadOnly() const { return true; }
Ogre::DataStreamPtr open(const Ogre::String& filename) const;
Ogre::StringVectorPtr list(bool recursive=true, bool dirs=false);
Ogre::FileInfoListPtr listFileInfo(bool recursive = true, bool dirs = false);
Ogre::StringVectorPtr find(const Ogre::String& pattern, bool recursive = true, bool dirs = false);
Ogre::FileInfoListPtr findFileInfo(const Ogre::String& pattern, bool recursive = true, bool dirs = false);
bool exists(const Ogre::String& filename);
time_t getModifiedTime(const Ogre::String& filename);
};
class FooArchiveFactory : public Ogre::ArchiveFactory
{
public:
virtual ~FooArchiveFactory();
const Ogre::String& getType() const;
Ogre::Archive *createInstance(const Ogre::String& name);
void destroyInstance(Ogre::Archive* arch);
};
class FooDataStream : public Ogre::DataStream
{
public:
FooDataStream(const Ogre::String& name);
size_t read(void* buf, size_t count);
void skip(long count);
void seek(size_t pos);
size_t tell() const;
bool eof() const;
void close();
private:
size_t idx_;
char buf_[26];
};
#endif /* _FOOARCHIVE_H_ */
[/code]
fooarchive.cpp 는 FooArchive 클래스의 구현만 담았다.
펼쳐두기..
[code cpp]
#include "fooarchive.hpp"
#include <OgreStringVector.h>
using namespace Ogre;
FooArchive::FooArchive(const Ogre::String name, const Ogre::String& archType) : Archive(name, archType)
{
}
FooArchive::~FooArchive()
{
}
void FooArchive::load()
{
}
void FooArchive::unload()
{
}
DataStreamPtr FooArchive::open(const String& filename) const
{
return DataStreamPtr(new FooDataStream(filename));
}
StringVectorPtr FooArchive::list(bool recursive, bool dirs)
{
// 걍 적당히 파일 두개를 가지고 있는셈 친다.
StringVectorPtr v(new StringVector);
v->push_back("1.foo");
v->push_back("2.foo");
return v;
}
FileInfoListPtr FooArchive::listFileInfo(bool recursive, bool dirs)
{
// 음 채울 정보가 많네. 그냥 빈거 줘본다.
// 원래는 이놈을 먼저 구현하고 list 를 구현해야 겠구나.
FileInfoListPtr fil(new FileInfoList);
return fil;
}
StringVectorPtr FooArchive::find(const String& pattern, bool recursive, bool dirs)
{
return StringVectorPtr(new StringVector);
}
FileInfoListPtr FooArchive::findFileInfo(const String& pattern, bool recursive, bool dirs)
{
return FileInfoListPtr(new FileInfoList);
}
bool FooArchive::exists(const String& filename)
{
return filename == "1.foo" || filename == "2.foo";
}
time_t FooArchive::getModifiedTime(const String& filename)
{
return 0;
}
[/code]
#include "fooarchive.hpp"
#include <OgreStringVector.h>
using namespace Ogre;
FooArchive::FooArchive(const Ogre::String name, const Ogre::String& archType) : Archive(name, archType)
{
}
FooArchive::~FooArchive()
{
}
void FooArchive::load()
{
}
void FooArchive::unload()
{
}
DataStreamPtr FooArchive::open(const String& filename) const
{
return DataStreamPtr(new FooDataStream(filename));
}
StringVectorPtr FooArchive::list(bool recursive, bool dirs)
{
// 걍 적당히 파일 두개를 가지고 있는셈 친다.
StringVectorPtr v(new StringVector);
v->push_back("1.foo");
v->push_back("2.foo");
return v;
}
FileInfoListPtr FooArchive::listFileInfo(bool recursive, bool dirs)
{
// 음 채울 정보가 많네. 그냥 빈거 줘본다.
// 원래는 이놈을 먼저 구현하고 list 를 구현해야 겠구나.
FileInfoListPtr fil(new FileInfoList);
return fil;
}
StringVectorPtr FooArchive::find(const String& pattern, bool recursive, bool dirs)
{
return StringVectorPtr(new StringVector);
}
FileInfoListPtr FooArchive::findFileInfo(const String& pattern, bool recursive, bool dirs)
{
return FileInfoListPtr(new FileInfoList);
}
bool FooArchive::exists(const String& filename)
{
return filename == "1.foo" || filename == "2.foo";
}
time_t FooArchive::getModifiedTime(const String& filename)
{
return 0;
}
[/code]
fooarchivefactory.cpp 는 FooArchvieFactory 클래스의 구현만 담았다.
펼쳐두기..
[code cpp]
#include "fooarchive.hpp"
#include <iostream>
using namespace Ogre;
using namespace std;
FooArchiveFactory::~FooArchiveFactory()
{
}
const String& FooArchiveFactory::getType() const
{
static const String s = "foo";
return s;
}
Archive* FooArchiveFactory::createInstance(const String& name)
{
// OGRE_NEW 등을 제공하는 모양인데 그냥 new 썼다.
return new FooArchive(name, "foo");
}
void FooArchiveFactory::destroyInstance(Ogre::Archive* arch)
{
delete arch;
}
[/code]
#include "fooarchive.hpp"
#include <iostream>
using namespace Ogre;
using namespace std;
FooArchiveFactory::~FooArchiveFactory()
{
}
const String& FooArchiveFactory::getType() const
{
static const String s = "foo";
return s;
}
Archive* FooArchiveFactory::createInstance(const String& name)
{
// OGRE_NEW 등을 제공하는 모양인데 그냥 new 썼다.
return new FooArchive(name, "foo");
}
void FooArchiveFactory::destroyInstance(Ogre::Archive* arch)
{
delete arch;
}
[/code]
foodatastream.cpp 는 FooDataStream 클래스의 구현만 담았다. 이쪽은 대강 구현한거라 버그가 많을듯. 어차피 내용 붙이면 모두 새로구현해야한다.
펼쳐두기..
[code cpp]
#include "fooarchive.hpp"
#include <algorithm>
using namespace std;
FooDataStream::FooDataStream(const Ogre::String& name) : DataStream(name)
{
// 어차피 예제 아닌가 그냥 적당히 고정 버퍼를 박았다.
mSize = sizeof(buf_);
idx_ = 0;
for(size_t i = 0; i < mSize; ++i)
{
buf_[i] = 'a'+i;
}
}
size_t FooDataStream::read(void* buf, size_t count)
{
int readlen = min(count, mSize - idx_);
memcpy(buf, buf_ + idx_, readlen);
idx_ += readlen;
return readlen;
}
void FooDataStream::skip(long count)
{
idx_ += count;
idx_ = min(idx_, mSize);
}
void FooDataStream::seek(size_t pos)
{
if(pos < mSize)
idx_ = pos;
}
size_t FooDataStream::tell() const
{
return idx_;
}
bool FooDataStream::eof() const
{
return idx_ == mSize;
}
void FooDataStream::close()
{
}
[/code]
#include "fooarchive.hpp"
#include <algorithm>
using namespace std;
FooDataStream::FooDataStream(const Ogre::String& name) : DataStream(name)
{
// 어차피 예제 아닌가 그냥 적당히 고정 버퍼를 박았다.
mSize = sizeof(buf_);
idx_ = 0;
for(size_t i = 0; i < mSize; ++i)
{
buf_[i] = 'a'+i;
}
}
size_t FooDataStream::read(void* buf, size_t count)
{
int readlen = min(count, mSize - idx_);
memcpy(buf, buf_ + idx_, readlen);
idx_ += readlen;
return readlen;
}
void FooDataStream::skip(long count)
{
idx_ += count;
idx_ = min(idx_, mSize);
}
void FooDataStream::seek(size_t pos)
{
if(pos < mSize)
idx_ = pos;
}
size_t FooDataStream::tell() const
{
return idx_;
}
bool FooDataStream::eof() const
{
return idx_ == mSize;
}
void FooDataStream::close()
{
}
[/code]
archive.cpp 는 위 세 클래스를 써먹는 예제를 담았다. 등록하는 코드도 봐두자..
펼쳐두기..
[code cpp]
#include "fooarchive.hpp"
#include <Ogre.h>
#include <iostream>
using namespace Ogre;
using namespace std;
class OgreApp
{
public:
OgreApp()
{
// root 를 만들기 전에는 ArchiveFactory 등록이 불가?
root_ = new Root("", "");
// 이제 등록가능하겠지
//
// 등록이 포인터를 등록하는 스타일이라 이걸 언제 delete 해줘야
// 하는지 애매한데 코드를 읽어보니 (1.6.4) delete 는 불러주지
// 않는다. 따라서 밖에서 포인터를 들고있다가 때되면(root
// 지운후가 되겠지) 지워주는 수고를 해줘야 한다.
faf_ = new FooArchiveFactory;
ArchiveManager& am = ArchiveManager::getSingleton();
am.addArchiveFactory(faf_);
// foo 타입을 처리하는 아카이브팩토리를 등록했으니 이제 foo 타입 리소스 추가가 가능할것이다
ResourceGroupManager& rgm = ResourceGroupManager::getSingleton();
rgm.addResourceLocation("noname", "foo", "nogroup");
rgm.initialiseAllResourceGroups();
// loadResourceGroup 을 하면 리소스를 완전히
// 로딩한다는데.. 지금 예제에선 별 의미가 없긴 하군.
rgm.loadResourceGroup("nogroup");
// 이제 리소스이름들을 읽어보자
// FooArchive 의 list 정도가 불리겠지?
StringVectorPtr v = rgm.listResourceNames("nogroup");
for(StringVector::const_iterator i = v->begin(); i != v->end(); ++i)
{
cout << "name: " << *i << endl;
}
// 이제 실제로 리소스에 접근을 해보자
for(StringVector::const_iterator i = v->begin(); i != v->end(); ++i)
{
cout << *i << " ==> " << rgm.openResource(*i, "nogroup")->getAsString() << endl;
}
}
~OgreApp()
{
delete root_;
delete faf_;
}
private:
Root* root_;
FooArchiveFactory* faf_;
};
int main()
{
OgreApp app;
}
[/code]
위 소스들을 빌드하는데 쓰인 CMakeLists.txt 의 일부. 아래 언급된 link_ogre3d_all() 매크로는 다른 파일에 있는데 적지 않았다.#include "fooarchive.hpp"
#include <Ogre.h>
#include <iostream>
using namespace Ogre;
using namespace std;
class OgreApp
{
public:
OgreApp()
{
// root 를 만들기 전에는 ArchiveFactory 등록이 불가?
root_ = new Root("", "");
// 이제 등록가능하겠지
//
// 등록이 포인터를 등록하는 스타일이라 이걸 언제 delete 해줘야
// 하는지 애매한데 코드를 읽어보니 (1.6.4) delete 는 불러주지
// 않는다. 따라서 밖에서 포인터를 들고있다가 때되면(root
// 지운후가 되겠지) 지워주는 수고를 해줘야 한다.
faf_ = new FooArchiveFactory;
ArchiveManager& am = ArchiveManager::getSingleton();
am.addArchiveFactory(faf_);
// foo 타입을 처리하는 아카이브팩토리를 등록했으니 이제 foo 타입 리소스 추가가 가능할것이다
ResourceGroupManager& rgm = ResourceGroupManager::getSingleton();
rgm.addResourceLocation("noname", "foo", "nogroup");
rgm.initialiseAllResourceGroups();
// loadResourceGroup 을 하면 리소스를 완전히
// 로딩한다는데.. 지금 예제에선 별 의미가 없긴 하군.
rgm.loadResourceGroup("nogroup");
// 이제 리소스이름들을 읽어보자
// FooArchive 의 list 정도가 불리겠지?
StringVectorPtr v = rgm.listResourceNames("nogroup");
for(StringVector::const_iterator i = v->begin(); i != v->end(); ++i)
{
cout << "name: " << *i << endl;
}
// 이제 실제로 리소스에 접근을 해보자
for(StringVector::const_iterator i = v->begin(); i != v->end(); ++i)
{
cout << *i << " ==> " << rgm.openResource(*i, "nogroup")->getAsString() << endl;
}
}
~OgreApp()
{
delete root_;
delete faf_;
}
private:
Root* root_;
FooArchiveFactory* faf_;
};
int main()
{
OgreApp app;
}
[/code]
펼쳐두기..
[code]
project(archive)
link_ogre3d_all()
add_library(fooarchive fooarchive.cpp fooarchivefactory.cpp foodatastream.cpp)
add_executable(archive archive.cpp)
target_link_libraries(archive fooarchive)
[/code]
project(archive)
link_ogre3d_all()
add_library(fooarchive fooarchive.cpp fooarchivefactory.cpp foodatastream.cpp)
add_executable(archive archive.cpp)
target_link_libraries(archive fooarchive)
[/code]
댓글 없음:
댓글 쓰기