2 Copyright (C) 1999-2006 Id Software, Inc. and contributors.
3 For a list of contributors, see the accompanying CONTRIBUTORS file.
5 This file is part of GtkRadiant.
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.
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.
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
22 #include "patchmanip.h"
24 #include "debugging/debugging.h"
27 #include "iselection.h"
30 #include "math/vector.h"
31 #include "math/aabb.h"
32 #include "generic/callback.h"
34 #include "gtkutil/menu.h"
35 #include "gtkutil/image.h"
37 #include "mainframe.h"
41 #include "texwindow.h"
47 PatchCreator* g_patchCreator = 0;
49 void Scene_PatchConstructPrefab(scene::Graph& graph, const AABB aabb, const char* shader, EPatchPrefab eType, int axis, std::size_t width = 3, std::size_t height = 3)
52 GlobalSelectionSystem().setSelectedAll(false);
54 NodeSmartReference node(g_patchCreator->createPatch());
55 Node_getTraversable(Map_FindOrInsertWorldspawn(g_map))->insert(node);
57 Patch* patch = Node_getPatch(node);
58 patch->SetShader(shader);
60 patch->ConstructPrefab(aabb, eType, axis, width, height);
61 patch->controlPointsChanged();
64 scene::Path patchpath(makeReference(GlobalSceneGraph().root()));
65 patchpath.push(makeReference(*Map_GetWorldspawn(g_map)));
66 patchpath.push(makeReference(node.get()));
67 Instance_getSelectable(*graph.find(patchpath))->setSelected(true);
72 void Patch_makeCaps(Patch& patch, scene::Instance& instance, EPatchCap type, const char* shader)
74 if((type == eCapEndCap || type == eCapIEndCap)
75 && patch.getWidth() != 5)
77 globalErrorStream() << "cannot create end-cap - patch width != 5\n";
80 if((type == eCapBevel || type == eCapIBevel)
81 && patch.getWidth() != 3 && patch.getWidth() != 5)
83 globalErrorStream() << "cannot create bevel-cap - patch width != 3\n";
86 if(type == eCapCylinder
87 && patch.getWidth() != 9)
89 globalErrorStream() << "cannot create cylinder-cap - patch width != 9\n";
94 NodeSmartReference cap(g_patchCreator->createPatch());
95 Node_getTraversable(instance.path().parent())->insert(cap);
97 patch.MakeCap(Node_getPatch(cap), type, ROW, true);
98 Node_getPatch(cap)->SetShader(shader);
100 scene::Path path(instance.path());
102 path.push(makeReference(cap.get()));
103 selectPath(path, true);
107 NodeSmartReference cap(g_patchCreator->createPatch());
108 Node_getTraversable(instance.path().parent())->insert(cap);
110 patch.MakeCap(Node_getPatch(cap), type, ROW, false);
111 Node_getPatch(cap)->SetShader(shader);
113 scene::Path path(instance.path());
115 path.push(makeReference(cap.get()));
116 selectPath(path, true);
120 typedef std::vector<scene::Instance*> InstanceVector;
122 class PatchStoreInstance
124 InstanceVector& m_instances;
126 PatchStoreInstance(InstanceVector& instances) : m_instances(instances)
129 void operator()(PatchInstance& patch) const
131 m_instances.push_back(&patch);
138 PATCHCAP_INVERTED_BEVEL,
139 PATCHCAP_INVERTED_ENDCAP,
143 EMessageBoxReturn DoCapDlg(ECapDialog *type);
145 void Scene_PatchDoCap_Selected(scene::Graph& graph, const char* shader)
149 if(DoCapDlg(&nType) == eIDOK)
154 case PATCHCAP_INVERTED_BEVEL:
160 case PATCHCAP_INVERTED_ENDCAP:
163 case PATCHCAP_ENDCAP:
166 case PATCHCAP_CYLINDER:
167 eType = eCapCylinder;
170 ERROR_MESSAGE("invalid patch cap type");
174 InstanceVector instances;
175 Scene_forEachVisibleSelectedPatchInstance(PatchStoreInstance(instances));
176 for(InstanceVector::const_iterator i = instances.begin(); i != instances.end(); ++i)
178 Patch_makeCaps(* Node_getPatch((*i)->path().top()), *(*i), eType, shader);
183 Patch* Scene_GetUltimateSelectedVisiblePatch()
185 if(GlobalSelectionSystem().countSelected() != 0)
187 scene::Node& node = GlobalSelectionSystem().ultimateSelected().path().top();
190 return Node_getPatch(node);
197 class PatchCapTexture
200 void operator()(Patch& patch) const
202 patch.ProjectTexture(Patch::m_CycleCapIndex);
206 void Scene_PatchCapTexture_Selected(scene::Graph& graph)
208 Scene_forEachVisibleSelectedPatch(PatchCapTexture());
209 Patch::m_CycleCapIndex = (Patch::m_CycleCapIndex == 0) ? 1 : (Patch::m_CycleCapIndex == 1) ? 2 : 0;
213 class PatchFlipTexture
217 PatchFlipTexture(int axis) : m_axis(axis)
220 void operator()(Patch& patch) const
222 patch.FlipTexture(m_axis);
226 void Scene_PatchFlipTexture_Selected(scene::Graph& graph, int axis)
228 Scene_forEachVisibleSelectedPatch(PatchFlipTexture(axis));
231 class PatchNaturalTexture
234 void operator()(Patch& patch) const
236 patch.NaturalTexture();
240 void Scene_PatchNaturalTexture_Selected(scene::Graph& graph)
242 Scene_forEachVisibleSelectedPatch(PatchNaturalTexture());
247 class PatchInsertRemove
249 bool m_insert, m_column, m_first;
251 PatchInsertRemove(bool insert, bool column, bool first) : m_insert(insert), m_column(column), m_first(first)
254 void operator()(Patch& patch) const
256 patch.InsertRemove(m_insert, m_column, m_first);
260 void Scene_PatchInsertRemove_Selected(scene::Graph& graph, bool bInsert, bool bColumn, bool bFirst)
262 Scene_forEachVisibleSelectedPatch(PatchInsertRemove(bInsert, bColumn, bFirst));
265 class PatchInvertMatrix
268 void operator()(Patch& patch) const
270 patch.InvertMatrix();
274 void Scene_PatchInvert_Selected(scene::Graph& graph)
276 Scene_forEachVisibleSelectedPatch(PatchInvertMatrix());
279 class PatchRedisperse
281 EMatrixMajor m_major;
283 PatchRedisperse(EMatrixMajor major) : m_major(major)
286 void operator()(Patch& patch) const
288 patch.Redisperse(m_major);
292 void Scene_PatchRedisperse_Selected(scene::Graph& graph, EMatrixMajor major)
294 Scene_forEachVisibleSelectedPatch(PatchRedisperse(major));
297 class PatchTransposeMatrix
300 void operator()(Patch& patch) const
302 patch.TransposeMatrix();
306 void Scene_PatchTranspose_Selected(scene::Graph& graph)
308 Scene_forEachVisibleSelectedPatch(PatchTransposeMatrix());
315 PatchSetShader(const char* name)
319 void operator()(Patch& patch) const
321 patch.SetShader(m_name);
325 void Scene_PatchSetShader_Selected(scene::Graph& graph, const char* name)
327 Scene_forEachVisibleSelectedPatch(PatchSetShader(name));
331 void Scene_PatchGetShader_Selected(scene::Graph& graph, CopiedString& name)
333 Patch* patch = Scene_GetUltimateSelectedVisiblePatch();
336 name = patch->GetShader();
340 class PatchSelectByShader
344 inline PatchSelectByShader(const char* name)
348 void operator()(PatchInstance& patch) const
350 if(shader_equal(patch.getPatch().GetShader(), m_name))
352 patch.setSelected(true);
357 void Scene_PatchSelectByShader(scene::Graph& graph, const char* name)
359 Scene_forEachVisiblePatchInstance(PatchSelectByShader(name));
363 class PatchFindReplaceShader
366 const char* m_replace;
368 PatchFindReplaceShader(const char* find, const char* replace) : m_find(find), m_replace(replace)
371 void operator()(Patch& patch) const
373 if(shader_equal(patch.GetShader(), m_find))
375 patch.SetShader(m_replace);
380 void Scene_PatchFindReplaceShader(scene::Graph& graph, const char* find, const char* replace)
382 Scene_forEachVisiblePatch(PatchFindReplaceShader(find, replace));
385 void Scene_PatchFindReplaceShader_Selected(scene::Graph& graph, const char* find, const char* replace)
387 Scene_forEachVisibleSelectedPatch(PatchFindReplaceShader(find, replace));
391 AABB PatchCreator_getBounds()
393 AABB aabb(aabb_for_minmax(Select_getWorkZone().d_work_min, Select_getWorkZone().d_work_max));
395 float gridSize = GetGridSize();
397 if(aabb.extents[0] == 0)
399 aabb.extents[0] = gridSize;
401 if(aabb.extents[1] == 0)
403 aabb.extents[1] = gridSize;
405 if(aabb.extents[2] == 0)
407 aabb.extents[2] = gridSize;
414 return AABB(Vector3(0, 0, 0), Vector3(64, 64, 64));
417 void Patch_Cylinder()
419 UndoableCommand undo("patchCreateCylinder");
421 Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eCylinder, GlobalXYWnd_getCurrentViewType());
424 void Patch_DenseCylinder()
426 UndoableCommand undo("patchCreateDenseCylinder");
428 Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eDenseCylinder, GlobalXYWnd_getCurrentViewType());
431 void Patch_VeryDenseCylinder()
433 UndoableCommand undo("patchCreateVeryDenseCylinder");
435 Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eVeryDenseCylinder, GlobalXYWnd_getCurrentViewType());
438 void Patch_SquareCylinder()
440 UndoableCommand undo("patchCreateSquareCylinder");
442 Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eSqCylinder, GlobalXYWnd_getCurrentViewType());
447 UndoableCommand undo("patchCreateCaps");
449 Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eEndCap, GlobalXYWnd_getCurrentViewType());
454 UndoableCommand undo("patchCreateBevel");
456 Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eBevel, GlobalXYWnd_getCurrentViewType());
459 void Patch_SquareBevel()
463 void Patch_SquareEndcap()
469 UndoableCommand undo("patchCreateCone");
471 Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), eCone, GlobalXYWnd_getCurrentViewType());
474 void DoNewPatchDlg();
478 UndoableCommand undo("patchCreatePlane");
483 void Patch_InsertInsertColumn()
485 UndoableCommand undo("patchInsertColumns");
487 Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), true, true, false);
490 void Patch_InsertAddColumn()
492 UndoableCommand undo("patchAddColumns");
494 Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), true, true, true);
497 void Patch_InsertInsertRow()
499 UndoableCommand undo("patchInsertRows");
501 Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), true, false, false);
504 void Patch_InsertAddRow()
506 UndoableCommand undo("patchAddRows");
508 Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), true, false, true);
511 void Patch_DeleteFirstColumn()
513 UndoableCommand undo("patchDeleteFirstColumns");
515 Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), false, true, true);
518 void Patch_DeleteLastColumn()
520 UndoableCommand undo("patchDeleteLastColumns");
522 Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), false, true, false);
525 void Patch_DeleteFirstRow()
527 UndoableCommand undo("patchDeleteFirstRows");
529 Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), false, false, true);
532 void Patch_DeleteLastRow()
534 UndoableCommand undo("patchDeleteLastRows");
536 Scene_PatchInsertRemove_Selected(GlobalSceneGraph(), false, false, false);
541 UndoableCommand undo("patchInvert");
543 Scene_PatchInvert_Selected(GlobalSceneGraph());
546 void Patch_RedisperseRows()
548 UndoableCommand undo("patchRedisperseRows");
550 Scene_PatchRedisperse_Selected(GlobalSceneGraph(), COL);
553 void Patch_RedisperseCols()
555 UndoableCommand undo("patchRedisperseColumns");
557 Scene_PatchRedisperse_Selected(GlobalSceneGraph(), COL);
560 void Patch_Transpose()
562 UndoableCommand undo("patchTranspose");
564 Scene_PatchTranspose_Selected(GlobalSceneGraph());
569 // FIXME: add support for patch cap creation
570 // Patch_CapCurrent();
571 UndoableCommand undo("patchCreateCaps");
573 Scene_PatchDoCap_Selected(GlobalSceneGraph(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()));
576 void Patch_CycleProjection()
578 UndoableCommand undo("patchCycleUVProjectionAxis");
580 Scene_PatchCapTexture_Selected(GlobalSceneGraph());
584 void Patch_OverlayOn()
589 void Patch_OverlayOff()
593 void Patch_FlipTextureX()
595 UndoableCommand undo("patchFlipTextureU");
597 Scene_PatchFlipTexture_Selected(GlobalSceneGraph(), 0);
600 void Patch_FlipTextureY()
602 UndoableCommand undo("patchFlipTextureV");
604 Scene_PatchFlipTexture_Selected(GlobalSceneGraph(), 1);
607 void Patch_NaturalTexture()
609 UndoableCommand undo("patchNaturalTexture");
611 Scene_PatchNaturalTexture_Selected(GlobalSceneGraph());
620 class filter_patch_all : public PatchFilter
623 bool filter(const Patch& patch) const
629 class filter_patch_shader : public PatchFilter
631 const char* m_shader;
633 filter_patch_shader(const char* shader) : m_shader(shader)
636 bool filter(const Patch& patch) const
638 return shader_equal(patch.GetShader(), m_shader);
642 class filter_patch_flags : public PatchFilter
646 filter_patch_flags(int flags) : m_flags(flags)
649 bool filter(const Patch& patch) const
651 return (patch.getShaderFlags() & m_flags) != 0;
656 filter_patch_all g_filter_patch_all;
657 filter_patch_shader g_filter_patch_clip("textures/common/clip");
658 filter_patch_shader g_filter_patch_weapclip("textures/common/weapclip");
659 filter_patch_flags g_filter_patch_translucent(QER_TRANS);
661 void PatchFilters_construct()
663 add_patch_filter(g_filter_patch_all, EXCLUDE_CURVES);
664 add_patch_filter(g_filter_patch_clip, EXCLUDE_CLIP);
665 add_patch_filter(g_filter_patch_weapclip, EXCLUDE_CLIP);
666 add_patch_filter(g_filter_patch_translucent, EXCLUDE_TRANSLUCENT);
670 #include "preferences.h"
672 void Patch_constructPreferences(PreferencesPage& page)
674 page.appendEntry("Patch Subdivide Threshold", g_PatchSubdivideThreshold);
676 void Patch_constructPage(PreferenceGroup& group)
678 PreferencesPage page(group.createPage("Patches", "Patch Display Preferences"));
679 Patch_constructPreferences(page);
681 void Patch_registerPreferencesPage()
683 PreferencesDialog_addDisplayPage(FreeCaller1<PreferenceGroup&, Patch_constructPage>());
687 #include "preferencesystem.h"
689 void PatchPreferences_construct()
691 GlobalPreferenceSystem().registerPreference("Subdivisions", IntImportStringCaller(g_PatchSubdivideThreshold), IntExportStringCaller(g_PatchSubdivideThreshold));
695 #include "generic/callback.h"
697 void Patch_registerCommands()
699 GlobalCommands_insert("InvertCurveTextureX", FreeCaller<Patch_FlipTextureX>(), Accelerator('I', (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
700 GlobalCommands_insert("InvertCurveTextureY", FreeCaller<Patch_FlipTextureY>(), Accelerator('I', (GdkModifierType)GDK_SHIFT_MASK));
701 GlobalCommands_insert("IncPatchColumn", FreeCaller<Patch_InsertInsertColumn>(), Accelerator(GDK_KP_Add, (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
702 GlobalCommands_insert("IncPatchRow", FreeCaller<Patch_InsertInsertRow>(), Accelerator(GDK_KP_Add, (GdkModifierType)GDK_CONTROL_MASK));
703 GlobalCommands_insert("DecPatchColumn", FreeCaller<Patch_DeleteLastColumn>(), Accelerator(GDK_KP_Subtract, (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
704 GlobalCommands_insert("DecPatchRow", FreeCaller<Patch_DeleteLastRow>(), Accelerator(GDK_KP_Subtract, (GdkModifierType)GDK_CONTROL_MASK));
705 GlobalCommands_insert("NaturalizePatch", FreeCaller<Patch_NaturalTexture>(), Accelerator('N', (GdkModifierType)GDK_CONTROL_MASK));
706 GlobalCommands_insert("PatchCylinder", FreeCaller<Patch_Cylinder>());
707 GlobalCommands_insert("PatchDenseCylinder", FreeCaller<Patch_DenseCylinder>());
708 GlobalCommands_insert("PatchVeryDenseCylinder", FreeCaller<Patch_VeryDenseCylinder>());
709 GlobalCommands_insert("PatchSquareCylinder", FreeCaller<Patch_SquareCylinder>());
710 GlobalCommands_insert("PatchEndCap", FreeCaller<Patch_Endcap>());
711 GlobalCommands_insert("PatchBevel", FreeCaller<Patch_Bevel>());
712 GlobalCommands_insert("PatchSquareBevel", FreeCaller<Patch_SquareBevel>());
713 GlobalCommands_insert("PatchSquareEndcap", FreeCaller<Patch_SquareEndcap>());
714 GlobalCommands_insert("PatchCone", FreeCaller<Patch_Cone>());
715 GlobalCommands_insert("SimplePatchMesh", FreeCaller<Patch_Plane>(), Accelerator('P', (GdkModifierType)GDK_SHIFT_MASK));
716 GlobalCommands_insert("PatchInsertInsertColumn", FreeCaller<Patch_InsertInsertColumn>());
717 GlobalCommands_insert("PatchInsertAddColumn", FreeCaller<Patch_InsertAddColumn>());
718 GlobalCommands_insert("PatchInsertInsertRow", FreeCaller<Patch_InsertInsertRow>());
719 GlobalCommands_insert("PatchInsertAddRow", FreeCaller<Patch_InsertAddRow>());
720 GlobalCommands_insert("PatchDeleteFirstColumn", FreeCaller<Patch_DeleteFirstColumn>());
721 GlobalCommands_insert("PatchDeleteLastColumn", FreeCaller<Patch_DeleteLastColumn>());
722 GlobalCommands_insert("PatchDeleteFirstRow", FreeCaller<Patch_DeleteFirstRow>());
723 GlobalCommands_insert("PatchDeleteLastRow", FreeCaller<Patch_DeleteLastRow>());
724 GlobalCommands_insert("InvertCurve", FreeCaller<Patch_Invert>(), Accelerator('I', (GdkModifierType)GDK_CONTROL_MASK));
725 GlobalCommands_insert("RedisperseRows", FreeCaller<Patch_RedisperseRows>(), Accelerator('E', (GdkModifierType)GDK_CONTROL_MASK));
726 GlobalCommands_insert("RedisperseCols", FreeCaller<Patch_RedisperseCols>(), Accelerator('E', (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
727 GlobalCommands_insert("MatrixTranspose", FreeCaller<Patch_Transpose>(), Accelerator('M', (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
728 GlobalCommands_insert("CapCurrentCurve", FreeCaller<Patch_Cap>(), Accelerator('C', (GdkModifierType)GDK_SHIFT_MASK));
729 GlobalCommands_insert("CycleCapTexturePatch", FreeCaller<Patch_CycleProjection>(), Accelerator('N', (GdkModifierType)(GDK_SHIFT_MASK|GDK_CONTROL_MASK)));
730 GlobalCommands_insert("MakeOverlayPatch", FreeCaller<Patch_OverlayOn>(), Accelerator('Y'));
731 GlobalCommands_insert("ClearPatchOverlays", FreeCaller<Patch_OverlayOff>(), Accelerator('L', (GdkModifierType)GDK_CONTROL_MASK));
734 void Patch_constructToolbar(GtkToolbar* toolbar)
736 toolbar_append_button(toolbar, "Put caps on the current patch (SHIFT + C)", "curve_cap.bmp", "CapCurrentCurve");
739 void Patch_constructMenu(GtkMenu* menu)
741 create_menu_item_with_mnemonic(menu, "Cylinder", "PatchCylinder");
743 GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic (menu, "More Cylinders");
744 if (g_Layout_enableDetachableMenus.m_value)
745 menu_tearoff (menu_in_menu);
746 create_menu_item_with_mnemonic(menu_in_menu, "Dense Cylinder", "PatchDenseCylinder");
747 create_menu_item_with_mnemonic(menu_in_menu, "Very Dense Cylinder", "PatchVeryDenseCylinder");
748 create_menu_item_with_mnemonic(menu_in_menu, "Square Cylinder", "PatchSquareCylinder");
750 menu_separator (menu);
751 create_menu_item_with_mnemonic(menu, "End cap", "PatchEndCap");
752 create_menu_item_with_mnemonic(menu, "Bevel", "PatchBevel");
754 GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic (menu, "More End caps, Bevels");
755 if (g_Layout_enableDetachableMenus.m_value)
756 menu_tearoff (menu_in_menu);
757 create_menu_item_with_mnemonic(menu_in_menu, "Square Endcap", "PatchSquareBevel");
758 create_menu_item_with_mnemonic(menu_in_menu, "Square Bevel", "PatchSquareEndcap");
760 menu_separator (menu);
761 create_menu_item_with_mnemonic(menu, "Cone", "PatchCone");
762 menu_separator (menu);
763 create_menu_item_with_mnemonic(menu, "Simple Patch Mesh...", "SimplePatchMesh");
764 menu_separator (menu);
766 GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic (menu, "Insert");
767 if (g_Layout_enableDetachableMenus.m_value)
768 menu_tearoff (menu_in_menu);
769 create_menu_item_with_mnemonic(menu_in_menu, "Insert (2) Columns", "PatchInsertInsertColumn");
770 create_menu_item_with_mnemonic(menu_in_menu, "Add (2) Columns", "PatchInsertAddColumn");
771 menu_separator (menu_in_menu);
772 create_menu_item_with_mnemonic(menu_in_menu, "Insert (2) Rows", "PatchInsertInsertRow");
773 create_menu_item_with_mnemonic(menu_in_menu, "Add (2) Rows", "PatchInsertAddRow");
776 GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic (menu, "Delete");
777 if (g_Layout_enableDetachableMenus.m_value)
778 menu_tearoff (menu_in_menu);
779 create_menu_item_with_mnemonic(menu_in_menu, "First (2) Columns", "PatchDeleteFirstColumn");
780 create_menu_item_with_mnemonic(menu_in_menu, "Last (2) Columns", "PatchDeleteLastColumn");
781 menu_separator (menu_in_menu);
782 create_menu_item_with_mnemonic(menu_in_menu, "First (2) Rows", "PatchDeleteFirstRow");
783 create_menu_item_with_mnemonic(menu_in_menu, "Last (2) Rows", "PatchDeleteLastRow");
785 menu_separator (menu);
787 GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic (menu, "Matrix");
788 if (g_Layout_enableDetachableMenus.m_value)
789 menu_tearoff (menu_in_menu);
790 create_menu_item_with_mnemonic(menu_in_menu, "Invert", "InvertCurve");
791 GtkMenu* menu_3 = create_sub_menu_with_mnemonic (menu_in_menu, "Re-disperse");
792 if (g_Layout_enableDetachableMenus.m_value)
793 menu_tearoff (menu_3);
794 create_menu_item_with_mnemonic(menu_3, "Rows", "RedisperseRows");
795 create_menu_item_with_mnemonic(menu_3, "Columns", "RedisperseCols");
796 create_menu_item_with_mnemonic(menu_in_menu, "Transpose", "MatrixTranspose");
798 menu_separator (menu);
799 create_menu_item_with_mnemonic(menu, "Cap Selection", "CapCurrentCurve");
800 create_menu_item_with_mnemonic(menu, "Cycle Cap Texture", "CycleCapTexturePatch");
801 menu_separator (menu);
803 GtkMenu* menu_in_menu = create_sub_menu_with_mnemonic (menu, "Overlay");
804 if (g_Layout_enableDetachableMenus.m_value)
805 menu_tearoff (menu_in_menu);
806 create_menu_item_with_mnemonic(menu_in_menu, "Set", "MakeOverlayPatch");
807 create_menu_item_with_mnemonic(menu_in_menu, "Clear", "ClearPatchOverlays");
812 #include <gtk/gtkbox.h>
813 #include <gtk/gtktable.h>
814 #include <gtk/gtktogglebutton.h>
815 #include <gtk/gtkradiobutton.h>
816 #include <gtk/gtkcombobox.h>
817 #include <gtk/gtklabel.h>
818 #include "gtkutil/dialog.h"
819 #include "gtkutil/widget.h"
827 GtkWindow* window = create_dialog_window(MainFrame_getWindow(), "Patch density", G_CALLBACK(dialog_delete_callback), &dialog);
829 GtkAccelGroup* accel = gtk_accel_group_new();
830 gtk_window_add_accel_group(window, accel);
833 GtkHBox* hbox = create_dialog_hbox(4, 4);
834 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
836 GtkTable* table = create_dialog_table(2, 2, 4, 4);
837 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(table), TRUE, TRUE, 0);
839 GtkLabel* label = GTK_LABEL(gtk_label_new("Width:"));
840 gtk_widget_show(GTK_WIDGET(label));
841 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 0, 1,
842 (GtkAttachOptions) (GTK_FILL),
843 (GtkAttachOptions) (0), 0, 0);
844 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
847 GtkLabel* label = GTK_LABEL(gtk_label_new("Height:"));
848 gtk_widget_show(GTK_WIDGET(label));
849 gtk_table_attach(table, GTK_WIDGET(label), 0, 1, 1, 2,
850 (GtkAttachOptions) (GTK_FILL),
851 (GtkAttachOptions) (0), 0, 0);
852 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
856 GtkComboBox* combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
857 gtk_combo_box_append_text(combo, "3");
858 gtk_combo_box_append_text(combo, "5");
859 gtk_combo_box_append_text(combo, "7");
860 gtk_combo_box_append_text(combo, "9");
861 gtk_combo_box_append_text(combo, "11");
862 gtk_combo_box_append_text(combo, "13");
863 gtk_combo_box_append_text(combo, "15");
864 gtk_widget_show(GTK_WIDGET(combo));
865 gtk_table_attach(table, GTK_WIDGET(combo), 1, 2, 0, 1,
866 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
867 (GtkAttachOptions) (0), 0, 0);
872 GtkComboBox* combo = GTK_COMBO_BOX(gtk_combo_box_new_text());
873 gtk_combo_box_append_text(combo, "3");
874 gtk_combo_box_append_text(combo, "5");
875 gtk_combo_box_append_text(combo, "7");
876 gtk_combo_box_append_text(combo, "9");
877 gtk_combo_box_append_text(combo, "11");
878 gtk_combo_box_append_text(combo, "13");
879 gtk_combo_box_append_text(combo, "15");
880 gtk_widget_show(GTK_WIDGET(combo));
881 gtk_table_attach(table, GTK_WIDGET(combo), 1, 2, 1, 2,
882 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
883 (GtkAttachOptions) (0), 0, 0);
890 GtkVBox* vbox = create_dialog_vbox(4);
891 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), TRUE, TRUE, 0);
893 GtkButton* button = create_dialog_button("OK", G_CALLBACK(dialog_button_ok), &dialog);
894 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
895 widget_make_default(GTK_WIDGET(button));
896 gtk_widget_grab_focus(GTK_WIDGET(button));
897 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Return, (GdkModifierType)0, (GtkAccelFlags)0);
900 GtkButton* button = create_dialog_button("Cancel", G_CALLBACK(dialog_button_cancel), &dialog);
901 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
902 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel, GDK_Escape, (GdkModifierType)0, (GtkAccelFlags)0);
908 gtk_combo_box_set_active(width, 0);
909 gtk_combo_box_set_active(height, 0);
911 if(modal_dialog_show(window, dialog) == eIDOK)
913 int w = gtk_combo_box_get_active(width) * 2 + 3;
914 int h = gtk_combo_box_get_active(height) * 2 + 3;
916 Scene_PatchConstructPrefab(GlobalSceneGraph(), PatchCreator_getBounds(), TextureBrowser_GetSelectedShader(GlobalTextureBrowser()), ePlane, GlobalXYWnd_getCurrentViewType(), w, h);
919 gtk_widget_destroy(GTK_WIDGET(window));
925 EMessageBoxReturn DoCapDlg(ECapDialog* type)
928 ModalDialogButton ok_button(dialog, eIDOK);
929 ModalDialogButton cancel_button(dialog, eIDCANCEL);
936 GtkWindow* window = create_modal_dialog_window(MainFrame_getWindow(), "Cap", dialog);
938 GtkAccelGroup *accel_group = gtk_accel_group_new();
939 gtk_window_add_accel_group(window, accel_group);
942 GtkHBox* hbox = create_dialog_hbox(4, 4);
943 gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(hbox));
946 // Gef: Added a vbox to contain the toggle buttons
947 GtkVBox* radio_vbox = create_dialog_vbox(4);
948 gtk_container_add(GTK_CONTAINER(hbox), GTK_WIDGET(radio_vbox));
951 GtkTable* table = GTK_TABLE(gtk_table_new(5, 2, FALSE));
952 gtk_widget_show(GTK_WIDGET(table));
953 gtk_box_pack_start(GTK_BOX(radio_vbox), GTK_WIDGET(table), TRUE, TRUE, 0);
954 gtk_table_set_row_spacings(table, 5);
955 gtk_table_set_col_spacings(table, 5);
958 GtkImage* image = new_local_image("cap_bevel.bmp");
959 gtk_widget_show(GTK_WIDGET(image));
960 gtk_table_attach(table, GTK_WIDGET(image), 0, 1, 0, 1,
961 (GtkAttachOptions) (GTK_FILL),
962 (GtkAttachOptions) (0), 0, 0);
965 GtkImage* image = new_local_image("cap_endcap.bmp");
966 gtk_widget_show(GTK_WIDGET(image));
967 gtk_table_attach(table, GTK_WIDGET(image), 0, 1, 1, 2,
968 (GtkAttachOptions) (GTK_FILL),
969 (GtkAttachOptions) (0), 0, 0);
972 GtkImage* image = new_local_image("cap_ibevel.bmp");
973 gtk_widget_show(GTK_WIDGET(image));
974 gtk_table_attach(table, GTK_WIDGET(image), 0, 1, 2, 3,
975 (GtkAttachOptions) (GTK_FILL),
976 (GtkAttachOptions) (0), 0, 0);
979 GtkImage* image = new_local_image("cap_iendcap.bmp");
980 gtk_widget_show(GTK_WIDGET(image));
981 gtk_table_attach(table, GTK_WIDGET(image), 0, 1, 3, 4,
982 (GtkAttachOptions) (GTK_FILL),
983 (GtkAttachOptions) (0), 0, 0);
986 GtkImage* image = new_local_image("cap_cylinder.bmp");
987 gtk_widget_show(GTK_WIDGET(image));
988 gtk_table_attach(table, GTK_WIDGET(image), 0, 1, 4, 5,
989 (GtkAttachOptions) (GTK_FILL),
990 (GtkAttachOptions) (0), 0, 0);
995 GtkWidget* button = gtk_radio_button_new_with_label (group, "Bevel");
996 gtk_widget_show (button);
997 gtk_table_attach(table, button, 1, 2, 0, 1,
998 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
999 (GtkAttachOptions) (0), 0, 0);
1000 group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1005 GtkWidget* button = gtk_radio_button_new_with_label (group, "Endcap");
1006 gtk_widget_show (button);
1007 gtk_table_attach(table, button, 1, 2, 1, 2,
1008 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
1009 (GtkAttachOptions) (0), 0, 0);
1010 group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1015 GtkWidget* button = gtk_radio_button_new_with_label (group, "Inverted Bevel");
1016 gtk_widget_show (button);
1017 gtk_table_attach(table, button, 1, 2, 2, 3,
1018 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
1019 (GtkAttachOptions) (0), 0, 0);
1020 group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1025 GtkWidget* button = gtk_radio_button_new_with_label (group, "Inverted Endcap");
1026 gtk_widget_show (button);
1027 gtk_table_attach(table, button, 1, 2, 3, 4,
1028 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
1029 (GtkAttachOptions) (0), 0, 0);
1030 group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1035 GtkWidget* button = gtk_radio_button_new_with_label (group, "Cylinder");
1036 gtk_widget_show (button);
1037 gtk_table_attach(table, button, 1, 2, 4, 5,
1038 (GtkAttachOptions) (GTK_FILL | GTK_EXPAND),
1039 (GtkAttachOptions) (0), 0, 0);
1040 group = gtk_radio_button_group (GTK_RADIO_BUTTON (button));
1048 GtkVBox* vbox = create_dialog_vbox(4);
1049 gtk_box_pack_start(GTK_BOX(hbox), GTK_WIDGET(vbox), FALSE, FALSE, 0);
1051 GtkButton* button = create_modal_dialog_button("OK", ok_button);
1052 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
1053 widget_make_default(GTK_WIDGET(button));
1054 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Return, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
1057 GtkButton* button = create_modal_dialog_button("Cancel", cancel_button);
1058 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(button), FALSE, FALSE, 0);
1059 gtk_widget_add_accelerator(GTK_WIDGET(button), "clicked", accel_group, GDK_Escape, (GdkModifierType)0, GTK_ACCEL_VISIBLE);
1064 // Initialize dialog
1065 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bevel), TRUE);
1067 EMessageBoxReturn ret = modal_dialog_show(window, dialog);
1070 if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (bevel)))
1071 *type = PATCHCAP_BEVEL;
1072 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(endcap)))
1073 *type = PATCHCAP_ENDCAP;
1074 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ibevel)))
1075 *type = PATCHCAP_INVERTED_BEVEL;
1076 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(iendcap)))
1077 *type = PATCHCAP_INVERTED_ENDCAP;
1078 else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(cylinder)))
1079 *type = PATCHCAP_CYLINDER;
1082 gtk_widget_destroy(GTK_WIDGET(window));