717 lines
20 KiB
C++
717 lines
20 KiB
C++
#include "Editor.hpp"
|
|
#include "project/node.hpp"
|
|
#include "modes/NBEditor.hpp"
|
|
#include "modes/TextureEditor.hpp"
|
|
#include "modes/NodeEditor.hpp"
|
|
#include "util/string.hpp"
|
|
#include <ctime>
|
|
#include <time.h>
|
|
#include <math.h>
|
|
|
|
Editor::Editor() :
|
|
state(NULL),
|
|
device(NULL),
|
|
target(NULL),
|
|
pivot(NULL),
|
|
currentWindow(-1),
|
|
viewport_contextmenu(VIEW_NONE),
|
|
viewport_drag(VIEW_NONE),
|
|
click_handled(true),
|
|
middle_click_handled(true)
|
|
{
|
|
for (int i = 0; i < 4; i++) {
|
|
camera[i] = NULL;
|
|
}
|
|
}
|
|
|
|
#ifdef _DEBUG
|
|
#include <sstream>
|
|
void debugRenderINT(int id, IrrlichtDevice *device, std::string name, int content)
|
|
{
|
|
int ResX = device->getVideoDriver()->getScreenSize().Width;
|
|
int ResY = device->getVideoDriver()->getScreenSize().Height;
|
|
std::ostringstream os;
|
|
os << name;
|
|
os << ": ";
|
|
os << content;
|
|
device->getGUIEnvironment()->getSkin()->getFont()->
|
|
draw(narrow_to_wide(os.str()).c_str(),
|
|
rect<s32>(80, ResY - id*20 - 10, ResX - 200, ResY - id*20), SColor(255, 255, 255, 255));
|
|
}
|
|
#endif
|
|
|
|
bool Editor::run(IrrlichtDevice* irr_device, Configuration* conf,
|
|
bool editor_is_installed)
|
|
{
|
|
// Do Irrlicht Stuff
|
|
device = irr_device;
|
|
IVideoDriver *driver = device->getVideoDriver();
|
|
ISceneManager *smgr = device->getSceneManager();
|
|
IGUIEnvironment *guienv = device->getGUIEnvironment();
|
|
device->setEventReceiver(this);
|
|
device->setWindowCaption(L"Node Box Editor");
|
|
|
|
if (!conf->getBool("fullscreen")) {
|
|
device->setResizable(true);
|
|
}
|
|
|
|
// Project and state
|
|
Project *proj = new Project();
|
|
state = new EditorState(device, proj, conf);
|
|
state->isInstalled = editor_is_installed;
|
|
|
|
// Menu State
|
|
state->menu = new MenuState(state);
|
|
|
|
// Add editor modes
|
|
state->AddMode(new NBEditor(state));
|
|
state->AddMode(new NodeEditor(state));
|
|
state->AddMode(new TextureEditor(state));
|
|
|
|
// Set up project
|
|
proj->AddNode(state, true, false);
|
|
|
|
proj->media.debug();
|
|
|
|
// Load user interface
|
|
LoadScene();
|
|
state->SelectMode(0);
|
|
|
|
int LastX = driver->getScreenSize().Width;
|
|
if (!state->settings->getBool("hide_sidebar")) {
|
|
LastX -= 256;
|
|
}
|
|
int LastY = driver->getScreenSize().Height;
|
|
#ifdef _DEBUG
|
|
int lastFPS = -1;
|
|
#endif
|
|
|
|
bool dosleep = state->settings->getBool("use_sleep");
|
|
u32 last = std::clock();
|
|
double dtime = 0;
|
|
while (device->run()) {
|
|
if (state->NeedsClose()) {
|
|
device->closeDevice();
|
|
return true;
|
|
}
|
|
|
|
driver->beginScene(true, true, irr::video::SColor(255, 150, 150, 150));
|
|
|
|
int ResX = driver->getScreenSize().Width;
|
|
if (!state->settings->getBool("hide_sidebar"))
|
|
ResX -= 256;
|
|
|
|
int ResY = driver->getScreenSize().Height;
|
|
|
|
if (currentWindow == -1) {
|
|
bool newmoused = (state->mousedown && !click_handled);
|
|
viewportTick(VIEW_TL, rect<s32>(0, 0, ResX/2, ResY/2),
|
|
newmoused, !middle_click_handled);
|
|
viewportTick(VIEW_TR, rect<s32>(ResX/2, 0, ResX, ResY/2),
|
|
newmoused, !middle_click_handled);
|
|
viewportTick(VIEW_BL, rect<s32>(0, ResY/2, ResX/2, ResY ),
|
|
newmoused, !middle_click_handled);
|
|
viewportTick(VIEW_BR, rect<s32>(ResX/2, ResY/2, ResX, ResY ),
|
|
newmoused, !middle_click_handled);
|
|
|
|
// Draw separating lines
|
|
driver->draw2DLine(vector2d<irr::s32>(0, ResY/2),
|
|
vector2d<irr::s32>(ResX, ResY/2), SColor(175,255,255,255));
|
|
driver->draw2DLine(vector2d<irr::s32>(0, ResY/2-1),
|
|
vector2d<irr::s32>(ResX, ResY/2-1), SColor(175,255,255,255));
|
|
driver->draw2DLine(vector2d<irr::s32>(ResX/2, 0),
|
|
vector2d<irr::s32>(ResX/2, ResY), SColor(175,255,255,255));
|
|
driver->draw2DLine(vector2d<irr::s32>(ResX/2+1, 0),
|
|
vector2d<irr::s32>(ResX/2+1, ResY), SColor(175,255,255,255));
|
|
} else if (camera[currentWindow]) {
|
|
viewportTick((EViewport)currentWindow, rect<s32>(0, 0, ResX, ResY),
|
|
(state->mousedown && !click_handled), !middle_click_handled);
|
|
}
|
|
|
|
if (state->menu) {
|
|
state->menu->draw(driver);
|
|
}
|
|
if (state->Mode()) {
|
|
state->Mode()->draw(driver);
|
|
}
|
|
|
|
if (state->project && state->project->GetCurrentNode()) {
|
|
vector3df pos = vector3df(
|
|
(f32)state->project->GetCurrentNode()->position.X,
|
|
(f32)state->project->GetCurrentNode()->position.Y,
|
|
(f32)state->project->GetCurrentNode()->position.Z
|
|
);
|
|
target->setPosition(pos);
|
|
}
|
|
|
|
guienv->drawAll();
|
|
|
|
if (state->menu->dialog)
|
|
state->menu->dialog->draw(driver);
|
|
|
|
#ifdef _DEBUG
|
|
debugRenderINT(1, device, "MaterialRenders", driver->getMaterialRendererCount());
|
|
debugRenderINT(2, device, "Triangles", driver->getPrimitiveCountDrawn());
|
|
debugRenderINT(3, device, "Textures", driver->getTextureCount());
|
|
#endif
|
|
|
|
driver->endScene();
|
|
|
|
#ifdef _DEBUG
|
|
int fps = driver->getFPS();
|
|
if (lastFPS != fps) {
|
|
irr::core::stringw str = L"Node Box Editor [FPS: ";
|
|
str += fps;
|
|
str += "]";
|
|
|
|
device->setWindowCaption(str.c_str());
|
|
lastFPS = fps;
|
|
}
|
|
#endif
|
|
|
|
if (LastX != ResX || LastY != ResY) {
|
|
LastX = ResX;
|
|
LastY = ResY;
|
|
recreateCameras();
|
|
}
|
|
|
|
// Update
|
|
if (state->Mode()) {
|
|
state->Mode()->update(dtime);
|
|
}
|
|
|
|
// Do perspective camera rotate
|
|
IGUIElement *el = state->device->getGUIEnvironment()->getFocus();
|
|
if (!el || el->getType() != EGUIET_EDIT_BOX) {
|
|
vector3df delta(0, 0, 0);
|
|
|
|
# define ROT_SP_X 0.5
|
|
# define ROT_SP_Y 0.5
|
|
# define ANG_MAX 89
|
|
|
|
if (state->keys[KEY_KEY_W])
|
|
delta.X += ROT_SP_X * dtime;
|
|
|
|
if (state->keys[KEY_KEY_S])
|
|
delta.X -= ROT_SP_X * dtime;
|
|
|
|
if (state->keys[KEY_KEY_A])
|
|
delta.Y += ROT_SP_Y * dtime;
|
|
|
|
if (state->keys[KEY_KEY_D])
|
|
delta.Y -= ROT_SP_Y * dtime;
|
|
|
|
delta += pivot->getRotation();
|
|
if (delta.X > ANG_MAX)
|
|
delta.X = ANG_MAX;
|
|
if (delta.X < -ANG_MAX)
|
|
delta.X = -ANG_MAX;
|
|
pivot->setRotation(delta);
|
|
}
|
|
|
|
// Do sleep
|
|
unsigned int now = std::clock();
|
|
if (dosleep) {
|
|
u32 sleeptime = int(double(1000) / double(60)) - (now - last);
|
|
if (sleeptime > 0 && sleeptime < 200)
|
|
device->sleep(sleeptime);
|
|
}
|
|
dtime = double(now - last) / 1000;
|
|
last = now;
|
|
|
|
click_handled = true;
|
|
middle_click_handled = true;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
EViewport Editor::getViewportAt(vector2di pos)
|
|
{
|
|
if (currentWindow == -1) {
|
|
IVideoDriver *driver = state->device->getVideoDriver();
|
|
int ResX = driver->getScreenSize().Width;
|
|
if (!state->settings->getBool("hide_sidebar"))
|
|
ResX -= 256;
|
|
int ResY = driver->getScreenSize().Height;
|
|
|
|
if (pos.X > ResX / 2)
|
|
if (pos.Y > ResY / 2)
|
|
return VIEW_BR;
|
|
else
|
|
return VIEW_TR;
|
|
else
|
|
if (pos.Y > ResY / 2)
|
|
return VIEW_BL;
|
|
else
|
|
return VIEW_TL;
|
|
} else
|
|
return (EViewport)currentWindow;
|
|
}
|
|
|
|
bool Editor::OnEvent(const SEvent& event)
|
|
{
|
|
// Store mouse state in EditorState
|
|
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT) {
|
|
if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) {
|
|
state->mousedown = false;
|
|
click_handled = true;
|
|
} else if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) {
|
|
state->mousedown = true;
|
|
click_handled = false;
|
|
} else if (event.MouseInput.Event == EMIE_MOUSE_MOVED) {
|
|
state->mouse_position.X = event.MouseInput.X;
|
|
state->mouse_position.Y = event.MouseInput.Y;
|
|
} else if (event.MouseInput.Event == EMIE_MMOUSE_LEFT_UP) {
|
|
viewport_drag = VIEW_NONE;
|
|
middle_click_handled = true;
|
|
} else if (event.MouseInput.Event == EMIE_MMOUSE_PRESSED_DOWN) {
|
|
middle_click_handled = false;
|
|
}
|
|
}
|
|
|
|
// Store keystates in EditorState
|
|
if (event.EventType == EET_KEY_INPUT_EVENT &&
|
|
event.KeyInput.Key < NUMBER_OF_KEYS) {
|
|
// Set key states
|
|
if (event.KeyInput.PressedDown)
|
|
state->keys[event.KeyInput.Key] = EKS_DOWN;
|
|
else
|
|
state->keys[event.KeyInput.Key] = EKS_UP;
|
|
}
|
|
|
|
// Pass event to EditorMode
|
|
if (state->Mode() && state->Mode()->OnEvent(event))
|
|
return true;
|
|
|
|
// Pass event to MenuState
|
|
if (state->menu && state->menu->OnEvent(event))
|
|
return true;
|
|
|
|
// EViewport Zoom
|
|
if (event.EventType == irr::EET_MOUSE_INPUT_EVENT &&
|
|
event.MouseInput.Event == EMIE_MOUSE_WHEEL) {
|
|
EViewport vp = getViewportAt(state->mouse_position);
|
|
viewport_offset[(int)vp].Z += event.MouseInput.Wheel;
|
|
if (viewport_offset[(int)vp].Z > 64)
|
|
viewport_offset[(int)vp].Z = 64;
|
|
if (viewport_offset[(int)vp].Z < -25)
|
|
viewport_offset[(int)vp].Z = -25;
|
|
applyCameraOffsets(vp);
|
|
}
|
|
|
|
//
|
|
// Key events
|
|
//
|
|
else if (event.EventType == EET_KEY_INPUT_EVENT &&
|
|
!event.KeyInput.PressedDown) {
|
|
// alt+W functionality
|
|
if (event.KeyInput.Key == KEY_KEY_W &&
|
|
state->keys[164] == EKS_DOWN) {
|
|
if (currentWindow == -1) {
|
|
currentWindow = (int)getViewportAt(state->mouse_position);
|
|
} else
|
|
currentWindow = -1;
|
|
return true;
|
|
}
|
|
|
|
// Don't do shortcuts if in text box
|
|
IGUIElement *el = state->device->getGUIEnvironment()->getFocus();
|
|
if (el && el->getType() == EGUIET_EDIT_BOX)
|
|
return false;
|
|
|
|
// Do shortcuts
|
|
switch (event.KeyInput.Key) {
|
|
case KEY_KEY_B:
|
|
if (!event.KeyInput.PressedDown)
|
|
state->SelectMode(0);
|
|
break;
|
|
case KEY_KEY_N:
|
|
if (!event.KeyInput.PressedDown)
|
|
state->SelectMode(1);
|
|
break;
|
|
case KEY_KEY_T:
|
|
if (!event.KeyInput.PressedDown)
|
|
state->SelectMode(2);
|
|
break;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// Handle menubar events
|
|
if (event.EventType == EET_GUI_EVENT &&
|
|
event.GUIEvent.EventType == EGET_MENU_ITEM_SELECTED) {
|
|
IGUIContextMenu* menu = (IGUIContextMenu*)event.GUIEvent.Caller;
|
|
switch (menu->getItemCommandId(menu->getSelectedItem())) {
|
|
case GUI_VIEW_SP_ALL:
|
|
currentWindow = -1;
|
|
break;
|
|
case GUI_VIEW_SP_PER:
|
|
currentWindow = 0;
|
|
break;
|
|
case GUI_VIEW_SP_TOP:
|
|
currentWindow = 1;
|
|
break;
|
|
case GUI_VIEW_SP_FRT:
|
|
currentWindow = 2;
|
|
break;
|
|
case GUI_VIEW_SP_RHT:
|
|
currentWindow = 3;
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Editor::LoadScene()
|
|
{
|
|
IVideoDriver *driver = device->getVideoDriver();
|
|
ISceneManager *smgr = device->getSceneManager();
|
|
|
|
// Create target
|
|
target = smgr->addEmptySceneNode(0, 200);
|
|
target->setPosition(vector3df(0, 0, 0));
|
|
|
|
// Create cameras
|
|
pivot = smgr->addEmptySceneNode(target, 199);
|
|
pivot->setRotation(vector3df(25, -45, 0));
|
|
recreateCameras();
|
|
|
|
// Add Light
|
|
ILightSceneNode* light = smgr->addLightSceneNode(target, vector3df(25, 50, 0));
|
|
light->setLightType(ELT_POINT);
|
|
light->setRadius(2000);
|
|
|
|
// Add Plane
|
|
plane = smgr->addCubeSceneNode(1, 0, -1,
|
|
vector3df(0.5, -5.5, 0.5), vector3df(0, 0, 0),
|
|
vector3df(10, 10, 10));
|
|
plane->setMaterialTexture(0, driver->getTexture("media/texture_terrain.png"));
|
|
plane->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
|
plane->setMaterialFlag(video::EMF_LIGHTING, false);
|
|
plane->setMaterialFlag(video::EMF_BACK_FACE_CULLING, true);
|
|
plane->getMaterial(0).getTextureMatrix(0).setTextureScale(10, 10);
|
|
|
|
// Add sky box
|
|
scene::IMeshSceneNode* skybox = smgr->addCubeSceneNode(50);
|
|
skybox->setMaterialTexture(0, driver->getTexture("media/sky.jpg"));
|
|
skybox->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
|
skybox->setMaterialFlag(video::EMF_LIGHTING, false);
|
|
smgr->getMeshManipulator()->flipSurfaces(skybox->getMesh());
|
|
state->plane_tri = smgr->createOctreeTriangleSelector(skybox->getMesh(), skybox);
|
|
}
|
|
|
|
void Editor::recreateCameras()
|
|
{
|
|
ISceneManager *smgr = device->getSceneManager();
|
|
for (int i = 0; i < 4; i++) {
|
|
// Delete old camera
|
|
if (camera[i]) {
|
|
camera[i]->remove();
|
|
camera[i] = NULL;
|
|
}
|
|
|
|
EViewportType type = state->getEViewportType((EViewport)i);
|
|
if (type == VIEWT_PERS) {
|
|
vector3df oldrot = pivot->getRotation();
|
|
pivot->setRotation(vector3df(0, 0, 0));
|
|
camera[i] = smgr->addCameraSceneNode(NULL, vector3df(0, 0, -2),
|
|
vector3df(0, 0, 0));
|
|
camera[i]->setParent(pivot);
|
|
pivot->setRotation(oldrot);
|
|
} else
|
|
camera[i] = smgr->addCameraSceneNode(target);
|
|
|
|
// Set position and zoom of camera
|
|
applyCameraOffsets((EViewport)i);
|
|
}
|
|
}
|
|
|
|
void camSetPosTar(ICameraSceneNode *camera, vector3df position,
|
|
vector3df target, vector3df up=vector3df(0, 1, 0))
|
|
{
|
|
camera->setPosition(position);
|
|
camera->updateAbsolutePosition();
|
|
camera->setTarget(target + position);
|
|
camera->updateAbsolutePosition();
|
|
camera->setUpVector(up);
|
|
camera->updateAbsolutePosition();
|
|
}
|
|
|
|
void Editor::applyCameraOffsets(EViewport viewport)
|
|
{
|
|
int i = (int)viewport;
|
|
EViewportType type = state->getEViewportType(viewport);
|
|
vector3df offset = viewport_offset[i];
|
|
switch(type) {
|
|
case VIEWT_TOP:
|
|
camSetPosTar(camera[i], vector3df(offset.X, 2, offset.Y),
|
|
vector3df(0, -100, 0), vector3df(0, 0, 1));
|
|
break;
|
|
case VIEWT_BOTTOM:
|
|
camSetPosTar(camera[i], vector3df(offset.X, -2, -offset.Y),
|
|
vector3df(0, 100, 0), vector3df(0, 0, -1));
|
|
break;
|
|
case VIEWT_LEFT:
|
|
camSetPosTar(camera[i], vector3df(-2, offset.Y, -offset.X),
|
|
vector3df(100, 0, 0));
|
|
break;
|
|
case VIEWT_RIGHT:
|
|
camSetPosTar(camera[i], vector3df(2, offset.Y, offset.X),
|
|
vector3df(-100, 0, 0));
|
|
break;
|
|
case VIEWT_FRONT:
|
|
camSetPosTar(camera[i], vector3df(offset.X, offset.Y, -2),
|
|
vector3df(0, 0, 100));
|
|
break;
|
|
case VIEWT_BACK:
|
|
camSetPosTar(camera[i], vector3df(-offset.X, offset.Y, 2),
|
|
vector3df(0, 0, -100));
|
|
break;
|
|
}
|
|
|
|
// Get screen sizes
|
|
IVideoDriver *driver = device->getVideoDriver();
|
|
int ResX = driver->getScreenSize().Width;
|
|
if (!state->settings->getBool("hide_sidebar"))
|
|
ResX -= 256;
|
|
int ResY = driver->getScreenSize().Height;
|
|
|
|
// Set zooms
|
|
float zoom = pow(2, -0.1 * offset.Z) + 0.1;
|
|
if (type == VIEWT_PERS) {
|
|
vector3df oldrot = pivot->getRotation();
|
|
pivot->setRotation(vector3df(0, 0, 0));
|
|
camera[i]->setPosition(vector3df(0, 0, -2.0 * zoom - 1.2));
|
|
camera[i]->setAspectRatio((float)ResX / (float)ResY);
|
|
pivot->setRotation(oldrot);
|
|
} else {
|
|
matrix4 projMat;
|
|
irr::f32 orth_w = 3 * ResX / (irr::f32)ResY;
|
|
projMat.buildProjectionMatrixOrthoLH(zoom * orth_w, zoom * 3, 1, 100);
|
|
camera[i]->setProjectionMatrix(projMat, true);
|
|
}
|
|
}
|
|
|
|
const char* viewportToSetting(EViewport port)
|
|
{
|
|
switch (port) {
|
|
case VIEW_TL:
|
|
return "viewport_top_left";
|
|
case VIEW_TR:
|
|
return "viewport_top_right";
|
|
case VIEW_BL:
|
|
return "viewport_bottom_left";
|
|
case VIEW_BR:
|
|
return "viewport_bottom_right";
|
|
default:
|
|
return "viewport_top_left";
|
|
}
|
|
}
|
|
|
|
const char* viewportTypeToSetting(EViewportType type)
|
|
{
|
|
switch (type) {
|
|
case VIEWT_PERS:
|
|
return "pers";
|
|
case VIEWT_FRONT:
|
|
return "front";
|
|
case VIEWT_RIGHT:
|
|
return "right";
|
|
case VIEWT_TOP:
|
|
return "top";
|
|
case VIEWT_BACK:
|
|
return "back";
|
|
case VIEWT_LEFT:
|
|
return "left";
|
|
case VIEWT_BOTTOM:
|
|
return "bottom";
|
|
default:
|
|
return "pers";
|
|
}
|
|
}
|
|
|
|
void drawCoord(IGUIFont* font, IVideoDriver *driver, unsigned int x,
|
|
unsigned int y, const wchar_t* xlabel, const wchar_t* ylabel)
|
|
{
|
|
static ITexture *axes = driver->getTexture("media/coordinates.png");
|
|
driver->draw2DImage(
|
|
axes,
|
|
position2d<s32>(x, y),
|
|
rect<s32>(0, 0, 32, 32),
|
|
NULL, SColor(255, 255, 255, 255), true
|
|
);
|
|
font->draw(
|
|
ylabel,
|
|
core::rect<s32>(x - 2, y - 20, 300, 50),
|
|
video::SColor(255, 255, 255, 255)
|
|
);
|
|
font->draw(
|
|
xlabel,
|
|
core::rect<s32>(x + 40, y + 22, 300, 50),
|
|
video::SColor(255, 255, 255, 255)
|
|
);
|
|
}
|
|
|
|
typedef rect<s32> rects32;
|
|
void Editor::viewportTick(EViewport viewport, rect<s32> rect,
|
|
bool mousehit, bool middlehit)
|
|
{
|
|
// Init
|
|
IVideoDriver *driver = device->getVideoDriver();
|
|
ISceneManager *smgr = device->getSceneManager();
|
|
IGUIEnvironment *guienv = device->getGUIEnvironment();
|
|
EViewportType type = state->getEViewportType(viewport);
|
|
|
|
// Draw camera
|
|
smgr->setActiveCamera(camera[(int)viewport]);
|
|
driver->setViewPort(rect);
|
|
if (type == VIEWT_BOTTOM)
|
|
plane->setVisible(false);
|
|
smgr->drawAll();
|
|
if (type == VIEWT_BOTTOM)
|
|
plane->setVisible(true);
|
|
|
|
// Callbacks
|
|
if (state->Mode())
|
|
state->Mode()->viewportTick(viewport, driver, rect);
|
|
|
|
driver->setViewPort(rects32(0, 0, driver->getScreenSize().Width,
|
|
driver->getScreenSize().Height));
|
|
if (state->Mode())
|
|
state->Mode()->drawViewport(driver, viewport, rect);
|
|
|
|
if (viewport_drag == viewport) {
|
|
vector2di delta = state->mouse_position;
|
|
delta -= viewport_drag_last;
|
|
viewport_drag_last = state->mouse_position;
|
|
viewport_offset[(int)viewport].X -= (f32)delta.X * 0.01f;
|
|
viewport_offset[(int)viewport].Y += (f32)delta.Y * 0.01f;
|
|
if (viewport_offset[(int)viewport].X > 0.5)
|
|
viewport_offset[(int)viewport].X = 0.5;
|
|
if (viewport_offset[(int)viewport].X < -0.5)
|
|
viewport_offset[(int)viewport].X = -0.5;
|
|
if (viewport_offset[(int)viewport].Y > 0.5)
|
|
viewport_offset[(int)viewport].Y = 0.5;
|
|
if (viewport_offset[(int)viewport].Y < -0.5)
|
|
viewport_offset[(int)viewport].Y = -0.5;
|
|
applyCameraOffsets(viewport);
|
|
}
|
|
|
|
if (middlehit && rect.isPointInside(state->mouse_position)
|
|
&& type != VIEWT_PERS) {
|
|
viewport_drag = viewport;
|
|
viewport_drag_last = state->mouse_position;
|
|
}
|
|
|
|
// Draw text
|
|
driver->setViewPort(rects32(0, 0, driver->getScreenSize().Width,
|
|
driver->getScreenSize().Height));
|
|
{
|
|
static const wchar_t* labels[7] = {L"Perspective", L"Front", L"Left",
|
|
L"Top", L"Back", L"Right", L"Bottom"};
|
|
|
|
// Handle clicking
|
|
position2d<s32> labelpos(rect.LowerRightCorner.X - 86,
|
|
rect.UpperLeftCorner.Y + ((rect.UpperLeftCorner.Y < 50)?30:10));
|
|
rects32 backgroundrect(rect.LowerRightCorner.X - 96,
|
|
rect.UpperLeftCorner.Y + ((rect.UpperLeftCorner.Y < 50)?25:5),
|
|
rect.LowerRightCorner.X - 5,
|
|
rect.UpperLeftCorner.Y + ((rect.UpperLeftCorner.Y < 50)?185:165));
|
|
bool context_is_open = (viewport_contextmenu == viewport);
|
|
if (mousehit && !state->menu->dialog) {
|
|
if ((rects32(labelpos.X, labelpos.Y, labelpos.X + 90,
|
|
labelpos.Y + 25)).isPointInside(state->mouse_position)) {
|
|
viewport_contextmenu = viewport;
|
|
} else if (context_is_open) {
|
|
context_is_open = false;
|
|
viewport_contextmenu = VIEW_NONE;
|
|
if (backgroundrect.isPointInside(state->mouse_position)) {
|
|
int y = 0;
|
|
for (int i = 0; i < 7; i++) {
|
|
if (i != (int)type) {
|
|
int ty = rect.UpperLeftCorner.Y +
|
|
((rect.UpperLeftCorner.Y < 50)?56:36)
|
|
+ y * 20;
|
|
rects32 trect(rect.LowerRightCorner.X - 96,
|
|
ty,
|
|
rect.LowerRightCorner.X - 5, ty + 20);
|
|
y++;
|
|
if (trect.isPointInside(state->mouse_position)) {
|
|
viewport_offset[(int)viewport] = vector3df(0, 0, 0);
|
|
state->settings->set(viewportToSetting(viewport),
|
|
viewportTypeToSetting((EViewportType)i));
|
|
recreateCameras();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Context menu
|
|
if (context_is_open) {
|
|
// Context menu background
|
|
driver->draw2DRectangle(SColor(100, 32, 32, 32), backgroundrect);
|
|
s32 y2 = rect.UpperLeftCorner.Y + ((rect.UpperLeftCorner.Y < 50)?52:32);
|
|
driver->draw2DLine(position2d<s32>(rect.LowerRightCorner.X - 96, y2),
|
|
position2d<s32>(rect.LowerRightCorner.X - 5, y2),
|
|
SColor(100, 255, 255, 255));
|
|
// Draw options
|
|
guienv->getSkin()->getFont()->draw(labels[(int)type],
|
|
core::rect<s32>(labelpos.X, labelpos.Y, 200, 50),
|
|
video::SColor(255, 255, 255, 255));
|
|
int y = 0;
|
|
for (int i = 0; i < 7; i++) {
|
|
if (i != (int)type) {
|
|
guienv->getSkin()->getFont()->draw(
|
|
labels[i],
|
|
core::rect<s32>(rect.LowerRightCorner.X - 86,
|
|
rect.UpperLeftCorner.Y + ((rect.UpperLeftCorner.Y < 50)?59:39) + y * 20,
|
|
200, 50),
|
|
video::SColor(255, 255, 255, 255)
|
|
);
|
|
y++;
|
|
}
|
|
}
|
|
} else {
|
|
// Draw label
|
|
guienv->getSkin()->getFont()->draw(labels[(int)type],
|
|
core::rect<s32>(rect.LowerRightCorner.X - wcslen(labels[(int)type]) * 6
|
|
- 20, labelpos.Y, 200, 50),
|
|
video::SColor(255, 255, 255, 255));
|
|
}
|
|
}
|
|
|
|
// Draw coordinate arrows
|
|
if (type != VIEWT_PERS) {
|
|
switch(type) {
|
|
case VIEWT_TOP:
|
|
drawCoord(guienv->getSkin()->getFont(), driver, rect.UpperLeftCorner.X + 10,
|
|
rect.LowerRightCorner.Y - 42, L"X", L"Z");
|
|
break;
|
|
case VIEWT_BOTTOM:
|
|
drawCoord(guienv->getSkin()->getFont(), driver, rect.UpperLeftCorner.X + 10,
|
|
rect.LowerRightCorner.Y - 42, L"X", L"-Z");
|
|
break;
|
|
case VIEWT_LEFT:
|
|
drawCoord(guienv->getSkin()->getFont(), driver, rect.UpperLeftCorner.X + 10,
|
|
rect.LowerRightCorner.Y - 42, L"-Z", L"Y");
|
|
break;
|
|
case VIEWT_RIGHT:
|
|
drawCoord(guienv->getSkin()->getFont(), driver, rect.UpperLeftCorner.X + 10,
|
|
rect.LowerRightCorner.Y - 42, L"Z", L"Y");
|
|
break;
|
|
case VIEWT_FRONT:
|
|
drawCoord(guienv->getSkin()->getFont(), driver, rect.UpperLeftCorner.X + 10,
|
|
rect.LowerRightCorner.Y - 42, L"X", L"Y");
|
|
break;
|
|
case VIEWT_BACK:
|
|
drawCoord(guienv->getSkin()->getFont(), driver, rect.UpperLeftCorner.X + 10,
|
|
rect.LowerRightCorner.Y - 42, L"-X", L"Y");
|
|
break;
|
|
}
|
|
}
|
|
}
|