mirror of https://github.com/Poikilos/b3view
implement playback controls
parent
ec30dae805
commit
1a77f1cc33
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## [git] - 2019-03-07
|
||||
(poikilos)
|
||||
### Added
|
||||
* playback controls
|
||||
|
||||
## [git] - 2019-03-06
|
||||
(poikilos)
|
||||
### Added
|
||||
|
|
90
Engine.cpp
90
Engine.cpp
|
@ -124,6 +124,8 @@ s32 Engine::getNumberOfVertices()
|
|||
|
||||
Engine::Engine()
|
||||
{
|
||||
this->worldFPS = 60;
|
||||
this->prevFPS = 30;
|
||||
#if WIN32
|
||||
m_Device = createDevice( EDT_DIRECT3D9, dimension2d<u32>( 1024, 768 ), 32, false, false, false, nullptr );
|
||||
#else
|
||||
|
@ -170,6 +172,7 @@ Engine::Engine()
|
|||
m_WindowSize = new dimension2d<u32>();
|
||||
m_WindowSize->Width = m_Driver->getScreenSize().Width;
|
||||
m_WindowSize->Height = m_Driver->getScreenSize().Height;
|
||||
this->playAnimation();
|
||||
}
|
||||
|
||||
Engine::~Engine()
|
||||
|
@ -187,8 +190,8 @@ void Engine::loadMesh( const wstring &fileName )
|
|||
//fn.assign(fileName.c_str());
|
||||
// std::wcerr << "fileName = " << fn << endl;
|
||||
// std::wcerr << "fileName = " << fileName << endl;
|
||||
this->m_EventHandler->m_PreviousPath = fileName;
|
||||
// std::wcerr << "this->m_EventHandler->m_PreviousPath = " << this->m_EventHandler->m_PreviousPath.c_str() << endl;
|
||||
this->m_PreviousPath = fileName;
|
||||
// std::wcerr << "this->m_PreviousPath = " << this->m_PreviousPath.c_str() << endl;
|
||||
// }
|
||||
if( m_LoadedMesh != nullptr )
|
||||
m_LoadedMesh->remove();
|
||||
|
@ -199,9 +202,9 @@ void Engine::loadMesh( const wstring &fileName )
|
|||
|
||||
void Engine::reloadMesh()
|
||||
{
|
||||
if (this->m_EventHandler->m_PreviousPath.length() > 0) {
|
||||
std::wcerr << "this->m_EventHandler->m_PreviousPath = " << this->m_EventHandler->m_PreviousPath.c_str() << endl;
|
||||
loadMesh(this->m_EventHandler->m_PreviousPath);
|
||||
if (this->m_PreviousPath.length() > 0) {
|
||||
std::wcerr << "this->m_PreviousPath = " << this->m_PreviousPath.c_str() << endl;
|
||||
loadMesh(this->m_PreviousPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -231,18 +234,89 @@ void Engine::setMeshDisplayMode( bool wireframe, bool lighting )
|
|||
}
|
||||
}
|
||||
|
||||
bool Engine::isAnimating()
|
||||
{
|
||||
return this->isPlaying;
|
||||
}
|
||||
|
||||
void Engine::playAnimation()
|
||||
{
|
||||
if (this->animationFPS() < 1) {
|
||||
this->setAnimationFPS(5);
|
||||
}
|
||||
if (!this->isAnimating()) {
|
||||
if (this->m_LoadedMesh != nullptr) {
|
||||
if (this->prevFPS < 1) this->prevFPS = 5;
|
||||
this->m_LoadedMesh->setAnimationSpeed(this->prevFPS);
|
||||
}
|
||||
}
|
||||
this->isPlaying = true;
|
||||
}
|
||||
|
||||
void Engine::pauseAnimation()
|
||||
{
|
||||
if (this->isAnimating()) {
|
||||
this->prevFPS = animationFPS();
|
||||
if (this->m_LoadedMesh != nullptr) {
|
||||
this->prevFPS = this->m_LoadedMesh->getAnimationSpeed();
|
||||
this->m_LoadedMesh->setAnimationSpeed(0);
|
||||
}
|
||||
}
|
||||
this->isPlaying = false;
|
||||
}
|
||||
|
||||
void Engine::toggleAnimation()
|
||||
{
|
||||
if (this->isAnimating()) {
|
||||
this->pauseAnimation();
|
||||
debug() << "paused " << this->animationFPS() << "fps" << endl;
|
||||
}
|
||||
else {
|
||||
this->playAnimation();
|
||||
debug() << "unpaused " << this->animationFPS() << "fps" << endl;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Engine::setAnimationFPS(u32 animationFPS)
|
||||
{
|
||||
if (this->m_LoadedMesh != nullptr) {
|
||||
this->m_LoadedMesh->setAnimationSpeed(animationFPS);
|
||||
}
|
||||
}
|
||||
|
||||
u32 Engine::animationFPS()
|
||||
{
|
||||
u32 ret = 0;
|
||||
if (this->m_LoadedMesh != nullptr) {
|
||||
ret = this->m_LoadedMesh->getAnimationSpeed();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Engine::run()
|
||||
{
|
||||
u32 timePerFrame = ( u32 ) ( 1000.0f / 60 );
|
||||
u32 timePerFrame = 1000.0f;
|
||||
if (this->worldFPS > 0) {
|
||||
timePerFrame = ( u32 ) ( 1000.0f / this->worldFPS );
|
||||
}
|
||||
ITimer *timer = m_Device->getTimer();
|
||||
|
||||
// Run the Device with 60 frames/sec
|
||||
// Run the Device with fps frames/sec
|
||||
while( m_Device->run() && m_RunEngine )
|
||||
{
|
||||
u32 startTime = timer->getRealTime();
|
||||
|
||||
checkResize();
|
||||
|
||||
if (this->m_LoadedMesh != nullptr) {
|
||||
//this->m_LoadedMesh->setAnimationSpeed(this->fps);
|
||||
if (isPlaying) {
|
||||
this->m_LoadedMesh->setLoopMode(true);
|
||||
}
|
||||
else {
|
||||
this->m_LoadedMesh->setLoopMode(false);
|
||||
}
|
||||
}
|
||||
m_Driver->beginScene();
|
||||
drawBackground(); // Draw Background
|
||||
drawAxisLines(); // Draw XYZ Axis
|
||||
|
|
13
Engine.h
13
Engine.h
|
@ -29,6 +29,7 @@ class Engine
|
|||
friend class View;
|
||||
|
||||
private:
|
||||
std::wstring m_NextPath;
|
||||
irr::IrrlichtDevice *m_Device;
|
||||
irr::video::IVideoDriver *m_Driver;
|
||||
irr::scene::ISceneManager *m_Scene;
|
||||
|
@ -51,8 +52,14 @@ private:
|
|||
void checkResize();
|
||||
irr::gui::IGUIEnvironment *getGUIEnvironment() const;
|
||||
irr::s32 getNumberOfVertices();
|
||||
bool isPlaying;
|
||||
irr::u32 worldFPS;
|
||||
irr::u32 prevFPS;
|
||||
|
||||
public:
|
||||
std::wstring m_PreviousPath;
|
||||
|
||||
|
||||
Engine();
|
||||
~Engine();
|
||||
|
||||
|
@ -61,6 +68,12 @@ public:
|
|||
void reloadMesh();
|
||||
void loadTexture( const std::wstring &fileName );
|
||||
void setMeshDisplayMode( bool wireframe = false, bool lighting = true );
|
||||
bool isAnimating();
|
||||
void playAnimation();
|
||||
void pauseAnimation();
|
||||
void toggleAnimation();
|
||||
void setAnimationFPS(irr::u32 animationFPS);
|
||||
irr::u32 animationFPS();
|
||||
};
|
||||
|
||||
#endif // ENGINE_H
|
||||
|
|
|
@ -11,14 +11,6 @@ using namespace irr::gui;
|
|||
// Public
|
||||
EventHandler::EventHandler( IrrlichtDevice *device )
|
||||
{
|
||||
// For monitoring single press: see
|
||||
// <http://irrlicht.sourceforge.net/forum/viewtopic.php?p=210744>
|
||||
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
|
||||
KeyIsDown[i] = false;
|
||||
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
|
||||
keyState[i] = 0;
|
||||
LMouseState = 0;
|
||||
RMouseState = 0;
|
||||
m_Device = device;
|
||||
m_EventReceivers = new map<EventReceiverType, IEventReceiver *>();
|
||||
}
|
||||
|
@ -49,16 +41,8 @@ bool EventHandler::OnEvent( const SEvent &event )
|
|||
iter->second->OnEvent( event );
|
||||
}
|
||||
else if (event.EventType == EET_KEY_INPUT_EVENT) {
|
||||
if (event.KeyInput.PressedDown && !KeyIsDown[event.KeyInput.Key]) {
|
||||
std::wstring basePath = L".";
|
||||
if (this->m_PreviousPath.length() > 0) {
|
||||
// std::wcerr << "this->m_PreviousPath: " << this->m_PreviousPath.c_str() << endl;
|
||||
std::wstring lastDirPath = Utility::parentOfPath(m_PreviousPath);
|
||||
std::wcerr << "lastDirPath: " << lastDirPath << endl;
|
||||
}
|
||||
else debug() << "Keydown" << endl;
|
||||
}
|
||||
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
|
||||
map<EventReceiverType,IEventReceiver *>::iterator iter = m_EventReceivers->find( ERT_USERINTERFACE );
|
||||
iter->second->OnEvent( event );
|
||||
}
|
||||
else if (event.EventType == EET_USER_EVENT)
|
||||
{
|
||||
|
|
|
@ -30,9 +30,6 @@ class EventHandler : public irr::IEventReceiver
|
|||
private:
|
||||
irr::IrrlichtDevice *m_Device;
|
||||
map<EventReceiverType, IEventReceiver*> *m_EventReceivers;
|
||||
bool KeyIsDown[irr::KEY_KEY_CODES_COUNT];
|
||||
irr::s32 keyState[irr::KEY_KEY_CODES_COUNT];
|
||||
irr::s32 LMouseState,RMouseState;
|
||||
public:
|
||||
EventHandler( irr::IrrlichtDevice *device );
|
||||
~EventHandler();
|
||||
|
@ -41,7 +38,6 @@ public:
|
|||
|
||||
// IEventReceiver
|
||||
virtual bool OnEvent( const irr::SEvent &event );
|
||||
std::wstring m_PreviousPath;
|
||||
};
|
||||
|
||||
#endif // EVENTHANDLER_H
|
||||
|
|
|
@ -55,6 +55,10 @@ This is a modernized fork by poikilos (see CHANGELOG.md).
|
|||
file. However, the program is much easier to use if you associate the
|
||||
format with b3view (see "Installation" above) so you can just double-
|
||||
click the file to open b3view automatically.
|
||||
* To change frame rate in increments of 5 fps, click "Faster" or
|
||||
"Slower," or use `-` key or `+`/`=` key. By default, the world runs
|
||||
at 60fps and the animation runs as 30 fps (Irrlicht does interpolation
|
||||
automatically).
|
||||
|
||||
## Known Issues
|
||||
* Warn on missing texture.
|
||||
|
|
|
@ -27,18 +27,39 @@ void UserInterface::setupUserInterface()
|
|||
viewMenu->addItem( L"Wireframe Mesh", UIC_VIEW_WIREFRAME, true, false, false, true );
|
||||
viewMenu->addItem( L"Lighting",UIC_VIEW_LIGHTING, true, false, true, true );
|
||||
|
||||
// TODO: Playback Control Window
|
||||
// dimension2d<u32> windowSize = m_Engine->m_Driver->getScreenSize();
|
||||
// IGUIWindow *playbackWindow = m_Gui->addWindow(
|
||||
// rect<s32>( vector2d<s32>( windowSize.Width - 4 - 160, 28 ), dimension2d<s32>( 160, 300 )), false, L"Playback", nullptr, UIE_PLAYBACKWINDOW );
|
||||
// playbackWindow->getCloseButton()->setVisible( false );
|
||||
// IGUIButton *playbackStartStopButton = m_Gui->addButton(
|
||||
// rect<s32>( vector2d<s32>( 4, 24 ), dimension2d<s32>( playbackWindow->getClientRect().getWidth() - 8, 24 )),
|
||||
// playbackWindow,
|
||||
// UIE_PLAYBACKSTARTSTOPBUTTON,
|
||||
// L"Start/Stop",
|
||||
// nullptr
|
||||
// );
|
||||
// Playback Control Window
|
||||
dimension2d<u32> windowSize = m_Engine->m_Driver->getScreenSize();
|
||||
IGUIWindow *playbackWindow = m_Gui->addWindow(
|
||||
rect<s32>( vector2d<s32>( windowSize.Width - 4 - 160, 28 ), dimension2d<s32>( 160, 300 )), false, L"Playback", nullptr, UIE_PLAYBACKWINDOW );
|
||||
playbackWindow->getCloseButton()->setVisible( false );
|
||||
s32 spacing_x = 4;
|
||||
s32 spacing_y = 4;
|
||||
s32 size_x = playbackWindow->getClientRect().getWidth() - 8;
|
||||
s32 size_y = 24;
|
||||
s32 y = 24;
|
||||
playbackStartStopButton = m_Gui->addButton(
|
||||
rect<s32>( vector2d<s32>( spacing_x, y ), dimension2d<s32>( size_x, size_y )),
|
||||
playbackWindow,
|
||||
UIE_PLAYBACKSTARTSTOPBUTTON,
|
||||
L"Start/Stop",
|
||||
nullptr
|
||||
);
|
||||
y += size_y + spacing_y;
|
||||
playbackIncreaseButton = m_Gui->addButton(
|
||||
rect<s32>( vector2d<s32>( spacing_x, y ), dimension2d<s32>( size_x, size_y )),
|
||||
playbackWindow,
|
||||
UIE_PLAYBACKINCREASEBUTTON,
|
||||
L"Faster",
|
||||
nullptr
|
||||
);
|
||||
y += size_y + spacing_y;
|
||||
playbackDecreaseButton = m_Gui->addButton(
|
||||
rect<s32>( vector2d<s32>( spacing_x, y ), dimension2d<s32>( size_x, size_y )),
|
||||
playbackWindow,
|
||||
UIE_PLAYBACKDECREASEBUTTON,
|
||||
L"Slower",
|
||||
nullptr
|
||||
);
|
||||
|
||||
// Set Font for UI Elements
|
||||
m_GuiFontFace = new CGUITTFace();
|
||||
|
@ -104,6 +125,16 @@ void UserInterface::handleMenuItemPressed( IGUIContextMenu *menu )
|
|||
// PUBLIC
|
||||
UserInterface::UserInterface( Engine *engine )
|
||||
{
|
||||
this->playbackStartStopButton = nullptr;
|
||||
// For monitoring single press: see
|
||||
// <http://irrlicht.sourceforge.net/forum/viewtopic.php?p=210744>
|
||||
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
|
||||
KeyIsDown[i] = false;
|
||||
for (u32 i=0; i<KEY_KEY_CODES_COUNT; ++i)
|
||||
keyState[i] = 0;
|
||||
LMouseState = 0;
|
||||
RMouseState = 0;
|
||||
|
||||
m_Engine = engine;
|
||||
m_Gui = engine->getGUIEnvironment();
|
||||
|
||||
|
@ -132,11 +163,90 @@ void UserInterface::drawStatusLine() const
|
|||
bool UserInterface::OnEvent( const SEvent &event )
|
||||
{
|
||||
// Events arriving here should be destined for us
|
||||
if (!(event.EventType == EET_GUI_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;
|
||||
}
|
||||
else if (event.KeyInput.Char == L'+' || event.KeyInput.Char == L'=') {
|
||||
m_Engine->setAnimationFPS(m_Engine->animationFPS() + 5);
|
||||
// std::wcerr << "m_Engine->animationFPS(): " << m_Engine->animationFPS() << endl;
|
||||
}
|
||||
else if (event.KeyInput.Char == L'-') {
|
||||
if (m_Engine->animationFPS() > 0) {
|
||||
m_Engine->setAnimationFPS(m_Engine->animationFPS() - 5);
|
||||
}
|
||||
// std::wcerr << "m_Engine->animationFPS(): " << m_Engine->animationFPS() << endl;
|
||||
}
|
||||
else if (event.KeyInput.Char == L' ') {
|
||||
m_Engine->toggleAnimation();
|
||||
// std::wcerr << "m_Engine->animationFPS(): " << m_Engine->animationFPS() << endl;
|
||||
}
|
||||
// std::wcerr << "Char: " << event.KeyInput.Char << endl;
|
||||
}
|
||||
KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (event.EventType == EET_MOUSE_INPUT_EVENT)
|
||||
{
|
||||
switch ( event.MouseInput.Event)
|
||||
{
|
||||
case EMIE_LMOUSE_LEFT_UP:
|
||||
if ( LMouseState == 2)
|
||||
{
|
||||
LMouseState = 3;
|
||||
}
|
||||
break;
|
||||
case EMIE_LMOUSE_PRESSED_DOWN:
|
||||
if ( LMouseState == 0)
|
||||
{
|
||||
LMouseState = 1;
|
||||
}
|
||||
break;
|
||||
case EMIE_RMOUSE_LEFT_UP:
|
||||
if ( RMouseState == 2)
|
||||
{
|
||||
RMouseState = 3;
|
||||
}
|
||||
break;
|
||||
case EMIE_RMOUSE_PRESSED_DOWN:
|
||||
if ( RMouseState == 0)
|
||||
{
|
||||
RMouseState = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (!(event.EventType == EET_GUI_EVENT))
|
||||
return false;
|
||||
|
||||
const SEvent::SGUIEvent *ge = &( event.GUIEvent );
|
||||
|
||||
bool isPress = false;
|
||||
|
||||
|
||||
|
||||
switch( ge->Caller->getID() )
|
||||
{
|
||||
case UIE_FILEMENU:
|
||||
|
@ -161,6 +271,26 @@ bool UserInterface::OnEvent( const SEvent &event )
|
|||
}
|
||||
break;
|
||||
|
||||
case UIE_PLAYBACKSTARTSTOPBUTTON:
|
||||
if ( ge->EventType == EGET_BUTTON_CLICKED) {
|
||||
this->m_Engine->toggleAnimation();
|
||||
}
|
||||
break;
|
||||
|
||||
case UIE_PLAYBACKINCREASEBUTTON:
|
||||
if ( ge->EventType == EGET_BUTTON_CLICKED) {
|
||||
this->m_Engine->setAnimationFPS(this->m_Engine->animationFPS() + 5);
|
||||
}
|
||||
break;
|
||||
|
||||
case UIE_PLAYBACKDECREASEBUTTON:
|
||||
if ( ge->EventType == EGET_BUTTON_CLICKED) {
|
||||
if (this->m_Engine->animationFPS() >= 5) {
|
||||
this->m_Engine->setAnimationFPS(this->m_Engine->animationFPS() - 5);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ enum UserInterfaceElements
|
|||
UIE_FILEMENU = 1003,
|
||||
UIE_PLAYBACKSTARTSTOPBUTTON = 1004,
|
||||
UIE_VIEWMENU = 1005,
|
||||
UIE_LOADTEXTUREDIALOG = 1006
|
||||
UIE_LOADTEXTUREDIALOG = 1006,
|
||||
UIE_PLAYBACKINCREASEBUTTON = 1007,
|
||||
UIE_PLAYBACKDECREASEBUTTON = 1008
|
||||
};
|
||||
|
||||
enum UserInterfaceCommands
|
||||
|
@ -49,7 +51,15 @@ private:
|
|||
bool m_WireframeDisplay;
|
||||
bool m_Lighting;
|
||||
|
||||
bool KeyIsDown[irr::KEY_KEY_CODES_COUNT];
|
||||
irr::s32 keyState[irr::KEY_KEY_CODES_COUNT];
|
||||
irr::s32 LMouseState,RMouseState;
|
||||
|
||||
public:
|
||||
irr::gui::IGUIButton *playbackStartStopButton;
|
||||
irr::gui::IGUIButton *playbackIncreaseButton;
|
||||
irr::gui::IGUIButton *playbackDecreaseButton;
|
||||
|
||||
UserInterface( Engine *device );
|
||||
~UserInterface();
|
||||
irr::gui::IGUIEnvironment *getGUIEnvironment() const;
|
||||
|
|
92
Utils.cpp
92
Utils.cpp
|
@ -1,4 +1,11 @@
|
|||
#include <string>
|
||||
#include <iostream>
|
||||
#include <clocale>
|
||||
#include <locale>
|
||||
#include <vector>
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
using namespace irr::core;
|
||||
using namespace irr::scene;
|
||||
using namespace irr::video;
|
||||
|
@ -59,4 +66,89 @@ std::wstring Utility::parentOfPath(const wstring &path)
|
|||
return ret;
|
||||
}
|
||||
|
||||
wstring Utility::basename(const wstring &path)
|
||||
{
|
||||
std::wstring ret = path;
|
||||
std::wstring::size_type lastSlashPos = path.find_last_of(L"/");
|
||||
if (lastSlashPos == std::wstring::npos) {
|
||||
std::wstring::size_type lastSlashPos = path.find_last_of(L"\\");
|
||||
}
|
||||
if (lastSlashPos != std::wstring::npos) {
|
||||
ret = path.substr(lastSlashPos+1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
wstring Utility::withoutExtension(const wstring &path)
|
||||
{
|
||||
std::wstring ret = path;
|
||||
std::wstring::size_type lastDotPos = path.find_last_of(L".");
|
||||
if (lastDotPos != std::wstring::npos) {
|
||||
std::wstring::size_type lastSlashPos = path.find_last_of(L"/");
|
||||
if (lastSlashPos == std::wstring::npos) {
|
||||
std::wstring::size_type lastSlashPos = path.find_last_of(L"\\");
|
||||
}
|
||||
if (lastSlashPos != std::wstring::npos) {
|
||||
if (lastDotPos > lastSlashPos) ret = path.substr(0, lastDotPos);
|
||||
}
|
||||
else ret = path.substr(0, lastDotPos);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
wstring Utility::delimiter(const wstring &path)
|
||||
{
|
||||
std::wstring ret = L"/";
|
||||
std::wstring::size_type lastSlashPos = path.find_last_of(L"/");
|
||||
if (lastSlashPos == std::wstring::npos) {
|
||||
// ret = "/";
|
||||
}
|
||||
else {
|
||||
std::wstring::size_type lastSlashPos = path.find_last_of(L"\\");
|
||||
if (lastSlashPos != std::wstring::npos) {
|
||||
ret = L"\\";
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Utility::exists(const std::string& name) {
|
||||
if (FILE *file = fopen(name.c_str(), "r")) {
|
||||
fclose(file);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Utility::toString(const std::wstring& ws) {
|
||||
std::string ret;
|
||||
// convert to w_string using locale: see Phillipp on <https://stackoverflow.com/questions/4804298/how-to-convert-wstring-into-string>
|
||||
std::setlocale(LC_ALL, "");
|
||||
const std::locale locale("");
|
||||
typedef std::codecvt<wchar_t, char, std::mbstate_t> converter_type;
|
||||
const converter_type& converter = std::use_facet<converter_type>(locale);
|
||||
std::vector<char> to(ws.length() * converter.max_length());
|
||||
std::mbstate_t state;
|
||||
const wchar_t* from_next;
|
||||
char* to_next;
|
||||
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;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Utility::exists(const std::wstring& name) {
|
||||
std::string name_s = toString(name);
|
||||
if (FILE *file = fopen(name_s.c_str(), "r")) {
|
||||
fclose(file);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
6
Utils.h
6
Utils.h
|
@ -11,6 +11,12 @@ public:
|
|||
static void dumpVectorToConsole( const irr::core::vector3df &vector );
|
||||
static void dumpMeshInfoToConsole( irr::scene::IAnimatedMeshSceneNode *node );
|
||||
static std::wstring parentOfPath(const std::wstring &path);
|
||||
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 std::string toString(const std::wstring &name);
|
||||
};
|
||||
|
||||
#endif // UTILS_H
|
||||
|
|
|
@ -125,6 +125,17 @@ if [ -f "$mime_path" ]; then
|
|||
echo "Successfully copied '$MIMETYPES_DB_PATH/packages/$mime_name'"
|
||||
fi
|
||||
|
||||
# Since OBJ Mime type is broken on linux (detected as TGIF), trying
|
||||
# to add an overlapping mime type breaks it worse (KDE detects the
|
||||
# file as "plain text file" if the xml file below is installed)
|
||||
mime_name=model-obj.xml
|
||||
mime_path="$mimes_path/$mime_name"
|
||||
# cp -f "$mime_path" "$MIMETYPES_DB_PATH/packages/"
|
||||
# if [ -f "$MIMETYPES_DB_PATH/packages/$mime_name" ]; then
|
||||
# echo "Successfully copied '$MIMETYPES_DB_PATH/packages/$mime_name'"
|
||||
# rm -f "$MIMETYPES_DB_PATH/packages/$mime_name"
|
||||
# fi
|
||||
|
||||
echo "Updating mime type database '$MIMETYPES_DB_PATH'..."
|
||||
update-mime-database "$MIMETYPES_DB_PATH" # must contain packages
|
||||
else
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
|
||||
<mime-type type="model/obj">
|
||||
<comment>OBJ file</comment>
|
||||
<icon name="model-obj"/>
|
||||
<glob-deleteall/>
|
||||
<remove fileExtension=".obj" />
|
||||
<mimeMap fileExtension=".obj" mimeType="text/plain" />
|
||||
<glob pattern="*.obj"/>
|
||||
</mime-type>
|
||||
</mime-info>
|
Loading…
Reference in New Issue