diff options
author | McCabe Maxsted | 2009-01-12 02:17:03 -0700 |
---|---|---|
committer | McCabe Maxsted | 2009-01-12 02:17:03 -0700 |
commit | dd99e2a6b5054927bba83d44a7a03bc365c28a77 (patch) | |
tree | 7f94ef4010b3bef22d8c481d8c700cfb1219ffe5 /linden/indra/llmath | |
parent | Wind disabled by default, ambient wind muting fixed, added debug setting 'Mut... (diff) | |
download | meta-impy-dd99e2a6b5054927bba83d44a7a03bc365c28a77.zip meta-impy-dd99e2a6b5054927bba83d44a7a03bc365c28a77.tar.gz meta-impy-dd99e2a6b5054927bba83d44a7a03bc365c28a77.tar.bz2 meta-impy-dd99e2a6b5054927bba83d44a7a03bc365c28a77.tar.xz |
Applied Aimee's patch for doing simple math in the build editor
Diffstat (limited to 'linden/indra/llmath')
-rw-r--r-- | linden/indra/llmath/CMakeLists.txt | 4 | ||||
-rw-r--r-- | linden/indra/llmath/llcalc.cpp | 155 | ||||
-rw-r--r-- | linden/indra/llmath/llcalc.h | 85 | ||||
-rw-r--r-- | linden/indra/llmath/llcalcparser.cpp | 45 | ||||
-rw-r--r-- | linden/indra/llmath/llcalcparser.h | 155 |
5 files changed, 444 insertions, 0 deletions
diff --git a/linden/indra/llmath/CMakeLists.txt b/linden/indra/llmath/CMakeLists.txt index 6a329fa..e5ec3e1 100644 --- a/linden/indra/llmath/CMakeLists.txt +++ b/linden/indra/llmath/CMakeLists.txt | |||
@@ -11,6 +11,8 @@ include_directories( | |||
11 | 11 | ||
12 | set(llmath_SOURCE_FILES | 12 | set(llmath_SOURCE_FILES |
13 | llbboxlocal.cpp | 13 | llbboxlocal.cpp |
14 | llcalc.cpp | ||
15 | llcalcparser.cpp | ||
14 | llcamera.cpp | 16 | llcamera.cpp |
15 | llcoordframe.cpp | 17 | llcoordframe.cpp |
16 | llline.cpp | 18 | llline.cpp |
@@ -40,6 +42,8 @@ set(llmath_HEADER_FILES | |||
40 | camera.h | 42 | camera.h |
41 | coordframe.h | 43 | coordframe.h |
42 | llbboxlocal.h | 44 | llbboxlocal.h |
45 | llcalc.h | ||
46 | llcalcparser.h | ||
43 | llcamera.h | 47 | llcamera.h |
44 | llcoord.h | 48 | llcoord.h |
45 | llcoordframe.h | 49 | llcoordframe.h |
diff --git a/linden/indra/llmath/llcalc.cpp b/linden/indra/llmath/llcalc.cpp new file mode 100644 index 0000000..feb072a --- /dev/null +++ b/linden/indra/llmath/llcalc.cpp | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * LLCalc.cpp | ||
3 | * SecondLife | ||
4 | * | ||
5 | * Created by Aimee Walton on 28/09/2008. | ||
6 | * Copyright 2008 Aimee Walton. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include "linden_common.h" | ||
11 | |||
12 | #include "llcalc.h" | ||
13 | |||
14 | #include <boost/spirit/core.hpp> | ||
15 | #include <boost/spirit/error_handling.hpp> | ||
16 | |||
17 | #include "llcalcparser.h" | ||
18 | #include "llmath.h" | ||
19 | |||
20 | |||
21 | // Variable names for use in the build floater | ||
22 | const char* LLCalc::X_POS = "X"; | ||
23 | const char* LLCalc::Y_POS = "Y"; | ||
24 | const char* LLCalc::Z_POS = "Z"; | ||
25 | const char* LLCalc::X_SCALE = "XS"; | ||
26 | const char* LLCalc::Y_SCALE = "YS"; | ||
27 | const char* LLCalc::Z_SCALE = "ZS"; | ||
28 | const char* LLCalc::X_ROT = "XR"; | ||
29 | const char* LLCalc::Y_ROT = "YR"; | ||
30 | const char* LLCalc::Z_ROT = "ZR"; | ||
31 | const char* LLCalc::HOLLOW = "HLW"; | ||
32 | const char* LLCalc::CUT_BEGIN = "CB"; | ||
33 | const char* LLCalc::CUT_END = "CE"; | ||
34 | const char* LLCalc::PATH_BEGIN = "PB"; | ||
35 | const char* LLCalc::PATH_END = "PE"; | ||
36 | const char* LLCalc::TWIST_BEGIN = "TB"; | ||
37 | const char* LLCalc::TWIST_END = "TE"; | ||
38 | const char* LLCalc::X_SHEAR = "XSH"; | ||
39 | const char* LLCalc::Y_SHEAR = "YSH"; | ||
40 | const char* LLCalc::X_TAPER = "XTP"; | ||
41 | const char* LLCalc::Y_TAPER = "YTP"; | ||
42 | const char* LLCalc::RADIUS_OFFSET = "ROF"; | ||
43 | const char* LLCalc::REVOLUTIONS = "REV"; | ||
44 | const char* LLCalc::SKEW = "SKW"; | ||
45 | const char* LLCalc::X_HOLE = "XHL"; | ||
46 | const char* LLCalc::Y_HOLE = "YHL"; | ||
47 | const char* LLCalc::TEX_U_SCALE = "TSU"; | ||
48 | const char* LLCalc::TEX_V_SCALE = "TSV"; | ||
49 | const char* LLCalc::TEX_U_OFFSET = "TOU"; | ||
50 | const char* LLCalc::TEX_V_OFFSET = "TOV"; | ||
51 | const char* LLCalc::TEX_ROTATION = "TROT"; | ||
52 | const char* LLCalc::TEX_TRANSPARENCY = "TRNS"; | ||
53 | const char* LLCalc::TEX_GLOW = "GLOW"; | ||
54 | |||
55 | |||
56 | LLCalc* LLCalc::sInstance = NULL; | ||
57 | |||
58 | LLCalc::LLCalc() : mLastErrorPos(0) | ||
59 | { | ||
60 | // mUserVariables = new calc_map_t; | ||
61 | mVariables = new calc_map_t; | ||
62 | mConstants = new calc_map_t; | ||
63 | |||
64 | // Init table of constants | ||
65 | (*mConstants)["PI"] = F_PI; | ||
66 | (*mConstants)["TWO_PI"] = F_TWO_PI; | ||
67 | (*mConstants)["PI_BY_TWO"] = F_PI_BY_TWO; | ||
68 | (*mConstants)["SQRT2"] = F_SQRT2; | ||
69 | (*mConstants)["DEG_TO_RAD"] = DEG_TO_RAD; | ||
70 | (*mConstants)["RAD_TO_DEG"] = RAD_TO_DEG; | ||
71 | (*mConstants)["GRAVITY"] = GRAVITY; | ||
72 | } | ||
73 | |||
74 | LLCalc::~LLCalc() | ||
75 | { | ||
76 | delete mConstants; | ||
77 | delete mVariables; | ||
78 | // delete mUserVariables; | ||
79 | } | ||
80 | |||
81 | //static | ||
82 | void LLCalc::cleanUp() | ||
83 | { | ||
84 | delete sInstance; | ||
85 | sInstance = NULL; | ||
86 | } | ||
87 | |||
88 | //static | ||
89 | LLCalc* LLCalc::getInstance() | ||
90 | { | ||
91 | if (!sInstance) sInstance = new LLCalc(); | ||
92 | return sInstance; | ||
93 | } | ||
94 | |||
95 | void LLCalc::setVar(const std::string& name, const F32& value) | ||
96 | { | ||
97 | (*mVariables)[name] = value; | ||
98 | } | ||
99 | |||
100 | void LLCalc::clearVar(const std::string& name) | ||
101 | { | ||
102 | mVariables->erase(name); | ||
103 | } | ||
104 | |||
105 | void LLCalc::clearAllVariables() | ||
106 | { | ||
107 | mVariables->clear(); | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | void LLCalc::updateVariables(LLSD& vars) | ||
112 | { | ||
113 | LLSD::map_iterator cIt = vars.beginMap(); | ||
114 | for(; cIt != vars.endMap(); cIt++) | ||
115 | { | ||
116 | setVar(cIt->first, (F32)(LLSD::Real)cIt->second); | ||
117 | } | ||
118 | } | ||
119 | */ | ||
120 | |||
121 | bool LLCalc::evalString(const std::string& expression, F32& result) | ||
122 | { | ||
123 | using namespace boost::spirit; | ||
124 | |||
125 | std::string expr_upper = expression; | ||
126 | LLStringUtil::toUpper(expr_upper); | ||
127 | |||
128 | LLCalcParser calc(result, mConstants, mVariables); | ||
129 | |||
130 | mLastErrorPos = 0; | ||
131 | std::string::iterator start = expr_upper.begin(); | ||
132 | parse_info<std::string::iterator> info; | ||
133 | |||
134 | try | ||
135 | { | ||
136 | info = parse(start, expr_upper.end(), calc, space_p); | ||
137 | lldebugs << "Math expression: " << expression << " = " << result << llendl; | ||
138 | } | ||
139 | catch(parser_error<std::string, std::string::iterator> &e) | ||
140 | { | ||
141 | mLastErrorPos = e.where - expr_upper.begin(); | ||
142 | |||
143 | llinfos << "Calc parser exception: " << e.descriptor << " at " << mLastErrorPos << " in expression: " << expression << llendl; | ||
144 | return false; | ||
145 | } | ||
146 | |||
147 | if (!info.full) | ||
148 | { | ||
149 | mLastErrorPos = info.stop - expr_upper.begin(); | ||
150 | llinfos << "Unhandled syntax error at " << mLastErrorPos << " in expression: " << expression << llendl; | ||
151 | return false; | ||
152 | } | ||
153 | |||
154 | return true; | ||
155 | } | ||
diff --git a/linden/indra/llmath/llcalc.h b/linden/indra/llmath/llcalc.h new file mode 100644 index 0000000..a376895 --- /dev/null +++ b/linden/indra/llmath/llcalc.h | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * LLCalc.h | ||
3 | * SecondLife | ||
4 | * | ||
5 | * Created by Aimee Walton on 28/09/2008. | ||
6 | * Copyright 2008 Aimee Walton. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #ifndef LL_CALC_H | ||
11 | #define LL_CALC_H | ||
12 | |||
13 | #include <map> | ||
14 | #include <string> | ||
15 | |||
16 | //#include "llsd.h" | ||
17 | |||
18 | class LLCalc | ||
19 | { | ||
20 | public: | ||
21 | LLCalc(); | ||
22 | ~LLCalc(); | ||
23 | |||
24 | // Variable name constants | ||
25 | static const char* X_POS; | ||
26 | static const char* Y_POS; | ||
27 | static const char* Z_POS; | ||
28 | static const char* X_SCALE; | ||
29 | static const char* Y_SCALE; | ||
30 | static const char* Z_SCALE; | ||
31 | static const char* X_ROT; | ||
32 | static const char* Y_ROT; | ||
33 | static const char* Z_ROT; | ||
34 | static const char* HOLLOW; | ||
35 | static const char* CUT_BEGIN; | ||
36 | static const char* CUT_END; | ||
37 | static const char* PATH_BEGIN; | ||
38 | static const char* PATH_END; | ||
39 | static const char* TWIST_BEGIN; | ||
40 | static const char* TWIST_END; | ||
41 | static const char* X_SHEAR; | ||
42 | static const char* Y_SHEAR; | ||
43 | static const char* X_TAPER; | ||
44 | static const char* Y_TAPER; | ||
45 | static const char* RADIUS_OFFSET; | ||
46 | static const char* REVOLUTIONS; | ||
47 | static const char* SKEW; | ||
48 | static const char* X_HOLE; | ||
49 | static const char* Y_HOLE; | ||
50 | static const char* TEX_U_SCALE; | ||
51 | static const char* TEX_V_SCALE; | ||
52 | static const char* TEX_U_OFFSET; | ||
53 | static const char* TEX_V_OFFSET; | ||
54 | static const char* TEX_ROTATION; | ||
55 | static const char* TEX_TRANSPARENCY; | ||
56 | static const char* TEX_GLOW; | ||
57 | |||
58 | void setVar(const std::string& name, const F32& value); | ||
59 | void clearVar(const std::string& name); | ||
60 | void clearAllVariables(); | ||
61 | // void updateVariables(LLSD& vars); | ||
62 | |||
63 | bool evalString(const std::string& expression, F32& result); | ||
64 | std::string::size_type getLastErrorPos() { return mLastErrorPos; } | ||
65 | |||
66 | static LLCalc* getInstance(); | ||
67 | static void cleanUp(); | ||
68 | |||
69 | typedef std::map<std::string, F32> calc_map_t; | ||
70 | |||
71 | private: | ||
72 | std::string::size_type mLastErrorPos; | ||
73 | |||
74 | calc_map_t* mConstants; | ||
75 | calc_map_t* mVariables; | ||
76 | |||
77 | // *TODO: Add support for storing user defined variables, and stored functions. | ||
78 | // Will need UI work, and a means to save them between sessions. | ||
79 | // calc_map_t* mUserVariables; | ||
80 | |||
81 | // "There shall be only one" | ||
82 | static LLCalc* sInstance; | ||
83 | }; | ||
84 | |||
85 | #endif // LL_CALC_H | ||
diff --git a/linden/indra/llmath/llcalcparser.cpp b/linden/indra/llmath/llcalcparser.cpp new file mode 100644 index 0000000..1546c09 --- /dev/null +++ b/linden/indra/llmath/llcalcparser.cpp | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * LLCalcParser.cpp | ||
3 | * SecondLife | ||
4 | * | ||
5 | * Created by Aimee Walton on 28/09/2008. | ||
6 | * Copyright 2008 Aimee Walton. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include "linden_common.h" | ||
11 | |||
12 | #include "llcalcparser.h" | ||
13 | |||
14 | F32 LLCalcParser::lookup(const std::string::iterator& start, const std::string::iterator& end) const | ||
15 | { | ||
16 | LLCalc::calc_map_t::iterator iter; | ||
17 | |||
18 | std::string name(start, end); | ||
19 | |||
20 | if (mConstants) | ||
21 | { | ||
22 | iter = mConstants->find(name); | ||
23 | if (iter != mConstants->end()) | ||
24 | { | ||
25 | return (*iter).second; | ||
26 | } | ||
27 | } | ||
28 | else | ||
29 | { | ||
30 | // This should never happen! | ||
31 | boost::spirit::throw_(end, std::string("Missing constants table")); | ||
32 | } | ||
33 | |||
34 | if (mVariables) | ||
35 | { | ||
36 | iter = mVariables->find(name); | ||
37 | if (iter != mVariables->end()) | ||
38 | { | ||
39 | return (*iter).second; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | boost::spirit::throw_(end, std::string("Unknown symbol " + name)); | ||
44 | return 0.f; | ||
45 | } | ||
diff --git a/linden/indra/llmath/llcalcparser.h b/linden/indra/llmath/llcalcparser.h new file mode 100644 index 0000000..c405b62 --- /dev/null +++ b/linden/indra/llmath/llcalcparser.h | |||
@@ -0,0 +1,155 @@ | |||
1 | /* | ||
2 | * LLCalcParser.h | ||
3 | * SecondLife | ||
4 | * | ||
5 | * Created by Aimee Walton on 28/09/2008. | ||
6 | * Copyright 2008 Aimee Walton. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #ifndef LL_CALCPARSER_H | ||
11 | #define LL_CALCPARSER_H | ||
12 | |||
13 | #include <boost/spirit/attribute.hpp> | ||
14 | #include <boost/spirit/core.hpp> | ||
15 | #include <boost/spirit/error_handling.hpp> | ||
16 | #include <boost/spirit/iterator/position_iterator.hpp> | ||
17 | #include <boost/spirit/phoenix/binders.hpp> | ||
18 | //#include <boost/spirit/symbols/symbols.hpp> | ||
19 | #include <map> | ||
20 | #include <string> | ||
21 | |||
22 | #include "llcalc.h" | ||
23 | #include "llmath.h" | ||
24 | |||
25 | struct LLCalcParser : boost::spirit::grammar<LLCalcParser> | ||
26 | { | ||
27 | LLCalcParser(F32& result, LLCalc::calc_map_t* constants, LLCalc::calc_map_t* vars) : | ||
28 | mResult(result), mConstants(constants), mVariables(vars) {}; | ||
29 | |||
30 | struct value_closure : boost::spirit::closure<value_closure, F32> | ||
31 | { | ||
32 | member1 value; | ||
33 | }; | ||
34 | |||
35 | template <typename ScannerT> | ||
36 | struct definition | ||
37 | { | ||
38 | // Rule declarations | ||
39 | boost::spirit::rule<ScannerT> statement, identifier; | ||
40 | boost::spirit::rule<ScannerT, value_closure::context_t> expression, term, | ||
41 | power, | ||
42 | unary_expr, | ||
43 | factor, | ||
44 | /*unary_func, | ||
45 | /binary_func,*/ | ||
46 | group; | ||
47 | |||
48 | // start() should return the starting symbol | ||
49 | boost::spirit::rule<ScannerT> const& start() const { return statement; } | ||
50 | |||
51 | definition(LLCalcParser const& self) | ||
52 | { | ||
53 | using namespace boost::spirit; | ||
54 | using namespace phoenix; | ||
55 | |||
56 | assertion<std::string> assert_domain("Domain error"); | ||
57 | // assertion<std::string> assert_symbol("Unknown symbol"); | ||
58 | assertion<std::string> assert_syntax("Syntax error"); | ||
59 | |||
60 | identifier = | ||
61 | lexeme_d[(alpha_p | '_') >> *(alnum_p | '_')] | ||
62 | ; | ||
63 | |||
64 | group = | ||
65 | '(' >> expression[group.value = arg1] >> assert_syntax(ch_p(')')) | ||
66 | ; | ||
67 | |||
68 | /*unary_func = | ||
69 | ((str_p("SIN") >> '(' >> expression[unary_func.value = bind(&sin)(DEG_TO_RAD * arg1)]) | | ||
70 | (str_p("COS") >> '(' >> expression[unary_func.value = bind(&cos)(DEG_TO_RAD * arg1)]) | | ||
71 | (str_p("TAN") >> '(' >> expression[unary_func.value = bind(&tan)(DEG_TO_RAD * arg1)]) | | ||
72 | (str_p("ASIN") >> '(' >> expression[unary_func.value = (bind(&asin)(arg1)) * RAD_TO_DEG]) | | ||
73 | (str_p("ACOS") >> '(' >> expression[unary_func.value = bind(&acos)(arg1) * RAD_TO_DEG]) | | ||
74 | (str_p("ATAN") >> '(' >> expression[unary_func.value = bind(&atan)(arg1) * RAD_TO_DEG]) | | ||
75 | (str_p("SQRT") >> '(' >> expression[unary_func.value = bind(&sqrt)(arg1)]) | | ||
76 | (str_p("LOG") >> '(' >> expression[unary_func.value = bind(&log)(arg1)]) | | ||
77 | (str_p("EXP") >> '(' >> expression[unary_func.value = bind(&exp)(arg1)]) | | ||
78 | (str_p("ABS") >> '(' >> expression[unary_func.value = bind(&fabs)(arg1)]) | ||
79 | ) >> assert_syntax(ch_p(')')) | ||
80 | ; | ||
81 | |||
82 | binary_func = | ||
83 | ((str_p("ATAN2") >> '(' >> expression[binary_func.value = arg1] >> ',' >> | ||
84 | expression[binary_func.value = bind(&atan2)(binary_func.value, arg1) * RAD_TO_DEG]) | | ||
85 | (str_p("MIN") >> '(' >> expression[binary_func.value = arg1] >> ',' >> | ||
86 | expression[binary_func.value = bind(&LLCalcParser::min)(self, binary_func.value, arg1)]) | | ||
87 | (str_p("MAX") >> '(' >> expression[binary_func.value = arg1] >> ',' >> | ||
88 | expression[binary_func.value = bind(&LLCalcParser::max)(self, binary_func.value, arg1)]) | ||
89 | ) >> assert_syntax(ch_p(')')) | ||
90 | ;*/ | ||
91 | |||
92 | // *TODO: Localisation of the decimal point? | ||
93 | // Problem, LLLineEditor::postvalidateFloat accepts a comma when appropriate | ||
94 | // for the current locale. However to do that here could clash with using | ||
95 | // the comma as a separator when passing arguments to functions. | ||
96 | factor = | ||
97 | (ureal_p[factor.value = arg1] | | ||
98 | group[factor.value = arg1] | | ||
99 | /*unary_func[factor.value = arg1] | | ||
100 | binary_func[factor.value = arg1] |*/ | ||
101 | // Lookup throws an Unknown Symbol error if it is unknown, while this works fine, | ||
102 | // would be "neater" to handle symbol lookup from here with an assertive parser. | ||
103 | // constants_p[factor.value = arg1]| | ||
104 | identifier[factor.value = bind(&LLCalcParser::lookup)(self, arg1, arg2)] | ||
105 | ) >> | ||
106 | // Detect and throw math errors. | ||
107 | assert_domain(eps_p(bind(&LLCalcParser::checkNaN)(self, factor.value))) | ||
108 | ; | ||
109 | |||
110 | unary_expr = | ||
111 | !ch_p('+') >> factor[unary_expr.value = arg1] | | ||
112 | '-' >> factor[unary_expr.value = -arg1] | ||
113 | ; | ||
114 | |||
115 | power = | ||
116 | unary_expr[power.value = arg1] >> | ||
117 | *('^' >> assert_syntax(unary_expr[power.value = bind(&powf)(power.value, arg1)])) | ||
118 | ; | ||
119 | |||
120 | term = | ||
121 | power[term.value = arg1] >> | ||
122 | *(('*' >> assert_syntax(power[term.value *= arg1])) | | ||
123 | ('/' >> assert_syntax(power[term.value /= arg1])) | ||
124 | ) | ||
125 | ; | ||
126 | |||
127 | expression = | ||
128 | assert_syntax(term[expression.value = arg1]) >> | ||
129 | *(('+' >> assert_syntax(term[expression.value += arg1])) | | ||
130 | ('-' >> assert_syntax(term[expression.value -= arg1])) | ||
131 | ) | ||
132 | ; | ||
133 | |||
134 | statement = | ||
135 | !ch_p('=') >> ( expression )[var(self.mResult) = arg1] >> (end_p) | ||
136 | ; | ||
137 | } | ||
138 | }; | ||
139 | |||
140 | private: | ||
141 | // Member functions for semantic actions | ||
142 | F32 lookup(const std::string::iterator&, const std::string::iterator&) const; | ||
143 | F32 min(const F32& a, const F32& b) const { return llmin(a, b); } | ||
144 | F32 max(const F32& a, const F32& b) const { return llmax(a, b); } | ||
145 | |||
146 | bool checkNaN(const F32& a) const { return !llisnan(a); } | ||
147 | |||
148 | LLCalc::calc_map_t* mConstants; | ||
149 | LLCalc::calc_map_t* mVariables; | ||
150 | // LLCalc::calc_map_t* mUserVariables; | ||
151 | |||
152 | F32& mResult; | ||
153 | }; | ||
154 | |||
155 | #endif // LL_CALCPARSER_H | ||