improve ui, target, improve pan

master
poikilos 2019-04-19 15:29:30 -04:00
parent fe7e4c6a5c
commit 036c0feb01
12 changed files with 535 additions and 195 deletions

View File

@ -1,5 +1,28 @@
# Changelog # Changelog
## [git] - 2019-04-18
(poikilos)
### Added
* box for axis length (size of the axis widget)
* box for frame rate
### Changed
* Reorder boxes.
* Changed hotkeys so they aren't triggered when typing in the panel.
## [git] - 2019-04-08
(poikilos)
### Added
* snapWidgets (move playbackWindow on resize, not leave past edge)
### Changed
* changed enum values to leave room in between, comment unused
* fixed issue in Utility not detecting backslashes correctly
* renamed Utils.* to Utility.* to match class name
* coding style to WebKit (run ./etc/quality.sh to check)
* improve pan - don't reset view
* improve initial camera settings: angle calculation
## [git] - 2019-04-08 ## [git] - 2019-04-08
(poikilos) (poikilos)
### Added ### Added

View File

@ -34,7 +34,7 @@ void Engine::setupScene()
// Setup Camera // Setup Camera
// (so z-forward characters face camera partially (formerly vector3df(0, 0, -10), vector3df()) // (so z-forward characters face camera partially (formerly vector3df(0, 0, -10), vector3df())
m_CamPos = vector3df(4.5, 3, 9); m_CamPos = vector3df(4.5, 3.5, 9);
m_CamTarget = vector3df(0, 3, 0); m_CamTarget = vector3df(0, 3, 0);
ICameraSceneNode* camera = m_Scene->addCameraSceneNode(nullptr, m_CamPos, m_CamTarget); // this will be overridden by View m_Yaw and m_Pitch--see "calculate m_Yaw" further down ICameraSceneNode* camera = m_Scene->addCameraSceneNode(nullptr, m_CamPos, m_CamTarget); // this will be overridden by View m_Yaw and m_Pitch--see "calculate m_Yaw" further down
camera->setAspectRatio(static_cast<f32>(m_Driver->getScreenSize().Width) / static_cast<f32>(m_Driver->getScreenSize().Height)); camera->setAspectRatio(static_cast<f32>(m_Driver->getScreenSize().Width) / static_cast<f32>(m_Driver->getScreenSize().Height));
@ -47,44 +47,109 @@ IGUIEnvironment* Engine::getGUIEnvironment() const
void Engine::drawAxisLines() void Engine::drawAxisLines()
{ {
SMaterial* lineX = new SMaterial(); SMaterial xMaterial;
lineX->Lighting = false; xMaterial.Lighting = false;
lineX->EmissiveColor = SColor(255, 255, 0, 0); xMaterial.EmissiveColor = SColor(255, 255, 0, 0);
lineX->Thickness = 1.0f; xMaterial.Thickness = 1.0f;
SMaterial* lineY = new SMaterial(*lineX); SMaterial yMaterial(xMaterial);
lineY->EmissiveColor = SColor(255, 0, 255, 0); yMaterial.EmissiveColor = SColor(255, 0, 255, 0);
SMaterial* lineZ = new SMaterial(*lineX); SMaterial zMaterial(xMaterial);
lineZ->EmissiveColor = SColor(255, 0, 0, 255); zMaterial.EmissiveColor = SColor(255, 0, 0, 255);
SMaterial descenderMaterialVert(xMaterial);
descenderMaterialVert.EmissiveColor = SColor(128, 128, 128, 128); // ARGB
SMaterial descenderMaterialHorz(xMaterial);
descenderMaterialHorz.EmissiveColor = SColor(255, 255, 255, 255);
vector3df descend3df(0, 0, 0);
// vector3df target = m_View->c
m_Driver->setTransform(ETS_WORLD, matrix4()); m_Driver->setTransform(ETS_WORLD, matrix4());
m_Driver->setMaterial(*lineX); if (m_View != nullptr) {
m_Driver->draw3DLine(vector3df(), vector3df(5, 0, 0), SColor(255, 255, 0, 0)); if (this->m_UserInterface->viewMenu->isItemChecked(this->m_UserInterface->viewTargetIdx)) {
position2d<s32> textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(vector3df(5.2f, 0, 0)); if (m_View->zUp()) {
descend3df.Z = this->m_CamTarget.Z;
}
else {
descend3df.Y = this->m_CamTarget.Y;
}
vector3df descendSideways3df(descend3df);
descendSideways3df.X = this->m_CamTarget.X;
vector3df descendSidewaysForward3df(descendSideways3df);
if (m_View->zUp()) {
descendSidewaysForward3df.Y = this->m_CamTarget.Y;
}
else {
descendSidewaysForward3df.Z = this->m_CamTarget.Z;
}
m_Driver->setMaterial(descenderMaterialVert);
m_Driver->draw3DLine(vector3df(), descend3df, descenderMaterialVert.EmissiveColor);
m_Driver->setMaterial(descenderMaterialHorz);
m_Driver->draw3DLine(descend3df, descendSideways3df, descenderMaterialHorz.EmissiveColor);
m_Driver->draw3DLine(descendSideways3df, descendSidewaysForward3df, descenderMaterialHorz.EmissiveColor);
f32 arrowDirection = 1.0f;
vector3df arrowLeft3df(descendSidewaysForward3df);
vector3df arrowRight3df(descendSidewaysForward3df);
f32 arrowSize = this->m_View->cameraDistance() / 30;
if (m_View->zUp()) {
if (descendSidewaysForward3df.Y > descendSideways3df.Y)
arrowDirection = -1.0f;
arrowLeft3df.X += arrowSize;
arrowLeft3df.Y += arrowSize * arrowDirection;
arrowRight3df.X -= arrowSize;
arrowRight3df.Y += arrowSize * arrowDirection;
}
else {
if (descendSidewaysForward3df.Z > descendSideways3df.Z)
arrowDirection = -1.0f;
arrowLeft3df.X += arrowSize;
arrowLeft3df.Z += arrowSize * arrowDirection;
arrowRight3df.X -= arrowSize;
arrowRight3df.Z += arrowSize * arrowDirection;
}
m_Driver->draw3DLine(descendSidewaysForward3df, arrowLeft3df, descenderMaterialHorz.EmissiveColor);
m_Driver->draw3DLine(descendSidewaysForward3df, arrowRight3df, descenderMaterialHorz.EmissiveColor);
// position2d<s32> targetPos2d = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(this->m_CamTarget);
// dimension2d<u32> textSize;
// if (m_AxisFont != nullptr) {
// textSize = m_AxisFont->getDimension(L"target");
// m_AxisFont->draw(L"target", rect<s32>(targetPos2d, textSize), descenderMaterial.EmissiveColor, true, true);
// }
}
}
m_Driver->setMaterial(xMaterial);
m_Driver->draw3DLine(vector3df(), vector3df(axisLength, 0, 0), SColor(255, 255, 0, 0));
position2d<s32> textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(vector3df(axisLength + axisLength*.1f, 0, 0));
dimension2d<u32> textSize; dimension2d<u32> textSize;
if (m_AxisFont != nullptr) { if (m_AxisFont != nullptr) {
textSize = m_AxisFont->getDimension(L"X+"); textSize = m_AxisFont->getDimension(L"X+");
m_AxisFont->draw(L"X+", rect<s32>(textPos, textSize), SColor(255, 255, 0, 0), true, true); m_AxisFont->draw(L"X+", rect<s32>(textPos, textSize), SColor(255, 255, 0, 0), true, true);
} }
m_Driver->setMaterial(*lineY);
m_Driver->draw3DLine(vector3df(), vector3df(0, 5, 0), SColor(255, 0, 255, 0)); m_Driver->setMaterial(yMaterial);
textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(vector3df(0, 5.2f, 0)); m_Driver->draw3DLine(vector3df(), vector3df(0, axisLength, 0), SColor(255, 0, 255, 0));
textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(vector3df(0, axisLength + axisLength*.1f, 0));
if (m_AxisFont != nullptr) { if (m_AxisFont != nullptr) {
textSize = m_AxisFont->getDimension(L"Y+"); textSize = m_AxisFont->getDimension(L"Y+");
m_AxisFont->draw(L"Y+", rect<s32>(textPos, textSize), SColor(255, 0, 255, 0), true, true); m_AxisFont->draw(L"Y+", rect<s32>(textPos, textSize), SColor(255, 0, 255, 0), true, true);
} }
m_Driver->setMaterial(*lineZ);
m_Driver->draw3DLine(vector3df(), vector3df(0, 0, 5), SColor(255, 0, 0, 255)); m_Driver->setMaterial(zMaterial);
textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(vector3df(0, 0, 5.2f)); m_Driver->draw3DLine(vector3df(), vector3df(0, 0, axisLength), SColor(255, 0, 0, 255));
textPos = m_Scene->getSceneCollisionManager()->getScreenCoordinatesFrom3DPosition(vector3df(0, 0, axisLength + axisLength*.1f));
if (m_AxisFont != nullptr) { if (m_AxisFont != nullptr) {
textSize = m_AxisFont->getDimension(L"Z+"); textSize = m_AxisFont->getDimension(L"Z+");
m_AxisFont->draw(L"Z+", rect<s32>(textPos, textSize), SColor(255, 0, 0, 255), true, true); m_AxisFont->draw(L"Z+", rect<s32>(textPos, textSize), SColor(255, 0, 0, 255), true, true);
} }
delete lineX; //delete xMaterial;
delete lineY; //delete yMaterial;
delete lineZ; //delete zMaterial;
} }
void Engine::drawBackground() void Engine::drawBackground()
@ -141,7 +206,7 @@ Engine::Engine()
keyState[i] = 0; keyState[i] = 0;
LMouseState = 0; LMouseState = 0;
RMouseState = 0; RMouseState = 0;
this->axisLength = 10;
this->worldFPS = 60; this->worldFPS = 60;
this->prevFPS = 30; this->prevFPS = 30;
this->textureExtensions.push_back(L"png"); this->textureExtensions.push_back(L"png");
@ -205,6 +270,11 @@ Engine::~Engine()
delete m_AxisFontFace; delete m_AxisFontFace;
} }
vector3df Engine::camTarget()
{
return m_CamTarget;
}
void Engine::loadMesh(const wstring& fileName) void Engine::loadMesh(const wstring& fileName)
{ {
this->m_PreviousPath = fileName; // even if bad, set this this->m_PreviousPath = fileName; // even if bad, set this
@ -223,6 +293,7 @@ void Engine::loadMesh(const wstring& fileName)
m_View->setZUp(false); m_View->setZUp(false);
} }
if (m_LoadedMesh != nullptr) { if (m_LoadedMesh != nullptr) {
this->m_UserInterface->playbackFPSEditBox->setText(Utility::toWstring(m_LoadedMesh->getAnimationSpeed()).c_str());
ICameraSceneNode* camera = this->m_Scene->getActiveCamera(); ICameraSceneNode* camera = this->m_Scene->getActiveCamera();
aabbox3d<f32> box = m_LoadedMesh->getTransformedBoundingBox(); aabbox3d<f32> box = m_LoadedMesh->getTransformedBoundingBox();
//vector3d<float> extents = box.getExtent(); //vector3d<float> extents = box.getExtent();
@ -288,14 +359,16 @@ void Engine::reloadTexture()
bool Engine::loadTexture(const wstring& fileName) bool Engine::loadTexture(const wstring& fileName)
{ {
ITexture* texture = this->m_Driver->getTexture(fileName.c_str());
bool ret = false; bool ret = false;
if (texture != nullptr) { if (m_LoadedMesh != nullptr) {
m_LoadedMesh->setMaterialTexture(0, texture); ITexture* texture = this->m_Driver->getTexture(fileName.c_str());
ret = true; if (texture != nullptr) {
m_LoadedMesh->setMaterialTexture(0, texture);
ret = true;
}
this->m_PrevTexturePath = fileName;
this->m_UserInterface->texturePathEditBox->setText(this->m_PrevTexturePath.c_str());
} }
this->m_PrevTexturePath = fileName;
this->m_UserInterface->texturePathEditBox->setText(this->m_PrevTexturePath.c_str());
return ret; return ret;
} }
@ -385,7 +458,25 @@ void Engine::toggleAnimation()
void Engine::setAnimationFPS(u32 animationFPS) void Engine::setAnimationFPS(u32 animationFPS)
{ {
if (this->m_LoadedMesh != nullptr) { if (this->m_LoadedMesh != nullptr) {
if (animationFPS > 0) this->isPlaying = true;
// Do NOT call playAnimation, otherwise infinite recursion occurs (it calls setAnimationFPS).
this->m_LoadedMesh->setAnimationSpeed(animationFPS); this->m_LoadedMesh->setAnimationSpeed(animationFPS);
this->m_UserInterface->playbackFPSEditBox->setText(Utility::toWstring(this->m_LoadedMesh->getAnimationSpeed()).c_str());
}
}
void Engine::incrementAnimationFPS(irr::f32 by)
{
if (this->m_LoadedMesh != nullptr) {
if (by < 0) {
if (this->m_LoadedMesh->getAnimationSpeed() + by >= 0.999999f) // don't use this->animationFPS(), because its unsigned!
this->setAnimationFPS(this->m_LoadedMesh->getAnimationSpeed() + by);
else
this->setAnimationFPS(1);
}
else {
this->setAnimationFPS(this->animationFPS() + by);
}
} }
} }
@ -398,11 +489,11 @@ void Engine::setZUp(bool zUp)
u32 Engine::animationFPS() u32 Engine::animationFPS()
{ {
u32 ret = 0; f32 ret = 0;
if (this->m_LoadedMesh != nullptr) { if (this->m_LoadedMesh != nullptr) {
ret = this->m_LoadedMesh->getAnimationSpeed(); ret = this->m_LoadedMesh->getAnimationSpeed();
} }
return ret; return static_cast<u32>(ret);
} }
void Engine::run() void Engine::run()

View File

@ -68,10 +68,13 @@ private:
public: public:
std::wstring m_PreviousPath; std::wstring m_PreviousPath;
std::wstring m_PrevTexturePath; std::wstring m_PrevTexturePath;
irr::f32 axisLength;
bool m_zUp;
Engine(); Engine();
~Engine(); ~Engine();
irr::core::vector3df camTarget();
void run(); void run();
void loadMesh(const std::wstring& fileName); void loadMesh(const std::wstring& fileName);
void reloadMesh(); void reloadMesh();
@ -83,6 +86,7 @@ public:
void pauseAnimation(); void pauseAnimation();
void toggleAnimation(); void toggleAnimation();
void setAnimationFPS(irr::u32 animationFPS); void setAnimationFPS(irr::u32 animationFPS);
void incrementAnimationFPS(irr::f32 by);
void setZUp(bool zUp); void setZUp(bool zUp);
irr::u32 animationFPS(); irr::u32 animationFPS();
}; };

