On 25/08/2013 at 11:32, xxxxxxxx wrote:
Hi Scott,
some notes about your code:
- Do not store the mouse position and the user area width globally, you can store it as an
attribute in your user-area. Furthermore, you can retrieve the width of a user-area at any
point by calling GetWidth().
- You do not need to use the user-areas Timer() method. As I stated above, I have hit the
same problem before and implementing the example I have shown does fix the updating
problem (I tested it in your plugin source code you've linked). [See code-reference #1]
- The mouse position does not reflect the value of the slider 1-by-1. You can calculate a value
between 0 and 1 by dividing the mouse X position by the width of the user-area. To be more
precise:
Real v01 = static_cast<Real>(mx) / static_cast<Real>(this->GetWidth());
You can then scale the value to match your minimum and maximum slider value. This is simple
range mapping.
Real vmm = v01 * (slider_max - slider_min) + slider_min;
And then notify the parent about the value change as you have done properly in your code.
See code-reference #2 for a more contextual snippet.
4. The EventAdd() call from DrawMsg() is absolutely redundant and should be avoided.
code-references
#1
virtual Bool SetData(const TriState<GeData> &tristate)
{
const GeData &value = tristate.GetValue(); //The value of the gui(the data port in xpresso & the data animation track)
LONG data = value.GetLong(); //Assign the value to a long type variable so we can use it
MousePos = data; //Use this value to set the slider's position using the data
ua.Redraw();
return TRUE;
}
#2
class MyUserArea : public GeUserArea
{
public:
** Real value;**
** Real slider_min, slider_max;**
virtual void DrawMsg(LONG x1, LONG y1, LONG x2, LONG y2, const BaseContainer& msg)
{
/* ... original code left out ... */
LONG Left = static_cast <Real>(x2 - x1) * value;
LONG Top = 0;
LONG Bottom = 0;
LONG Right = 0;
DrawRectangle(x1+Left, y1+Top, x2-Right, y2-Bottom);
// EventAdd();
}
virtual Bool InputEvent(const BaseContainer& msg)
{
BaseContainer action; //Create an empty container
action.SetData(BFM_ACTION_ID, 1000); //Store the ID for the active gizmo in the container
BaseContainer state;
while (GetInputState(BFM_INPUT_MOUSE, BFM_INPUT_MOUSELEFT, state)) //While the LMB is down
{
if (state.GetLong(BFM_INPUT_VALUE) == 0) break; //If the state value is 0 the LMB is no longer down..so don't continue
LONG mx = state.GetReal(BFM_INPUT_X);
LONG my = state.GetReal(BFM_INPUT_Y);
Global2Local(&mx,&my);
//GePrint("X Pos: " +LongToString(mx) + " " + "Y Pos: " +LongToString(my));
** // Calculate the value based on the user-areas size.**
** LONG width = GetWidth();**
** if (width == 0) continue; // avoid zero-division error, if the width is zero, nothing of the following needs to be done.**
** Real v01 = static_cast<Real>(mx) / static_cast<Real>(width);**
** value = v01 * (slider_max - slider_min) + slider_min;**
** // MousePos = mx; //Send the position data to the global variable so that all the other classes and functions can use it**
Redraw(); //Refreshes the UA slider changes while dragging. Instead of when finished dragging
//Send a message to the parent dialog telling it that the UA slider being used by the mouse in some manner and not finished
action.SetData(BFM_ACTION_INDRAG, TRUE);
SendParentMessage(action);
//GeDialog *dlg = GetDialog();
BaseContainer actionmsg(BFM_ACTION); //Create a container with the BFM_ACTION in it
actionmsg.SetLong(BFM_ACTION_ID, MY_MESSAGE); //Add the ID of the dialog gizmo that has changed to the container
BaseContainer actionresult; //Create another container to hold the result
dlg->Message(actionmsg, actionresult); //Send a custom message containing this value to the dialog
}
//Notify the parent dialog that the dragging is now finished
action.SetBool(BFM_ACTION_INDRAG, FALSE);
SendParentMessage(action);
Redraw();
return TRUE;
}
};
class MyCustomGui : public iCustomGui
{
typedef iCustomGui super;
private:
MyUserArea ua; //A local copy of the User area so we can use it in this class
public:
MyCustomGui(const BaseContainer &settings, CUSTOMGUIPLUGIN *plug) : super(settings, plug) {
** // Retrieve the minimum and maximum slider value from the **
** ua.value = 0;**
** Real min_default = settings.GetReal(DESC_MIN, 0.0);**
** Real max_default = settings.GetReal(DESC_MAX, 1.0);**
** ua.slider_min = settings.GetReal(DESC_MINSLIDER, min_default);**
** ua.slider_max = settings.GetReal(DESC_MAXSLIDER, max_default);**
}
virtual Bool CreateLayout()
{
//Attach the User Area to the custom GUI gizmo
AddUserArea(1000, BFH_SCALEFIT, 0, 0);
AttachUserArea(ua, 1000);
return TRUE;
}
virtual Bool InitValues(){ return TRUE; };
virtual Bool Command(LONG id, const BaseContainer &msg)
{
if (id == MY_MESSAGE)
{
valueChanged(this, msg); //Execute this custom method when the LMB is pressed
this->SendParentMessage(msg);
}
return TRUE;
}
virtual Bool SetData(const TriState<GeData> &tristate)
{
const GeData &value = tristate.GetValue(); //The value of the gui(the data port in xpresso & the data animation track)
** // Real data = value.GetReal(); //Assign the value to a long type variable so we can use it**
** // MousePos = data; //Use this value to set the slider's position using the data**
** ua.value = value.GetReal();**
** ua.Redraw();**
return TRUE;
}
};
> Note : You still have to handle the case where multiple values need to be displayed in the GUI. You can check if you have to switch to the "Multiple Values" display by calling TriState<T>::GetTri(). You have to handle this case respectively in your UI.
Best,
-Niklas