]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - plugins/textool/2DView.cpp
Merge branch 'fix-fast' into 'master'
[xonotic/netradiant.git] / plugins / textool / 2DView.cpp
1 /*
2    Copyright (C) 1999-2006 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     }
63     c[0] /= m_GridStep[0];
64     c[1] /= m_GridStep[1];
65     c[0] = (float) floor(c[0] + 0.5f);
66     c[1] = (float) floor(c[1] + 0.5f);
67     c[0] *= m_GridStep[0];
68     c[1] *= m_GridStep[1];
69 }
70
71 void C2DView::WindowForSpace(int &x, int &y, const float c[2])
72 {
73     x = m_rect.left + (int) (((float) (m_rect.right - m_rect.left)) * (c[0] - m_Mins[0]) / (m_Maxs[0] - m_Mins[0]));
74     y = m_rect.top + (int) (((float) (m_rect.bottom - m_rect.top)) * (c[1] - m_Mins[1]) / (m_Maxs[1] - m_Mins[1]));
75 }
76
77 qboolean C2DView::DoesSelect(int x, int y, float c[2])
78 {
79     int xc, yc;
80     WindowForSpace(xc, yc, c);
81     if (abs(xc - x) <= 3 && abs(yc - y) <= 3) {
82         return true;
83     }
84     return false;
85 }
86
87 void C2DView::ZoomIn()
88 {
89     m_Mins[0] = 0.5f * (m_Mins[0] - m_Center[0]) + m_Center[0];
90     m_Mins[1] = 0.5f * (m_Mins[1] - m_Center[1]) + m_Center[1];
91     m_Maxs[0] = 0.5f * (m_Maxs[0] - m_Center[0]) + m_Center[0];
92     m_Maxs[1] = 0.5f * (m_Maxs[1] - m_Center[1]) + m_Center[1];
93     g_pToolWnd->Redraw();
94 }
95
96 void C2DView::ZoomOut()
97 {
98     m_Mins[0] = 2.0f * (m_Mins[0] - m_Center[0]) + m_Center[0];
99     m_Mins[1] = 2.0f * (m_Mins[1] - m_Center[1]) + m_Center[1];
100     m_Maxs[0] = 2.0f * (m_Maxs[0] - m_Center[0]) + m_Center[0];
101     m_Maxs[1] = 2.0f * (m_Maxs[1] - m_Center[1]) + m_Center[1];
102     g_pToolWnd->Redraw();
103 }
104
105 bool C2DView::OnRButtonDown(int x, int y)
106 {
107     if (ViewState == View_Idle) {
108         m_xPosMove = x; // horizontal position of cursor
109         m_yPosMove = y; // vertical position of cursor
110         // store
111         m_MinsMove[0] = m_Mins[0];
112         m_MinsMove[1] = m_Mins[1];
113         m_MaxsMove[0] = m_Maxs[0];
114         m_MaxsMove[1] = m_Maxs[1];
115         ViewState = View_Move;
116         // set popup to true
117         m_bPopup = true;
118         return true;
119     }
120     return false;
121 }
122
123 bool C2DView::OnRButtonUp(int x, int y)
124 {
125     if (ViewState == View_Move) {
126         // maybe it's time for popup menu
127         if (m_bPopup) {
128             GtkWidget *menu, *item;
129
130             menu = ui::Menu();
131
132             item = ui::MenuItem("Validate (RETURN)");
133             item.connect("activate", G_CALLBACK(Textool_Validate), NULL);
134             item.show();
135             gtk_menu_append(GTK_MENU(menu), item);
136
137             item = ui::MenuItem("Zoom in (INSERT)");
138             item.connect("activate", G_CALLBACK(view_ZoomIn), this);
139             item.show();
140             gtk_menu_append(GTK_MENU(menu), item);
141
142             item = ui::MenuItem("Zoom out (DELETE)");
143             item.connect("activate", G_CALLBACK(view_ZoomOut), this);
144             item.show();
145             gtk_menu_append(GTK_MENU(menu), item);
146
147             item = ui::MenuItem("Cancel (ESC)");
148             item.connect("activate", G_CALLBACK(Textool_Cancel), NULL);
149             item.show();
150             gtk_menu_append(GTK_MENU(menu), item);
151
152             gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 1, GDK_CURRENT_TIME);
153         }
154
155         // back to Idle mode
156         ViewState = View_Idle;
157         return true;
158     }
159     return false;
160 }
161
162 bool C2DView::OnMouseMove(int xPos, int yPos)
163 {
164     if (ViewState == View_Move) {
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         if (!strcmp(s, "Insert")) {
189             ZoomOut();
190             return true;
191         }
192         if (!strcmp(s, "Delete")) {
193             ZoomIn();
194             return true;
195         }
196     }
197     return false;
198 }