summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKadah_Coba <none@none>2011-06-29 23:40:20 -0700
committerKadah_Coba <none@none>2011-06-29 23:40:20 -0700
commitc47d42d9459445d9e9869c49ebe66a0671a3a0a7 (patch)
tree439119cbe0dc332aaf829f4a582c4026804155e2
parenta300902494f76b9542c3978c2ca80726cefbc942 (diff)
STORM-1315 Ability to do simple math in numeric edit fields
-rw-r--r--doc/contributions.txt1
-rw-r--r--indra/llmath/CMakeLists.txt4
-rw-r--r--indra/llmath/llcalc.cpp150
-rw-r--r--indra/llmath/llcalc.h83
-rw-r--r--indra/llmath/llcalcparser.cpp46
-rw-r--r--indra/llmath/llcalcparser.h169
-rw-r--r--indra/llui/lllineeditor.cpp33
-rw-r--r--indra/llui/lllineeditor.h4
-rw-r--r--indra/llui/llspinctrl.cpp31
-rw-r--r--indra/newview/llappviewer.cpp5
-rw-r--r--indra/newview/llpanelface.cpp11
-rw-r--r--indra/newview/llpanelobject.cpp51
12 files changed, 571 insertions, 17 deletions
diff --git a/doc/contributions.txt b/doc/contributions.txt
index 729c73f777..e9c9369f2c 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -20,6 +20,7 @@ Aimee Trescothick
SNOW-570
SNOW-572
SNOW-575
+ STORM-1315
VWR-3321
VWR-3336
VWR-3903
diff --git a/indra/llmath/CMakeLists.txt b/indra/llmath/CMakeLists.txt
index 9dadad7dd3..cd100cdf9f 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -12,6 +12,8 @@ include_directories(
set(llmath_SOURCE_FILES
llbbox.cpp
llbboxlocal.cpp
+ llcalc.cpp
+ llcalcparser.cpp
llcamera.cpp
llcoordframe.cpp
llline.cpp
@@ -46,6 +48,8 @@ set(llmath_HEADER_FILES
coordframe.h
llbbox.h
llbboxlocal.h
+ llcalc.h
+ llcalcparser.h
llcamera.h
llcoord.h
llcoordframe.h
diff --git a/indra/llmath/llcalc.cpp b/indra/llmath/llcalc.cpp
new file mode 100644
index 0000000000..f399463a47
--- /dev/null
+++ b/indra/llmath/llcalc.cpp
@@ -0,0 +1,150 @@
+/*
+ * LLCalc.cpp
+ * SecondLife
+ *
+ * Created by Aimee Walton on 28/09/2008.
+ * Copyright 2008 Aimee Walton.
+ *
+ */
+
+#include "linden_common.h"
+
+#include "llcalc.h"
+
+#include "llcalcparser.h"
+#include "llmath.h"
+
+
+// Variable names for use in the build floater
+const char* LLCalc::X_POS = "PX";
+const char* LLCalc::Y_POS = "PY";
+const char* LLCalc::Z_POS = "PZ";
+const char* LLCalc::X_SCALE = "SX";
+const char* LLCalc::Y_SCALE = "SY";
+const char* LLCalc::Z_SCALE = "SZ";
+const char* LLCalc::X_ROT = "RX";
+const char* LLCalc::Y_ROT = "RY";
+const char* LLCalc::Z_ROT = "RZ";
+const char* LLCalc::HOLLOW = "HLW";
+const char* LLCalc::CUT_BEGIN = "CB";
+const char* LLCalc::CUT_END = "CE";
+const char* LLCalc::PATH_BEGIN = "PB";
+const char* LLCalc::PATH_END = "PE";
+const char* LLCalc::TWIST_BEGIN = "TB";
+const char* LLCalc::TWIST_END = "TE";
+const char* LLCalc::X_SHEAR = "SHX";
+const char* LLCalc::Y_SHEAR = "SHY";
+const char* LLCalc::X_TAPER = "TPX";
+const char* LLCalc::Y_TAPER = "TPY";
+const char* LLCalc::RADIUS_OFFSET = "ROF";
+const char* LLCalc::REVOLUTIONS = "REV";
+const char* LLCalc::SKEW = "SKW";
+const char* LLCalc::X_HOLE = "HLX";
+const char* LLCalc::Y_HOLE = "HLY";
+const char* LLCalc::TEX_U_SCALE = "TSU";
+const char* LLCalc::TEX_V_SCALE = "TSV";
+const char* LLCalc::TEX_U_OFFSET = "TOU";
+const char* LLCalc::TEX_V_OFFSET = "TOV";
+const char* LLCalc::TEX_ROTATION = "TROT";
+const char* LLCalc::TEX_TRANSPARENCY = "TRNS";
+const char* LLCalc::TEX_GLOW = "GLOW";
+
+
+LLCalc* LLCalc::sInstance = NULL;
+
+LLCalc::LLCalc() : mLastErrorPos(0)
+{
+// mUserVariables = new calc_map_t;
+ mVariables = new calc_map_t;
+ mConstants = new calc_map_t;
+
+ // Init table of constants
+ (*mConstants)["PI"] = F_PI;
+ (*mConstants)["TWO_PI"] = F_TWO_PI;
+ (*mConstants)["PI_BY_TWO"] = F_PI_BY_TWO;
+ (*mConstants)["SQRT2"] = F_SQRT2;
+ (*mConstants)["DEG_TO_RAD"] = DEG_TO_RAD;
+ (*mConstants)["RAD_TO_DEG"] = RAD_TO_DEG;
+ (*mConstants)["GRAVITY"] = GRAVITY;
+}
+
+LLCalc::~LLCalc()
+{
+ delete mConstants;
+ delete mVariables;
+// delete mUserVariables;
+}
+
+//static
+void LLCalc::cleanUp()
+{
+ delete sInstance;
+ sInstance = NULL;
+}
+
+//static
+LLCalc* LLCalc::getInstance()
+{
+ if (!sInstance) sInstance = new LLCalc();
+ return sInstance;
+}
+
+void LLCalc::setVar(const std::string& name, const F32& value)
+{
+ (*mVariables)[name] = value;
+}
+
+void LLCalc::clearVar(const std::string& name)
+{
+ mVariables->erase(name);
+}
+
+void LLCalc::clearAllVariables()
+{
+ mVariables->clear();
+}
+
+/*
+void LLCalc::updateVariables(LLSD& vars)
+{
+ LLSD::map_iterator cIt = vars.beginMap();
+ for(; cIt != vars.endMap(); cIt++)
+ {
+ setVar(cIt->first, (F32)(LLSD::Real)cIt->second);
+ }
+}
+*/
+
+bool LLCalc::evalString(const std::string& expression, F32& result)
+{
+ std::string expr_upper = expression;
+ LLStringUtil::toUpper(expr_upper);
+
+ LLCalcParser calc(result, mConstants, mVariables);
+
+ mLastErrorPos = 0;
+ std::string::iterator start = expr_upper.begin();
+ parse_info<std::string::iterator> info;
+
+ try
+ {
+ info = parse(start, expr_upper.end(), calc, space_p);
+ lldebugs << "Math expression: " << expression << " = " << result << llendl;
+ }
+ catch(parser_error<std::string, std::string::iterator> &e)
+ {
+ mLastErrorPos = e.where - expr_upper.begin();
+
+ llinfos << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << llendl;
+ return false;
+ }
+
+ if (!info.full)
+ {
+ mLastErrorPos = info.stop - expr_upper.begin();
+ llinfos << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << llendl;
+ return false;
+ }
+
+ return true;
+}
diff --git a/indra/llmath/llcalc.h b/indra/llmath/llcalc.h
new file mode 100644
index 0000000000..23c83f623e
--- /dev/null
+++ b/indra/llmath/llcalc.h
@@ -0,0 +1,83 @@
+/*
+ * LLCalc.h
+ * SecondLife
+ *
+ * Created by Aimee Walton on 28/09/2008.
+ * Copyright 2008 Aimee Walton.
+ *
+ */
+
+#ifndef LL_CALC_H
+#define LL_CALC_H
+
+#include <map>
+#include <string>
+
+class LLCalc
+{
+public:
+ LLCalc();
+ ~LLCalc();
+
+ // Variable name constants
+ static const char* X_POS;
+ static const char* Y_POS;
+ static const char* Z_POS;
+ static const char* X_SCALE;
+ static const char* Y_SCALE;
+ static const char* Z_SCALE;
+ static const char* X_ROT;
+ static const char* Y_ROT;
+ static const char* Z_ROT;
+ static const char* HOLLOW;
+ static const char* CUT_BEGIN;
+ static const char* CUT_END;
+ static const char* PATH_BEGIN;
+ static const char* PATH_END;
+ static const char* TWIST_BEGIN;
+ static const char* TWIST_END;
+ static const char* X_SHEAR;
+ static const char* Y_SHEAR;
+ static const char* X_TAPER;
+ static const char* Y_TAPER;
+ static const char* RADIUS_OFFSET;
+ static const char* REVOLUTIONS;
+ static const char* SKEW;
+ static const char* X_HOLE;
+ static const char* Y_HOLE;
+ static const char* TEX_U_SCALE;
+ static const char* TEX_V_SCALE;
+ static const char* TEX_U_OFFSET;
+ static const char* TEX_V_OFFSET;
+ static const char* TEX_ROTATION;
+ static const char* TEX_TRANSPARENCY;
+ static const char* TEX_GLOW;
+
+ void setVar(const std::string& name, const F32& value);
+ void clearVar(const std::string& name);
+ void clearAllVariables();
+// void updateVariables(LLSD& vars);
+
+ bool evalString(const std::string& expression, F32& result);
+ std::string::size_type getLastErrorPos() { return mLastErrorPos; }
+
+ static LLCalc* getInstance();
+ static void cleanUp();
+
+ typedef std::map<std::string, F32> calc_map_t;
+
+private:
+ std::string::size_type mLastErrorPos;
+
+ calc_map_t* mConstants;
+ calc_map_t* mVariables;
+
+ // *TODO: Add support for storing user defined variables, and stored functions.
+ // Will need UI work, and a means to save them between sessions.
+// calc_map_t* mUserVariables;
+
+ // "There shall be only one"
+ static LLCalc* sInstance;
+};
+
+#endif // LL_CALC_H
diff --git a/indra/llmath/llcalcparser.cpp b/indra/llmath/llcalcparser.cpp
new file mode 100644
index 0000000000..fd55376fa9
--- /dev/null
+++ b/indra/llmath/llcalcparser.cpp
@@ -0,0 +1,46 @@
+/*
+ * LLCalcParser.cpp
+ * SecondLife
+ *
+ * Created by Aimee Walton on 28/09/2008.
+ * Copyright 2008 Aimee Walton.
+ *
+ */
+
+#include "linden_common.h"
+
+#include "llcalcparser.h"
+using namespace boost::spirit::classic;
+
+F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const
+{
+ LLCalc::calc_map_t::iterator iter;
+
+ std::string name(start, end);
+
+ if (mConstants)
+ {
+ iter = mConstants->find(name);
+ if (iter != mConstants->end())
+ {
+ return (*iter).second;
+ }
+ }
+ else
+ {
+ // This should never happen!
+ throw_(end, std::string("Missing constants table"));
+ }
+
+ if (mVariables)
+ {
+ iter = mVariables->find(name);
+ if (iter != mVariables->end())
+ {
+ return (*iter).second;
+ }
+ }
+
+ throw_(end, std::string("Unknown symbol " + name));
+ return 0.f;
+}
diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h
new file mode 100644
index 0000000000..a759a35710
--- /dev/null
+++ b/indra/llmath/llcalcparser.h
@@ -0,0 +1,169 @@
+/*
+ * LLCalcParser.h
+ * SecondLife
+ *
+ * Created by Aimee Walton on 28/09/2008.
+ * Copyright 2008 Aimee Walton.
+ *
+ */
+
+#ifndef LL_CALCPARSER_H
+#define LL_CALCPARSER_H
+
+#include <boost/spirit/include/classic_attribute.hpp>
+#include <boost/spirit/include/classic_core.hpp>
+#include <boost/spirit/include/classic_error_handling.hpp>
+#include <boost/spirit/include/classic_position_iterator.hpp>
+#include <boost/spirit/include/phoenix1_binders.hpp>
+#include <boost/spirit/include/classic_symbols.hpp>
+using namespace boost::spirit::classic;
+
+#include "llcalc.h"
+#include "llmath.h"
+
+struct LLCalcParser : grammar<LLCalcParser>
+{
+ LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) :
+ mResult(result), mConstants(constants), mVariables(vars) {};
+
+ struct value_closure : closure<value_closure, F32>
+ {
+ member1 value;
+ };
+
+ template <typename ScannerT>
+ struct definition
+ {
+ // Rule declarations
+ rule<ScannerT> statement, identifier;
+ rule<ScannerT, value_closure::context_t> expression, term,
+ power,
+ unary_expr,
+ factor,
+ unary_func,
+ binary_func,
+ group;
+
+ // start() should return the starting symbol
+ rule<ScannerT> const& start() const { return statement; }
+
+ definition(LLCalcParser const& self)
+ {
+ using namespace phoenix;
+
+ assertion<std::string> assert_domain("Domain error");
+// assertion<std::string> assert_symbol("Unknown symbol");
+ assertion<std::string> assert_syntax("Syntax error");
+
+ identifier =
+ lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')]
+ ;
+
+ group =
+ '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')'))
+ ;
+
+ unary_func =
+ ((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sin)(self,arg1)]) |
+ (str_p("COS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_cos)(self,arg1)]) |
+ (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_tan)(self,arg1)]) |
+ (str_p("ASIN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_asin)(self,arg1)]) |
+ (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_acos)(self,arg1)]) |
+ (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_atan)(self,arg1)]) |
+ (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_sqrt)(self,arg1)]) |
+ (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_log)(self,arg1)]) |
+ (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_exp)(self,arg1)]) |
+ (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&LLCalcParser::_fabs)(self,arg1)])
+ ) >> assert_syntax(ch_p(')'))
+ ;
+
+ binary_func =
+ ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
+ expression[binary_func.value = bind(&LLCalcParser::_atan2)(self, binary_func.value, arg1)]) |
+ (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
+ expression[binary_func.value = bind(&LLCalcParser::_min)(self, binary_func.value, arg1)]) |
+ (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >>
+ expression[binary_func.value = bind(&LLCalcParser::_max)(self, binary_func.value, arg1)])
+ ) >> assert_syntax(ch_p(')'))
+ ;
+
+ // *TODO: Localisation of the decimal point?
+ // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate
+ // for the current locale. However to do that here could clash with using
+ // the comma as a separator when passing arguments to functions.
+ factor =
+ (ureal_p[factor.value = arg1] |
+ group[factor.value = arg1] |
+ unary_func[factor.value = arg1] |
+ binary_func[factor.value = arg1] |
+ // Lookup throws an Unknown Symbol error if it is unknown, while this works fine,
+ // would be "neater" to handle symbol lookup from here with an assertive parser.
+// constants_p[factor.value = arg1]|
+ identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)]
+ ) >>
+ // Detect and throw math errors.
+ assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value)))
+ ;
+
+ unary_expr =
+ !ch_p('+') >> factor[unary_expr.value = arg1] |
+ '-' >> factor[unary_expr.value = -arg1]
+ ;
+
+ power =
+ unary_expr[power.value = arg1] >>
+ *('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)]))
+ ;
+
+ term =
+ power[term.value = arg1] >>
+ *(('*' >> assert_syntax(power[term.value *= arg1])) |
+ ('/' >> assert_syntax(power[term.value /= arg1]))
+ )
+ ;
+
+ expression =
+ assert_syntax(term[expression.value = arg1]) >>
+ *(('+' >> assert_syntax(term[expression.value += arg1])) |
+ ('-' >> assert_syntax(term[expression.value -= arg1]))
+ )
+ ;
+
+ statement =
+ !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p)
+ ;
+ }
+ };
+
+private:
+ // Member functions for semantic actions
+ F32 lookup(const std::string::iterator&, const std::string::iterator&) const;
+ F32 _min(const F32& a, const F32& b) const { return llmin(a, b); }
+ F32 _max(const F32& a, const F32& b) const { return llmax(a, b); }
+
+ bool checkNaN(const F32& a) const { return !llisnan(a); }
+
+ //FIX* non ambigious function fix making SIN() work for calc -Cryogenic Blitz
+ F32 _sin(const F32& a) const { return sin(DEG_TO_RAD * a); }
+ F32 _cos(const F32& a) const { return cos(DEG_TO_RAD * a); }
+ F32 _tan(const F32& a) const { return tan(DEG_TO_RAD * a); }
+ F32 _asin(const F32& a) const { return asin(a * RAD_TO_DEG); }
+ F32 _acos(const F32& a) const { return acos(a * RAD_TO_DEG); }
+ F32 _atan(const F32& a) const { return atan(a * RAD_TO_DEG); }
+ F32 _sqrt(const F32& a) const { return sqrt(a); }
+ F32 _log(const F32& a) const { return log(a); }
+ F32 _exp(const F32& a) const { return exp(a); }
+ F32 _fabs(const F32& a) const { return fabs(a) * RAD_TO_DEG; }
+
+ F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); }
+
+
+
+ LLCalc::calc_map_t* mConstants;
+ LLCalc::calc_map_t* mVariables;
+// LLCalc::calc_map_t* mUserVariables;
+
+ F32& mResult;
+};
+
+#endif // LL_CALCPARSER_H
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 0196080d90..64969856da 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -37,6 +37,7 @@
#include "llgl.h"
#include "lltimer.h"
+#include "llcalc.h"
//#include "llclipboard.h"
#include "llcontrol.h"
#include "llbutton.h"
@@ -132,6 +133,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mIgnoreTab( p.ignore_tab ),
mDrawAsterixes( p.is_password ),
mSelectAllonFocusReceived( p.select_on_focus ),
+ mSelectAllonCommit( TRUE ),
mPassDelete(FALSE),
mReadOnly(FALSE),
mBgImage( p.background_image ),
@@ -228,7 +230,10 @@ void LLLineEditor::onCommit()
setControlValue(getValue());
LLUICtrl::onCommit();
- selectAll();
+
+ // Selection on commit needs to be turned off when evaluating maths
+ // expressions, to allow indication of the error position
+ if (mSelectAllonCommit) selectAll();
}
// Returns TRUE if user changed value at all
@@ -1995,6 +2000,32 @@ BOOL LLLineEditor::postvalidateFloat(const std::string &str)
return success;
}
+BOOL LLLineEditor::evaluateFloat()
+{
+ bool success;
+ F32 result = 0.f;
+ std::string expr = getText();
+ LLStringUtil::toUpper(expr);
+
+ success = LLCalc::getInstance()->evalString(expr, result);
+
+ if (!success)
+ {
+ // Move the cursor to near the error on failure
+ setCursor(LLCalc::getInstance()->getLastErrorPos());
+ // *TODO: Translated error message indicating the type of error? Select error text?
+ }
+ else
+ {
+ // Replace the expression with the result
+ std::string result_str = llformat("%f",result);
+ setText(result_str);
+ selectAll();
+ }
+
+ return success;
+}
+
void LLLineEditor::onMouseCaptureLost()
{
endSelection();
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index fe191e5971..987abc038c 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -220,6 +220,7 @@ public:
void deleteSelection();
void setSelectAllonFocusReceived(BOOL b);
+ void setSelectAllonCommit(BOOL b) { mSelectAllonCommit = b; }
typedef boost::function<void (LLLineEditor* caller, void* user_data)> callback_t;
void setKeystrokeCallback(callback_t callback, void* user_data);
@@ -234,6 +235,8 @@ public:
void setPrevalidate( LLTextValidate::validate_func_t func );
static BOOL postvalidateFloat(const std::string &str);
+ BOOL evaluateFloat();
+
// line history support:
void setEnableLineHistory( BOOL enabled ) { mHaveHistory = enabled; } // switches line history on or off
void updateHistory(); // stores current line in history
@@ -330,6 +333,7 @@ protected:
BOOL mDrawAsterixes;
BOOL mSelectAllonFocusReceived;
+ BOOL mSelectAllonCommit;
BOOL mPassDelete;
BOOL mReadOnly;
diff --git a/indra/llui/llspinctrl.cpp b/indra/llui/llspinctrl.cpp
index 15a7438ec9..b76d604953 100644
--- a/indra/llui/llspinctrl.cpp
+++ b/indra/llui/llspinctrl.cpp
@@ -44,7 +44,7 @@
#include "llresmgr.h"
#include "lluictrlfactory.h"
-const U32 MAX_STRING_LENGTH = 32;
+const U32 MAX_STRING_LENGTH = 255;
static LLDefaultChildRegistry::Register<LLSpinCtrl> r2("spinner");
@@ -124,14 +124,15 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
params.max_length.bytes(MAX_STRING_LENGTH);
params.commit_callback.function((boost::bind(&LLSpinCtrl::onEditorCommit, this, _2)));
- if( mPrecision>0 )//should accept float numbers
- {
- params.prevalidate_callback(&LLTextValidate::validateFloat);
- }
- else //should accept int numbers
- {
- params.prevalidate_callback(&LLTextValidate::validateInt);
- }
+ //allow entering of any chars for LLCalc, proper input will be evaluated on commit
+ //if( mPrecision>0 )//should accept float numbers
+ //{
+ // params.prevalidate_callback(&LLTextValidate::validateFloat);
+ //}
+ //else //should accept int numbers
+ //{
+ // params.prevalidate_callback(&LLTextValidate::validateInt);
+ //}
params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM);
mEditor = LLUICtrlFactory::create<LLLineEditor> (params);
@@ -140,6 +141,7 @@ LLSpinCtrl::LLSpinCtrl(const LLSpinCtrl::Params& p)
// than when it doesn't. Instead, if you always have to double click to select all the text,
// it's easier to understand
//mEditor->setSelectAllonFocusReceived(TRUE);
+ mEditor->setSelectAllonCommit(FALSE);
addChild(mEditor);
updateEditor();
@@ -304,9 +306,10 @@ void LLSpinCtrl::onEditorCommit( const LLSD& data )
{
BOOL success = FALSE;
- std::string text = mEditor->getText();
- if( LLLineEditor::postvalidateFloat( text ) )
+ if( mEditor->evaluateFloat() )
{
+ std::string text = mEditor->getText();
+
LLLocale locale(LLLocale::USER_LOCALE);
F32 val = (F32) atof(text.c_str());
@@ -327,7 +330,11 @@ void LLSpinCtrl::onEditorCommit( const LLSD& data )
}
updateEditor();
- if( !success )
+ if( success )
+ {
+ updateEditor();
+ }
+ else
{
reportInvalidData();
}
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d2582d524d..fa841074fd 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -56,6 +56,7 @@
#include "llallocator.h"
#include "llares.h"
#include "llcurl.h"
+#include "llcalc.h"
#include "lltexturestats.h"
#include "lltexturestats.h"
#include "llviewerwindow.h"
@@ -1543,7 +1544,9 @@ bool LLAppViewer::cleanup()
// Note: this is where gLocalSpeakerMgr and gActiveSpeakerMgr used to be deleted.
LLWorldMap::getInstance()->reset(); // release any images
-
+
+ LLCalc::cleanUp();
+
llinfos << "Global stuff deleted" << llendflush;
if (gAudiop)
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 07c7f35989..de5522c8fb 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -30,6 +30,7 @@
#include "llpanelface.h"
// library includes
+#include "llcalc.h"
#include "llerror.h"
#include "llfocusmgr.h"
#include "llrect.h"
@@ -926,6 +927,16 @@ void LLPanelFace::getState()
getChildView("button apply")->setEnabled(enabled);
}
}
+
+ // Set variable values for numeric expressions
+ LLCalc* calcp = LLCalc::getInstance();
+ calcp->setVar(LLCalc::TEX_U_SCALE, childGetValue("TexScaleU").asReal());
+ calcp->setVar(LLCalc::TEX_V_SCALE, childGetValue("TexScaleV").asReal());
+ calcp->setVar(LLCalc::TEX_U_OFFSET, childGetValue("TexOffsetU").asReal());
+ calcp->setVar(LLCalc::TEX_V_OFFSET, childGetValue("TexOffsetV").asReal());
+ calcp->setVar(LLCalc::TEX_ROTATION, childGetValue("TexRot").asReal());
+ calcp->setVar(LLCalc::TEX_TRANSPARENCY, childGetValue("ColorTrans").asReal());
+ calcp->setVar(LLCalc::TEX_GLOW, childGetValue("glow").asReal());
}
else
{
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp
index 52917ff20b..c222bbb191 100644
--- a/indra/newview/llpanelobject.cpp
+++ b/indra/newview/llpanelobject.cpp
@@ -41,6 +41,7 @@
// project includes
#include "llagent.h"
#include "llbutton.h"
+#include "llcalc.h"
#include "llcheckboxctrl.h"
#include "llcolorswatch.h"
#include "llcombobox.h"
@@ -318,6 +319,8 @@ void LLPanelObject::getState( )
}
}
+ LLCalc* calcp = LLCalc::getInstance();
+
LLVOVolume *volobjp = NULL;
if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
{
@@ -334,6 +337,7 @@ void LLPanelObject::getState( )
// Disable all text input fields
clearCtrls();
+ calcp->clearAllVariables();
return;
}
@@ -360,12 +364,18 @@ void LLPanelObject::getState( )
mCtrlPosX->set( vec.mV[VX] );
mCtrlPosY->set( vec.mV[VY] );
mCtrlPosZ->set( vec.mV[VZ] );
+ calcp->setVar(LLCalc::X_POS, vec.mV[VX]);
+ calcp->setVar(LLCalc::Y_POS, vec.mV[VY]);
+ calcp->setVar(LLCalc::Z_POS, vec.mV[VZ]);
}
else
{
mCtrlPosX->clear();
mCtrlPosY->clear();
mCtrlPosZ->clear();
+ calcp->clearVar(LLCalc::X_POS);
+ calcp->clearVar(LLCalc::Y_POS);
+ calcp->clearVar(LLCalc::Z_POS);
}
@@ -380,12 +390,18 @@ void LLPanelObject::getState( )
mCtrlScaleX->set( vec.mV[VX] );
mCtrlScaleY->set( vec.mV[VY] );
mCtrlScaleZ->set( vec.mV[VZ] );
+ calcp->setVar(LLCalc::X_SCALE, vec.mV[VX]);
+ calcp->setVar(LLCalc::Y_SCALE, vec.mV[VY]);
+ calcp->setVar(LLCalc::Z_SCALE, vec.mV[VZ]);
}
else
{
mCtrlScaleX->clear();
mCtrlScaleY->clear();
mCtrlScaleZ->clear();
+ calcp->setVar(LLCalc::X_SCALE, 0.f);
+ calcp->setVar(LLCalc::Y_SCALE, 0.f);
+ calcp->setVar(LLCalc::Z_SCALE, 0.f);
}
mLabelSize->setEnabled( enable_scale );
@@ -405,12 +421,18 @@ void LLPanelObject::getState( )
mCtrlRotX->set( mCurEulerDegrees.mV[VX] );
mCtrlRotY->set( mCurEulerDegrees.mV[VY] );
mCtrlRotZ->set( mCurEulerDegrees.mV[VZ] );
+ calcp->setVar(LLCalc::X_ROT, mCurEulerDegrees.mV[VX]);
+ calcp->setVar(LLCalc::Y_ROT, mCurEulerDegrees.mV[VY]);
+ calcp->setVar(LLCalc::Z_ROT, mCurEulerDegrees.mV[VZ]);
}
else
{
mCtrlRotX->clear();
mCtrlRotY->clear();
mCtrlRotZ->clear();
+ calcp->clearVar(LLCalc::X_ROT);
+ calcp->clearVar(LLCalc::Y_ROT);
+ calcp->clearVar(LLCalc::Z_ROT);
}
mLabelRotation->setEnabled( enable_rotate );
@@ -625,9 +647,9 @@ void LLPanelObject::getState( )
F32 end_t = volume_params.getEndT();
// Hollowness
- F32 hollow = volume_params.getHollow();
- mSpinHollow->set( 100.f * hollow );
-
+ F32 hollow = 100.f * volume_params.getHollow();
+ mSpinHollow->set( hollow );
+ calcp->setVar(LLCalc::HOLLOW, hollow);
// All hollow objects allow a shape to be selected.
if (hollow > 0.f)
{
@@ -679,6 +701,10 @@ void LLPanelObject::getState( )
mSpinCutEnd ->set( cut_end );
mCtrlPathBegin ->set( adv_cut_begin );
mCtrlPathEnd ->set( adv_cut_end );
+ calcp->setVar(LLCalc::CUT_BEGIN, cut_begin);
+ calcp->setVar(LLCalc::CUT_END, cut_end);
+ calcp->setVar(LLCalc::PATH_BEGIN, adv_cut_begin);
+ calcp->setVar(LLCalc::PATH_END, adv_cut_end);
// Twist
F32 twist = volume_params.getTwist();
@@ -697,18 +723,24 @@ void LLPanelObject::getState( )
mSpinTwist ->set( twist );
mSpinTwistBegin ->set( twist_begin );
+ calcp->setVar(LLCalc::TWIST_END, twist);
+ calcp->setVar(LLCalc::TWIST_BEGIN, twist_begin);
// Shear
F32 shear_x = volume_params.getShearX();
F32 shear_y = volume_params.getShearY();
mSpinShearX->set( shear_x );
mSpinShearY->set( shear_y );
+ calcp->setVar(LLCalc::X_SHEAR, shear_x);
+ calcp->setVar(LLCalc::Y_SHEAR, shear_y);
// Taper
F32 taper_x = volume_params.getTaperX();
F32 taper_y = volume_params.getTaperY();
mSpinTaperX->set( taper_x );
mSpinTaperY->set( taper_y );
+ calcp->setVar(LLCalc::X_TAPER, taper_x);
+ calcp->setVar(LLCalc::Y_TAPER, taper_y);
// Radius offset.
F32 radius_offset = volume_params.getRadiusOffset();
@@ -738,10 +770,12 @@ void LLPanelObject::getState( )
}
}
mSpinRadiusOffset->set( radius_offset);
+ calcp->setVar(LLCalc::RADIUS_OFFSET, radius_offset);
// Revolutions
F32 revolutions = volume_params.getRevolutions();
mSpinRevolutions->set( revolutions );
+ calcp->setVar(LLCalc::REVOLUTIONS, revolutions);
// Skew
F32 skew = volume_params.getSkew();
@@ -766,6 +800,7 @@ void LLPanelObject::getState( )
}
}
mSpinSkew->set( skew );
+ calcp->setVar(LLCalc::SKEW, skew);
}
// Compute control visibility, label names, and twist range.
@@ -869,6 +904,8 @@ void LLPanelObject::getState( )
case MI_RING:
mSpinScaleX->set( scale_x );
mSpinScaleY->set( scale_y );
+ calcp->setVar(LLCalc::X_HOLE, scale_x);
+ calcp->setVar(LLCalc::Y_HOLE, scale_y);
mSpinScaleX->setMinValue(OBJECT_MIN_HOLE_SIZE);
mSpinScaleX->setMaxValue(OBJECT_MAX_HOLE_SIZE_X);
mSpinScaleY->setMinValue(OBJECT_MIN_HOLE_SIZE);
@@ -883,6 +920,14 @@ void LLPanelObject::getState( )
mSpinScaleX->setMaxValue(1.f);
mSpinScaleY->setMinValue(-1.f);
mSpinScaleY->setMaxValue(1.f);
+
+ // Torus' Hole Size is Box/Cyl/Prism's Taper
+ calcp->setVar(LLCalc::X_TAPER, 1.f - scale_x);
+ calcp->setVar(LLCalc::Y_TAPER, 1.f - scale_y);
+
+ // Box/Cyl/Prism have no hole size
+ calcp->setVar(LLCalc::X_HOLE, 0.f);
+ calcp->setVar(LLCalc::Y_HOLE, 0.f);
}
break;
}