-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add generic GL dialog and canvas classes
GLCanvas, GLDialog
- Loading branch information
Showing
7 changed files
with
321 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
BodySlide and Outfit Studio | ||
See the included LICENSE file | ||
*/ | ||
|
||
#include "GLDialog.h" | ||
|
||
wxBEGIN_EVENT_TABLE(GLCanvas, wxGLCanvas) | ||
EVT_PAINT(GLCanvas::OnPaint) | ||
EVT_MOTION(GLCanvas::OnMotion) | ||
EVT_MOUSEWHEEL(GLCanvas::OnMouseWheel) | ||
EVT_KEY_UP(GLCanvas::OnKeyUp) | ||
EVT_SIZE(GLCanvas::OnResized) | ||
wxEND_EVENT_TABLE() | ||
|
||
GLCanvas::GLCanvas(GLDialog* parent, const wxGLAttributes& attribs) | ||
: wxGLCanvas(parent, attribs, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE) | ||
, parent(parent) {} | ||
|
||
void GLCanvas::OnPaint(wxPaintEvent& WXUNUSED(event)) { | ||
// Initialize OpenGL the first time the window is painted. | ||
// We unfortunately can't initialize it before the window is shown. | ||
// We could register for the EVT_SHOW event, but unfortunately it | ||
// appears to only be called after the first few EVT_PAINT events. | ||
// It also isn't supported on all platforms. | ||
if (firstPaint) { | ||
firstPaint = false; | ||
parent->OnShown(); | ||
} | ||
parent->Render(); | ||
} | ||
|
||
void GLCanvas::OnMotion(wxMouseEvent& event) { | ||
if (parent->IsActive()) | ||
SetFocus(); | ||
|
||
auto delta = event.GetPosition() - lastMousePosition; | ||
|
||
if (event.LeftIsDown()) { | ||
parent->LeftDrag(delta.x, delta.y); | ||
} | ||
else if (event.MiddleIsDown()) { | ||
if (wxGetKeyState(WXK_SHIFT)) | ||
parent->MouseWheel(delta.y); | ||
else | ||
parent->LeftDrag(delta.x, delta.y); | ||
} | ||
else if (event.RightIsDown()) { | ||
if (wxGetKeyState(WXK_SHIFT)) | ||
parent->LeftDrag(delta.x, delta.y); | ||
else | ||
parent->RightDrag(delta.x, delta.y); | ||
} | ||
else | ||
parent->TrackMouse(event.GetX(), event.GetY()); | ||
|
||
lastMousePosition = event.GetPosition(); | ||
} | ||
|
||
void GLCanvas::OnMouseWheel(wxMouseEvent& event) { | ||
parent->MouseWheel(event.GetWheelRotation()); | ||
} | ||
|
||
void GLCanvas::OnKeyUp(wxKeyEvent& event) { | ||
int key = event.GetKeyCode(); | ||
switch (key) { | ||
case 'T': parent->ToggleTextures(); break; | ||
case 'W': parent->ToggleWireframe(); break; | ||
case 'L': parent->ToggleLighting(); break; | ||
case 'G': parent->ToggleFloor(); break; | ||
} | ||
} | ||
|
||
void GLCanvas::OnResized(wxSizeEvent& event) { | ||
parent->Resized(event.GetSize().GetWidth(), event.GetSize().GetHeight()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* | ||
BodySlide and Outfit Studio | ||
See the included LICENSE file | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <wx/wx.h> | ||
#include <wx/glcanvas.h> | ||
|
||
class GLDialog; | ||
|
||
class GLCanvas : public wxGLCanvas { | ||
GLDialog* parent = nullptr; | ||
bool firstPaint = true; | ||
wxPoint lastMousePosition; | ||
|
||
public: | ||
GLCanvas(GLDialog* parent, const wxGLAttributes& attribs); | ||
|
||
void OnPaint(wxPaintEvent& event); | ||
void OnMotion(wxMouseEvent& event); | ||
void OnMouseWheel(wxMouseEvent& event); | ||
void OnKeyUp(wxKeyEvent& event); | ||
void OnResized(wxSizeEvent& event); | ||
|
||
wxDECLARE_EVENT_TABLE(); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/* | ||
BodySlide and Outfit Studio | ||
See the included LICENSE file | ||
*/ | ||
|
||
#include "GLDialog.h" | ||
#include "../utils/ConfigurationManager.h" | ||
|
||
using namespace nifly; | ||
|
||
extern ConfigurationManager Config; | ||
|
||
|
||
wxBEGIN_EVENT_TABLE(GLDialog, wxDialog) | ||
EVT_CLOSE(GLDialog::OnClose) | ||
wxEND_EVENT_TABLE() | ||
|
||
GLDialog::GLDialog() { | ||
CenterOnParent(); | ||
SetDoubleBuffered(true); | ||
} | ||
|
||
GLCanvas* GLDialog::CreateCanvas() { | ||
canvas = new GLCanvas(this, GLSurface::GetGLAttribs()); | ||
context = std::make_unique<wxGLContext>(canvas, nullptr, &GLSurface::GetGLContextAttribs()); | ||
return canvas; | ||
} | ||
|
||
void GLDialog::OnShown() { | ||
if (!context->IsOK()) { | ||
Destroy(); | ||
canvas = nullptr; | ||
wxLogError("Preview failed: OpenGL context is not OK."); | ||
wxMessageBox(_("Preview failed: OpenGL context is not OK."), _("OpenGL Error"), wxICON_ERROR); | ||
return; | ||
} | ||
|
||
gls.Initialize(canvas, context.get()); | ||
|
||
auto size = canvas->GetSize(); | ||
gls.SetStartingView(Vector3(0.0f, -5.0f, -15.0f), Vector3(15.0f, 0.0f, 0.0f), size.GetWidth(), size.GetHeight(), 65.0); | ||
|
||
int ambient = Config.GetIntValue("Lights/Ambient"); | ||
int frontal = Config.GetIntValue("Lights/Frontal"); | ||
|
||
int directional0 = Config.GetIntValue("Lights/Directional0"); | ||
int directional0X = Config.GetIntValue("Lights/Directional0.x"); | ||
int directional0Y = Config.GetIntValue("Lights/Directional0.y"); | ||
int directional0Z = Config.GetIntValue("Lights/Directional0.z"); | ||
|
||
int directional1 = Config.GetIntValue("Lights/Directional1"); | ||
int directional1X = Config.GetIntValue("Lights/Directional1.x"); | ||
int directional1Y = Config.GetIntValue("Lights/Directional1.y"); | ||
int directional1Z = Config.GetIntValue("Lights/Directional1.z"); | ||
|
||
int directional2 = Config.GetIntValue("Lights/Directional2"); | ||
int directional2X = Config.GetIntValue("Lights/Directional2.x"); | ||
int directional2Y = Config.GetIntValue("Lights/Directional2.y"); | ||
int directional2Z = Config.GetIntValue("Lights/Directional2.z"); | ||
|
||
Vector3 directional0Dir = Vector3(directional0X / 100.0f, directional0Y / 100.0f, directional0Z / 100.0f); | ||
Vector3 directional1Dir = Vector3(directional1X / 100.0f, directional1Y / 100.0f, directional1Z / 100.0f); | ||
Vector3 directional2Dir = Vector3(directional2X / 100.0f, directional2Y / 100.0f, directional2Z / 100.0f); | ||
gls.UpdateLights(ambient, frontal, directional0, directional1, directional2, directional0Dir, directional1Dir, directional2Dir); | ||
|
||
if (Config.Exists("Rendering/ColorBackground")) { | ||
int colorBackgroundR = Config.GetIntValue("Rendering/ColorBackground.r"); | ||
int colorBackgroundG = Config.GetIntValue("Rendering/ColorBackground.g"); | ||
int colorBackgroundB = Config.GetIntValue("Rendering/ColorBackground.b"); | ||
gls.SetBackgroundColor(Vector3(colorBackgroundR / 255.0f, colorBackgroundG / 255.0f, colorBackgroundB / 255.0f)); | ||
} | ||
|
||
if (Config.Exists("Rendering/ColorWire")) { | ||
int colorWireR = Config.GetIntValue("Rendering/ColorWire.r"); | ||
int colorWireG = Config.GetIntValue("Rendering/ColorWire.g"); | ||
int colorWireB = Config.GetIntValue("Rendering/ColorWire.b"); | ||
gls.SetWireColor(Vector3(colorWireR / 255.0f, colorWireG / 255.0f, colorWireB / 255.0f)); | ||
} | ||
|
||
// Turn texture rendering off initially | ||
gls.ToggleTextures(); | ||
|
||
floorMeshes = gls.AddFloor(); | ||
} | ||
|
||
void GLDialog::OnClose(wxCloseEvent& WXUNUSED(event)) { | ||
Cleanup(); | ||
Destroy(); | ||
} | ||
|
||
void GLDialog::LeftDrag(int dX, int dY) { | ||
gls.PanCamera(dX, dY); | ||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::RightDrag(int dX, int dY) { | ||
gls.TurnTableCamera(dX); | ||
gls.PitchCamera(dY); | ||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::MouseWheel(int dW) { | ||
gls.DollyCamera(dW); | ||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::TrackMouse(int X, int Y) { | ||
gls.UpdateCursor(X, Y); | ||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::ToggleTextures() { | ||
gls.ToggleTextures(); | ||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::ToggleWireframe() { | ||
gls.ToggleWireframe(); | ||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::ToggleLighting() { | ||
gls.ToggleLighting(); | ||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::ToggleFloor() { | ||
for (auto& m : floorMeshes) | ||
m->bVisible = !m->bVisible; | ||
|
||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::Render() { | ||
gls.RenderOneFrame(); | ||
} | ||
|
||
void GLDialog::Resized(uint32_t w, uint32_t h) { | ||
gls.SetSize(w, h); | ||
} | ||
|
||
void GLDialog::Cleanup() { | ||
// Set current context for resource deletion | ||
if (canvas && context) | ||
canvas->SetCurrent(*context); | ||
|
||
gls.Cleanup(); | ||
shapeMaterials.clear(); | ||
gls.RenderOneFrame(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
BodySlide and Outfit Studio | ||
See the included LICENSE file | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <wx/wx.h> | ||
|
||
#include "GLCanvas.h" | ||
#include "GLSurface.h" | ||
|
||
class GLDialog : public wxDialog { | ||
public: | ||
GLDialog(); | ||
|
||
GLCanvas* CreateCanvas(); | ||
virtual void OnShown(); | ||
void OnClose(wxCloseEvent& event); | ||
|
||
GLCanvas* GetCanvas() { return canvas; } | ||
wxGLContext* GetContext() { return context.get(); } | ||
GLSurface& GetSurface() { return gls; } | ||
|
||
void LeftDrag(int dX, int dY); | ||
void RightDrag(int dX, int dY); | ||
void MouseWheel(int dW); | ||
void TrackMouse(int X, int Y); | ||
|
||
void ToggleTextures(); | ||
void ToggleWireframe(); | ||
void ToggleLighting(); | ||
void ToggleFloor(); | ||
|
||
void Resized(uint32_t w, uint32_t h); | ||
|
||
void Render(); | ||
void Cleanup(); | ||
|
||
wxDECLARE_EVENT_TABLE(); | ||
|
||
private: | ||
GLCanvas* canvas = nullptr; | ||
std::unique_ptr<wxGLContext> context; | ||
GLSurface gls; | ||
|
||
std::unordered_map<std::string, GLMaterial*> shapeMaterials; | ||
std::vector<Mesh*> floorMeshes; | ||
}; |