View File

@ -42,6 +42,7 @@ bool EventHandler::OnEvent(const SEvent& event)
} else if (event.EventType == EET_USER_EVENT) { } else if (event.EventType == EET_USER_EVENT) {
if (event.UserEvent.UserData1 == UEI_WINDOWSIZECHANGED) { if (event.UserEvent.UserData1 == UEI_WINDOWSIZECHANGED) {
// Window resize handling - send to all subscribers // Window resize handling - send to all subscribers
// (UserInterface will call snapWidgets to fix playbackWindow position)
map<EventReceiverType, IEventReceiver*>::iterator iter; map<EventReceiverType, IEventReceiver*>::iterator iter;
for (iter = m_EventReceivers->begin(); iter != m_EventReceivers->end(); iter++) for (iter = m_EventReceivers->begin(); iter != m_EventReceivers->end(); iter++)
iter->second->OnEvent(event); iter->second->OnEvent(event);

View File

@ -117,25 +117,27 @@ only applies to Visual Studio users.)
file. However, the program is much easier to use if you associate the file. However, the program is much easier to use if you associate the
format with b3view (see "Installation" above) so you can just double- format with b3view (see "Installation" above) so you can just double-
click the file to open b3view automatically. click the file to open b3view automatically.
* `-` / `+`: To change animation frame rate in increments of 5 fps, * `Ctrl left` / `Ctrl right` (arrow keys) to change animation frame rate
click "Faster" or "Slower," or use `-` key or `+`/`=` key. By default, in increments of 5 fps, click "Faster" or "Slower," or use `-` key or
the scene refreshes at 60fps and the animation runs as 30 fps `+`/`=` key. By default, the scene refreshes at 60fps and the
(Irrlicht does interpolation automatically). animation runs as 30 fps (Irrlicht does interpolation automatically).
* `t` / `e`: cycle through textures in `../textures` using `t` key (`e` Edit the frame rate manually using the input box under "Faster" and
to go back) such as for Minetest mods, where model must be in "Slower."
`modname/models/` and texture must be in `modname/textures/`. * `F3` / `Shift F3`: cycle through textures in `../textures` using `F3`
key (`Shift` to go backward) such as for Minetest mods, where model
must be in `modname/models/` and texture must be in `modname/textures/`.
- If `"../textures/" + basename(modelName) + ".png"` or `".jpg"` is - If `"../textures/" + basename(modelName) + ".png"` or `".jpg"` is
present, pressing `t` for the first time will load it. present, pressing `t` for the first time will load it.
- If `../textures` doesn't exist relative to the model file's - If `../textures` doesn't exist relative to the model file's
directory, the model file's own directory will be used. directory, the model file's own directory will be used.
* `x`: toggle texture interpolation (shortcut for View, Texture * `Ctrl i`: toggle texture interpolation (shortcut for View, Texture
Interpolation) Interpolation)
* `F5`: Reload last model file * `F5`: Reload last model file
* `r`: Reload last texture file (may not be working due to caching, * `Shift F5`: Reload last texture file (may not be working due to caching,
but does try to load different file if texture edit box changed). but does try to load different file if texture edit box changed).
* drag with middle button: rotate view * drag with middle button: rotate view
* drag with middle button while holding shift key: pan up and down * drag with middle button while holding shift key: pan up and down
* `z` or `y`: change camera "up" axis to Z or Y (Y is default; * View, choose "Up" axis: change camera "up" axis to Z or Y (Y is default;
automatically changed to Z when 3ds file is loaded) automatically changed to Z when 3ds file is loaded)
## Known Issues ## Known Issues

View File

@ -35,15 +35,24 @@ void UserInterface::setupUserInterface()
// File Menu // File Menu
fileMenu = menu->getSubMenu(0); fileMenu = menu->getSubMenu(0);
fileMenu->addItem(L"Load", UIC_FILE_LOAD); fileMenu->addItem(L"Open", UIC_FILE_OPEN);
fileMenu->addItem(L"LoadTexture", UIC_FILE_LOAD_TEXTURE); fileMenu->addItem(L"Change Texture", UIC_FILE_OPEN_TEXTURE);
fileMenu->addItem(L"Previous Texture Shift F3", UIC_FILE_PREVIOUS_TEXTURE);
fileMenu->addItem(L"Next Texture F3", UIC_FILE_NEXT_TEXTURE);
fileMenu->addItem(L"Quit", UIC_FILE_QUIT); fileMenu->addItem(L"Quit", UIC_FILE_QUIT);
// View Menu // View Menu
viewMenu = menu->getSubMenu(1); viewMenu = menu->getSubMenu(1);
INDEX_VIEW_WIREFRAME_MESH = viewMenu->addItem(L"Wireframe Mesh", UIC_VIEW_WIREFRAME, true, false, this->m_WireframeDisplay, true); viewWireframeIdx = viewMenu->addItem(L"Wireframe", UIC_VIEW_WIREFRAME, true, false, this->m_WireframeDisplay, true);
INDEX_VIEW_LIGHTING = viewMenu->addItem(L"Lighting", UIC_VIEW_LIGHTING, true, false, this->m_Lighting, true); viewLightingIdx = viewMenu->addItem(L"Lighting", UIC_VIEW_LIGHTING, true, false, this->m_Lighting, true);
INDEX_VIEW_TEXTURE_INTERPOLATION = viewMenu->addItem(L"Texture Interpolation", UIC_VIEW_TEXTURE_INTERPOLATION, true, false, this->m_TextureInterpolation, true); viewTargetIdx = viewMenu->addItem(L"Camera Target", UIC_VIEW_TARGET, true, false, true, true);
viewTextureInterpolationIdx = viewMenu->addItem(L"Texture Interpolation Ctrl i", UIC_VIEW_TEXTURE_INTERPOLATION, true, false, this->m_TextureInterpolation, true);
viewYUpIdx = viewMenu->addItem(L"Y Up", UIC_VIEW_Y_UP, true, false, true, true);
viewZUpIdx = viewMenu->addItem(L"Z Up", UIC_VIEW_Z_UP, true, false, false, true);
viewMenu->addItem(L"Slower Ctrl Left", UIC_VIEW_SLOWER, true, false, false, false);
viewMenu->addItem(L"Faster Ctrl Right", UIC_VIEW_FASTER, true, false, false, false);
// Playback Control Window // Playback Control Window
dimension2d<u32> windowSize = m_Engine->m_Driver->getScreenSize(); dimension2d<u32> windowSize = m_Engine->m_Driver->getScreenSize();
@ -51,6 +60,7 @@ void UserInterface::setupUserInterface()
rect<s32>(vector2d<s32>(windowSize.Width - 4 - 160, 28), dimension2d<s32>(160, 300)), false, L"Playback", nullptr, UIE_PLAYBACKWINDOW); rect<s32>(vector2d<s32>(windowSize.Width - 4 - 160, 28), dimension2d<s32>(160, 300)), false, L"Playback", nullptr, UIE_PLAYBACKWINDOW);
playbackWindow->getCloseButton()->setVisible(false); playbackWindow->getCloseButton()->setVisible(false);
s32 spacing_x = 4; s32 spacing_x = 4;
s32 margin_y = 4;
spacing_y = 4; spacing_y = 4;
s32 size_x = playbackWindow->getClientRect().getWidth() - 8; s32 size_x = playbackWindow->getClientRect().getWidth() - 8;
s32 size_y = 24; s32 size_y = 24;
@ -61,6 +71,16 @@ void UserInterface::setupUserInterface()
UIE_PLAYBACKSTARTSTOPBUTTON, UIE_PLAYBACKSTARTSTOPBUTTON,
L"Start/Stop", L"Start/Stop",
nullptr); nullptr);
y += size_y + spacing_y;
playbackSetFrameEditBox = m_Gui->addEditBox(
L"",
rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)),
true,
playbackWindow,
UIE_PLAYBACKSETFRAMEEDITBOX);
y += margin_y;
y += size_y + spacing_y; y += size_y + spacing_y;
playbackIncreaseButton = m_Gui->addButton( playbackIncreaseButton = m_Gui->addButton(
rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)), rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)),
@ -68,6 +88,7 @@ void UserInterface::setupUserInterface()
UIE_PLAYBACKINCREASEBUTTON, UIE_PLAYBACKINCREASEBUTTON,
L"Faster", L"Faster",
nullptr); nullptr);
y += size_y + spacing_y; y += size_y + spacing_y;
playbackDecreaseButton = m_Gui->addButton( playbackDecreaseButton = m_Gui->addButton(
rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)), rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)),
@ -77,12 +98,13 @@ void UserInterface::setupUserInterface()
nullptr); nullptr);
y += size_y + spacing_y; y += size_y + spacing_y;
playbackSetFrameEditBox = m_Gui->addEditBox( playbackFPSEditBox = m_Gui->addEditBox(
L"", L"",
rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)), rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)),
true, true,
playbackWindow, playbackWindow,
UIE_PLAYBACKSETFRAMEEDITBOX); UIE_FPSEDITBOX);
y += margin_y;
y += size_y + spacing_y; y += size_y + spacing_y;
texturePathStaticText = m_Gui->addStaticText( texturePathStaticText = m_Gui->addStaticText(
@ -93,6 +115,7 @@ void UserInterface::setupUserInterface()
playbackWindow, playbackWindow,
UIE_TEXTUREPATHSTATICTEXT, UIE_TEXTUREPATHSTATICTEXT,
false); false);
y += size_y + spacing_y; y += size_y + spacing_y;
texturePathEditBox = m_Gui->addEditBox( texturePathEditBox = m_Gui->addEditBox(
L"", L"",
@ -100,6 +123,28 @@ void UserInterface::setupUserInterface()
true, true,
playbackWindow, playbackWindow,
UIE_TEXTUREPATHEDITBOX); UIE_TEXTUREPATHEDITBOX);
y += margin_y;
y += size_y + spacing_y;
axisSizeStaticText = m_Gui->addStaticText(
L"Axis Size:",
rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)),
true,
true,
playbackWindow,
UIE_AXISSIZESTATICTEXT,
false);
y += size_y + spacing_y;
axisSizeEditBox = m_Gui->addEditBox(
L"",
rect<s32>(vector2d<s32>(spacing_x, y), dimension2d<s32>(size_x, size_y)),
true,
playbackWindow,
UIE_AXISSIZEEDITBOX);
y += margin_y;
y += size_y + spacing_y;
// Set Font for UI Elements // Set Font for UI Elements
m_GuiFontFace = new CGUITTFace(); m_GuiFontFace = new CGUITTFace();
@ -156,30 +201,52 @@ void UserInterface::handleMenuItemPressed(IGUIContextMenu* menu)
s32 id = menu->getItemCommandId(static_cast<u32>(selected)); s32 id = menu->getItemCommandId(static_cast<u32>(selected));
switch (id) { switch (id) {
case UIC_FILE_LOAD: case UIC_FILE_OPEN:
displayLoadFileDialog(); displayLoadFileDialog();
break; break;
case UIC_FILE_LOAD_TEXTURE: case UIC_FILE_OPEN_TEXTURE:
displayLoadTextureDialog(); displayLoadTextureDialog();
break; break;
case UIC_FILE_PREVIOUS_TEXTURE:
loadNextTexture(-1);
break;
case UIC_FILE_NEXT_TEXTURE:
loadNextTexture(1);
break;
case UIC_FILE_QUIT: case UIC_FILE_QUIT:
m_Engine->m_RunEngine = false; m_Engine->m_RunEngine = false;
break; break;
case UIC_VIEW_WIREFRAME: case UIC_VIEW_WIREFRAME:
m_WireframeDisplay = viewMenu->isItemChecked(INDEX_VIEW_WIREFRAME_MESH); m_WireframeDisplay = viewMenu->isItemChecked(viewWireframeIdx);
m_Engine->setMeshDisplayMode(m_WireframeDisplay, m_Lighting, m_TextureInterpolation); m_Engine->setMeshDisplayMode(m_WireframeDisplay, m_Lighting, m_TextureInterpolation);
break; break;
case UIC_VIEW_LIGHTING: case UIC_VIEW_LIGHTING:
m_Lighting = viewMenu->isItemChecked(INDEX_VIEW_LIGHTING); m_Lighting = viewMenu->isItemChecked(viewLightingIdx);
m_Engine->setMeshDisplayMode(m_WireframeDisplay, m_Lighting, m_TextureInterpolation); m_Engine->setMeshDisplayMode(m_WireframeDisplay, m_Lighting, m_TextureInterpolation);
break; break;
case UIC_VIEW_TARGET:
//
break;
case UIC_VIEW_Y_UP:
m_Engine->setZUp(false);
viewMenu->setItemChecked(viewZUpIdx, false);
break;
case UIC_VIEW_Z_UP:
m_Engine->setZUp(true);
viewMenu->setItemChecked(viewYUpIdx, false);
break;
case UIC_VIEW_TEXTURE_INTERPOLATION: case UIC_VIEW_TEXTURE_INTERPOLATION:
m_TextureInterpolation = viewMenu->isItemChecked(INDEX_VIEW_TEXTURE_INTERPOLATION); m_TextureInterpolation = viewMenu->isItemChecked(viewTextureInterpolationIdx);
m_Engine->setMeshDisplayMode(m_WireframeDisplay, m_Lighting, m_TextureInterpolation); m_Engine->setMeshDisplayMode(m_WireframeDisplay, m_Lighting, m_TextureInterpolation);
break; break;
} }
@ -210,9 +277,9 @@ void UserInterface::snapWidgets()
// PUBLIC // PUBLIC
UserInterface::UserInterface(Engine* engine) UserInterface::UserInterface(Engine* engine)
{ {
INDEX_VIEW_TEXTURE_INTERPOLATION = 0; viewTextureInterpolationIdx = 0;
INDEX_VIEW_WIREFRAME_MESH = 0; viewWireframeIdx = 0;
INDEX_VIEW_LIGHTING = 0; viewLightingIdx = 0;
this->playbackStartStopButton = nullptr; this->playbackStartStopButton = nullptr;
m_Engine = engine; m_Engine = engine;
@ -286,7 +353,6 @@ bool UserInterface::loadNextTexture(int direction)
// debug() << "tryPath 1b " << Utility::toString(tryPath) << "..." << endl; // debug() << "tryPath 1b " << Utility::toString(tryPath) << "..." << endl;
// tryPath = texturesPath + dirSeparator + Utility::basename(this->m_Engine->m_PreviousPath) + L".png"; // tryPath = texturesPath + dirSeparator + Utility::basename(this->m_Engine->m_PreviousPath) + L".png";
if (!Utility::isFile(tryPath)) { if (!Utility::isFile(tryPath)) {
//asdf
tryPath = texturesPath + dirSeparator + Utility::withoutExtension(Utility::basename(this->m_Engine->m_PreviousPath)) + L".jpg"; tryPath = texturesPath + dirSeparator + Utility::withoutExtension(Utility::basename(this->m_Engine->m_PreviousPath)) + L".jpg";
// debug() << "tryPath 2a " << Utility::toString(tryPath) << "..." << endl; // debug() << "tryPath 2a " << Utility::toString(tryPath) << "..." << endl;
tryPath = Utility::toWstring(Utility::toString(tryPath)); tryPath = Utility::toWstring(Utility::toString(tryPath));
@ -305,8 +371,8 @@ bool UserInterface::loadNextTexture(int direction)
} }
} }
} }
//debug() << "tryPath: " << Utility::toString(tryPath) << endl; // debug() << "tryPath: " << Utility::toString(tryPath) << endl;
//debug() << "nextPath: " << Utility::toString(nextPath) << endl; // debug() << "nextPath: " << Utility::toString(nextPath) << endl;
for (const auto& itr : fs::directory_iterator(path)) { for (const auto& itr : fs::directory_iterator(path)) {
std::wstring ext = Utility::extensionOf(itr.path().wstring()); // no dot! std::wstring ext = Utility::extensionOf(itr.path().wstring()); // no dot!
if (!is_directory(itr.status()) if (!is_directory(itr.status())
@ -346,40 +412,128 @@ bool UserInterface::loadNextTexture(int direction)
bool UserInterface::OnEvent(const SEvent& event) bool UserInterface::OnEvent(const SEvent& event)
{ {
// Events arriving here should be destined for us // Events arriving here should be destined for us
bool handled = false;
if (event.EventType == EET_USER_EVENT) { if (event.EventType == EET_USER_EVENT) {
// debug() << "EET_USER_EVENT..." << endl;
if (event.UserEvent.UserData1 == UEI_WINDOWSIZECHANGED) { if (event.UserEvent.UserData1 == UEI_WINDOWSIZECHANGED) {
if ((m_WindowSize.Width != m_Engine->m_Driver->getScreenSize().Width) || (m_WindowSize.Height != m_Engine->m_Driver->getScreenSize().Height)) { if ((m_WindowSize.Width != m_Engine->m_Driver->getScreenSize().Width) || (m_WindowSize.Height != m_Engine->m_Driver->getScreenSize().Height)) {
snapWidgets(); snapWidgets();
} }
handled = true;
}
} else if (event.EventType == EET_GUI_EVENT) {
// debug() << "EET_GUI_EVENT..." << endl;
handled = true; // set to false below if not handled
const SEvent::SGUIEvent* ge = &(event.GUIEvent);
switch (ge->Caller->getID()) {
case UIE_FILEMENU:
case UIE_VIEWMENU:
// call handler for all menu related actions
handleMenuItemPressed(static_cast<IGUIContextMenu*>(ge->Caller));
break;
case UIE_LOADFILEDIALOG:
if (ge->EventType == EGET_FILE_SELECTED) {
IGUIFileOpenDialog* fileOpenDialog = static_cast<IGUIFileOpenDialog*>(ge->Caller);
m_Engine->loadMesh(fileOpenDialog->getFileName());
}
break;
case UIE_LOADTEXTUREDIALOG:
if (ge->EventType == EGET_FILE_SELECTED) {
IGUIFileOpenDialog* fileOpenDialog = static_cast<IGUIFileOpenDialog*>(ge->Caller);
m_Engine->loadTexture(fileOpenDialog->getFileName());
}
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->incrementAnimationFPS(5);
}
break;
case UIE_PLAYBACKDECREASEBUTTON:
if (ge->EventType == EGET_BUTTON_CLICKED) {
this->m_Engine->incrementAnimationFPS(-5);
}
break;
case UIE_PLAYBACKSETFRAMEEDITBOX:
if (ge->EventType == EGET_EDITBOX_ENTER) {
if (this->m_Engine->m_LoadedMesh != nullptr) {
this->m_Engine->m_LoadedMesh->setCurrentFrame(Utility::toF32(this->playbackSetFrameEditBox->getText()));
}
}
break;
case UIE_TEXTUREPATHEDITBOX:
if (ge->EventType == EGET_EDITBOX_ENTER) {
if (this->m_Engine->m_LoadedMesh != nullptr) {
this->m_Engine->loadTexture(texturePathEditBox->getText());
}
}
break;
case UIE_FPSEDITBOX:
if (ge->EventType == EGET_EDITBOX_ENTER) {
if (this->m_Engine->m_LoadedMesh != nullptr) {
this->m_Engine->m_LoadedMesh->setAnimationSpeed(Utility::toF32(this->playbackFPSEditBox->getText()));
}
}
break;
case UIE_AXISSIZEEDITBOX:
if (ge->EventType == EGET_EDITBOX_ENTER) {
this->m_Engine->axisLength = Utility::toF32(this->axisSizeEditBox->getText());
}
break;
default:
// break;
handled = false;
} }
return true;
} else if (event.EventType == EET_KEY_INPUT_EVENT) { } else if (event.EventType == EET_KEY_INPUT_EVENT) {
// debug() << "EET_KEY_INPUT_EVENT..." << endl;
handled = true; // set to false below if not handled
if (event.KeyInput.PressedDown && !m_Engine->KeyIsDown[event.KeyInput.Key]) { if (event.KeyInput.PressedDown && !m_Engine->KeyIsDown[event.KeyInput.Key]) {
if (event.KeyInput.Key == irr::KEY_F5) { if (event.KeyInput.Key == irr::KEY_F5) {
m_Engine->reloadMesh(); if (m_Engine->KeyIsDown[irr::KEY_LSHIFT] || m_Engine->KeyIsDown[irr::KEY_RSHIFT]) {
} else if (event.KeyInput.Key == irr::KEY_KEY_T) { m_Engine->reloadTexture();
loadNextTexture(1);
} else if (event.KeyInput.Key == irr::KEY_KEY_E) {
loadNextTexture(-1);
} else if (event.KeyInput.Key == irr::KEY_KEY_R) {
m_Engine->reloadTexture();
} else if (event.KeyInput.Key == irr::KEY_KEY_Z) {
m_Engine->setZUp(true);
} else if (event.KeyInput.Key == irr::KEY_KEY_Y) {
m_Engine->setZUp(false);
} else if (event.KeyInput.Key == irr::KEY_KEY_X) {
// IGUIContextMenu* textureInterpolationElement = dynamic_cast<IGUIContextMenu*>(viewMenu->getElementFromId(UIC_VIEW_TEXTURE_INTERPOLATION));
//m_TextureInterpolation = textureInterpolationElement->isItemChecked(UIC_VIEW_TEXTURE_INTERPOLATION);
m_TextureInterpolation = m_TextureInterpolation ? false : true;
//doesn't work: m_TextureInterpolation = viewMenu->isItemChecked(UIC_VIEW_TEXTURE_INTERPOLATION);
m_Engine->setMeshDisplayMode(m_WireframeDisplay, m_Lighting, m_TextureInterpolation);
viewMenu->setItemChecked(INDEX_VIEW_TEXTURE_INTERPOLATION, m_TextureInterpolation);
} else if (event.KeyInput.Char == L'+' || event.KeyInput.Char == L'=') {
m_Engine->setAnimationFPS(m_Engine->animationFPS() + 5);
} else if (event.KeyInput.Char == L'-') {
if (m_Engine->animationFPS() > 0) {
m_Engine->setAnimationFPS(m_Engine->animationFPS() - 5);
} }
else
m_Engine->reloadMesh();
} else if (event.KeyInput.Key == irr::KEY_F3) {
if (m_Engine->KeyIsDown[irr::KEY_LSHIFT] || m_Engine->KeyIsDown[irr::KEY_RSHIFT]) {
loadNextTexture(-1);
debug() << " - back" << endl;
}
else
loadNextTexture(1);
} else if (event.KeyInput.Key == irr::KEY_KEY_I) {
if (m_Engine->KeyIsDown[irr::KEY_LCONTROL] || m_Engine->KeyIsDown[irr::KEY_RCONTROL]) {
// IGUIContextMenu* textureInterpolationElement = dynamic_cast<IGUIContextMenu*>(viewMenu->getElementFromId(UIC_VIEW_TEXTURE_INTERPOLATION));
// m_TextureInterpolation = textureInterpolationElement->isItemChecked(UIC_VIEW_TEXTURE_INTERPOLATION);
m_TextureInterpolation = m_TextureInterpolation ? false : true;
// doesn't work: m_TextureInterpolation = viewMenu->isItemChecked(UIC_VIEW_TEXTURE_INTERPOLATION);
m_Engine->setMeshDisplayMode(m_WireframeDisplay, m_Lighting, m_TextureInterpolation);
viewMenu->setItemChecked(viewTextureInterpolationIdx, m_TextureInterpolation);
}
else
handled = false;
} else if (event.KeyInput.Key == irr::KEY_RIGHT) {
if (m_Engine->KeyIsDown[irr::KEY_LCONTROL] || m_Engine->KeyIsDown[irr::KEY_RCONTROL]) {
m_Engine->incrementAnimationFPS(5);
}
else
handled = false;
} else if (event.KeyInput.Key == irr::KEY_LEFT) {
if (m_Engine->KeyIsDown[irr::KEY_LCONTROL] || m_Engine->KeyIsDown[irr::KEY_RCONTROL]) {
m_Engine->incrementAnimationFPS(-5);
}
else
handled = false;
} else if (event.KeyInput.Char == L' ') { } else if (event.KeyInput.Char == L' ') {
m_Engine->toggleAnimation(); m_Engine->toggleAnimation();
} else if (event.KeyInput.Key == irr::KEY_LEFT) { } else if (event.KeyInput.Key == irr::KEY_LEFT) {
@ -397,13 +551,18 @@ bool UserInterface::OnEvent(const SEvent& event)
this->playbackSetFrameEditBox->setText(Utility::toWstring(this->m_Engine->m_LoadedMesh->getFrameNr()).c_str()); this->playbackSetFrameEditBox->setText(Utility::toWstring(this->m_Engine->m_LoadedMesh->getFrameNr()).c_str());
} }
} }
else
handled = false;
// std::wcerr << "Char: " << event.KeyInput.Char << endl; // std::wcerr << "Char: " << event.KeyInput.Char << endl;
} }
m_Engine->KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; m_Engine->KeyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown;
return true; return true;
} else if (event.EventType == EET_MOUSE_INPUT_EVENT) { } else if (event.EventType == EET_MOUSE_INPUT_EVENT) {
// TODO: improve this copypasta // debug() << "EET_MOUSE_INPUT_EVENT..." << endl;
handled = true; // set to false below if not handled
// TODO: improve this copypasta (or elsewhere use states 1 and 3 as
// events, and add 1 as "handled" (or set back to 0 for no drag feature)
// as intended for drag or long press handling).
switch (event.MouseInput.Event) { switch (event.MouseInput.Event) {
case EMIE_LMOUSE_LEFT_UP: case EMIE_LMOUSE_LEFT_UP:
if (m_Engine->LMouseState == 2) { if (m_Engine->LMouseState == 2) {
@ -428,63 +587,9 @@ bool UserInterface::OnEvent(const SEvent& event)
m_Engine->RMouseState = 1; m_Engine->RMouseState = 1;
} }
break; break;
default:
handled = false;
} }
} else if (!(event.EventType == EET_GUI_EVENT))
return false;
const SEvent::SGUIEvent* ge = &(event.GUIEvent);
switch (ge->Caller->getID()) {
case UIE_FILEMENU:
case UIE_VIEWMENU:
// call handler for all menu related actions
handleMenuItemPressed(static_cast<IGUIContextMenu*>(ge->Caller));
break;
case UIE_LOADFILEDIALOG:
if (ge->EventType == EGET_FILE_SELECTED) {
IGUIFileOpenDialog* fileOpenDialog = static_cast<IGUIFileOpenDialog*>(ge->Caller);
m_Engine->loadMesh(fileOpenDialog->getFileName());
}
break;
case UIE_LOADTEXTUREDIALOG:
if (ge->EventType == EGET_FILE_SELECTED) {
IGUIFileOpenDialog* fileOpenDialog = static_cast<IGUIFileOpenDialog*>(ge->Caller);
m_Engine->loadTexture(fileOpenDialog->getFileName());
}
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;
case UIE_PLAYBACKSETFRAMEEDITBOX:
if (ge->EventType == EGET_EDITBOX_ENTER) {
if (this->m_Engine->m_LoadedMesh != nullptr) {
this->m_Engine->m_LoadedMesh->setCurrentFrame(Utility::toF32(this->playbackSetFrameEditBox->getText()));
}
}
break;
default:
break;
} }
return handled;
return true;
} }

View File

@ -17,20 +17,30 @@ enum UserInterfaceElements {
UIE_PLAYBACKWINDOW = 3000, UIE_PLAYBACKWINDOW = 3000,
UIE_PLAYBACKSTARTSTOPBUTTON = 3001, UIE_PLAYBACKSTARTSTOPBUTTON = 3001,
UIE_PLAYBACKINCREASEBUTTON = 3002, UIE_PLAYBACKSETFRAMEEDITBOX = 3002,
UIE_PLAYBACKDECREASEBUTTON = 3003, UIE_PLAYBACKINCREASEBUTTON = 3003,
UIE_PLAYBACKSETFRAMEEDITBOX = 3004, UIE_PLAYBACKDECREASEBUTTON = 3004,
UIE_TEXTUREPATHSTATICTEXT = 3005, UIE_FPSEDITBOX = 3005,
UIE_TEXTUREPATHEDITBOX = 3006 UIE_TEXTUREPATHSTATICTEXT = 3006,
UIE_TEXTUREPATHEDITBOX = 3007,
UIE_AXISSIZESTATICTEXT = 3008,
UIE_AXISSIZEEDITBOX = 3009
}; };
enum UserInterfaceCommands { enum UserInterfaceCommands {
UIC_FILE_LOAD = 1000, UIC_FILE_OPEN = 1000,
UIC_FILE_QUIT = 1001, UIC_FILE_QUIT = 1001,
UIC_FILE_LOAD_TEXTURE = 1002, UIC_FILE_OPEN_TEXTURE = 1002,
UIC_FILE_NEXT_TEXTURE = 1003,
UIC_FILE_PREVIOUS_TEXTURE = 1004,
UIC_VIEW_WIREFRAME = 2001, UIC_VIEW_WIREFRAME = 2001,
UIC_VIEW_LIGHTING = 2002, UIC_VIEW_LIGHTING = 2002,
UIC_VIEW_TEXTURE_INTERPOLATION = 2003 UIC_VIEW_TARGET = 2003,
UIC_VIEW_TEXTURE_INTERPOLATION = 2004,
UIC_VIEW_Y_UP = 2005,
UIC_VIEW_Z_UP = 2006,
UIC_VIEW_SLOWER = 2007,
UIC_VIEW_FASTER = 2008
}; };
class UserInterface : public irr::IEventReceiver { class UserInterface : public irr::IEventReceiver {
@ -56,14 +66,20 @@ public:
irr::gui::IGUIContextMenu* fileMenu; irr::gui::IGUIContextMenu* fileMenu;
irr::gui::IGUIContextMenu* viewMenu; irr::gui::IGUIContextMenu* viewMenu;
irr::gui::IGUIButton* playbackStartStopButton; irr::gui::IGUIButton* playbackStartStopButton;
irr::gui::IGUIEditBox* playbackSetFrameEditBox;
irr::gui::IGUIButton* playbackIncreaseButton; irr::gui::IGUIButton* playbackIncreaseButton;
irr::gui::IGUIButton* playbackDecreaseButton; irr::gui::IGUIButton* playbackDecreaseButton;
irr::gui::IGUIEditBox* playbackSetFrameEditBox; irr::gui::IGUIEditBox* playbackFPSEditBox;
irr::gui::IGUIStaticText* texturePathStaticText; irr::gui::IGUIStaticText* texturePathStaticText;
irr::gui::IGUIEditBox* texturePathEditBox; irr::gui::IGUIEditBox* texturePathEditBox;
irr::u32 INDEX_VIEW_TEXTURE_INTERPOLATION; irr::gui::IGUIStaticText* axisSizeStaticText;
irr::u32 INDEX_VIEW_WIREFRAME_MESH; irr::gui::IGUIEditBox* axisSizeEditBox;
irr::u32 INDEX_VIEW_LIGHTING; irr::u32 viewTextureInterpolationIdx;
irr::u32 viewWireframeIdx;
irr::u32 viewLightingIdx;
irr::u32 viewTargetIdx;
irr::u32 viewYUpIdx;
irr::u32 viewZUpIdx;
void snapWidgets(); void snapWidgets();

View File

@ -218,6 +218,12 @@ irr::f32 Utility::toF32(wstring val)
return ret; return ret;
} }
irr::f32 Utility::distance(const vector3df &start, const vector3df &end)
{
vector3df offsetVec3(end.X - start.X, end.Y - start.Y, end.Z - start.Z);
return offsetVec3.getLength();
}
bool Utility::isFile(const std::wstring& name) bool Utility::isFile(const std::wstring& name)
{ {
std::string name_s = toString(name); std::string name_s = toString(name);

View File

@ -24,6 +24,7 @@ public:
static std::wstring toWstring(int val); static std::wstring toWstring(int val);
static std::wstring toWstring(const std::string& str); static std::wstring toWstring(const std::string& str);
static irr::f32 toF32(std::wstring val); static irr::f32 toF32(std::wstring val);
static irr::f32 distance(const irr::core::vector3df& start, const irr::core::vector3df& end);
// compiler doesn't like template function when class is not a template--instantiate immediately // compiler doesn't like template function when class is not a template--instantiate immediately
// see http://processors.wiki.ti.com/index.php/C%2B%2B_Template_Instantiation_Issues // see http://processors.wiki.ti.com/index.php/C%2B%2B_Template_Instantiation_Issues
template <typename T> template <typename T>

165
View.cpp
View File

@ -2,6 +2,8 @@
#include "Engine.h" #include "Engine.h"
#include <iostream> #include <iostream>
#include "Utility.h"
using namespace irr; using namespace irr;
using namespace irr::core; using namespace irr::core;
using namespace irr::scene; using namespace irr::scene;
@ -43,16 +45,15 @@ void View::setNewCameraPosition(bool zUp)
} }
if (zUp) { if (zUp) {
newCameraPosition.X = 0; newCameraPosition.X = 0;
newCameraPosition.Y = m_CameraDistance * cos(m_Pitch); newCameraPosition.Y = m_CameraDistance * cos(m_PitchFromTarget);
newCameraPosition.Z = m_CameraDistance * sin(m_Pitch); newCameraPosition.Z = m_CameraDistance * sin(m_PitchFromTarget);
yawMatrix.setRotationRadians(vector3df(0, 0, m_Yaw)); yawMatrix.setRotationRadians(vector3df(0, 0, m_YawFromTarget));
} else { } else {
newCameraPosition.X = 0; newCameraPosition.X = 0;
newCameraPosition.Y = m_CameraDistance * sin(m_Pitch); newCameraPosition.Y = m_CameraDistance * sin(m_PitchFromTarget);
newCameraPosition.Z = m_CameraDistance * cos(m_Pitch); newCameraPosition.Z = m_CameraDistance * cos(m_PitchFromTarget);
yawMatrix.setRotationRadians(vector3df(0, m_Yaw, 0)); yawMatrix.setRotationRadians(vector3df(0, m_YawFromTarget, 0));
} }
yawMatrix.transformVect(newCameraPosition); yawMatrix.transformVect(newCameraPosition);
if (zUp) { if (zUp) {
@ -68,17 +69,17 @@ void View::setNewCameraPosition(bool zUp)
camera->setTarget(m_Engine->m_CamTarget); camera->setTarget(m_Engine->m_CamTarget);
// Set Light direction // Set Light direction
setNewLightDirection(newCameraPosition); setNewLightDirection(newCameraPosition, m_Engine->m_CamTarget);
m_zUp = zUp; m_zUp = zUp;
// std::wcerr << L" setCameraPosition pitch: " << m_Pitch << endl; // std::wcerr << L" setCameraPosition pitch: " << m_Pitch << endl;
} }
void View::setNewLightDirection(const vector3df& cameraPosition) void View::setNewLightDirection(const vector3df& cameraPosition, const vector3df& cameraTarget)
{ {
ILightSceneNode* light = static_cast<ILightSceneNode*>(m_Engine->m_Scene->getSceneNodeFromId(SIID_LIGHT)); ILightSceneNode* light = static_cast<ILightSceneNode*>(m_Engine->m_Scene->getSceneNodeFromId(SIID_LIGHT));
matrix4 m; matrix4 m;
m.buildRotateFromTo(vector3df(0, 0, 1), vector3df(cameraPosition).invert().normalize()); m.buildRotateFromTo(cameraTarget, vector3df(cameraPosition).invert().normalize());
light->setRotation(m.getRotationDegrees()); light->setRotation(m.getRotationDegrees());
} }
@ -90,7 +91,9 @@ View::View(Engine* engine)
m_LastMousePosition = new vector2d<int>(); m_LastMousePosition = new vector2d<int>();
m_RotMouse = false; m_RotMouse = false;
m_Pitch = PI; //m_Pitch = PI;
// Initial camera values: see Engine::setupScene
// Set Camera Distance // Set Camera Distance
// m_CameraDistance = 10; // m_CameraDistance = 10;
@ -110,14 +113,14 @@ View::View(Engine* engine)
// see rogerborg on <http://irrlicht.sourceforge.net/forum/viewtopic.php?f=1&t=30477> // see rogerborg on <http://irrlicht.sourceforge.net/forum/viewtopic.php?f=1&t=30477>
// const f32 dot = engine->tmpTargetVec3f.dotProduct(engine->tmpPosVec3f); // to...(from) // angle only // const f32 dot = engine->tmpTargetVec3f.dotProduct(engine->tmpPosVec3f); // to...(from) // angle only
m_Yaw = atan2(offsetVec3.X, offsetVec3.Z); m_YawFromTarget = atan2(offsetVec3.X, offsetVec3.Z);
m_Pitch = asin(-offsetVec3.Y); m_PitchFromTarget = asin(offsetVec3.Y);
// m_Yaw = rotationVec3.Y; // m_Yaw = rotationVec3.Y;
// m_Pitch = rotationVec3.X; // m_Pitch = rotationVec3.X;
debug() << "Yaw: " << radToDeg(m_Yaw) << endl; debug() << "STARTING Yaw: " << radToDeg(m_YawFromTarget)<< " Pitch: " << radToDeg(m_PitchFromTarget) << endl;
debug() << "Pitch: " << radToDeg(m_Pitch) << endl; setNewCameraPosition();
} }
View::~View() View::~View()
@ -132,6 +135,11 @@ void View::setZUp(bool zUp)
} }
} }
float View::cameraDistance()
{
return m_CameraDistance;
}
void View::setCameraDistance(float cameraDistance) void View::setCameraDistance(float cameraDistance)
{ {
m_CameraDistance = cameraDistance; m_CameraDistance = cameraDistance;
@ -139,7 +147,7 @@ void View::setCameraDistance(float cameraDistance)
bool View::zUp() bool View::zUp()
{ {
return m_zUp; return this->m_zUp;
} }
// IEventReceiver // IEventReceiver
@ -153,7 +161,7 @@ bool View::OnEvent(const SEvent& event)
if (event.EventType == EET_USER_EVENT && event.UserEvent.UserData1 == UEI_WINDOWSIZECHANGED) { if (event.EventType == EET_USER_EVENT && event.UserEvent.UserData1 == UEI_WINDOWSIZECHANGED) {
dimension2d<u32> windowSize = m_Engine->m_Driver->getScreenSize(); dimension2d<u32> windowSize = m_Engine->m_Driver->getScreenSize();
f32 aspectRatio = static_cast<f32>(windowSize.Width) / static_cast<f32>(windowSize.Height); f32 aspectRatio = static_cast<f32>(windowSize.Width) / static_cast<f32>(windowSize.Height);
debug() << "Setting aspect to: " << aspectRatio << endl; // debug() << "Setting aspect to: " << aspectRatio << endl;
m_Engine->m_Scene->getActiveCamera()->setAspectRatio(aspectRatio); m_Engine->m_Scene->getActiveCamera()->setAspectRatio(aspectRatio);
} }
@ -167,12 +175,41 @@ bool View::OnEvent(const SEvent& event)
} else if (mouseEvent->Event == EMIE_MMOUSE_LEFT_UP) { } else if (mouseEvent->Event == EMIE_MMOUSE_LEFT_UP) {
m_RotMouse = false; m_RotMouse = false;
} else if (mouseEvent->Event == EMIE_MOUSE_WHEEL) { } else if (mouseEvent->Event == EMIE_MOUSE_WHEEL) {
f32 distanceDelta = mouseEvent->Wheel / 2.5f; // Zoom camera.
if (m_CameraDistance - distanceDelta > 0.1f) //debug() << "Wheel=" << mouseEvent->Wheel; // -1 or 1
m_CameraDistance -= distanceDelta; vector3df offsetVec3(
m_Engine->m_CamPos.X - m_Engine->m_CamTarget.X,
m_Engine->m_CamPos.Y - m_Engine->m_CamTarget.Y,
m_Engine->m_CamPos.Z - m_Engine->m_CamTarget.Z);
f32 distanceDelta = mouseEvent->Wheel * -1 * (offsetVec3.getLength() / 10);
ICameraSceneNode* camera = m_Engine->m_Scene->getActiveCamera();
f32 distanceFactor = distanceDelta / Utility::distance(m_Engine->m_CamPos, m_Engine->m_CamTarget);
////m_Engine->m_CamPos.interpolate(m_Engine->m_CamPos, m_Engine->m_CamTarget, distanceFactor);
////offsetVec3.normalize();
//m_Engine->m_CamPos.X -= offsetVec3.X * distanceFactor;
//m_Engine->m_CamPos.Y -= offsetVec3.Y * distanceFactor;
//m_Engine->m_CamPos.Z -= offsetVec3.Z * distanceFactor;
//m_Engine->m_CamTarget.X -= offsetVec3.X * distanceFactor;
//m_Engine->m_CamTarget.Y -= offsetVec3.Y * distanceFactor;
//m_Engine->m_CamTarget.Z -= offsetVec3.Z * distanceFactor;
offsetVec3 = vector3df(
m_Engine->m_CamPos.X - m_Engine->m_CamTarget.X,
m_Engine->m_CamPos.Y - m_Engine->m_CamTarget.Y,
m_Engine->m_CamPos.Z - m_Engine->m_CamTarget.Z);
//camera->setPosition(m_Engine->m_CamPos);
//camera->setTarget(m_Engine->m_CamTarget);
//m_Yaw = atan2(offsetVec3.X, offsetVec3.Z);
//m_Pitch = asin(offsetVec3.Y);
//m_CameraDistance = Utility::distance(m_Engine->m_CamPos, m_Engine->m_CamTarget);
m_CameraDistance += distanceDelta;
setNewCameraPosition(); setNewCameraPosition();
debug() << "m_CamPos: " << m_Engine->m_CamPos.X << "," << m_Engine->m_CamPos.Y << " m_CamTarget: " << m_Engine->m_CamTarget.X << "," << m_Engine->m_CamTarget.Y << endl;
} else if (m_RotMouse) { } else if (m_RotMouse) {
// debug() << "Yaw: " << radToDeg(m_Yaw) << " Pitch: " << radToDeg(m_Pitch) << endl;
int dx = mouseEvent->X - m_LastMousePosition->X; int dx = mouseEvent->X - m_LastMousePosition->X;
int dy = mouseEvent->Y - m_LastMousePosition->Y; int dy = mouseEvent->Y - m_LastMousePosition->Y;
@ -180,23 +217,36 @@ bool View::OnEvent(const SEvent& event)
m_LastMousePosition->Y = mouseEvent->Y; m_LastMousePosition->Y = mouseEvent->Y;
if (m_Engine->KeyIsDown[irr::KEY_RSHIFT] || m_Engine->KeyIsDown[irr::KEY_LSHIFT]) { if (m_Engine->KeyIsDown[irr::KEY_RSHIFT] || m_Engine->KeyIsDown[irr::KEY_LSHIFT]) {
// Pan camera. // Pan camera.
float yDelta = (dy / 400.0f) * m_CameraDistance; float yDelta = (dy / static_cast<float>(m_Engine->m_Driver->getScreenSize().Height/2)) * m_CameraDistance;
ICameraSceneNode* camera = m_Engine->m_Scene->getActiveCamera(); ICameraSceneNode* camera = m_Engine->m_Scene->getActiveCamera();
vector3df rotationVec3; f32 sidewaysAngle = 0;
rotationVec3 = camera->getRotation(); vector3df target3df = camera->getTarget();
vector3df camera3df = camera->getAbsolutePosition();
vector2df cameraFromTarget;
cameraFromTarget.X = camera3df.X - target3df.X;
cameraFromTarget.Y = camera3df.Y - target3df.Y;
if (!m_zUp) {
// sidewaysAngle = camera->getRotation().Y;
cameraFromTarget.Y = camera3df.Z - camera3df.Z;
}
// sidewaysAngle = camera->getRotation().Z; // always zero for unknown reason
// sidewaysAngle = atan2(cameraFromTarget.Y, cameraFromTarget.X);
// if (sidewaysAngle > 2 * PI)
// sidewaysAngle -= 2 * PI;
// vector3df rotationVec3;
// rotationVec3 = camera->getRotation();
vector3df forwards(0, 0, 1); vector3df forwards(0, 0, 1);
vector3df dirVec3 = camera->getUpVector(); vector3df dirVec3 = camera->getUpVector();
// vector3df camRot = camera->getRotation(); // vector3df camRot = camera->getRotation();
vector3df camRot(0, 0, 0); vector3df camRot(0, 0, 0);
// TODO: fix this (pitch becomes flat) camRot.X = m_PitchFromTarget;
camRot.X = m_Pitch;
if (m_zUp) { if (m_zUp) {
camRot.Z = m_Yaw; camRot.Z = m_YawFromTarget;
forwards = vector3df(0, 1, 0); forwards = vector3df(0, 1, 0);
dirVec3.rotateYZBy(camRot.X); dirVec3.rotateYZBy(camRot.X);
dirVec3.rotateXYBy(camRot.Z); dirVec3.rotateXYBy(camRot.Z);
} else { } else {
camRot.Z = m_Pitch; camRot.Z = m_PitchFromTarget;
dirVec3.rotateYZBy(camRot.X); dirVec3.rotateYZBy(camRot.X);
dirVec3.rotateXYBy(camRot.Y); dirVec3.rotateXYBy(camRot.Y);
} }
@ -214,6 +264,8 @@ bool View::OnEvent(const SEvent& event)
m_Engine->m_CamTarget.X += dirVec3.X; m_Engine->m_CamTarget.X += dirVec3.X;
m_Engine->m_CamTarget.Y += dirVec3.Y; m_Engine->m_CamTarget.Y += dirVec3.Y;
m_Engine->m_CamTarget.Z += dirVec3.Z; m_Engine->m_CamTarget.Z += dirVec3.Z;
if (m_zUp) { if (m_zUp) {
//m_Engine->m_CamPos.Z += yDelta; //m_Engine->m_CamPos.Z += yDelta;
//m_Engine->m_CamTarget.Z += yDelta; //m_Engine->m_CamTarget.Z += yDelta;
@ -221,16 +273,51 @@ bool View::OnEvent(const SEvent& event)
//m_Engine->m_CamPos.Y += yDelta; //m_Engine->m_CamPos.Y += yDelta;
//m_Engine->m_CamTarget.Y += yDelta; //m_Engine->m_CamTarget.Y += yDelta;
} }
camera->setPosition(m_Engine->m_CamPos); // camera->setPosition(m_Engine->m_CamPos);
camera->setTarget(m_Engine->m_CamTarget); // camera->setTarget(m_Engine->m_CamTarget);
vector3df offsetVec3( vector3df offsetVec3(
m_Engine->m_CamPos.X - m_Engine->m_CamTarget.X, m_Engine->m_CamPos.X - m_Engine->m_CamTarget.X,
m_Engine->m_CamPos.Y - m_Engine->m_CamTarget.Y, m_Engine->m_CamPos.Y - m_Engine->m_CamTarget.Y,
m_Engine->m_CamPos.Z - m_Engine->m_CamTarget.Z); m_Engine->m_CamPos.Z - m_Engine->m_CamTarget.Z
m_CameraDistance = offsetVec3.getLength(); );
m_Yaw = atan2(offsetVec3.X, offsetVec3.Z); // m_CameraDistance = offsetVec3.getLength(); //bad: resets zoom
m_Pitch = asin(-offsetVec3.Y);
// m_Yaw = atan2(offsetVec3.X, offsetVec3.Z);
// m_Pitch = asin(offsetVec3.Y);
setNewCameraPosition();
debug() << "AFTER Yaw: " << radToDeg(m_YawFromTarget)<< " Pitch: " << radToDeg(m_PitchFromTarget) << endl;
float xDelta = (dx / static_cast<float>(m_Engine->m_Driver->getScreenSize().Width/2)) * m_CameraDistance;
vector3df sidewaysVec3;
sidewaysAngle = m_YawFromTarget;
// sidewaysAngle += ((PI / 2.0) * 1.0);
if (sidewaysAngle > 2 * PI) {
sidewaysAngle -= 2 * PI;
}
else if (sidewaysAngle < -2 * PI) {
sidewaysAngle += 2 * PI;
}
if (sidewaysAngle > PI) {
sidewaysAngle = sidewaysAngle - 2 * PI;
}
sidewaysVec3.X = xDelta * cos(sidewaysAngle);
if (m_zUp) {
sidewaysVec3.Y = xDelta * sin(sidewaysAngle);
sidewaysVec3.Z = 0;
}
else {
sidewaysVec3.Z = xDelta * sin(sidewaysAngle);
sidewaysVec3.Y = 0;
}
debug() << "sidewaysAngle:" << sidewaysAngle << " zUp:" << ((m_zUp)?"true":"false") << endl;
m_Engine->m_CamPos.X += sidewaysVec3.X;
m_Engine->m_CamPos.Y += sidewaysVec3.Y;
m_Engine->m_CamPos.Z += sidewaysVec3.Z;
m_Engine->m_CamTarget.X += sidewaysVec3.X;
m_Engine->m_CamTarget.Y += sidewaysVec3.Y;
m_Engine->m_CamTarget.Z += sidewaysVec3.Z;
setNewCameraPosition(); setNewCameraPosition();
} else { } else {
// Revolve camera around object. // Revolve camera around object.
@ -239,16 +326,16 @@ bool View::OnEvent(const SEvent& event)
// (This old code which may make assumptions about view tends to lock on min/max) // (This old code which may make assumptions about view tends to lock on min/max)
// if ((m_Pitch - pitchDelta > (PI - (PI / 2))) && (m_Pitch - pitchDelta < PI + (PI/2))) // if ((m_Pitch - pitchDelta > (PI - (PI / 2))) && (m_Pitch - pitchDelta < PI + (PI/2)))
// m_Pitch -= dy / 120.0f; // m_Pitch -= dy / 120.0f;
m_Pitch += pitchDelta; m_PitchFromTarget += pitchDelta;
float minPitch = -PI / 2.0f + PI / 1000.0f; float minPitch = -PI / 2.0f + PI / 1000.0f;
float maxPitch = PI / 2.0f - PI / 1000.0f; float maxPitch = PI / 2.0f - PI / 1000.0f;
if (m_Pitch < minPitch) if (m_PitchFromTarget < minPitch)
m_Pitch = minPitch; m_PitchFromTarget = minPitch;
else if (m_Pitch > maxPitch) else if (m_PitchFromTarget > maxPitch)
m_Pitch = maxPitch; m_PitchFromTarget = maxPitch;
// std::wcerr << "pitch = " << m_Pitch << endl; // std::wcerr << "pitch = " << m_Pitch << endl;
m_Yaw += dx / 120.0f; m_YawFromTarget += dx / 120.0f;
// Set Camera to new rotation // Set Camera to new rotation
setNewCameraPosition(); setNewCameraPosition();

5
View.h
View File

@ -8,19 +8,20 @@ class Engine;
class View : public irr::IEventReceiver { class View : public irr::IEventReceiver {
private: private:
Engine* m_Engine; Engine* m_Engine;
irr::f32 m_Yaw, m_Pitch, m_CameraDistance; irr::f32 m_YawFromTarget, m_PitchFromTarget, m_CameraDistance;
irr::core::vector2d<int>* m_LastMousePosition; irr::core::vector2d<int>* m_LastMousePosition;
bool m_RotMouse; bool m_RotMouse;
bool m_zUp; bool m_zUp;
void setNewCameraPosition(); void setNewCameraPosition();
void setNewCameraPosition(bool zUp); void setNewCameraPosition(bool zUp);
void setNewLightDirection(const irr::core::vector3df& cameraPosition); void setNewLightDirection(const irr::core::vector3df& cameraPosition, const irr::core::vector3df& cameraTarget);
public: public:
View(Engine* engine); View(Engine* engine);
~View(); ~View();
void setZUp(bool zUp); void setZUp(bool zUp);
float cameraDistance();
void setCameraDistance(float cameraDistance); void setCameraDistance(float cameraDistance);
bool zUp(); bool zUp();
bool m_Shift; bool m_Shift;

View File

@ -24,6 +24,9 @@ if [ -d "$dump_dest" ]; then
fi fi
mkdir "$dump_dest" || customDie "Cannot mkdir $dump_dest" mkdir "$dump_dest" || customDie "Cannot mkdir $dump_dest"
chmod +x ./etc/pushtmp.sh chmod +x ./etc/pushtmp.sh
if [ ! -f "`command -v clang-format`" ]; then
customDie "clang-format command is not in path. You must install clang."
fi
echo "* Using -style=WebKit to avoid .clang-format version issues..." echo "* Using -style=WebKit to avoid .clang-format version issues..."
#echo "* rewriting .clang-format to avoid clang-format version issues..." #echo "* rewriting .clang-format to avoid clang-format version issues..."
#rewriting avoids the following error: #rewriting avoids the following error: