STORM-1315 Ability to do simple math in numeric edit fields
parent
a300902494
commit
c47d42d945
|
|
@ -20,6 +20,7 @@ Aimee Trescothick
|
|||
SNOW-570
|
||||
SNOW-572
|
||||
SNOW-575
|
||||
STORM-1315
|
||||
VWR-3321
|
||||
VWR-3336
|
||||
VWR-3903
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue