mirror of https://github.com/Poikilos/b3view
cycle through textures thanks to C++17 filesystem
parent
1a77f1cc33
commit
bf870ab941
|
@ -13,6 +13,7 @@
|
|||
* icon, install scripts, and mime type (`model/b3d`)--see README.md
|
||||
* mime type (`model/x`)
|
||||
* added ClearSansRegular.ttf
|
||||
* hotkeys to cycle ../textures/*
|
||||
|
||||
### Changed
|
||||
* The program can now start without "test.b3d" in the current working
|
||||
|
|
11
Engine.cpp
11
Engine.cpp
|
@ -208,9 +208,16 @@ void Engine::reloadMesh()
|
|||
}
|
||||
}
|
||||
|
||||
void Engine::loadTexture(const wstring &fileName)
|
||||
bool Engine::loadTexture(const wstring &fileName)
|
||||
{
|
||||
m_LoadedMesh->setMaterialTexture(0, this->m_Driver->getTexture(fileName.c_str()));
|
||||
ITexture* texture = this->m_Driver->getTexture(fileName.c_str());
|
||||
bool ret = false;
|
||||
if (texture != nullptr) {
|
||||
m_LoadedMesh->setMaterialTexture(0, texture);
|
||||
ret = true;
|
||||
}
|
||||
this->m_PrevTexturePath = fileName;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Engine::setMeshDisplayMode( bool wireframe, bool lighting )
|
||||
|
|
3
Engine.h
3
Engine.h
|
@ -58,6 +58,7 @@ private:
|
|||
|
||||
public:
|
||||
std::wstring m_PreviousPath;
|
||||
std::wstring m_PrevTexturePath;
|
||||
|
||||
|
||||
Engine();
|
||||
|
@ -66,7 +67,7 @@ public:
|
|||
void run();
|
||||
void loadMesh( const std::wstring &fileName );
|
||||
void reloadMesh();
|
||||
void loadTexture( const std::wstring &fileName );
|
||||
bool loadTexture( const std::wstring &fileName );
|
||||
void setMeshDisplayMode( bool wireframe = false, bool lighting = true );
|
||||
bool isAnimating();
|
||||
void playAnimation();
|
||||
|
|
17
README.md
17
README.md
|
@ -1,13 +1,17 @@
|
|||
# b3view
|
||||
View B3D or X files (and possibly other files supported by Irrlicht)
|
||||
View B3D, X, OBJ files (and possibly other files supported by Irrlicht)
|
||||
with double-click if this program is associated with the file types.
|
||||
|
||||
This is a modernized fork by poikilos (see CHANGELOG.md).
|
||||
|
||||
## Compiling
|
||||
* You may need gcc 8.2.1 or higher (C++17 filesystem works on 8.2.1
|
||||
for sure)
|
||||
* Make sure you have the Irrlicht and Qt development packages
|
||||
(such as via `sudo dnf -y install qt-devel qt-creator irrlicht-devel`
|
||||
on Fedora 29)
|
||||
- Qt is not actually used, only Qt creator (the `CONFIG -= qt`
|
||||
setting is used in the `.pro` file).
|
||||
* Open Qt Creator, click File, Open, then choose this project's .pro
|
||||
file.
|
||||
* Build & Run (if you have trouble compiling, see
|
||||
|
@ -20,12 +24,12 @@ This is a modernized fork by poikilos (see CHANGELOG.md).
|
|||
|
||||
## Installation
|
||||
### Windows
|
||||
* copy install.bat to your build directory if you are not using a
|
||||
release version.
|
||||
* If you are not using a release version, compile the program (see
|
||||
above) then copy install.bat to your build directory.
|
||||
* double-click install.bat (read any messages that appear then press
|
||||
a key to continue when prompted).
|
||||
* Associate the b3d file extension (and possibly other Irrlicht-
|
||||
compatible 3D mesh formats) with
|
||||
* Associate the B3D file extension (and possibly other Irrlicht-
|
||||
compatible 3D mesh formats--X and OBJ are tested) with
|
||||
`%USERPROFILE%\Applications\b3view\b3view.exe` (right-click a b3d
|
||||
file, then Open With, show additional programs, then either paste that
|
||||
path or choose This PC, C:, Users, your username, Applications,
|
||||
|
@ -59,6 +63,9 @@ This is a modernized fork by poikilos (see CHANGELOG.md).
|
|||
"Slower," or use `-` key or `+`/`=` key. By default, the world runs
|
||||
at 60fps and the animation runs as 30 fps (Irrlicht does interpolation
|
||||
automatically).
|
||||
* cycle through textures in `../textures` using `t` key (`e` to go back)
|
||||
(such as for Minetest mods, where model must be in `modname/models/`
|
||||
and texture must be in `modname/textures/`)
|
||||
|
||||
## Known Issues
|
||||
* Warn on missing texture.
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#include "UserInterface.h"
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
//#include <filesystem>
|
||||
#include <experimental/filesystem>
|
||||
|
||||
using namespace irr;
|
||||
using namespace irr::core;
|
||||
|
@ -7,6 +10,12 @@ using namespace irr::gui;
|
|||
|
||||
using std::string;
|
||||
using std::wstring;
|
||||
using namespace std;
|
||||
|
||||
// C++14: namespace filesystem = std::experimental::filesystem;
|
||||
// namespace fs = std::filesystem; // doesn't work (not a namespace in gcc's C++17)
|
||||
// using namespace std::filesystem; // doesn't work (not a namespace in gcc's C++17)
|
||||
namespace fs = std::experimental::filesystem;
|
||||
|
||||
// PRIVATE
|
||||
void UserInterface::setupUserInterface()
|
||||
|
@ -159,6 +168,81 @@ void UserInterface::drawStatusLine() const
|
|||
{
|
||||
}
|
||||
|
||||
bool UserInterface::loadNextTexture(int direction)
|
||||
{
|
||||
bool ret = false;
|
||||
this->m_Engine->m_NextPath = L"";
|
||||
std::wstring basePath = L".";
|
||||
if (this->m_Engine->m_PreviousPath.length() > 0) {
|
||||
// std::wcerr << "this->m_PreviousPath: " << this->m_PreviousPath.c_str() << endl;
|
||||
std::wstring lastName = Utility::basename(this->m_Engine->m_PreviousPath);
|
||||
std::wstring lastDirPath = Utility::parentOfPath(this->m_Engine->m_PreviousPath);
|
||||
// std::wcerr << "lastDirPath: " << lastDirPath << endl;
|
||||
std::wstring parentPath = Utility::parentOfPath(lastDirPath);
|
||||
// std::wcerr << "parentPath: " << parentPath << endl;
|
||||
std::wstring dirSeparator = Utility::delimiter(this->m_Engine->m_PreviousPath);
|
||||
std::wstring texturesPath = parentPath + dirSeparator + L"textures";
|
||||
// std::wcerr << "lastName: " << lastName << endl;
|
||||
// std::wcerr << "pathWithoutExt: " << Utility::withoutExtension(m_PreviousPath) << endl;
|
||||
//std::wcerr << "nameWithoutExt: " << Utility::withoutExtension(lastName) << endl;
|
||||
std::wstring tryTexPath = texturesPath + dirSeparator + Utility::withoutExtension(lastName) + L".png";
|
||||
std::wcerr << "tryTexPath: " << tryTexPath << endl;
|
||||
if (direction==0 && Utility::isFile(tryTexPath)) {
|
||||
std::wcerr << "is file: " << tryTexPath << endl;
|
||||
this->m_Engine->m_NextPath = tryTexPath;
|
||||
this->m_Engine->loadTexture(this->m_Engine->m_NextPath);
|
||||
}
|
||||
else {
|
||||
tryTexPath = lastDirPath + dirSeparator + Utility::withoutExtension(lastName) + L".png";
|
||||
// std::wcerr << "alternate tryTexPath: " << tryTexPath << endl;
|
||||
if (direction==0 && Utility::isFile(tryTexPath)) {
|
||||
std::wcerr << "is file: " << tryTexPath << endl;
|
||||
this->m_Engine->m_NextPath = tryTexPath;
|
||||
ret = this->m_Engine->loadTexture(this->m_Engine->m_NextPath);
|
||||
}
|
||||
else {
|
||||
//wcerr << L"converting path " << texturesPath << endl;
|
||||
//std::string path = Utility::toString(texturesPath);
|
||||
std::wstring path = texturesPath;
|
||||
|
||||
//cerr << "looking for next texture in " << path << endl;
|
||||
wcerr << "looking for next texture in " << path << endl;
|
||||
|
||||
fs::directory_iterator end_itr; // default construction yields past-the-end
|
||||
|
||||
std::wstring nextPath = L"";
|
||||
std::wstring retroPath = L"";
|
||||
std::wstring lastPath = L"";
|
||||
//std::string nextPath = "";
|
||||
|
||||
bool found = false;
|
||||
//for (directory_iterator itr(path); itr != end_itr; ++itr) {
|
||||
for (const auto & itr : fs::directory_iterator(texturesPath)) {
|
||||
// std::cout << entry.path() << std::endl;
|
||||
if (!is_directory(itr.status())) {
|
||||
//if (!itr.is_directory()) {
|
||||
// cycle through files (go to next after m_PrevTexturePath
|
||||
// if any, otherwise first)
|
||||
if (nextPath.length() == 0) nextPath = itr.path().wstring();
|
||||
lastPath = itr.path().wstring();
|
||||
if (found) {
|
||||
nextPath = itr.path().wstring();
|
||||
break;
|
||||
}
|
||||
if (itr.path().wstring()==this->m_Engine->m_PrevTexturePath) found = true;
|
||||
if (!found) retroPath = itr.path().wstring();
|
||||
}
|
||||
}
|
||||
if (retroPath.length()==0) retroPath = lastPath; // previous is last if at beginning
|
||||
if (direction < 0) nextPath = retroPath;
|
||||
if (nextPath.length() > 0) ret = this->m_Engine->loadTexture(nextPath);
|
||||
wcerr << "chose texture '" << nextPath << "': " << (ret?"OK":"FAIL") << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
else debug() << "Can't cycle texture since no file was opened" << endl;
|
||||
}
|
||||
|
||||
// IEventReceiver
|
||||
bool UserInterface::OnEvent( const SEvent &event )
|
||||
{
|
||||
|
@ -166,27 +250,10 @@ bool UserInterface::OnEvent( const SEvent &event )
|
|||
if (event.EventType == EET_KEY_INPUT_EVENT) {
|
||||
if (event.KeyInput.PressedDown && !KeyIsDown[event.KeyInput.Key]) {
|
||||
if (event.KeyInput.Key == irr::KEY_KEY_T) {
|
||||
this->m_Engine->m_NextPath = L"";
|
||||
std::wstring basePath = L".";
|
||||
if (this->m_Engine->m_PreviousPath.length() > 0) {
|
||||
// std::wcerr << "this->m_PreviousPath: " << this->m_PreviousPath.c_str() << endl;
|
||||
std::wstring lastName = Utility::basename(this->m_Engine->m_PreviousPath);
|
||||
std::wstring lastDirPath = Utility::parentOfPath(this->m_Engine->m_PreviousPath);
|
||||
// std::wcerr << "lastDirPath: " << lastDirPath << endl;
|
||||
std::wstring parentPath = Utility::parentOfPath(lastDirPath);
|
||||
// std::wcerr << "parentPath: " << parentPath << endl;
|
||||
std::wstring dirSeparator = Utility::delimiter(this->m_Engine->m_PreviousPath);
|
||||
std::wstring texturesPath = parentPath + dirSeparator + L"textures";
|
||||
// std::wcerr << "lastName: " << lastName << endl;
|
||||
// std::wcerr << "pathWithoutExt: " << Utility::withoutExtension(m_PreviousPath) << endl;
|
||||
// std::wcerr << "nameWithoutExt: " << Utility::withoutExtension(lastName) << endl;
|
||||
std::wstring tryTexPath = texturesPath + dirSeparator + Utility::withoutExtension(lastName) + L".png";
|
||||
if (Utility::exists(tryTexPath)) {
|
||||
this->m_Engine->m_NextPath = tryTexPath;
|
||||
this->m_Engine->loadTexture(this->m_Engine->m_NextPath);
|
||||
}
|
||||
}
|
||||
else debug() << "Can't cycle texture since no file was opened" << endl;
|
||||
loadNextTexture(1);
|
||||
}
|
||||
else if (event.KeyInput.Key == irr::KEY_KEY_E) {
|
||||
loadNextTexture(-1);
|
||||
}
|
||||
else if (event.KeyInput.Char == L'+' || event.KeyInput.Char == L'=') {
|
||||
m_Engine->setAnimationFPS(m_Engine->animationFPS() + 5);
|
||||
|
@ -243,10 +310,6 @@ bool UserInterface::OnEvent( const SEvent &event )
|
|||
|
||||
const SEvent::SGUIEvent *ge = &( event.GUIEvent );
|
||||
|
||||
bool isPress = false;
|
||||
|
||||
|
||||
|
||||
switch( ge->Caller->getID() )
|
||||
{
|
||||
case UIE_FILEMENU:
|
||||
|
|
|
@ -64,6 +64,7 @@ public:
|
|||
~UserInterface();
|
||||
irr::gui::IGUIEnvironment *getGUIEnvironment() const;
|
||||
void drawStatusLine() const;
|
||||
bool loadNextTexture(int direction);
|
||||
|
||||
// IEventReceiver
|
||||
virtual bool OnEvent( const irr::SEvent &event );
|
||||
|
|
|
@ -112,7 +112,7 @@ wstring Utility::delimiter(const wstring &path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
bool Utility::exists(const std::string& name) {
|
||||
bool Utility::isFile(const std::string& name) {
|
||||
if (FILE *file = fopen(name.c_str(), "r")) {
|
||||
fclose(file);
|
||||
return true;
|
||||
|
@ -135,13 +135,13 @@ std::string Utility::toString(const std::wstring& ws) {
|
|||
const converter_type::result result = converter.out(state, ws.data(), ws.data() + ws.length(), from_next, &to[0], &to[0] + to.size(), to_next);
|
||||
if (result == converter_type::ok or result == converter_type::noconv) {
|
||||
const std::string s(&to[0], to_next);
|
||||
std::cout <<"std::string = "<<s<<std::endl;
|
||||
ret += s;
|
||||
//std::cout <<"std::string = "<<s<<std::endl;
|
||||
ret = s;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Utility::exists(const std::wstring& name) {
|
||||
bool Utility::isFile(const std::wstring& name) {
|
||||
std::string name_s = toString(name);
|
||||
if (FILE *file = fopen(name_s.c_str(), "r")) {
|
||||
fclose(file);
|
||||
|
|
4
Utils.h
4
Utils.h
|
@ -14,8 +14,8 @@ public:
|
|||
static std::wstring basename(const std::wstring &path);
|
||||
static std::wstring withoutExtension(const std::wstring &path);
|
||||
static std::wstring delimiter(const std::wstring &path);
|
||||
static bool exists(const std::string &name);
|
||||
static bool exists(const std::wstring &name);
|
||||
static bool isFile(const std::string &name);
|
||||
static bool isFile(const std::wstring &name);
|
||||
static std::string toString(const std::wstring &name);
|
||||
};
|
||||
|
||||
|
|
17
b3view.pro
17
b3view.pro
|
@ -20,15 +20,24 @@ HEADERS += Engine.h \
|
|||
CONFIG += warn_off
|
||||
|
||||
# Irrlicht
|
||||
IRRLICHTBASE = /home/er/tmp/irrlicht/trunk
|
||||
INCLUDEPATH += $$IRRLICHTBASE/include
|
||||
LIBS += -L$$IRRLICHTBASE/lib/Linux \
|
||||
-lIrrlicht \
|
||||
#IRRLICHTBASE = /home/er/tmp/irrlicht/trunk
|
||||
#INCLUDEPATH += $$IRRLICHTBASE/include
|
||||
#LIBS += -L$$IRRLICHTBASE/lib/Linux \
|
||||
# -lIrrlicht \
|
||||
# -lX11 \
|
||||
# -lGL \
|
||||
# -lXxf86vm \
|
||||
# -lXcursor
|
||||
|
||||
LIBS += -lIrrlicht \
|
||||
-lX11 \
|
||||
-lGL \
|
||||
-lXxf86vm \
|
||||
-lXcursor
|
||||
|
||||
# <experimental/filesystem>:
|
||||
LIBS += -lstdc++fs
|
||||
|
||||
# Freetype
|
||||
INCLUDEPATH += /usr/include/freetype2
|
||||
LIBS += -lfreetype
|
||||
|
|
Loading…
Reference in New Issue