diff --git a/direct/src/gui/DirectGui.py b/direct/src/gui/DirectGui.py index 20713845ce..5bf2c48a07 100644 --- a/direct/src/gui/DirectGui.py +++ b/direct/src/gui/DirectGui.py @@ -17,5 +17,6 @@ from DirectLabel import * from DirectScrolledList import * from DirectDialog import * from DirectWaitBar import * +from DirectSliderBar import * from DirectCheckButton import * from DirectOptionMenu import * diff --git a/direct/src/gui/DirectGuiBase.py b/direct/src/gui/DirectGuiBase.py index 0bdb3ec99c..c8c738c871 100644 --- a/direct/src/gui/DirectGuiBase.py +++ b/direct/src/gui/DirectGuiBase.py @@ -865,6 +865,7 @@ class DirectGuiWidget(DirectGuiBase, NodePath): if self['frameSize']: # Use user specified bounds self.bounds = self['frameSize'] + #print "%s bounds = %s" % (self.getName(),self.bounds) else: if fClearFrame and (frameType != PGFrameStyle.TNone): self.frameStyle[0].setType(PGFrameStyle.TNone) diff --git a/direct/src/gui/DirectSliderBar.py b/direct/src/gui/DirectSliderBar.py new file mode 100755 index 0000000000..01461b000a --- /dev/null +++ b/direct/src/gui/DirectSliderBar.py @@ -0,0 +1,144 @@ +from DirectButton import * +from DirectFrame import * + +""" +import DirectSliderBar +d = DirectSliderBar(borderWidth=(0,0)) + +""" + +class DirectSliderButton(DirectButton): + def __init__(self, parent = None, **kw): + optiondefs = ( + # Define type of DirectGuiWidget + ('pgFunc', PGSliderButton, None), + ) + # Merge keyword options with default options + self.defineoptions(kw, optiondefs) + # Initialize superclasses + DirectButton.__init__(self,parent) + # Call option initialization functions + self.initialiseoptions(DirectSliderButton) + +class DirectSliderBar(DirectFrame): + """ + DirectEntry(parent) - Create a DirectGuiWidget which responds + to keyboard buttons + """ + def __init__(self, parent = None, **kw): + # Inherits from DirectFrame + # A Direct Frame can have: + # - A background texture (pass in path to image, or Texture Card) + # - A midground geometry item (pass in geometry) + # - A foreground text Node (pass in text string or Onscreen Text) + optiondefs = ( + # Define type of DirectGuiWidget + ('pgFunc', PGSliderBar, None), + ('width', 10, None), + ('height', 1, None), + ('button', None, None), + ('sliderOnly', 0, self.setSliderOnly), + ('negativeMapping',0, self.setNegativeMapping), + ('range', 100, self.setRange), + ('value', 0, self.setValue), + ('barBorderWidth', (0,0), self.setBarBorderWidth), + ('barColor', (1,0,0,1), self.setBarColor), + ('barRelief', FLAT, self.setBarRelief), + ('active', 0, self.setActive), + ('sortOrder', NO_FADE_SORT_INDEX, None), + # Command to be called on button movement + ('command', None, None), + ('extraArgs', [], None), + ) + if kw.has_key('text'): + textoptiondefs = ( + ('text_pos', (0,-0.025), None), + ('text_scale', 0.1, None) + ) + else: + textoptiondefs = () + # Merge keyword options with default options + self.defineoptions(kw, optiondefs + textoptiondefs) + # Initialize superclasses + DirectFrame.__init__(self, parent) + self.barStyle = PGFrameStyle() + # Call option initialization functions + self.initialiseoptions(DirectSliderBar) + + if (self['button'] != None): + self.guiItem.setSliderButton(self['button'], self['button'].guiItem) + + if (self['image'] != None): + self.guiItem.setScale(self['image_scale'][0]) + self.guiItem.setup(self.getWidth(), self.getHeight(), self['range']) + else: + #figure out what is happening????? + #self.guiItem.setState(0) + #self.guiItem.clearStateDef(0) + self.guiItem.setFrame(-3.0, 3.0, -0.25, 0.25) + self.barStyle.setWidth(0.05, 0.05) + self.barStyle.setColor(0.6,0.6,0.6,1) + self.barStyle.setType(PGFrameStyle.TBevelIn) + self.guiItem.setFrameStyle(0, self.barStyle) + self.guiItem.setScale(2) + self.guiItem.setup(6, 0.5, self['range']) + self.guiItem.setValue(self['value']) + if (self['scale'] != None): + self.setScale(self['scale']) + else: + self.setScale(0.1) + + self.guiItem.setActive(1) + + self.barStyle.setColor(0.8,0.8,0.8,1) + self.barStyle.setType(PGFrameStyle.TBevelOut) + self.updateBarStyle() + + if (self['command'] != None): + # Attach command function to slider button movement + self.bind('updated-slider-', self.commandFunc) + + def destroy(self): + del self.barStyle + DirectFrame.destroy(self) + + def setSliderOnly(self): + self.guiItem.setSliderOnly(self['sliderOnly']) + + def setNegativeMapping(self): + self.guiItem.setNegativeMapping(self['negativeMapping']) + + def setRange(self): + self.guiItem.setRange(self['range']) + + def setValue(self): + self.guiItem.setValue(self['value']) + + def getPercent(self): + return self.guiItem.getPercent() + + def updateBarStyle(self): + if not self.fInit: + self.guiItem.setBarStyle(self.barStyle) + + def setBarRelief(self): + self.barStyle.setType(self['barRelief']) + self.updateBarStyle() + + def setBarBorderWidth(self): + self.barStyle.setWidth(*self['barBorderWidth']) + self.updateBarStyle() + + def setBarColor(self): + color = self['barColor'] + self.barStyle.setColor(color[0], color[1], color[2], color[3]) + self.updateBarStyle() + + def setActive(self): + self.guiItem.setActive(self['active']) + + def commandFunc(self): + if self['command']: + # Pass any extra args to command + apply(self['command'], self['extraArgs']) + diff --git a/panda/src/pgui/pgSliderBar.I b/panda/src/pgui/pgSliderBar.I index 9d94d68969..536e275709 100755 --- a/panda/src/pgui/pgSliderBar.I +++ b/panda/src/pgui/pgSliderBar.I @@ -47,7 +47,10 @@ get_range() const { INLINE void PGSliderBar:: set_value(float value) { _value = value; + _mapped_value = _negative_mapping ? (_value*0.5 + 0.5) : _value; + _update_position = _width * (2*_mapped_value - 1); _bar_state = -1; + _update_slider = true; } //////////////////////////////////////////////////////////////////// @@ -60,6 +63,28 @@ get_value() const { return _value; } +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar:get_mapped_value +// Access: Published +// Description: Returns the _mapped_value which is caluclated from +// _value with negative_mapping bool +//////////////////////////////////////////////////////////////////// +INLINE float PGSliderBar:: +get_mapped_value() const { + return _mapped_value; +} + +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar::get_update_position +// Access: Published +// Description: Returns the _update_position which is caluclated from +// _mapped_value with width formula +//////////////////////////////////////////////////////////////////// +INLINE float PGSliderBar:: +get_update_position() const { + return _update_position; +} + //////////////////////////////////////////////////////////////////// // Function: PGSliderBar::set_speed // Access: Published @@ -81,13 +106,66 @@ get_speed() const { } //////////////////////////////////////////////////////////////////// -// Function: PGSliderBar::get_percent +// Function: PGSliderBar::set_scale // Access: Published -// Description: Returns the percentage complete. +// Description: Sets the scale of the traugh image +//////////////////////////////////////////////////////////////////// +INLINE void PGSliderBar:: +set_scale(float scale) { + _scale = scale/10; +} + +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar::get_scale +// Access: Published +// Description: Returns the scale set on the traugh image //////////////////////////////////////////////////////////////////// INLINE float PGSliderBar:: -get_percent() const { - return (_value / _range) * 100.0f; +get_scale() const { + return _scale; +} + +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar::set_slider_only +// Access: Published +// Description: Sets _slider_only. True:only slider button desired. +// No left or right button to control slider needed. +// Else, the left and right slider buttons are shown. +//////////////////////////////////////////////////////////////////// +INLINE void PGSliderBar:: +set_slider_only(bool value) { + _slider_only = value; +} + +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar::get_slider_only +// Access: Published +// Description: Returns what type of slider option set +//////////////////////////////////////////////////////////////////// +INLINE bool PGSliderBar:: +get_slider_only() const { + return _slider_only; +} + +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar::set_negative_mapping +// Access: Published +// Description: Sets _negative_mapping. True: slider will receive +// _value from -1 to +1 else, _value from 0 to + 1 +//////////////////////////////////////////////////////////////////// +INLINE void PGSliderBar:: +set_negative_mapping(bool value) { + _negative_mapping = value; +} + +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar::get_negative_mapping +// Access: Published +// Description: Returns what type of value range option set +//////////////////////////////////////////////////////////////////// +INLINE bool PGSliderBar:: +get_negative_mapping() const { + return _negative_mapping; } //////////////////////////////////////////////////////////////////// @@ -113,6 +191,17 @@ get_bar_style() const { return _bar_style; } +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar::get_click_event +// Access: Published +// Description: Returns the event name that will be thrown when the +// slider button is moved +//////////////////////////////////////////////////////////////////// +INLINE string PGSliderBar:: +get_click_event() const { + return "updated-slider-" + get_id(); +} + //////////////////////////////////////////////////////////////////// // Function: PGSliderBar::get_slider_button // Access: Published @@ -124,6 +213,18 @@ get_slider_button() const { return _slider_button; } +//////////////////////////////////////////////////////////////////// +// Function: PGSliderBar::set_slider_button +// Access: Published +// Description: sets slider button that is drawn on the +// SliderBar to move the slider left or right +//////////////////////////////////////////////////////////////////// +INLINE void PGSliderBar:: +set_slider_button(NodePath &np, PGSliderButton *button) { + _slider_button = np; + _slider = button; +} + //////////////////////////////////////////////////////////////////// // Function: PGSliderBar::get_left_button // Access: Published diff --git a/panda/src/pgui/pgSliderBar.cxx b/panda/src/pgui/pgSliderBar.cxx index 37bd9828bd..9c84e2817b 100755 --- a/panda/src/pgui/pgSliderBar.cxx +++ b/panda/src/pgui/pgSliderBar.cxx @@ -31,15 +31,24 @@ TypeHandle PGSliderBar::_type_handle; PGSliderBar:: PGSliderBar(const string &name) : PGItem(name), - _slider("slider"), + // _slider("slider"), _left("left"), _right("right") { + _slider = NULL; _range = 100.0; + // _value is a range from (-1 to +1) that represents slider _value = 0.0; + // _mapped_value is a mapping of (-1<->1) into (0<->1) + _mapped_value = 0.5*_value + 0.5; + // _update_position is mapping of _mapped_value wrt slider width + _update_position = 0.0; //will be set when _width is defined _speed = 0.05; + _scale = 0.05; _bar_state = -1; _update_slider = false; + _slider_only = true; + _negative_mapping = false; } //////////////////////////////////////////////////////////////////// @@ -61,11 +70,12 @@ PGSliderBar(const PGSliderBar ©) : PGItem(copy), _range(copy._range), _value(copy._value), - _slider(copy._slider), + // _slider(copy._slider), _left(copy._left), _right(copy._right) { _bar_state = -1; + _slider = NULL; } //////////////////////////////////////////////////////////////////// @@ -128,40 +138,49 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { //////////////////////////////////////////////////////////////////// void PGSliderBar:: setup(float width, float height, float range) { - set_state(0); - clear_state_def(0); + //set_state(0); + //clear_state_def(0); _width = 0.5 * width; // quick reference to find the left and right max points - set_frame(-0.5f * width, 0.5f * width, -0.5f * height, 0.5f * height); + //set_frame(-0.5f * width, 0.5f * width, -0.5f * height, 0.5f * height); + set_range(range); NodePath current = NodePath(this); - _slider_button = current.attach_new_node(&_slider); - _slider.set_slider_bar(this); - _left_button = current.attach_new_node(&_left); - _left.set_slider_bar(this); - _right_button = current.attach_new_node(&_right); - _right.set_slider_bar(this); - _slider.setup(_slider.get_name()); - _slider.set_drag_n_drop(true); - _left.setup(_left.get_name()); - _right.setup(_right.get_name()); - _slider_button.set_scale(0.5); - _slider_button.set_pos(0, 0, -0.25); - _left_button.set_scale(0.5); - _left_button.set_pos(-6.0, 0, -0.25); - _right_button.set_scale(0.5); - _right_button.set_pos(5.5, 0, -0.25); + if (!_slider) { + _slider = new PGSliderButton("slider"); + _slider_button = current.attach_new_node(_slider); + } + + _slider->set_slider_bar(this); + _slider->setup(_slider->get_name()); + _slider->set_drag_n_drop(true); + _slider_button.set_scale(_scale); + _slider_button.set_pos(0, 0, -_scale*0.5); // center it + + // if left or right button to control slider desired, create them + if (!_slider_only) { + _left_button = current.attach_new_node(&_left); + _left.set_slider_bar(this); + _right_button = current.attach_new_node(&_right); + _right.set_slider_bar(this); + _left.setup(_left.get_name()); + _right.setup(_right.get_name()); + _left_button.set_scale(0.5); + _left_button.set_pos(-(_width+1), 0, -0.25); + _right_button.set_scale(0.5); + _right_button.set_pos((_width+0.5), 0, -0.25); + } PGFrameStyle style; style.set_width(0.05f, 0.05f); style.set_color(0.6f, 0.6f, 0.6f, 1.0f); style.set_type(PGFrameStyle::T_bevel_in); - set_frame_style(0, style); + //set_frame_style(0, style); style.set_color(0.8f, 0.8f, 0.8f, 1.0f); style.set_type(PGFrameStyle::T_bevel_out); - set_bar_style(style); + //set_bar_style(style); } //////////////////////////////////////////////////////////////////// @@ -175,28 +194,27 @@ void PGSliderBar:: press(const MouseWatcherParameter ¶m, bool background) { PGItem::press(param, background); //pgui_cat.info() << get_name() << "::" << param << endl; - //pgui_cat.info() << _slider.get_name() << "::" << _slider_button.get_x() << endl; + //pgui_cat.info() << _slider->get_name() << "::press:" << _slider_button.get_x() << endl; // translate the mouse param position into frame space LPoint2f mouse_point = param.get_mouse(); LVector3f result(mouse_point[0], mouse_point[1], 0); result = get_frame_inv_xform().xform_point(result); - //pgui_cat.info() << "mouse_point: " << result << endl; - //_update_slider = true; - //_update_value = result[0]; - _slider_button.set_x(result[0]); + _update_slider = true; + _update_position = result[0]; + //_slider_button.set_x(result[0]); } //////////////////////////////////////////////////////////////////// // Function: PGSliderBar::drag // Access: Public, Virtual // Description: This is a hook function, called when the user -// id trying to drag the slider button +// is trying to drag the slider button //////////////////////////////////////////////////////////////////// void PGSliderBar:: drag(const MouseWatcherParameter ¶m) { //pgui_cat.info() << get_name() << "::" << param << endl; - //pgui_cat.info() << _slider.get_name() << "::" << _slider_button.get_x() << endl; + //pgui_cat.info() << _slider->get_name() << "::drag:" << _slider_button.get_x() << endl; // translate the mouse param position into frame space LPoint2f mouse_point = param.get_mouse(); @@ -207,10 +225,9 @@ drag(const MouseWatcherParameter ¶m) { result[0] = -_width; if (result[0] > _width) result[0] = _width; - //pgui_cat.info() << "mouse_point: " << result << endl; - //_update_slider = true; - //_update_value = result[0]; - _slider_button.set_x(result[0]); + _update_slider = true; + _update_position = result[0]; + //_slider_button.set_x(result[0]); } //////////////////////////////////////////////////////////////////// @@ -223,25 +240,36 @@ void PGSliderBar:: update() { int state = get_state(); - // Handle left and right button presses - if (_left.is_button_down()) { - // move the slider to the left - float x = _slider_button.get_x() - _speed; - _slider_button.set_x(max(x, -_width)); + // need left and right button input if they exist + if (!_slider_only) { + // Handle left and right button presses + if (_left.is_button_down()) { + // move the slider to the left + float x = _slider_button.get_x() - _speed; + _update_slider = true; + _update_position = max(x, -_width); + //_slider_button.set_x(max(x, -_width)); + } + + if (_right.is_button_down()) { + // move the slider to the right + float x = _slider_button.get_x() + _speed; + _update_slider = true; + _update_position = min(x, _width); + //_slider_button.set_x(min(x, _width)); + } } - if (_right.is_button_down()) { - // move the slider to the right - float x = _slider_button.get_x() + _speed; - _slider_button.set_x(min(x, _width)); - } - - /* - // press() and drag() update schedules this values that need to be applied - // here so that it keeps integrity of the update regardless of bar orientation + // press() and drag() update schedules this values that need to be + // applied here so that value of current slider position as a ratio + // of range can be updated if (_update_slider) { - _slider_button.set_x(_update_value); + //pgui_cat.info() << "mouse_point: " << _update_position << endl; + if (!_slider_button.is_empty()) + _slider_button.set_x(_update_position); + _mapped_value = (_update_position + _width)/(2*_width); + _value = _negative_mapping ? ((_mapped_value-0.5)*2) : _mapped_value; _update_slider = false; + throw_event(get_click_event()); } - */ } diff --git a/panda/src/pgui/pgSliderBar.h b/panda/src/pgui/pgSliderBar.h index 3ba5205992..46c57afac6 100755 --- a/panda/src/pgui/pgSliderBar.h +++ b/panda/src/pgui/pgSliderBar.h @@ -54,14 +54,25 @@ PUBLISHED: INLINE void set_value(float value); INLINE float get_value() const; + INLINE float get_mapped_value() const; + INLINE float get_update_position() const; INLINE void set_speed(float speed); INLINE float get_speed() const; - INLINE float get_percent() const; + INLINE void set_scale(float speed); + INLINE float get_scale() const; + + INLINE void set_slider_only(bool value); + INLINE bool get_slider_only() const ; + INLINE void set_negative_mapping(bool value); + INLINE bool get_negative_mapping() const ; INLINE void set_bar_style(const PGFrameStyle &style); INLINE PGFrameStyle get_bar_style() const; + INLINE string get_click_event() const; + + INLINE void set_slider_button(NodePath &np, PGSliderButton *button); INLINE NodePath get_slider_button() const; INLINE NodePath get_left_button() const; @@ -70,14 +81,21 @@ PUBLISHED: private: void update(); + bool _slider_only; + bool _negative_mapping; bool _update_slider; - float _update_value; - float _range, _value; + // These 3 variables control slider range + float _value; + float _mapped_value; + float _update_position; + + float _range; float _speed, _width; + float _scale; int _bar_state; PGFrameStyle _bar_style; - PGSliderButton _slider; + PGSliderButton *_slider; PGSliderButton _left; PGSliderButton _right; NodePath _bar; diff --git a/panda/src/pgui/pgSliderButton.I b/panda/src/pgui/pgSliderButton.I index 967abfcfc9..e329c6bd2a 100755 --- a/panda/src/pgui/pgSliderButton.I +++ b/panda/src/pgui/pgSliderButton.I @@ -25,7 +25,6 @@ INLINE bool PGSliderButton:: is_drag_n_drop() { return _drag_n_drop; } - INLINE bool is_drag_n_drop(); //////////////////////////////////////////////////////////////////// // Function: PGSliderButton::set_drag_n_drop diff --git a/panda/src/pgui/pgSliderButton.cxx b/panda/src/pgui/pgSliderButton.cxx index b3b3c1fce5..df19df2eb6 100755 --- a/panda/src/pgui/pgSliderButton.cxx +++ b/panda/src/pgui/pgSliderButton.cxx @@ -50,6 +50,33 @@ PGSliderButton:: ~PGSliderButton() { } +//////////////////////////////////////////////////////////////////// +// Function: PGSliderButton::Copy Constructor +// Access: Public +// Description: +//////////////////////////////////////////////////////////////////// +PGSliderButton:: +PGSliderButton(const PGSliderButton ©) : + PGButton(copy), + _drag_n_drop(copy._drag_n_drop) + // _slider_bar(copy._slider_bar) +{ + _slider_bar = NULL; +} + +//////////////////////////////////////////////////////////////////// +// Function: PGSliderButton::make_copy +// Access: Public, Virtual +// Description: Returns a newly-allocated Node that is a shallow copy +// of this one. It will be a different Node pointer, +// but its internal data may or may not be shared with +// that of the original Node. +//////////////////////////////////////////////////////////////////// +PandaNode *PGSliderButton:: +make_copy() const { + return new PGSliderButton(*this); +} + //////////////////////////////////////////////////////////////////// // Function: PGSliderButton::move // Access: Public, Virtual diff --git a/panda/src/pgui/pgSliderButton.h b/panda/src/pgui/pgSliderButton.h index 36a8ce1412..6f70c82034 100755 --- a/panda/src/pgui/pgSliderButton.h +++ b/panda/src/pgui/pgSliderButton.h @@ -40,7 +40,8 @@ PUBLISHED: public: virtual void move(const MouseWatcherParameter ¶m); - + PGSliderButton(const PGSliderButton ©); + PUBLISHED: INLINE bool is_drag_n_drop(); @@ -48,6 +49,7 @@ PUBLISHED: INLINE void set_slider_bar(PGItem *item); public: + virtual PandaNode *make_copy() const; bool _drag_n_drop; PGItem *_slider_bar;