cycle through textures thanks to C++17 filesystem

master
poikilos 2019-03-08 02:30:06 -05:00
parent 1a77f1cc33
commit bf870ab941
9 changed files with 132 additions and 43 deletions

View File

@ -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

View File

@ -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 )

View File

@ -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();

View File

@ -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.

View File

@ -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:

View File

@ -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 );

View File

@ -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);

View File

@ -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);
};

View File

@ -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