]> git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/meshtex/MainMenu.cpp
Merge commit '4645e19ce9e8f8034233ac965a4103a13b75714c' into garux-merge
[xonotic/netradiant.git] / contrib / meshtex / MainMenu.cpp
1 /**
2  * @file MainMenu.cpp
3  * Implements the MainMenu class.
4  * @ingroup meshtex-ui
5  */
6
7 /*
8  * Copyright 2012 Joel Baxter
9  *
10  * This file is part of MeshTex.
11  *
12  * MeshTex is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * MeshTex is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with MeshTex.  If not, see <http://www.gnu.org/licenses/>.
24  */
25
26 #include "MainMenu.h"
27 #include "PluginUI.h"
28 #include "PluginUIMessages.h"
29
30 #include "scenelib.h"
31 #include "iundo.h"
32
33
34 /**
35  * Constructor.
36  *
37  * @param visitorFunctor The functor for the mesh preset function.
38  * @param axes           The texture axes to affect.
39  */
40 MainMenu::PresetFuncVisitor::PresetFuncVisitor(
41    const VisitorFunctor& visitorFunctor,
42    MeshEntity::TextureAxisSelection axes) :
43    _visitorFunctor(visitorFunctor),
44    _axes(axes)
45 {
46 }
47
48 /**
49  * Visitor action; invoke a preset function on a mesh.
50  *
51  * @param [in,out] meshEntity The mesh entity.
52  *
53  * @return true.
54  */
55 bool
56 MainMenu::PresetFuncVisitor::Execute(MeshEntity& meshEntity) const
57 {
58    (meshEntity.*_visitorFunctor)(_axes);
59    return true;
60 }
61
62 /**
63  * Constructor. Instantiate the command callbacks and construct the command
64  * list.
65  *
66  * @param setScaleDialog Reference-counted handle on the Set S/T Scale dialog.
67  * @param getInfoDialog  Reference-counted handle on the Get Info dialog.
68  * @param genFuncDialog  Reference-counted handle on the General Function
69  *                       dialog.
70  */
71 MainMenu::MainMenu(SmartPointer<GenericDialog>& setScaleDialog,
72                    SmartPointer<GenericDialog>& getInfoDialog,
73                    SmartPointer<GenericDialog>& genFuncDialog) :
74    _commandMeshVisitor(*this)
75 {
76    // Like _commandMeshVisitor, the callbacks for the Help and About commands
77    // also specify functions on this object. 
78    const CommandCallbackMethod
79       <MainMenu, &MainMenu::CommandHelp> commandHelp(*this);
80    const CommandCallbackMethod
81       <MainMenu, &MainMenu::CommandAbout> commandAbout(*this);
82
83    // Start constructing the command list.
84    BeginEntries();
85    // First two commands summon dialogs.
86    AddDialogShowEntry("Set S/T Scale...", "SetScale", setScaleDialog);
87    AddDialogShowEntry("Get Info...", "GetInfo", getInfoDialog);
88    AddSeparator();
89    // Next command summons a dialog.
90    AddDialogShowEntry("General Function...", "GeneralFunction", genFuncDialog);
91    AddSeparator();
92    // The next few groups of commands are all similar "preset function"
93    // commands. They will each trigger the CommandMeshVisitor callback when
94    // selected in the menu. CommandMeshVisitor needs a visitor object to apply
95    // to the selected meshes, which we are specifying here. 
96    AddMeshVisitorEntry("S&T Align Auto", "STMinMaxAlignAuto",
97                        SmartPointer<MeshVisitor>(
98                           new PresetFuncVisitor(&MeshEntity::MinMaxAlignAutoScale,
99                                                 MeshEntity::ALL_TEX_AXES)));
100    AddMeshVisitorEntry("S Align Auto", "SMinMaxAlignAuto",
101                        SmartPointer<MeshVisitor>(
102                           new PresetFuncVisitor(&MeshEntity::MinMaxAlignAutoScale,
103                                                 MeshEntity::S_TEX_AXIS_ONLY)));
104    AddMeshVisitorEntry("T Align Auto", "TMinMaxAlignAuto",
105                        SmartPointer<MeshVisitor>(
106                           new PresetFuncVisitor(&MeshEntity::MinMaxAlignAutoScale,
107                                                 MeshEntity::T_TEX_AXIS_ONLY)));
108    AddSeparator();
109    AddMeshVisitorEntry("S Align Stretch", "SMinMaxAlignStretch",
110                        SmartPointer<MeshVisitor>(
111                           new PresetFuncVisitor(&MeshEntity::MinMaxAlignStretch,
112                                                 MeshEntity::S_TEX_AXIS_ONLY)));
113    AddMeshVisitorEntry("S Align Shrink", "SMinMaxAlignShrink",
114                        SmartPointer<MeshVisitor>(
115                           new PresetFuncVisitor(&MeshEntity::MinMaxAlignShrink,
116                                                 MeshEntity::S_TEX_AXIS_ONLY)));
117    AddMeshVisitorEntry("T Align Stretch", "TMinMaxAlignStretch",
118                        SmartPointer<MeshVisitor>(
119                           new PresetFuncVisitor(&MeshEntity::MinMaxAlignStretch,
120                                                 MeshEntity::T_TEX_AXIS_ONLY)));
121    AddMeshVisitorEntry("T Align Shrink", "TMinMaxAlignShrink",
122                    SmartPointer<MeshVisitor>(
123                       new PresetFuncVisitor(&MeshEntity::MinMaxAlignShrink,
124                                             MeshEntity::T_TEX_AXIS_ONLY)));
125    AddSeparator();
126    AddMeshVisitorEntry("S Min Align", "SMinAlign",
127                        SmartPointer<MeshVisitor>(
128                           new PresetFuncVisitor(&MeshEntity::MinAlign,
129                                                 MeshEntity::S_TEX_AXIS_ONLY)));
130    AddMeshVisitorEntry("S Max Align", "SMaxAlign",
131                        SmartPointer<MeshVisitor>(
132                           new PresetFuncVisitor(&MeshEntity::MaxAlign,
133                                                 MeshEntity::S_TEX_AXIS_ONLY)));
134    AddMeshVisitorEntry("T Min Align", "TMinAlign",
135                        SmartPointer<MeshVisitor>(
136                           new PresetFuncVisitor(&MeshEntity::MinAlign,
137                                                 MeshEntity::T_TEX_AXIS_ONLY)));
138    AddMeshVisitorEntry("T Max Align", "TMaxAlign",
139                        SmartPointer<MeshVisitor>(
140                           new PresetFuncVisitor(&MeshEntity::MaxAlign,
141                                                 MeshEntity::T_TEX_AXIS_ONLY)));
142    AddSeparator();
143    // These commands each invoke a unique callback when selected.
144    AddEntry("Help...", "Help", commandHelp);
145    AddEntry("About...", "About", commandAbout);
146    // Done!
147    EndEntries();
148 }
149
150 /**
151  * Destructor.
152  */
153 MainMenu::~MainMenu()
154 {
155 }
156
157 /**
158  * Callback common to all of the commands that trigger a processing by mesh
159  * visitor when selected. This callback does its own internal dispatch to
160  * distinctly handle the various commands.
161  *
162  * @param commandString The command token.
163  */
164 void
165 MainMenu::CommandMeshVisitor(const std::string& commandString)
166 {
167    // Look up the registered mesh visitor for this command.
168    VisitorMap::const_iterator visitorMapIter = _visitorMap.find(commandString);
169    MeshVisitor *meshVisitor;
170    if (visitorMapIter == _visitorMap.end() ||
171        (meshVisitor = visitorMapIter->second) == NULL)
172    {
173       // That's odd, there isn't one. Bail out.
174       std::string message(commandString + ": " + DIALOG_INTERNAL_ERROR);
175       GenericPluginUI::ErrorReportDialog(DIALOG_ERROR_TITLE, message.c_str());
176       return;
177    }
178    // Let Radiant know the name of the operation responsible for the changes
179    // that are about to happen.
180    UndoableCommand undo(commandString.c_str());
181    // Apply the visitor to every selected mesh.
182    meshVisitor->ResetVisitedCount();
183    GlobalSelectionSystem().foreachSelected(*meshVisitor);
184    if (meshVisitor->GetVisitedCount() == 0)
185    {
186       // Warn if there weren't any meshes selected (so nothing happened). 
187       GenericPluginUI::WarningReportDialog(DIALOG_WARNING_TITLE,
188                                            DIALOG_NOMESHES_MSG);
189    }
190 }
191
192 /**
193  * Callback triggered when the Help menu entry is selected.
194  *
195  * @param commandString The command token.
196  */
197 void
198 MainMenu::CommandHelp(const std::string& commandString)
199 {
200    // Pop up a hopefully somewhat helpful message dialog.
201    GenericPluginUI::InfoReportDialog(DIALOG_HELP_TITLE,
202                                      DIALOG_HELP_MSG);
203 }
204
205 /**
206  * Callback triggered when the About menu entry is selected.
207  *
208  * @param commandString The command token.
209  */
210 void
211 MainMenu::CommandAbout(const std::string& commandString)
212 {
213    // Pop up a message dialog that describes the plugin.
214    GenericPluginUI::InfoReportDialog(DIALOG_ABOUT_TITLE,
215                                      DIALOG_ABOUT_MSG);
216 }
217
218 /**
219  * Register a mesh visitor to be used to implement a specified command.
220  *
221  * @param commandLabel The command label.
222  * @param command      The command token.
223  * @param visitor      The mesh visitor.
224  */
225 void
226 MainMenu::AddMeshVisitorEntry(const char *commandLabel,
227                               const char *command,
228                               const SmartPointer<MeshVisitor>& visitor)
229 {
230    // Add to the command list, and indicate that CommandMeshVisitor is the
231    // callback for this command. Then save the association between command and
232    // visitor, for CommandMeshVisitor to reference.
233    _visitorMap.insert(
234       std::make_pair(AddEntry(commandLabel, command, _commandMeshVisitor),
235                      visitor));
236 }