Files
FC1/Editor/2DViewport.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

1409 lines
34 KiB
C++

// TopRendererWnd.cpp: implementation of the C2DViewport class.
//
//////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "2DViewport.h"
#include "CryEditDoc.h"
#include "Grid.h"
#include "DisplaySettings.h"
#include "EditTool.h"
#include "ViewManager.h"
#include "Settings.h"
#include "Objects\ObjectManager.h"
// Include OpenGL
//#include "GL\gl.h"
#include "Brush\Brush.h"
#include "Objects\BrushObject.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define MARKER_SIZE 6.0f
#define MARKER_DIR_SIZE 10.0f
#define SELECTION_RADIUS 30.0f
#define GL_RGBA 0x1908
#define GL_BGRA 0x80E1
#define BACKGROUND_COLOR Vec3(1.0f,1.0f,1.0f)
#define SELECTION_RECT_COLOR Vec3(0.8f,0.8f,0.8f)
#define MINOR_GRID_COLOR Vec3(0.55f,0.55f,0.55f)
#define MAJOR_GRID_COLOR Vec3(0.6f,0.6f,0.6f)
#define AXIS_GRID_COLOR Vec3(0,0,0)
#define GRID_TEXT_COLOR Vec3(0,0,1.0f)
#define MAX_WORLD_SIZE 10000
//////////////////////////////////////////////////////////////////////////
IMPLEMENT_DYNCREATE(C2DViewport,CViewport)
//////////////////////////////////////////////////////////////////////////
BEGIN_MESSAGE_MAP(C2DViewport, CViewport)
//{{AFX_MSG_MAP(C2DViewport)
ON_WM_LBUTTONDOWN()
ON_WM_MBUTTONUP()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_SIZE()
ON_WM_ERASEBKGND()
ON_WM_PAINT()
ON_WM_CREATE()
ON_WM_RBUTTONDOWN()
ON_WM_RBUTTONUP()
ON_WM_MOUSEWHEEL()
//}}AFX_MSG_MAP
ON_WM_DESTROY()
END_MESSAGE_MAP()
//////////////////////////////////////////////////////////////////////////
static int m_fontList = 0;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
C2DViewport::C2DViewport()
{
CLogFile::WriteLine("2D Viewport Created");
// Scroll offset equals origin
m_rcSelect.SetRect( 0,0,0,0 );
m_viewType = ET_ViewportXY;
m_axis = VPA_XY;
m_bShowTerrain = true;
m_gridAlpha = 1;
m_origin2D.Set(0,0,0);
//m_colorGridText = RGB(0,0,255);
//m_colorAxisText = RGB(0,0,0);
//m_colorBackground = Vec2Rgb(BACKGROUND_COLOR);
//m_gridAlpha = 0.3f;
m_colorGridText = RGB(220,220,220);
m_colorAxisText = RGB(220,220,220);
m_colorBackground = RGB(128,128,128);
m_screenTM.SetIdentity();
m_fZoomFactor = 1;
}
//////////////////////////////////////////////////////////////////////////
C2DViewport::~C2DViewport()
{
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::SetType( EViewportType type )
{
//assert( type == ET_ViewportXY || type == ET_ViewportXZ || type == ET_ViewportYZ );
m_viewType = type;
switch (m_viewType)
{
case ET_ViewportXY:
m_axis = VPA_XY;
break;
case ET_ViewportXZ:
m_axis = VPA_XZ;
break;
case ET_ViewportYZ:
m_axis = VPA_YZ;
break;
};
SetAxis( m_axis );
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::SetAxis( EViewportAxis axis )
{
m_axis = axis;
switch (m_axis)
{
case VPA_XY:
m_cullAxis = 2;
break;
case VPA_XZ:
m_cullAxis = 1;
break;
case VPA_YZ:
m_cullAxis = 0;
break;
}
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::CalculateViewTM()
{
Matrix44 tm;
tm.SetIdentity();
m_constructionViewTM.SetIdentity();
float fScale = GetZoomFactor();
Vec3 origin = GetOrigin2D();
//float origin[2] = { -m_cScrollOffset.x,-m_cScrollOffset.y };
float height = m_rcClient.Height()/fScale;
Vec3 v1;
switch (m_axis)
{
case VPA_XY:
tm = Matrix33::CreateScale( Vec3(fScale,-fScale,fScale) ) * tm; // No fScale for Z
tm.SetTranslationOLD( Vec3(-origin.x,height+origin.y,0)*fScale );
break;
case VPA_XZ:
//tm.ScaleMatrix( fScale,fScale,fScale );
//tm.RotateX( 90 * PI/180.0f );
m_constructionViewTM.BuildFromVectors( Vec3(1,0,0),Vec3(0,0,1),Vec3(0,1,0),Vec3(0,0,0) );
//m_constructionViewTM.BuildFromVectors( Vec3(1,0,0),Vec3(0,0,1),Vec3(0,1,0),Vec3(0,0,0) );
tm.BuildFromVectors( Vec3(1,0,0)*fScale,Vec3(0,0,1)*fScale,Vec3(0,-1,0)*fScale,Vec3(0,0,0) );
tm.SetTranslationOLD( Vec3(-origin.x,height+origin.z,0)*fScale );
break;
case VPA_YZ:
//tm.RotateY( 180 * PI/180.0f );
m_constructionViewTM.BuildFromVectors( Vec3(0,1,0),Vec3(0,0,1),Vec3(1,0,0),Vec3(0,0,0) );
//m_constructionViewTM.BuildFromVectors( Vec3(0,0,1),Vec3(1,0,0),Vec3(0,1,0),Vec3(0,0,0) );
tm.BuildFromVectors( Vec3(0,0,1)*fScale,Vec3(1,0,0)*fScale,Vec3(0,-1,0)*fScale,Vec3(0,0,0) ); // No fScale for Z
tm.SetTranslationOLD( Vec3(-origin.y,height+origin.z,0)*fScale );
break;
}
SetViewTM( m_constructionViewTM );
m_screenTM = tm;
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::ResetContent()
{
CViewport::ResetContent();
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::UpdateContent( int flags )
{
CViewport::UpdateContent(flags);
if (flags & eUpdateObjects)
{
Invalidate(FALSE);
}
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnRButtonDown(UINT nFlags, CPoint point)
{
m_bRMouseDown = true;
SetObjectCursor(0);
if (GetIEditor()->IsInGameMode())
return;
if (GetIEditor()->GetEditTool())
{
GetIEditor()->GetEditTool()->MouseCallback( this,eMouseRDown,point,nFlags );
}
// Save the mouse down position
m_RMouseDownPos = point;
m_prevZoomFactor = GetZoomFactor();
//m_prevScrollOffset = m_cScrollOffset;
CaptureMouse();
SetViewMode( ScrollZoomMode );
CViewport::OnRButtonDown(nFlags, point);
Invalidate(FALSE);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnRButtonUp(UINT nFlags, CPoint point)
{
m_bRMouseDown = false;
ReleaseMouse();
SetViewMode( NothingMode );
CViewport::OnRButtonUp(nFlags, point);
GetViewManager()->UpdateViews(eUpdateObjects);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnMButtonDown(UINT nFlags, CPoint point)
{
////////////////////////////////////////////////////////////////////////
// User pressed the middle mouse button
////////////////////////////////////////////////////////////////////////
CViewport::OnMButtonDown(nFlags, point);
// Save the mouse down position
m_RMouseDownPos = point;
/*
// Are we in spline mode or scroll / zoom mode ?
if (GetViewMode() == SplineMode)
{
// TODO
}
else*/
CaptureMouse();
Invalidate(FALSE);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnMButtonUp(UINT nFlags, CPoint point)
{
ReleaseMouse();
Invalidate(FALSE);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnLButtonDown(UINT nFlags, CPoint point)
{
////////////////////////////////////////////////////////////////////////
// User pressed the left mouse button
////////////////////////////////////////////////////////////////////////
if (GetViewMode() != NothingMode)
return;
m_cMouseDownPos = point;
m_prevZoomFactor = GetZoomFactor();
//m_prevScrollOffset = m_cScrollOffset;
CViewport::OnLButtonDown(nFlags, point);
Invalidate(FALSE);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnLButtonUp(UINT nFlags, CPoint point)
{
////////////////////////////////////////////////////////////////////////
// Process the various events depending on the selection and the view
// mode
////////////////////////////////////////////////////////////////////////
CViewport::OnLButtonUp(nFlags, point);
GetViewManager()->UpdateViews(eUpdateObjects);
}
//////////////////////////////////////////////////////////////////////////
BOOL C2DViewport::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
float z = GetZoomFactor();
float scale = 1.2f * fabs(zDelta/120.0f);
if (zDelta > 0)
{
z = z * scale;
}
else
{
z = z / scale;
}
SetZoom( z,m_cMousePos );
GetViewManager()->UpdateViews(eUpdateObjects);
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnMouseMove(UINT nFlags, CPoint point)
{
m_cMousePos = point;
if (GetViewMode() == ScrollZoomMode)
{
CRect rc;
// You can only scroll while the middle mouse button is down
if (nFlags & MK_RBUTTON || nFlags & MK_MBUTTON)
{
if (nFlags & MK_SHIFT)
{
// Get the dimensions of the window
GetClientRect(&rc);
CRect rc;
GetClientRect( rc );
int w = rc.right;
int h = rc.bottom;
// Zoom to mouse position.
float z = m_prevZoomFactor + (point.y - m_RMouseDownPos.y) * 0.02f;
SetZoom( z,m_RMouseDownPos );
}
else
{
// Set the new scrolled coordinates
float fScale = GetZoomFactor();
float ofsx,ofsy;
GetScrollOffset( ofsx,ofsy );
ofsx -= (point.x - m_RMouseDownPos.x)/fScale;
ofsy += (point.y - m_RMouseDownPos.y)/fScale;
SetScrollOffset( ofsx,ofsy );
m_RMouseDownPos = point;
}
}
return;
}
CViewport::OnMouseMove(nFlags, point);
//////////////////////////////////////////////////////////////////////////
//@FIXME: REMOVE
//GetViewManager()->UpdateViews(eUpdateObjects);
Invalidate(FALSE);
//////////////////////////////////////////////////////////////////////////
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::SetScrollOffset( float x,float y,bool bLimits )
{
if (bLimits)
{
float maxMapSize = 4096;
// Limit scroll offsets.
x = max(x,-maxMapSize);
y = max(y,-maxMapSize);
x = min(x,maxMapSize);
y = min(y,maxMapSize);
}
Vec3 org = GetOrigin2D();
switch (m_axis)
{
case VPA_XY:
org.x = x; org.y = y;
break;
case VPA_XZ:
org.x = x; org.z = y;
break;
case VPA_YZ:
org.y = x; org.z = y;
break;
}
SetOrigin2D(org);
CalculateViewTM();
//GetViewManager()->UpdateViews(eUpdateObjects);
Invalidate(FALSE);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::GetScrollOffset( float &x,float &y )
{
Vec3 origin = GetOrigin2D();
switch (m_axis)
{
case VPA_XY:
x = origin.x;
y = origin.y;
break;
case VPA_XZ:
x = origin.x;
y = origin.z;
break;
case VPA_YZ:
x = origin.y;
y = origin.z;
break;
}
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::SetZoom( float fZoomFactor,CPoint center )
{
if (fZoomFactor < 0.01f)
fZoomFactor = 0.01f;
float prevz = GetZoomFactor();
// Zoom to mouse position.
float ofsx,ofsy;
GetScrollOffset( ofsx,ofsy );
float s1 = GetZoomFactor();
float s2 = fZoomFactor;
SetZoomFactor( fZoomFactor );
// Calculate new offset to center zoom on mouse.
float x2 = center.x;
float y2 = m_rcClient.Height() - center.y;
ofsx = -(x2/s2 - x2/s1 - ofsx);
ofsy = -(y2/s2 - y2/s1 - ofsy);
SetScrollOffset( ofsx,ofsy,false );
CalculateViewTM();
//GetViewManager()->UpdateViews(eUpdateObjects);
Invalidate(FALSE);
}
//////////////////////////////////////////////////////////////////////////
afx_msg void C2DViewport::OnSize(UINT nType, int cx, int cy)
{
////////////////////////////////////////////////////////////////////////
// Re-evaluate the zoom / scroll offset values
// TODO: Restore the zoom rectangle instead of resetting it
////////////////////////////////////////////////////////////////////////
CViewport::OnSize(nType, cx, cy);
GetClientRect( &m_rcClient );
CalculateViewTM();
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnPaint()
{
CRect rc;
CPaintDC dc(this); // device context for painting
//Draw( dc,dc.m_ps.rcPaint );
Render();
}
//////////////////////////////////////////////////////////////////////////
BOOL C2DViewport::OnEraseBkgnd(CDC* pDC)
{
return TRUE;
}
//////////////////////////////////////////////////////////////////////////
int C2DViewport::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CViewport::OnCreate(lpCreateStruct) == -1)
return -1;
m_renderer = GetIEditor()->GetRenderer();
if (!m_renderer)
{
// Create renderer.
m_renderer = GetIEditor()->GetSystem()->CreateRenderer( false,AfxGetInstanceHandle(),GetSafeHwnd() );
}
if (m_renderer)
{
m_renderer->CreateContext( m_hWnd );
m_renderer->MakeCurrent();
/*
if (!m_fontList)
{
// Create font list for this view.
// create GL font
CFont font;
font.CreateFont(
12, // logical height of font
6, // logical average character width
0, // angle of escapement
0, // base-line orientation angle
0, // font weight
0, // italic attribute flag
0, // underline attribute flag
0, // strikeout attribute flag
0, // character set identifier
0, // output precision
0, // clipping precision
0, // output quality
0, // pitch and family
"system font" // pointer to typeface name string
);
CClientDC dc(this);
CFont* def_font = dc.SelectObject(&font);
m_fontList = glGenLists (256);
if (m_fontList == 0)
CLogFile::WriteLine( "Couldn't create font drawlists" );
if (!wglUseFontBitmapsA( dc.GetSafeHdc(), 0, 255, m_fontList) )
CLogFile::WriteLine( "wglUseFontBitmaps failed" );
dc.SelectObject(def_font);
// Done with the font. Delete the font object.
font.DeleteObject();
}
*/
}
// Caluclate view tranform.
CalculateViewTM();
return 0;
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::Update()
{
//Render();
CViewport::Update();
}
//////////////////////////////////////////////////////////////////////////
CPoint C2DViewport::WorldToView( Vec3 wp )
{
CPoint p;
float fScale = GetZoomFactor();
Vec3 origin = GetOrigin2D();
int ix = 0;
int iy = 0;
switch (m_axis)
{
case VPA_XY:
ix = 0; iy = 1;
break;
case VPA_XZ:
ix = 0; iy = 2;
break;
case VPA_YZ:
ix = 1; iy = 2;
break;
}
p.x = (wp[ix] - origin[ix])*fScale;
p.y = m_rcClient.Height() - (wp[iy] - origin[iy])*fScale;
return p;
}
//////////////////////////////////////////////////////////////////////////
Vec3 C2DViewport::ViewToWorld( CPoint vp,bool *collideWithTerrain,bool onlyTerrain )
{
Vec3 wp(0,0,0);
float fScale = GetZoomFactor();
Vec3 origin = GetOrigin2D();
int ix = 0;
int iy = 0;
switch (m_axis)
{
case VPA_XY:
ix = 0; iy = 1;
break;
case VPA_XZ:
ix = 0; iy = 2;
break;
case VPA_YZ:
ix = 1; iy = 2;
break;
}
wp[ix] = (vp.x)/fScale + origin[ix];
wp[iy] = (m_rcClient.Height()-vp.y)/fScale + origin[iy];
return wp;
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::ViewToWorldRay( CPoint vp,Vec3 &raySrc,Vec3 &rayDir )
{
raySrc = ViewToWorld( vp );
switch (m_axis)
{
case VPA_XY:
raySrc.z = MAX_WORLD_SIZE;
rayDir(0,0,-1);
break;
case VPA_XZ:
raySrc.y = MAX_WORLD_SIZE;
rayDir(0,-1,0);
break;
case VPA_YZ:
raySrc.x = MAX_WORLD_SIZE;
rayDir(-1,0,0);
break;
}
}
//////////////////////////////////////////////////////////////////////////
float C2DViewport::GetScreenScaleFactor( const Vec3 &worldPoint )
{
return 400.0f / GetZoomFactor();
//return 100.0f / ;
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnTitleMenu( CMenu &menu )
{
bool labels = GetIEditor()->GetDisplaySettings()->IsDisplayLabels();
bool bGrid = GetIEditor()->GetViewManager()->GetGrid()->bEnabled;
menu.AppendMenu( MF_STRING|(labels)?MF_CHECKED:MF_UNCHECKED,1,"Labels" );
menu.AppendMenu( MF_STRING|(bGrid)?MF_CHECKED:MF_UNCHECKED,2,"Grid" );
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnTitleMenuCommand( int id )
{
switch (id)
{
case 1:
GetIEditor()->GetDisplaySettings()->DisplayLabels( !GetIEditor()->GetDisplaySettings()->IsDisplayLabels() );
break;
case 2:
{
CGrid *grid = GetIEditor()->GetViewManager()->GetGrid();
grid->Enable( !grid->IsEnabled() );
}
break;
}
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnDestroy()
{
if (m_renderer)
m_renderer->DeleteContext( m_hWnd );
CViewport::OnDestroy();
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::Render()
{
if (GetIEditor()->IsInGameMode())
return;
if (!m_renderer)
return;
if (!IsWindowVisible())
return;
if (!GetIEditor()->GetDocument()->IsDocumentReady())
return;
FUNCTION_PROFILER( GetIEditor()->GetSystem(),PROFILE_EDITOR );
CRect rc;
GetClientRect( rc );
CalculateViewTM();
// Render
m_renderer->SetCurrentContext( m_hWnd );
m_renderer->BeginFrame();
m_renderer->ChangeViewport(0,0,rc.right,rc.bottom);
m_renderer->SetPolygonMode( R_SOLID_MODE );
m_renderer->ClearColorBuffer( Rgb2Vec(m_colorBackground) );
m_renderer->Set2DMode( true,m_rcClient.right,m_rcClient.bottom );
/*
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, m_rcClient.right, 0,m_rcClient.bottom, -9999.0, 9999.0);
glMatrixMode(GL_MODELVIEW);
*/
//////////////////////////////////////////////////////////////////////////
// Draw viewport elements here.
//////////////////////////////////////////////////////////////////////////
// Calc world bounding box for objects rendering.
m_displayBounds = GetWorldBounds( CPoint(0,0),CPoint(m_rcClient.Width(),m_rcClient.Height()) );
// Draw all objects.
DisplayContext dc;
dc.settings = GetIEditor()->GetDisplaySettings();
dc.view = this;
dc.renderer = m_renderer;
dc.engine = GetIEditor()->Get3DEngine();
dc.flags = DISPLAY_2D;
dc.box = m_displayBounds;
dc.camera = &GetIEditor()->GetSystem()->GetViewCamera();
if (!dc.settings->IsDisplayLabels())
{
dc.flags |= DISPLAY_HIDENAMES;
}
if (dc.settings->IsDisplayLinks())
{
dc.flags |= DISPLAY_LINKS;
}
if (m_bDegradateQuality)
{
dc.flags |= DISPLAY_DEGRADATED;
}
m_renderer->EF_StartEf();
//m_renderer->EnableDepthTest(false);
//m_renderer->EnableDepthWrites(false);
m_renderer->SetState(GS_NODEPTHTEST);
Draw( dc );
//m_renderer->EnableDepthTest(true);
//m_renderer->EnableDepthWrites(true);
m_renderer->EF_EndEf3D(SHDF_SORT);
m_renderer->FlushTextMessages();
m_renderer->Update();
// Return back from 2D mode.
m_renderer->Set2DMode( false,m_rcClient.right,m_rcClient.bottom );
GetIEditor()->GetRenderer()->MakeCurrent();
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::Draw( DisplayContext &dc )
{
DrawGrid(dc);
DrawObjects(dc);
DrawSelection(dc);
DrawViewerMarker(dc);
DrawAxis(dc);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::DrawGrid( DisplayContext &dc,bool bNoXNumbers )
{
CGrid *pGrid = GetIEditor()->GetViewManager()->GetGrid();
float gridSize = pGrid->size;
if (gridSize < 0.00001)
return;
//////////////////////////////////////////////////////////////////////////
bool bShowGrid = pGrid->IsEnabled();
///if (!bShowGrid)
//return;
float fScale = GetZoomFactor();
int width = m_rcClient.Width();
int height = m_rcClient.Height();
float origin[2];
GetScrollOffset( origin[0],origin[1] );
//////////////////////////////////////////////////////////////////////////
// Draw major blocks
Matrix44 tm;
tm.SetIdentity();
dc.PushMatrix( tm );
//Matrix tm = GetViewTM();
//glMultMatrixf( (float*)(&tm) );
int gx,gy;
//////////////////////////////////////////////////////////////////////////
// Draw Minor grid lines.
//////////////////////////////////////////////////////////////////////////
int firstGridLineX = origin[0] / gridSize - 1;
int firstGridLineY = origin[1] / gridSize - 1;
int numGridLinesX = (m_rcClient.Width()/fScale) / gridSize + 1;
int numGridLinesY = (m_rcClient.Height()/fScale) / gridSize + 1;
float pixelsPerGrid = gridSize*fScale;
if (pixelsPerGrid > 4)
{
dc.SetColor( MINOR_GRID_COLOR,m_gridAlpha );
// Draw horizontal grid lines.
for (gy = firstGridLineY; gy < firstGridLineY+numGridLinesY+1; gy++)
{
float y = height - (gy*gridSize - origin[1])*fScale;
m_renderer->DrawLine( Vec3(0,y,0),Vec3(width,y,0) );
}
// Draw vertical grid lines.
for (gx = firstGridLineX; gx < firstGridLineX+numGridLinesX+1; gx++)
{
float x = (gx*gridSize - origin[0])*fScale;
m_renderer->DrawLine( Vec3(x,0,0),Vec3(x,height,0) );
}
}
//////////////////////////////////////////////////////////////////////////
// Draw Major grid lines.
//////////////////////////////////////////////////////////////////////////
gridSize = gridSize * pGrid->majorLine;
int iters = 0;
pixelsPerGrid = gridSize*fScale;
while (pixelsPerGrid < 20 && iters < 20)
{
gridSize = gridSize*2;
pixelsPerGrid = gridSize*fScale;
iters++;
}
if (pixelsPerGrid < 20)
return;
dc.SetColor( MAJOR_GRID_COLOR,m_gridAlpha );
// Draw major grid lines.
firstGridLineX = origin[0] / gridSize;
firstGridLineY = origin[1] / gridSize;
firstGridLineX--;
firstGridLineX--;
numGridLinesX = 2 + (m_rcClient.Width()/fScale) / gridSize;
numGridLinesY = 2 + (m_rcClient.Height()/fScale) / gridSize;
numGridLinesX += 2;
numGridLinesX += 2;
// Draw horizontal grid lines.
for (gy = firstGridLineY; gy < firstGridLineY+numGridLinesY; gy++)
{
float y = height - (gy*gridSize - origin[1])*fScale;
if (gy != 0)
{
m_renderer->DrawLine( Vec3(0,y,0),Vec3(width,y,0) );
}
else
{
dc.SetColor( AXIS_GRID_COLOR );
m_renderer->DrawLine( Vec3(0,y,0),Vec3(width,y,0) );
dc.SetColor( MAJOR_GRID_COLOR,m_gridAlpha );
}
}
// Draw vertical grid lines.
for (gx = firstGridLineX; gx < firstGridLineX+numGridLinesX; gx++)
{
float x = (gx*gridSize - origin[0])*fScale;
if (gx != 0)
m_renderer->DrawLine( Vec3(x,0,0),Vec3(x,height,0) );
else
{
dc.SetColor( AXIS_GRID_COLOR );
m_renderer->DrawLine( Vec3(x,0,0),Vec3(x,height,0) );
dc.SetColor( MAJOR_GRID_COLOR,m_gridAlpha );
}
}
// Draw numbers.
{
char text[64];
dc.SetColor( m_colorGridText );
if (!bNoXNumbers)
{
// Draw horizontal grid text.
for (gx = firstGridLineX; gx < firstGridLineX+numGridLinesX; gx++)
{
sprintf( text, "%i",(int)(gx*gridSize) );
float x = (gx*gridSize - origin[0])*fScale;
dc.Draw2dTextLabel( x,10,1,text );
}
}
// Draw vertical grid text.
for (gy = firstGridLineY; gy < firstGridLineY+numGridLinesY; gy++)
{
sprintf( text, "%i",(int)(gy*gridSize) );
float y = (gy*gridSize - origin[1])*fScale;
dc.Draw2dTextLabel( 2,height-y,1,text );
}
}
dc.PopMatrix();
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::DrawAxis( DisplayContext &dc )
{
int ix = 0;
int iy = 0;
float cl = 0.85f;
char xstr[2],ystr[2],zstr[2];
Vec3 colx,coly,colz;
Vec3 colorX(cl,0,0);
Vec3 colorY(0,cl,0);
Vec3 colorZ(0,0,cl);
switch (m_axis)
{
case VPA_XY:
strcpy( xstr,"x" );
strcpy( ystr,"y" );
strcpy( zstr,"z" );
colx = colorX;
coly = colorY;
colz = colorZ;
break;
case VPA_XZ:
strcpy( xstr,"x" );
strcpy( ystr,"z" );
strcpy( zstr,"y" );
colx = colorX;
coly = colorZ;
colz = colorY;
break;
case VPA_YZ:
strcpy( xstr,"y" );
strcpy( ystr,"z" );
strcpy( zstr,"x" );
colx = colorY;
coly = colorZ;
colz = colorX;
break;
}
int width = m_rcClient.Width();
int height = m_rcClient.Height();
int size = 25;
Vec3 pos( 30,height-15,0 );
m_renderer->SetMaterialColor( colx.x,colx.y,colx.z,1 );
m_renderer->DrawLine( pos,pos + Vec3(size,0,0) );
m_renderer->SetMaterialColor( coly.x,coly.y,coly.z,1 );
m_renderer->DrawLine( pos,pos - Vec3(0,size,0) );
//m_renderer->SetMaterialColor( 0,0,1,1 );
//m_renderer->DrawLine( pos,pos + Vec3(0,0,20) );
//gl.PrintText( pos.x+size,pos.y,"x" );
dc.SetColor( m_colorAxisText );
pos.x -= 3;
pos.y -= 4;
dc.Draw2dTextLabel( pos.x+size+4,pos.y-2,1,xstr );
dc.Draw2dTextLabel( pos.x+3,pos.y-size,1,ystr );
dc.Draw2dTextLabel( pos.x-5,pos.y+5,1,zstr );
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::DrawSelection( DisplayContext &dc )
{
BBox box;
GetIEditor()->GetSelectedRegion( box );
if (!IsEquivalent(box.min,box.max,0))
{
//m_renderer->SetMaterialColor( SELECTION_RECT_COLOR.x,SELECTION_RECT_COLOR.y,SELECTION_RECT_COLOR.z,1 ); // white
//m_renderer->DrawWireB
/*
CRect rc;
CPoint p1 = WorldToView( box.min );
CPoint p2 = WorldToView( box.max );
rc.SetRect( p1,p2 );
rc.NormalizeRect();
// Draw selection.
if (rc.left != rc.right || rc.top != rc.bottom)
{
// Draw select rectangle.
m_renderer->SetMaterialColor( SELECTION_RECT_COLOR.x,SELECTION_RECT_COLOR.y,SELECTION_RECT_COLOR.z,1 ); // white
m_renderer->DrawLine( Vec3(rc.left,rc.top,0),Vec3(rc.right,rc.top,0) );
m_renderer->DrawLine( Vec3(rc.right,rc.top,0),Vec3(rc.right,rc.bottom,0) );
m_renderer->DrawLine( Vec3(rc.right,rc.bottom,0),Vec3(rc.left,rc.bottom,0) );
m_renderer->DrawLine( Vec3(rc.left,rc.bottom,0),Vec3(rc.left,rc.top,0) );
}
*/
}
if (!IsEquivalent(box.min,box.max,0))
{
switch (m_axis)
{
case VPA_XY:
box.min.z = box.max.z = 0;
break;
case VPA_XZ:
box.min.y = box.max.y = 0;
break;
case VPA_YZ:
box.min.x = box.max.x = 0;
break;
}
dc.PushMatrix( GetScreenTM() );
dc.SetColor( SELECTION_RECT_COLOR.x,SELECTION_RECT_COLOR.y,SELECTION_RECT_COLOR.z,1 );
dc.DrawWireBox( box.min,box.max );
dc.PopMatrix();
}
if (!m_selectedRect.IsRectEmpty())
{
dc.SetColor( SELECTION_RECT_COLOR.x,SELECTION_RECT_COLOR.y,SELECTION_RECT_COLOR.z,1 );
CPoint p1 = CPoint( m_selectedRect.left,m_selectedRect.top );
CPoint p2 = CPoint( m_selectedRect.right,m_selectedRect.bottom );
dc.DrawLine( Vec3(p1.x,p1.y,0),Vec3(p2.x,p1.y,0) );
dc.DrawLine( Vec3(p1.x,p2.y,0),Vec3(p2.x,p2.y,0) );
dc.DrawLine( Vec3(p1.x,p1.y,0),Vec3(p1.x,p2.y,0) );
dc.DrawLine( Vec3(p2.x,p1.y,0),Vec3(p2.x,p2.y,0) );
}
}
//////////////////////////////////////////////////////////////////////////
Vec3 C2DViewport::SnapToGrid( Vec3 vec )
{
CGrid *pGrid = GetIEditor()->GetViewManager()->GetGrid();
return pGrid->Snap( vec );
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::DrawViewerMarker( DisplayContext &dc )
{
float noScale = 1.0f/GetZoomFactor();
Vec3 viewAngles = GetIEditor()->GetViewerAngles();
Matrix44 tm;
switch (m_axis)
{
case VPA_XY:
tm = Matrix44::CreateRotationZYX(-DEG2RAD(Vec3(0,0,viewAngles.z)));
break;
case VPA_XZ:
tm = Matrix44::CreateRotationZYX(-DEG2RAD(Vec3(0,viewAngles.y,0)));
break;
case VPA_YZ:
tm = Matrix44::CreateRotationZYX(-DEG2RAD(Vec3(viewAngles.x,0,0)));
break;
}
tm.SetTranslationOLD( GetIEditor()->GetViewerPos() );
dc.PushMatrix( tm*GetScreenTM() );
Vec3 dim(MARKER_SIZE,MARKER_SIZE/2,MARKER_SIZE);
dc.SetColor( RGB(0,0,255) ); // red
dc.DrawWireBox( -dim*noScale,dim*noScale );
float fov = GetIEditor()->GetSystem()->GetViewCamera().GetFov();
Vec3 q[4];
float dist = 30;
float ta = (float)tan(0.5f*fov);
float w = dist * ta;
float h = w * gSettings.viewports.fDefaultAspectRatio; // ASPECT ??
//float h = w / GetAspect();
q[0] = Vec3( w,-dist, h) * noScale;
q[1] = Vec3(-w,-dist, h) * noScale;
q[2] = Vec3(-w,-dist,-h) * noScale;
q[3] = Vec3( w,-dist,-h) * noScale;
// Draw frustum.
dc.DrawLine( Vec3(0,0,0),q[0] );
dc.DrawLine( Vec3(0,0,0),q[1] );
dc.DrawLine( Vec3(0,0,0),q[2] );
dc.DrawLine( Vec3(0,0,0),q[3] );
// Draw quad.
dc.DrawPolyLine( q,4 );
dc.PopMatrix();
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::DrawObjects( DisplayContext &dc )
{
dc.renderer->SetState(GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA);
//dc.renderer->SetBlendMode();
//dc.renderer->EnableBlend(true);
dc.PushMatrix( GetScreenTM() );
GetIEditor()->GetObjectManager()->Display( dc );
// Display editing tool.
if (GetIEditor()->GetEditTool())
{
GetIEditor()->GetEditTool()->Display( dc );
}
dc.PopMatrix();
dc.renderer->SetState(GS_DEPTHWRITE);
//dc.renderer->EnableBlend(false);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::DrawBrush( DisplayContext &dc,struct SBrush *brush,const Matrix44 &brushTM,int flags )
{
float fScale = GetZoomFactor();
//Matrix tm = brushTM * GetViewTM();
//glMultMatrixf( (float*)(&tm) );
dc.PushMatrix( brushTM );
// if selected.
bool bSelected = flags == 1;
if (bSelected)
{
dc.SetLineWidth(2);
//glEnable(GL_LINE_STIPPLE);
//glLineStipple( 10,0xAAAA );
}
int i, j;
for (i = 0; i < brush->m_Faces.size(); i++)
{
SBrushFace *f = brush->m_Faces[i];
// if (f->m_Plane.normal[0] <= 0)
//if (f->m_Plane.normal[m_cullAxis] <= 0)
//continue;
//CHANGED_BY_IVO
//Vec3 norm = brushTM.TransformVector( f->m_Plane.normal );
Vec3 norm = GetTransposed44(brushTM) * ( f->m_Plane.normal );
if (norm[m_cullAxis] <= 0)
continue;
SBrushPoly *poly = f->m_Poly;
if (!poly)
continue;
int numv = poly->m_Pts.size();
//glBegin(GL_LINE_LOOP);
for (j=0; j < numv; j++)
{
int k = ((j+1) < numv) ? j+1 : 0;
SBrushVert &vert = poly->m_Pts[j];
SBrushVert &vert1 = poly->m_Pts[k];
dc.DrawLine( vert.xyz,vert1.xyz );
//glVertex3fv( &vert.xyz[0] );
//glVertex3fv(&poly->m_Pts[j].xyz[0]);
}
//glEnd();
}
brush->m_bounds;
if (bSelected)
{
//glDisable(GL_LINE_STIPPLE);
dc.SetLineWidth(1);
}
dc.PopMatrix();
if (bSelected)
{
int ix = 0;
int iy = 0;
switch (m_axis)
{
case VPA_XY:
ix = 0; iy = 1;
break;
case VPA_XZ:
ix = 0; iy = 2;
break;
case VPA_YZ:
ix = 1; iy = 2;
break;
}
Vec3 p1(brush->m_bounds.min[ix],brush->m_bounds.min[iy],0);
Vec3 p2(brush->m_bounds.max[ix],brush->m_bounds.max[iy],0);
}
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::DrawTextLabel( DisplayContext &dc,const Vec3& pos,float size,const CFColor& color,const char *text )
{
float fCol[4] = { color.r,color.g,color.b,color.a };
Vec3 p = GetScreenTM().TransformPointOLD( pos );
m_renderer->Draw2dLabel( p.x,p.y,size,fCol,false,"%s",text);
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::SetConstrPlane( CPoint cursor,const Matrix44 &xform )
{
m_constructionOriginalMatrix = xform;
m_constructionMatrix = xform;
// Remove scale component.
m_constructionMatrix.NoScale();
Vec3 pos = m_constructionMatrix.GetTranslationOLD();
// Remove position component.
m_constructionMatrix.SetTranslationOLD( Vec3(0,0,0) );
switch (m_axis)
{
case VPA_XY:
m_constructionPlane.Init( pos,pos+Vec3(1,0,0),pos+Vec3(0,1,0) );
break;
case VPA_XZ:
m_constructionPlane.Init( pos,pos+Vec3(1,0,0),pos+Vec3(0,0,1) );
break;
case VPA_YZ:
m_constructionPlane.Init( pos,pos+Vec3(0,1,0),pos+Vec3(0,0,1) );
break;
}
}
Vec3 C2DViewport::GetCPVector( const Vec3 &p1,const Vec3 &p2 )
{
return CViewport::GetCPVector(p1,p2);
}
//////////////////////////////////////////////////////////////////////////
BBox C2DViewport::GetWorldBounds( CPoint pnt1,CPoint pnt2 )
{
Vec3 org;
BBox box;
box.Reset();
box.Add( ViewToWorld( pnt1 ) );
box.Add( ViewToWorld( pnt2 ) );
int maxSize = MAX_WORLD_SIZE;
switch (m_axis)
{
case VPA_XY:
box.min.z = -maxSize;
box.max.z = maxSize;
break;
case VPA_XZ:
box.min.y = -maxSize;
box.max.y = maxSize;
break;
case VPA_YZ:
box.min.x = -maxSize;
box.max.x = maxSize;
break;
}
return box;
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::OnDragSelectRectangle( CPoint pnt1,CPoint pnt2,bool bNormilizeRect )
{
Vec3 org;
BBox box;
box.Reset();
Vec3 p1 = ViewToWorld( pnt1 );
Vec3 p2 = ViewToWorld( pnt2 );
org = p1;
// Calculate selection volume.
box.Add( p1 );
box.Add( p2 );
int maxSize = MAX_WORLD_SIZE;
char szNewStatusText[512];
float w,h;
switch (m_axis)
{
case VPA_XY:
box.min.z = -maxSize;
box.max.z = maxSize;
w = box.max.x - box.min.x;
h = box.max.y - box.min.y;
sprintf(szNewStatusText, "X:%g Y:%g W:%g H:%g",org.x,org.y,w,h );
break;
case VPA_XZ:
box.min.y = -maxSize;
box.max.y = maxSize;
w = box.max.x - box.min.x;
h = box.max.z - box.min.z;
sprintf(szNewStatusText, "X:%g Z:%g W:%g H:%g",org.x,org.z,w,h );
break;
case VPA_YZ:
box.min.x = -maxSize;
box.max.x = maxSize;
w = box.max.y - box.min.y;
h = box.max.z - box.min.z;
sprintf(szNewStatusText, "Y:%g Z:%g W:%g H:%g",org.y,org.z,w,h );
break;
}
GetIEditor()->SetSelectedRegion( box );
// Show marker position in the status bar
GetIEditor()->SetStatusText(szNewStatusText);
}
//////////////////////////////////////////////////////////////////////////
bool C2DViewport::HitTest( CPoint point,ObjectHitInfo &hitInfo,int flags )
{
hitInfo.bounds = m_displayBounds;
return CViewport::HitTest( point,hitInfo,flags );
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
bool C2DViewport::IsBoundsVisible( const BBox &box ) const
{
// If at least part of bbox is visible then its visible.
if (m_displayBounds.IsIntersectBox( box ))
return true;
return false;
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::CenterOnSelection()
{
CSelectionGroup *sel = GetIEditor()->GetSelection();
if (sel->IsEmpty())
return;
//SetZoomFactor(1);
BBox bounds = sel->GetBounds();
Vec3 selPos = sel->GetCenter();
float size = GetLength(bounds.max - bounds.min);
//CPoint p1 = WorldToView(bounds.min);
//CPoint p2 = WorldToView(bounds.max);
Vec3 v1 = ViewToWorld( CPoint(m_rcClient.left,m_rcClient.bottom) );
Vec3 v2 = ViewToWorld( CPoint(m_rcClient.right,m_rcClient.top) );
Vec3 vofs = (v2-v1) * 0.5f;
selPos -= vofs;
SetOrigin2D( selPos );
Invalidate(FALSE);
//SetZoomFactor( size / 10 );
/*
CSelectionGroup *sel = GetIEditor()->GetSelection();
BBox bounds = sel->GetBounds();
Vec3 selPos = sel->GetCenter();
float size = GetLength(bounds.max - bounds.min);
Vec3 pos = selPos;
pos += Vec3(0,size*2,size);
//pos.z = GetIEditor()->GetTerrainElevation(pos.x,pos.y)+5;
GetIEditor()->SetViewerPos( pos );
Vec3 dir = GetNormalized(selPos - pos);
dir = ConvertVectorToCameraAngles(dir);
GetIEditor()->SetViewerAngles( dir );
*/
}
//////////////////////////////////////////////////////////////////////////
Vec3 C2DViewport::GetOrigin2D() const
{
if (gSettings.viewports.bSync2DViews)
return GetViewManager()->GetOrigin2D();
else
return m_origin2D;
}
//////////////////////////////////////////////////////////////////////////
void C2DViewport::SetOrigin2D( const Vec3 &org )
{
m_origin2D = org;
if (gSettings.viewports.bSync2DViews)
GetViewManager()->SetOrigin2D( m_origin2D );
}