1 #pragma once 2 3 #include <map> 4 #include "iselection.h" 5 #include "iregistry.h" 6 #include "gtkutil/RegistryConnector.h" 7 #include "gtkutil/TextPanel.h" 8 #include "gtkutil/event/SingleIdleCallback.h" 9 #include "../../ui/common/ShaderChooser.h" 10 #include "../../brush/ContentsFlagsValue.h" 11 #include "../sidebar.h" 12 13 // Forward declarations to decrease compile times 14 typedef struct _GtkSpinButton GtkSpinButton; 15 typedef struct _GtkEditable GtkEditable; 16 typedef struct _GtkTable GtkTable; 17 typedef struct _GtkWidget GtkWidget; 18 typedef struct _GtkCheckButton GtkCheckButton; 19 namespace gtkutil { 20 class ControlButton; 21 } 22 23 namespace ui { 24 25 class SurfaceInspector: public RegistryKeyObserver, 26 public SelectionSystem::Observer, 27 public ShaderChooser::ChooserClient, 28 public SidebarComponent, 29 public gtkutil::SingleIdleCallback { 30 // The actual dialog window 31 GtkWidget* _dialogVBox; 32 33 typedef gtkutil::ControlButton* ControlButtonPtr; 34 35 struct ManipulatorRow 36 { 37 GtkWidget* hbox; 38 GtkWidget* label; 39 GtkWidget* value; 40 gulong valueChangedHandler; 41 ControlButtonPtr smaller; 42 ControlButtonPtr larger; 43 GtkWidget* step; 44 GtkWidget* steplabel; 45 }; 46 47 // This are the named manipulator rows (shift, scale, rotation, etc) 48 typedef std::map<std::string, ManipulatorRow> ManipulatorMap; 49 ManipulatorMap _manipulators; 50 51 GtkCheckButton* _surfaceFlags[32]; 52 GtkCheckButton* _contentFlags[32]; 53 54 // The "shader" entry field 55 GtkWidget* _shaderEntry; 56 GtkWidget* _selectShaderButton; 57 58 ContentsFlagsValue _selectedFlags; 59 60 struct FitTextureWidgets 61 { 62 GtkWidget* hbox; 63 GtkObject* widthAdj; 64 GtkObject* heightAdj; 65 GtkWidget* width; 66 GtkWidget* height; 67 GtkWidget* button; 68 GtkWidget* label; 69 } _fitTexture; 70 71 struct FlipTextureWidgets 72 { 73 GtkWidget* hbox; 74 GtkWidget* flipX; 75 GtkWidget* flipY; 76 GtkWidget* label; 77 } _flipTexture; 78 79 struct ApplyTextureWidgets 80 { 81 GtkWidget* hbox; 82 GtkWidget* label; 83 GtkWidget* natural; 84 } _applyTex; 85 86 GtkWidget* _defaultTexScale; 87 GtkWidget* _texLockButton; 88 89 gtkutil::TextPanel _valueEntryWidget; 90 // if more than one of the selected objects has a value set, this is inconsistent and we can't know which we should take 91 // So in this case we just don't change the old value until we explicitly edit the value entry field 92 bool _valueInconsistent; 93 94 // To avoid key changed loopbacks when the registry is updated 95 bool _callbackActive; 96 97 // This member takes care of importing/exporting Registry 98 // key values from and to widgets 99 gtkutil::RegistryConnector _connector; 100 101 // A reference to the SelectionInfo structure (with the counters) 102 const SelectionInfo& _selectionInfo; 103 104 public: 105 106 // Constructor 107 SurfaceInspector (); 108 109 ~SurfaceInspector (); 110 111 /** Connect and updates the widgets 112 */ 113 void init (); 114 115 /** greebo: Some sort of "soft" destructor that de-registers 116 * this class from the SelectionSystem, etc. 117 */ 118 void shutdown (); 119 120 /** greebo: Contains the static instance of this dialog. 121 * Constructs the instance and calls toggle() when invoked. 122 */ 123 static SurfaceInspector& Instance (); 124 125 /** greebo: Gets called when the default texscale registry key changes 126 */ 127 void keyChanged (const std::string&, const std::string&); 128 129 /** greebo: SelectionSystem::Observer implementation. Gets called by 130 * the SelectionSystem upon selection change to allow updating of the 131 * texture properties. 132 */ 133 void selectionChanged (scene::Instance& instance, bool isComponent); 134 135 // Updates the widgets 136 void queueUpdate (); 137 138 /** greebo: Gets called upon shader selection change (during ShaderChooser display) 139 */ 140 void shaderSelectionChanged (const std::string& shaderName); 141 142 GtkWidget* getWidget () const; 143 144 const std::string getTitle() const; 145 146 void switchPage (int pageIndex); 147 148 // Executes the fit command for the selection 149 void fitTexture (); 150 151 // Idle callback, used for deferred updates 152 void onGtkIdle(); 153 private: 154 // Updates the widgets (this is private, use queueUpdate() instead) 155 void update(); 156 157 /** greebo: Creates a row consisting of label, value entry, 158 * two arrow buttons and a step entry field. 159 * 160 * @table: the GtkTable the row should be packed into. 161 * @row: the target row number (first table row = 0). 162 * 163 * @returns: the structure containing the widget pointers. 164 */ 165 ManipulatorRow createManipulatorRow (const std::string& label, GtkTable* table, int row, bool vertical); 166 167 const std::string& getContentFlagName (std::size_t bit) const; 168 169 const std::string& getSurfaceFlagName (std::size_t bit) const; 170 171 // Adds all the widgets to the window 172 void populateWindow (); 173 174 // Connect IEvents to the widgets 175 void connectEvents (); 176 177 // Updates the content- and surfaceflags 178 void updateFlags (); 179 180 // Updates the texture shift/scale/rotation fields 181 void updateTexDef (); 182 183 // The counter-part of updateTexDef() - emits the TexCoords to the selection 184 void emitTexDef (); 185 186 // Applies the entered shader to the current selection 187 void emitShader (); 188 189 void updateFlagButtons (); 190 191 void setFlagsForSelected (const ContentsFlagsValue& flags); 192 193 // Saves the connected widget content into the registry 194 void saveToRegistry (); 195 196 // The callback when the "select shader" button is pressed, opens the ShaderChooser dialog 197 static void onShaderSelect (GtkWidget* button, SurfaceInspector* self); 198 199 // The callback for the delete event (toggles the visibility) 200 static gboolean onDelete (GtkWidget* widget, GdkEvent* event, SurfaceInspector* self); 201 202 // Gets called when the step entry fields get changed 203 static void onStepChanged (GtkEditable* editable, SurfaceInspector* self); 204 205 // Gets called when the value entry field is changed (shift/scale/rotation) - emits the texcoords 206 static gboolean onDefaultScaleChanged (GtkSpinButton* spinbutton, SurfaceInspector* self); 207 208 // The callback for the Fit Texture button 209 static gboolean onFit (GtkWidget* widget, SurfaceInspector* self); 210 static gboolean doUpdate (GtkWidget* widget, SurfaceInspector* self); 211 212 // the callback for the surface flag value 213 static void onValueToggle (GtkWidget *widget, SurfaceInspector *self); 214 215 // the callback for the flags toggle 216 static void onApplyFlagsToggle (GtkWidget *activatedWidget, SurfaceInspector *self); 217 218 // The keypress handler for catching the Enter key when in the shader entry field 219 static gboolean onKeyPress (GtkWidget* entry, GdkEventKey* event, SurfaceInspector* self); 220 221 // The keypress handler for catching the Enter key when in the value entry fields 222 static gboolean onValueKeyPress (GtkWidget* entry, GdkEventKey* event, SurfaceInspector* self); 223 224 // the callback for changing the surface property value like e.g. the light intensity for surface lights 225 static gboolean onValueEntryKeyPress (GtkWindow* window, GdkEventKey* event, SurfaceInspector* self); 226 227 // the callback that changes the value when we focus-out the entry field 228 static gboolean onValueEntryFocusOut (GtkWidget* widget, GdkEventKey* event, SurfaceInspector* self); 229 }; // class SurfaceInspector 230 231 } // namespace ui 232