eol
[xonotic/netradiant.git] / plugins / textool / 2DView.cpp
1 /*
2 Copyright (C) 1999-2007 id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
4
5 This file is part of GtkRadiant.
6
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20 */
21
22 //-----------------------------------------------------------------------------
23 //
24 // DESCRIPTION:
25 // a class to provide basic services for 2D view of a world
26 // window <-> local 2D space transforms
27 // snap to grid
28 // TODO: this one can be placed under an interface, and provided to the editor as a service
29
30 #include "StdAfx.h"
31
32 static void view_ZoomIn (GtkWidget* widget, gpointer data)
33 {
34   ((C2DView*)data)->ZoomIn ();
35 }
36
37 static void view_ZoomOut (GtkWidget* widget, gpointer data)
38 {
39   ((C2DView*)data)->ZoomOut ();
40 }
41
42 void C2DView::PreparePaint()
43 {
44   g_QglTable.m_pfn_qglClearColor( 0, 0, 0, 0 );
45   g_QglTable.m_pfn_qglViewport( 0, 0, m_rect.right, m_rect.bottom );
46   g_QglTable.m_pfn_qglMatrixMode( GL_PROJECTION );
47   g_QglTable.m_pfn_qglLoadIdentity();
48   g_QglTable.m_pfn_qglOrtho( m_Mins[0], m_Maxs[0], m_Maxs[1], m_Mins[1], -1, 1 );       
49 }
50
51 void C2DView::SpaceForWindow( float c[2], int x, int y)
52 {
53   c[0] = ((float)(x))/((float)(m_rect.right-m_rect.left))*(m_Maxs[0]-m_Mins[0])+m_Mins[0];
54   c[1] = ((float)(y))/((float)(m_rect.bottom-m_rect.top))*(m_Maxs[1]-m_Mins[1])+m_Mins[1];
55 }
56
57 void C2DView::GridForWindow( float c[2], int x, int y)
58 {
59   SpaceForWindow( c, x, y );
60   if ( !m_bDoGrid )
61     return;
62   c[0] /= m_GridStep[0];
63   c[1] /= m_GridStep[1];
64   c[0] = (float)floor( c[0] + 0.5f );
65   c[1] = (float)floor( c[1] + 0.5f );
66   c[0] *= m_GridStep[0];
67   c[1] *= m_GridStep[1];
68 }
69
70 void C2DView::WindowForSpace( int &x, int &y, const float c[2] )
71 {
72   x = m_rect.left + (int)( ((float)(m_rect.right-m_rect.left))*(c[0]-m_Mins[0])/(m_Maxs[0]-m_Mins[0]) );
73   y = m_rect.top + (int)( ((float)(m_rect.bottom-m_rect.top))*(c[1]-m_Mins[1])/(m_Maxs[1]-m_Mins[1]) );
74 }
75
76 qboolean C2DView::DoesSelect( int x, int y, float c[2] )
77 {
78   int xc,yc;
79   WindowForSpace( xc, yc, c );
80   if ( abs(xc-x)<=3 && abs(yc-y)<=3 )
81     return true;
82   return false;
83 }
84
85 void C2DView::ZoomIn()
86 {
87   m_Mins[0] = 0.5f * ( m_Mins[0] - m_Center[0] ) + m_Center[0];
88   m_Mins[1] = 0.5f * ( m_Mins[1] - m_Center[1] ) + m_Center[1];
89   m_Maxs[0] = 0.5f * ( m_Maxs[0] - m_Center[0] ) + m_Center[0];
90   m_Maxs[1] = 0.5f * ( m_Maxs[1] - m_Center[1] ) + m_Center[1];
91   g_pToolWnd->Redraw ();
92 }
93
94 void C2DView::ZoomOut()
95 {
96   m_Mins[0] = 2.0f * ( m_Mins[0] - m_Center[0] ) + m_Center[0];
97   m_Mins[1] = 2.0f * ( m_Mins[1] - m_Center[1] ) + m_Center[1];
98   m_Maxs[0] = 2.0f * ( m_Maxs[0] - m_Center[0] ) + m_Center[0];
99   m_Maxs[1] = 2.0f * ( m_Maxs[1] - m_Center[1] ) + m_Center[1];
100   g_pToolWnd->Redraw ();
101 }
102
103 bool C2DView::OnRButtonDown (int x, int y)
104 {
105   if (ViewState == View_Idle)
106   {
107     m_xPosMove = x; // horizontal position of cursor
108     m_yPosMove = y; // vertical position of cursor
109     // store
110     m_MinsMove[0] = m_Mins[0]; m_MinsMove[1] = m_Mins[1];
111     m_MaxsMove[0] = m_Maxs[0]; m_MaxsMove[1] = m_Maxs[1];
112     ViewState = View_Move;
113     // set popup to true
114     m_bPopup = true;
115     return true;
116   }
117   return false;
118 }
119
120 bool C2DView::OnRButtonUp (int x, int y)
121 {
122   if (ViewState == View_Move)
123   {
124     // maybe it's time for popup menu
125     if (m_bPopup)
126     {
127       GtkWidget *menu, *item;
128
129       menu = gtk_menu_new ();
130
131       item = gtk_menu_item_new_with_label ("Validate (RETURN)");
132       gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (Textool_Validate), NULL);
133       gtk_widget_show (item);
134       gtk_menu_append (GTK_MENU (menu), item);
135
136       item = gtk_menu_item_new_with_label ("Zoom in (INSERT)");
137       gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (view_ZoomIn), this);
138       gtk_widget_show (item);
139       gtk_menu_append (GTK_MENU (menu), item);
140
141       item = gtk_menu_item_new_with_label ("Zoom out (DELETE)");
142       gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (view_ZoomOut), this);
143       gtk_widget_show (item);
144       gtk_menu_append (GTK_MENU (menu), item);
145
146       item = gtk_menu_item_new_with_label ("Cancel (ESC)");
147       gtk_signal_connect (GTK_OBJECT (item), "activate", GTK_SIGNAL_FUNC (Textool_Cancel), NULL);
148       gtk_widget_show (item);
149       gtk_menu_append (GTK_MENU (menu), item);
150
151       gtk_menu_popup (GTK_MENU (menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
152     }
153
154     // back to Idle mode
155     ViewState = View_Idle;
156     return true;
157   }
158   return false;
159 }
160
161 bool C2DView::OnMouseMove (int xPos, int yPos)
162 {
163   if (ViewState == View_Move)
164   {
165     float V[2];
166     // V is the offset
167     V[0] = ((float)( xPos - m_xPosMove )) * ( m_MaxsMove[0] - m_MinsMove[0] ) / ((float)( m_rect.left - m_rect.right ));
168     V[1] = ((float)( yPos - m_yPosMove )) * ( m_MaxsMove[1] - m_MinsMove[1] ) / ((float)( m_rect.top - m_rect.bottom ));
169     // update m_Mins m_Maxs and m_Center
170     m_Mins[0] = m_MinsMove[0] + V[0];
171     m_Mins[1] = m_MinsMove[1] + V[1];
172     m_Maxs[0] = m_MaxsMove[0] + V[0];
173     m_Maxs[1] = m_MaxsMove[1] + V[1];
174     m_Center[0] = 0.5f * ( m_Mins[0] + m_Maxs[0] );
175     m_Center[1] = 0.5f * ( m_Mins[1] + m_Maxs[1] );
176     // no popup menu if we moved
177     m_bPopup = false;
178     // send a repaint message
179     g_pToolWnd->Redraw ();
180     return true;
181   }
182   return false;
183 }
184
185 bool C2DView::OnKeyDown (char *s)
186 {
187   if (ViewState == View_Idle)
188   {
189     if (!strcmp(s,"Insert"))
190     {
191       ZoomOut();
192       return true;
193     }
194     if (!strcmp(s,"Delete"))
195     {
196       ZoomIn();
197       return true;
198     }
199   }
200   return false;
201 }
202