diff options
Diffstat (limited to 'linden/indra/newview/llhudeffectlookat.cpp')
-rw-r--r-- | linden/indra/newview/llhudeffectlookat.cpp | 239 |
1 files changed, 182 insertions, 57 deletions
diff --git a/linden/indra/newview/llhudeffectlookat.cpp b/linden/indra/newview/llhudeffectlookat.cpp index da0ec60..6922f29 100644 --- a/linden/indra/newview/llhudeffectlookat.cpp +++ b/linden/indra/newview/llhudeffectlookat.cpp | |||
@@ -39,6 +39,10 @@ | |||
39 | #include "llselectmgr.h" | 39 | #include "llselectmgr.h" |
40 | #include "llglheaders.h" | 40 | #include "llglheaders.h" |
41 | 41 | ||
42 | |||
43 | #include "llxmltree.h" | ||
44 | |||
45 | |||
42 | BOOL LLHUDEffectLookAt::sDebugLookAt = FALSE; | 46 | BOOL LLHUDEffectLookAt::sDebugLookAt = FALSE; |
43 | 47 | ||
44 | // packet layout | 48 | // packet layout |
@@ -54,69 +58,179 @@ const F32 MAX_SENDS_PER_SEC = 4.f; | |||
54 | const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; | 58 | const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; |
55 | const F32 MIN_TARGET_OFFSET_SQUARED = 0.0001f; | 59 | const F32 MIN_TARGET_OFFSET_SQUARED = 0.0001f; |
56 | 60 | ||
57 | // timeouts | 61 | |
58 | // can't use actual F32_MAX, because we add this to the current frametime | 62 | // can't use actual F32_MAX, because we add this to the current frametime |
59 | const F32 MAX_TIMEOUT = F32_MAX / 2.f; | 63 | const F32 MAX_TIMEOUT = F32_MAX / 2.f; |
60 | 64 | ||
61 | const F32 LOOKAT_TIMEOUTS[LOOKAT_NUM_TARGETS] = | 65 | /** |
66 | * Simple data class holding values for a particular type of attention. | ||
67 | */ | ||
68 | class LLAttention | ||
62 | { | 69 | { |
63 | MAX_TIMEOUT, //LOOKAT_TARGET_NONE | 70 | public: |
64 | 3.f, //LOOKAT_TARGET_IDLE | 71 | LLAttention(){} |
65 | 4.f, //LOOKAT_TARGET_AUTO_LISTEN | 72 | LLAttention(F32 timeout, F32 priority, char *name, LLColor3 color) : |
66 | 2.f, //LOOKAT_TARGET_FREELOOK | 73 | mTimeout(timeout), mPriority(priority), mName(name), mColor(color) |
67 | 4.f, //LOOKAT_TARGET_RESPOND | 74 | { |
68 | 1.f, //LOOKAT_TARGET_HOVER | 75 | } |
69 | MAX_TIMEOUT, //LOOKAT_TARGET_CONVERSATION | 76 | F32 mTimeout, mPriority; |
70 | MAX_TIMEOUT, //LOOKAT_TARGET_SELECT | 77 | LLString mName; |
71 | MAX_TIMEOUT, //LOOKAT_TARGET_FOCUS | 78 | LLColor3 mColor; |
72 | MAX_TIMEOUT, //LOOKAT_TARGET_MOUSELOOK | ||
73 | 0.f, //LOOKAT_TARGET_CLEAR | ||
74 | }; | 79 | }; |
75 | 80 | ||
76 | const S32 LOOKAT_PRIORITIES[LOOKAT_NUM_TARGETS] = | 81 | /** |
82 | * Simple data class holding a list of attentions, one for every type. | ||
83 | */ | ||
84 | class LLAttentionSet | ||
77 | { | 85 | { |
78 | 0, //LOOKAT_TARGET_NONE | 86 | public: |
79 | 1, //LOOKAT_TARGET_IDLE | 87 | LLAttentionSet(const LLAttention attentions[]) |
80 | 3, //LOOKAT_TARGET_AUTO_LISTEN | 88 | { |
81 | 2, //LOOKAT_TARGET_FREELOOK | 89 | for(int i=0; i<LOOKAT_NUM_TARGETS; i++) |
82 | 3, //LOOKAT_TARGET_RESPOND | 90 | { |
83 | 4, //LOOKAT_TARGET_HOVER | 91 | mAttentions[i] = attentions[i]; |
84 | 5, //LOOKAT_TARGET_CONVERSATION | 92 | } |
85 | 6, //LOOKAT_TARGET_SELECT | 93 | } |
86 | 6, //LOOKAT_TARGET_FOCUS | 94 | LLAttention mAttentions[LOOKAT_NUM_TARGETS]; |
87 | 7, //LOOKAT_TARGET_MOUSELOOK | 95 | LLAttention& operator[](int idx) { return mAttentions[idx]; } |
88 | 8, //LOOKAT_TARGET_CLEAR | ||
89 | }; | 96 | }; |
90 | 97 | ||
91 | const char *LOOKAT_STRINGS[] = | 98 | // Default attribute set data. |
99 | // Used to initialize the global attribute set objects, one of which will be | ||
100 | // refered to by the hud object at any given time. | ||
101 | // Note that the values below are only the default values and that any or all of them | ||
102 | // can be overwritten with customizing data from the XML file. The actual values below | ||
103 | // are those that will give exactly the same look-at behavior as before the ability | ||
104 | // to customize was added. - MG | ||
105 | static const | ||
106 | LLAttention | ||
107 | BOY_ATTS[] = { // default set of masculine attentions | ||
108 | LLAttention(MAX_TIMEOUT, 0, "None", LLColor3(0.3f, 0.3f, 0.3f)), // LOOKAT_TARGET_NONE | ||
109 | LLAttention(3.f, 1, "Idle", LLColor3(0.5f, 0.5f, 0.5f)), // LOOKAT_TARGET_IDLE | ||
110 | LLAttention(4.f, 3, "AutoListen", LLColor3(0.5f, 0.5f, 0.5f)), // LOOKAT_TARGET_AUTO_LISTEN | ||
111 | LLAttention(2.f, 2, "FreeLook", LLColor3(0.5f, 0.5f, 0.9f)), // LOOKAT_TARGET_FREELOOK | ||
112 | LLAttention(4.f, 3, "Respond", LLColor3(0.0f, 0.0f, 0.0f)), // LOOKAT_TARGET_RESPOND | ||
113 | LLAttention(1.f, 4, "Hover", LLColor3(0.5f, 0.9f, 0.5f)), // LOOKAT_TARGET_HOVER | ||
114 | LLAttention(MAX_TIMEOUT, 0, "Conversation", LLColor3(0.1f, 0.1f, 0.5f)), // LOOKAT_TARGET_CONVERSATION | ||
115 | LLAttention(MAX_TIMEOUT, 6, "Select", LLColor3(0.9f, 0.5f, 0.5f)), // LOOKAT_TARGET_SELECT | ||
116 | LLAttention(MAX_TIMEOUT, 6, "Focus", LLColor3(0.9f, 0.5f, 0.9f)), // LOOKAT_TARGET_FOCUS | ||
117 | LLAttention(MAX_TIMEOUT, 7, "Mouselook", LLColor3(0.9f, 0.9f, 0.5f)), // LOOKAT_TARGET_MOUSELOOK | ||
118 | LLAttention(0.f, 8, "Clear", LLColor3(1.0f, 1.0f, 1.0f)), // LOOKAT_TARGET_CLEAR | ||
119 | }, | ||
120 | GIRL_ATTS[] = { // default set of feminine attentions | ||
121 | LLAttention(MAX_TIMEOUT, 0, "None", LLColor3(0.3f, 0.3f, 0.3f)), // LOOKAT_TARGET_NONE | ||
122 | LLAttention(3.f, 1, "Idle", LLColor3(0.5f, 0.5f, 0.5f)), // LOOKAT_TARGET_IDLE | ||
123 | LLAttention(4.f, 3, "AutoListen", LLColor3(0.5f, 0.5f, 0.5f)), // LOOKAT_TARGET_AUTO_LISTEN | ||
124 | LLAttention(2.f, 2, "FreeLook", LLColor3(0.5f, 0.5f, 0.9f)), // LOOKAT_TARGET_FREELOOK | ||
125 | LLAttention(4.f, 3, "Respond", LLColor3(0.0f, 0.0f, 0.0f)), // LOOKAT_TARGET_RESPOND | ||
126 | LLAttention(1.f, 4, "Hover", LLColor3(0.5f, 0.9f, 0.5f)), // LOOKAT_TARGET_HOVER | ||
127 | LLAttention(MAX_TIMEOUT, 0, "Conversation", LLColor3(0.1f, 0.1f, 0.5f)), // LOOKAT_TARGET_CONVERSATION | ||
128 | LLAttention(MAX_TIMEOUT, 6, "Select", LLColor3(0.9f, 0.5f, 0.5f)), // LOOKAT_TARGET_SELECT | ||
129 | LLAttention(MAX_TIMEOUT, 6, "Focus", LLColor3(0.9f, 0.5f, 0.9f)), // LOOKAT_TARGET_FOCUS | ||
130 | LLAttention(MAX_TIMEOUT, 7, "Mouselook", LLColor3(0.9f, 0.9f, 0.5f)), // LOOKAT_TARGET_MOUSELOOK | ||
131 | LLAttention(0.f, 8, "Clear", LLColor3(1.0f, 1.0f, 1.0f)), // LOOKAT_TARGET_CLEAR | ||
132 | }; | ||
133 | |||
134 | static LLAttentionSet | ||
135 | gBoyAttentions(BOY_ATTS), | ||
136 | gGirlAttentions(GIRL_ATTS); | ||
137 | |||
138 | |||
139 | static BOOL loadGender(LLXmlTreeNode* gender) | ||
92 | { | 140 | { |
93 | "None", //LOOKAT_TARGET_NONE | 141 | if( !gender) |
94 | "Idle", //LOOKAT_TARGET_IDLE | 142 | { |
95 | "AutoListen", //LOOKAT_TARGET_AUTO_LISTEN | 143 | return FALSE; |
96 | "FreeLook", //LOOKAT_TARGET_FREELOOK | 144 | } |
97 | "Respond", //LOOKAT_TARGET_RESPOND | 145 | LLString str; |
98 | "Hover", //LOOKAT_TARGET_HOVER | 146 | gender->getAttributeString("name", str); |
99 | "Conversation", //LOOKAT_TARGET_CONVERSATION | 147 | LLAttentionSet& attentions = (str.compare("Masculine") == 0) ? gBoyAttentions : gGirlAttentions; |
100 | "Select", //LOOKAT_TARGET_SELECT | 148 | for (LLXmlTreeNode* attention_node = gender->getChildByName( "param" ); |
101 | "Focus", //LOOKAT_TARGET_FOCUS | 149 | attention_node; |
102 | "Mouselook", //LOOKAT_TARGET_MOUSELOOK | 150 | attention_node = gender->getNextNamedChild()) |
103 | "Clear", //LOOKAT_TARGET_CLEAR | 151 | { |
104 | }; | 152 | attention_node->getAttributeString("attention", str); |
153 | LLAttention* attention; | ||
154 | if (str == "idle") attention = &attentions[LOOKAT_TARGET_IDLE]; | ||
155 | else if(str == "auto_listen") attention = &attentions[LOOKAT_TARGET_AUTO_LISTEN]; | ||
156 | else if(str == "freelook") attention = &attentions[LOOKAT_TARGET_FREELOOK]; | ||
157 | else if(str == "respond") attention = &attentions[LOOKAT_TARGET_RESPOND]; | ||
158 | else if(str == "hover") attention = &attentions[LOOKAT_TARGET_HOVER]; | ||
159 | else if(str == "conversation") attention = &attentions[LOOKAT_TARGET_CONVERSATION]; | ||
160 | else if(str == "select") attention = &attentions[LOOKAT_TARGET_SELECT]; | ||
161 | else if(str == "focus") attention = &attentions[LOOKAT_TARGET_FOCUS]; | ||
162 | else if(str == "mouselook") attention = &attentions[LOOKAT_TARGET_MOUSELOOK]; | ||
163 | else return FALSE; | ||
164 | |||
165 | F32 priority, timeout; | ||
166 | attention_node->getAttributeF32("priority", priority); | ||
167 | attention_node->getAttributeF32("timeout", timeout); | ||
168 | if(timeout < 0) timeout = MAX_TIMEOUT; | ||
169 | attention->mPriority = priority; | ||
170 | attention->mTimeout = timeout; | ||
171 | } | ||
172 | return TRUE; | ||
173 | } | ||
105 | 174 | ||
106 | const LLColor3 LOOKAT_COLORS[LOOKAT_NUM_TARGETS] = | 175 | static BOOL loadAttentions() |
107 | { | 176 | { |
108 | LLColor3(0.3f, 0.3f, 0.3f), //LOOKAT_TARGET_NONE | 177 | static BOOL first_time = TRUE; |
109 | LLColor3(0.5f, 0.5f, 0.5f), //LOOKAT_TARGET_IDLE | 178 | if( ! first_time) |
110 | LLColor3(0.5f, 0.5f, 0.5f), //LOOKAT_TARGET_AUTO_LISTEN | 179 | { |
111 | LLColor3(0.5f, 0.5f, 0.9f), //LOOKAT_TARGET_FREELOOK | 180 | return TRUE; // maybe not ideal but otherwise it can continue to fail forever. |
112 | LLColor3(0.f, 0.f, 0.f), //LOOKAT_TARGET_RESPOND | 181 | } |
113 | LLColor3(0.5f, 0.9f, 0.5f), //LOOKAT_TARGET_HOVER | 182 | first_time = FALSE; |
114 | LLColor3(0.1f, 0.1f, 0.5f), //LOOKAT_TARGET_CONVERSATION | 183 | |
115 | LLColor3(0.9f, 0.5f, 0.5f), //LOOKAT_TARGET_SELECT | 184 | char filename[MAX_PATH]; /*Flawfinder: ignore*/ |
116 | LLColor3(0.9f, 0.5f, 0.9f), //LOOKAT_TARGET_FOCUS | 185 | strncpy(filename,gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"attentions.xml").c_str(), sizeof(filename) -1); /*Flawfinder: ignore*/ |
117 | LLColor3(0.9f, 0.9f, 0.5f), //LOOKAT_TARGET_MOUSELOOK | 186 | filename[sizeof(filename) -1] = '\0'; |
118 | LLColor3(1.f, 1.f, 1.f), //LOOKAT_TARGET_CLEAR | 187 | LLXmlTree xml_tree; |
119 | }; | 188 | BOOL success = xml_tree.parseFile( filename, FALSE ); |
189 | if( !success ) | ||
190 | { | ||
191 | return FALSE; | ||
192 | } | ||
193 | LLXmlTreeNode* root = xml_tree.getRoot(); | ||
194 | if( !root ) | ||
195 | { | ||
196 | return FALSE; | ||
197 | } | ||
198 | |||
199 | //------------------------------------------------------------------------- | ||
200 | // <linden_attentions version="1.0"> (root) | ||
201 | //------------------------------------------------------------------------- | ||
202 | if( !root->hasName( "linden_attentions" ) ) | ||
203 | { | ||
204 | llwarns << "Invalid linden_attentions file header: " << filename << llendl; | ||
205 | return FALSE; | ||
206 | } | ||
207 | |||
208 | LLString version; | ||
209 | static LLStdStringHandle version_string = LLXmlTree::addAttributeString("version"); | ||
210 | if( !root->getFastAttributeString( version_string, version ) || (version != "1.0") ) | ||
211 | { | ||
212 | llwarns << "Invalid linden_attentions file version: " << version << llendl; | ||
213 | return FALSE; | ||
214 | } | ||
215 | |||
216 | //------------------------------------------------------------------------- | ||
217 | // <gender> | ||
218 | //------------------------------------------------------------------------- | ||
219 | for (LLXmlTreeNode* child = root->getChildByName( "gender" ); | ||
220 | child; | ||
221 | child = root->getNextNamedChild()) | ||
222 | { | ||
223 | if( !loadGender( child ) ) | ||
224 | { | ||
225 | return FALSE; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | return TRUE; | ||
230 | } | ||
231 | |||
232 | |||
233 | |||
120 | 234 | ||
121 | //----------------------------------------------------------------------------- | 235 | //----------------------------------------------------------------------------- |
122 | // LLHUDEffectLookAt() | 236 | // LLHUDEffectLookAt() |
@@ -127,6 +241,10 @@ LLHUDEffectLookAt::LLHUDEffectLookAt(const U8 type) : | |||
127 | mLastSendTime(0.f) | 241 | mLastSendTime(0.f) |
128 | { | 242 | { |
129 | clearLookAtTarget(); | 243 | clearLookAtTarget(); |
244 | // parse the default sets | ||
245 | loadAttentions(); | ||
246 | // initialize current attention set. switches when avatar sex changes. | ||
247 | mAttentions = &gGirlAttentions; | ||
130 | } | 248 | } |
131 | 249 | ||
132 | //----------------------------------------------------------------------------- | 250 | //----------------------------------------------------------------------------- |
@@ -280,7 +398,7 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec | |||
280 | llassert(target_type < LOOKAT_NUM_TARGETS); | 398 | llassert(target_type < LOOKAT_NUM_TARGETS); |
281 | 399 | ||
282 | // must be same or higher priority than existing effect | 400 | // must be same or higher priority than existing effect |
283 | if (LOOKAT_PRIORITIES[target_type] < LOOKAT_PRIORITIES[mTargetType]) | 401 | if ((*mAttentions)[target_type].mPriority < (*mAttentions)[mTargetType].mPriority) |
284 | { | 402 | { |
285 | return FALSE; | 403 | return FALSE; |
286 | } | 404 | } |
@@ -288,8 +406,7 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec | |||
288 | F32 current_time = mTimer.getElapsedTimeF32(); | 406 | F32 current_time = mTimer.getElapsedTimeF32(); |
289 | 407 | ||
290 | // type of lookat behavior or target object has changed | 408 | // type of lookat behavior or target object has changed |
291 | BOOL lookAtChanged = (target_type != mTargetType) || | 409 | BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); |
292 | (object != mTargetObject); | ||
293 | 410 | ||
294 | // lookat position has moved a certain amount and we haven't just sent an update | 411 | // lookat position has moved a certain amount and we haven't just sent an update |
295 | lookAtChanged = lookAtChanged || (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && | 412 | lookAtChanged = lookAtChanged || (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && |
@@ -298,7 +415,8 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec | |||
298 | if (lookAtChanged) | 415 | if (lookAtChanged) |
299 | { | 416 | { |
300 | mLastSentOffsetGlobal = position; | 417 | mLastSentOffsetGlobal = position; |
301 | setDuration(LOOKAT_TIMEOUTS[target_type]); | 418 | F32 timeout = (*mAttentions)[target_type].mTimeout; |
419 | setDuration(timeout); | ||
302 | setNeedsSendToSim(TRUE); | 420 | setNeedsSendToSim(TRUE); |
303 | } | 421 | } |
304 | 422 | ||
@@ -379,7 +497,7 @@ void LLHUDEffectLookAt::render() | |||
379 | glScalef(0.3f, 0.3f, 0.3f); | 497 | glScalef(0.3f, 0.3f, 0.3f); |
380 | glBegin(GL_LINES); | 498 | glBegin(GL_LINES); |
381 | { | 499 | { |
382 | LLColor3 color = LOOKAT_COLORS[mTargetType]; | 500 | LLColor3 color = (*mAttentions)[mTargetType].mColor; |
383 | glColor3f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]); | 501 | glColor3f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE]); |
384 | glVertex3f(-1.f, 0.f, 0.f); | 502 | glVertex3f(-1.f, 0.f, 0.f); |
385 | glVertex3f(1.f, 0.f, 0.f); | 503 | glVertex3f(1.f, 0.f, 0.f); |
@@ -412,6 +530,13 @@ void LLHUDEffectLookAt::update() | |||
412 | return; | 530 | return; |
413 | } | 531 | } |
414 | 532 | ||
533 | // make sure the proper set of avatar attention are currently being used. | ||
534 | LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; | ||
535 | // for now the first cut will just switch on sex. future development could adjust | ||
536 | // timeouts according to avatar age and/or other features. | ||
537 | mAttentions = (source_avatar->getSex() == SEX_MALE) ? &gBoyAttentions : &gGirlAttentions; | ||
538 | //printf("updated to %s\n", (source_avatar->getSex() == SEX_MALE) ? "male" : "female"); | ||
539 | |||
415 | F32 time = mTimer.getElapsedTimeF32(); | 540 | F32 time = mTimer.getElapsedTimeF32(); |
416 | 541 | ||
417 | // clear out the effect if time is up | 542 | // clear out the effect if time is up |
@@ -438,7 +563,7 @@ void LLHUDEffectLookAt::update() | |||
438 | 563 | ||
439 | if (sDebugLookAt) | 564 | if (sDebugLookAt) |
440 | { | 565 | { |
441 | ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->addDebugText(LOOKAT_STRINGS[mTargetType]); | 566 | ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->addDebugText((*mAttentions)[mTargetType].mName); |
442 | } | 567 | } |
443 | } | 568 | } |
444 | 569 | ||