1 /*
2 TODO:
3  * Get Roja working.
4  * New effect options.
5  * New effects.
6 */
7 
8 #ifdef EYE_CANDY
9 
10 #include "global.h"
11 #include "interface.h"
12 #include "elwindows.h"
13 #include "shadows.h"
14 #include "gui.h"
15 #include "editor.h"
16 
17 #include "../eye_candy/eye_candy.h"
18 #include <vector>
19 #include "eye_candy_window.h"
20 
21 extern "C"
22 {
23 int view_eye_candy_window=0;
24 int last_ec_index = -2;	// None selected.
25 int eye_candy_window = -1;
26 int eye_candy_confirmed = 0;
27 int eye_candy_initialized = 0;
28 int eye_candy_ready_to_add = 0;
29 }
30 
31 static int eye_candy_window_x=15;
32 static int eye_candy_window_y=50;
33 static int eye_candy_window_x_len=600;
34 static int eye_candy_window_y_len=470;
35 std::vector<EffectDefinition> effects;
36 EffectDefinition current_effect;
37 
create_eye_candy_window()38 extern "C" void create_eye_candy_window ()
39 {
40   if (eye_candy_window < 0)
41   {
42     eye_candy_window = create_window ("eye_candy", 0, 0, eye_candy_window_x, eye_candy_window_y, eye_candy_window_x_len, eye_candy_window_y_len, ELW_WIN_DEFAULT & ~ELW_SHOW);
43 
44     set_window_handler (eye_candy_window, ELW_HANDLER_DISPLAY, &display_eye_candy_window_handler);
45     set_window_handler (eye_candy_window, ELW_HANDLER_CLICK, &check_eye_candy_window_interface);
46   }
47 }
48 
change_eye_candy_effect()49 extern "C" void change_eye_candy_effect()
50 {
51   if (!eye_candy_initialized)
52     return;
53   current_effect.effect = gtk_combo_box_get_active(GTK_COMBO_BOX(gtk_effect_list));
54   current_effect.hue = GTK_ADJUSTMENT(gtk_effect_hue_obj)->value;
55   current_effect.saturation = GTK_ADJUSTMENT(gtk_effect_saturation_obj)->value;
56   current_effect.scale = GTK_ADJUSTMENT(gtk_effect_scale_obj)->value;
57   current_effect.density = GTK_ADJUSTMENT(gtk_effect_density_obj)->value;
58   current_effect.base_height = atoi(gtk_entry_get_text(GTK_ENTRY(gtk_effect_base_height)));
59   if (current_effect.reference)
60   {
61     ec_recall_effect(current_effect.reference);
62     current_effect.reference = NULL;
63   }
64   switch (current_effect.effect)
65   {
66     case 0:    // Fire
67       gtk_widget_show(gtk_effect_hue_box);
68       gtk_widget_show(gtk_effect_saturation_box);
69       gtk_widget_show(gtk_effect_scale_box);
70       gtk_widget_hide(gtk_effect_density_box);
71       gtk_widget_hide(gtk_effect_base_height_box);
72       current_effect.reference = ec_create_campfire(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, 10, current_effect.scale);
73       break;
74     case 1:    // Cloud/Fog
75       gtk_widget_show(gtk_effect_hue_box);
76       gtk_widget_show(gtk_effect_saturation_box);
77       gtk_widget_hide(gtk_effect_scale_box);
78       gtk_widget_show(gtk_effect_density_box);
79       gtk_widget_hide(gtk_effect_base_height_box);
80       current_effect.reference = ec_create_cloud(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.density, (current_effect.bounds.elements.size() > 1 ? &current_effect.bounds : &initial_bounds), 10);
81       break;
82     case 2:    // Fireflies
83       gtk_widget_show(gtk_effect_hue_box);
84       gtk_widget_show(gtk_effect_saturation_box);
85       gtk_widget_show(gtk_effect_scale_box);
86       gtk_widget_show(gtk_effect_density_box);
87       gtk_widget_hide(gtk_effect_base_height_box);
88       current_effect.reference = ec_create_fireflies(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.density, current_effect.scale, (current_effect.bounds.elements.size() > 1 ? &current_effect.bounds : &initial_bounds));
89       break;
90     case 3:    // Fountain
91       gtk_widget_show(gtk_effect_hue_box);
92       gtk_widget_show(gtk_effect_saturation_box);
93       gtk_widget_show(gtk_effect_scale_box);
94       gtk_widget_hide(gtk_effect_density_box);
95       gtk_widget_show(gtk_effect_base_height_box);
96       current_effect.reference = ec_create_fountain(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.base_height, false, current_effect.scale, 10);
97       break;
98     case 4:    // Lamp/Torch
99       gtk_widget_show(gtk_effect_hue_box);
100       gtk_widget_show(gtk_effect_saturation_box);
101       gtk_widget_show(gtk_effect_scale_box);
102       gtk_widget_hide(gtk_effect_density_box);
103       gtk_widget_hide(gtk_effect_base_height_box);
104       current_effect.reference = ec_create_lamp(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.scale, 10);
105       break;
106     case 5:    // Magic Protection
107       gtk_widget_show(gtk_effect_hue_box);
108       gtk_widget_show(gtk_effect_saturation_box);
109       gtk_widget_show(gtk_effect_scale_box);
110       gtk_widget_hide(gtk_effect_density_box);
111       gtk_widget_hide(gtk_effect_base_height_box);
112       current_effect.reference = ec_create_ongoing_magic_protection(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, 10, current_effect.scale);
113       break;
114     case 6:    // Shield
115       gtk_widget_show(gtk_effect_hue_box);
116       gtk_widget_show(gtk_effect_saturation_box);
117       gtk_widget_show(gtk_effect_scale_box);
118       gtk_widget_hide(gtk_effect_density_box);
119       gtk_widget_hide(gtk_effect_base_height_box);
120       current_effect.reference = ec_create_ongoing_shield(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, 10, current_effect.scale);
121       break;
122     case 7:    // Magic Immunity
123       gtk_widget_show(gtk_effect_hue_box);
124       gtk_widget_show(gtk_effect_saturation_box);
125       gtk_widget_show(gtk_effect_scale_box);
126       gtk_widget_hide(gtk_effect_density_box);
127       gtk_widget_hide(gtk_effect_base_height_box);
128       current_effect.reference = ec_create_ongoing_magic_immunity(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, 10, current_effect.scale);
129       break;
130     case 8:    // Poison
131       gtk_widget_show(gtk_effect_hue_box);
132       gtk_widget_show(gtk_effect_saturation_box);
133       gtk_widget_show(gtk_effect_scale_box);
134       gtk_widget_hide(gtk_effect_density_box);
135       gtk_widget_hide(gtk_effect_base_height_box);
136       current_effect.reference = ec_create_ongoing_poison(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, 10, current_effect.scale);
137       break;
138     case 9:    // Smoke
139       gtk_widget_show(gtk_effect_hue_box);
140       gtk_widget_show(gtk_effect_saturation_box);
141       gtk_widget_hide(gtk_effect_scale_box);
142       gtk_widget_show(gtk_effect_density_box);
143       gtk_widget_hide(gtk_effect_base_height_box);
144       current_effect.reference = ec_create_smoke(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.scale, 10);
145       break;
146     case 10:  // Teleporter
147       gtk_widget_show(gtk_effect_hue_box);
148       gtk_widget_show(gtk_effect_saturation_box);
149       gtk_widget_show(gtk_effect_scale_box);
150       gtk_widget_hide(gtk_effect_density_box);
151       gtk_widget_hide(gtk_effect_base_height_box);
152       current_effect.reference = ec_create_teleporter(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.scale, 10);
153       break;
154     case 11:  // Leaves
155       gtk_widget_show(gtk_effect_hue_box);
156       gtk_widget_show(gtk_effect_saturation_box);
157       gtk_widget_show(gtk_effect_scale_box);
158       gtk_widget_show(gtk_effect_density_box);
159       gtk_widget_hide(gtk_effect_base_height_box);
160 //      std::cout << "1: " << current_effect.hue << " / " << current_effect.saturation << " / " << current_effect.scale << " / " << current_effect.density << std::endl;
161       current_effect.reference = ec_create_wind_leaves(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.scale, current_effect.density, (current_effect.bounds.elements.size() > 1 ? &current_effect.bounds : &initial_bounds), 1.0, 0.0, 0.0);
162       break;
163     case 12:  // Flower Petals
164       gtk_widget_show(gtk_effect_hue_box);
165       gtk_widget_show(gtk_effect_saturation_box);
166       gtk_widget_show(gtk_effect_scale_box);
167       gtk_widget_show(gtk_effect_density_box);
168       gtk_widget_hide(gtk_effect_base_height_box);
169       current_effect.reference = ec_create_wind_petals(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.scale, current_effect.density, (current_effect.bounds.elements.size() > 1 ? &current_effect.bounds : &initial_bounds), 1.0, 0.0, 0.0);
170       break;
171     case 13:  // Waterfall
172       gtk_widget_show(gtk_effect_hue_box);
173       gtk_widget_show(gtk_effect_saturation_box);
174       gtk_widget_show(gtk_effect_scale_box);
175       gtk_widget_hide(gtk_effect_density_box);
176       gtk_widget_show(gtk_effect_base_height_box);
177 //      current_effect.reference = ec_create_waterfall(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation);
178       break;
179     case 14:  // Bees
180       gtk_widget_show(gtk_effect_hue_box);
181       gtk_widget_show(gtk_effect_saturation_box);
182       gtk_widget_show(gtk_effect_scale_box);
183       gtk_widget_show(gtk_effect_density_box);
184       gtk_widget_hide(gtk_effect_base_height_box);
185       current_effect.reference = NULL;
186 //      current_effect.reference = ec_create_bees(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation);
187       break;
188     case 15:  // Portal
189       gtk_widget_show(gtk_effect_hue_box);
190       gtk_widget_show(gtk_effect_saturation_box);
191       gtk_widget_show(gtk_effect_scale_box);
192       gtk_widget_hide(gtk_effect_density_box);
193       gtk_widget_hide(gtk_effect_base_height_box);
194       current_effect.reference = NULL;
195 //      current_effect.reference = ec_create_bees(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation);
196       break;
197     case 16:    // Candle
198       gtk_widget_show(gtk_effect_hue_box);
199       gtk_widget_show(gtk_effect_saturation_box);
200       gtk_widget_show(gtk_effect_scale_box);
201       gtk_widget_hide(gtk_effect_density_box);
202       gtk_widget_hide(gtk_effect_base_height_box);
203       current_effect.reference = ec_create_candle(current_effect.position.x, current_effect.position.y, current_effect.position.z, current_effect.hue, current_effect.saturation, current_effect.scale, 10);
204       break;
205   }
206 }
207 
remove_current_eye_candy_effect()208 extern "C" void remove_current_eye_candy_effect()
209 {
210   if (current_effect.reference)
211   {
212     ec_recall_effect(current_effect.reference);
213     current_effect.reference = NULL;
214   }
215 }
216 
confirm_eye_candy_effect()217 void confirm_eye_candy_effect()
218 {
219   eye_candy_confirmed = 1;
220   change_eye_candy_effect();
221   gtk_widget_hide(gtk_effect_win);
222   switch (current_effect.effect)
223   {
224     case 1:    // Cloud/Fog
225     case 2:    // Fireflies
226     case 11:   // Leaves
227     case 12:   // Flower Petals
228     {
229       current_effect.position = ec::Vec3(-1.0, -1.0, 0.0);
230       minimap_on = 1;
231       break;
232     }
233   }
234   eye_candy_ready_to_add = 1;
235 }
236 
display_eye_candy_window_handler()237 extern "C" int display_eye_candy_window_handler()
238 {
239   return 1;
240 }
241 
check_eye_candy_window_interface()242 extern "C" int check_eye_candy_window_interface()
243 {
244   return 1;
245 }
246 
update_eye_candy_position(float x,float y)247 extern "C" void update_eye_candy_position(float x, float y)
248 {
249   if (!minimap_on)
250   {
251     switch (current_effect.effect)
252     {
253       case 1:    // Cloud/Fog
254       case 2:    // Fireflies
255       case 11:   // Leaves
256       case 12:   // Flower Petals
257       {
258         if (current_effect.bounds.elements.size() > 1)
259           return;
260       }
261     }
262     current_effect.position.x = x;
263     current_effect.position.y = y;
264     if (current_effect.reference)
265       ec_set_position(current_effect.reference, x, y, current_effect.position.z);
266   }
267 }
268 
add_eye_candy_point()269 extern "C" void add_eye_candy_point()
270 {
271   int x0, y0, y1, width, height;
272   get_minimap_dimensions(&x0, &y0, &width, &height);
273   y1 = y0 + height;
274 
275   if (mouse_x < x0 || mouse_y < y0 || mouse_x > x0 + width || mouse_y > y1) return;
276 
277   float x = float(mouse_x - x0) * 3 * tile_map_size_x / width;
278   float y = float(y1 - mouse_y) * 3 * tile_map_size_y / height;
279   int x_tile = int(x) / 3;
280   int y_tile = int(y) / 3;
281   const float z = -2.2f + tile_map[y_tile*tile_map_size_x + x_tile] * 0.2f;
282 
283   if (left_click <= 1)
284   {
285     const bool ret = find_bounds_index(x, y);
286     if (!ret)  // Didn't click on anything; create new.
287     {
288       if ((current_effect.bounds.elements.size() == 0) && (current_effect.position == ec::Vec3(-1.0, -1.0, 0.0)))
289         current_effect.position = ec::Vec3(x, y, z);
290       else if (current_effect.bounds.elements.size() < 13)
291         current_effect.bounds.elements.insert(current_effect.bounds.elements.begin() + last_ec_index, angle_to(current_effect.position.x, current_effect.position.y, x, y));
292       else
293         ; // Can't add any more; too many already.
294     }
295   }
296   else
297   {
298     if (last_ec_index == -1)  // Clicked on the center; drag it.
299       current_effect.position = ec::Vec3(x, y, z);
300     else if (last_ec_index >= 0)      // Clicked on another point; drag it.
301     {
302       const ec::SmoothPolygonElement new_angle = angle_to(current_effect.position.x, current_effect.position.y, x, y);
303       current_effect.bounds.elements.erase(current_effect.bounds.elements.begin() + last_ec_index);
304       int i;
305       for (i = 0; i < (int)current_effect.bounds.elements.size(); i++)
306       {
307         if (new_angle.angle < current_effect.bounds.elements[i].angle)
308           break;
309       }
310       current_effect.bounds.elements.insert(current_effect.bounds.elements.begin() + i, new_angle);
311       last_ec_index = i;
312     }
313   }
314   change_eye_candy_effect();
315 }
316 
delete_eye_candy_point()317 extern "C" void delete_eye_candy_point()
318 {
319   int x0, y0, y1, width, height;
320   get_minimap_dimensions(&x0, &y0, &width, &height);
321   y1 = y0 + height;
322 
323   if (mouse_x < x0 || mouse_y < y0 || mouse_x > x0 + width || mouse_y > y1) return;
324 
325   float x = float(mouse_x - x0) * 3 * tile_map_size_x / width;
326   float y = float(y1 - mouse_y) * 3 * tile_map_size_y / height;
327 
328   if (find_bounds_index(x, y))
329   {
330     if (last_ec_index >= 0)  // Clicked on a bounds point; delete it
331     {
332       current_effect.bounds.elements.erase(current_effect.bounds.elements.begin() + last_ec_index);
333     }
334     else if (last_ec_index == -1)  // Clicked on the center; cancel the effect
335     {
336       current_effect = EffectDefinition();
337       eye_candy_done_adding_effect();
338       cur_mode = mode_tile;
339       minimap_on = 0;
340     }
341   }
342 }
343 
eye_candy_add_effect()344 extern "C" void eye_candy_add_effect()
345 {
346   if (eye_candy_initialized && eye_candy_ready_to_add)
347   {
348     effects.push_back(current_effect);
349     current_effect.reference = NULL;
350     switch (current_effect.effect)
351     {
352       case 1:    // Cloud/Fog
353       case 2:    // Fireflies
354       case 11:   // Leaves
355       case 12:   // Flower Petals
356       {
357         current_effect.effect = 0;
358         cur_mode = mode_tile;
359         return;
360       }
361       default:
362       {
363         change_eye_candy_effect();
364         current_effect.bounds = ec::SmoothPolygonBoundingRange();
365       }
366     }
367   }
368 }
369 
eye_candy_done_adding_effect()370 extern "C" void eye_candy_done_adding_effect()
371 {
372   if (eye_candy_initialized)
373   {
374     eye_candy_ready_to_add = 0;
375     if (current_effect.reference)
376     {
377       switch (current_effect.effect)
378       {
379         case 1:    // Cloud/Fog
380         case 2:    // Fireflies
381         case 11:   // Leaves
382         case 12:   // Flower Petals
383         {
384           effects.push_back(current_effect);
385           break;
386         }
387         default:
388         {
389           remove_current_eye_candy_effect();
390         }
391       }
392       current_effect.reference = NULL;
393       current_effect.bounds = ec::SmoothPolygonBoundingRange();
394       current_effect.position = ec::Vec3(-1.0, -1.0, 0.0);
395     }
396   }
397 }
398 
eye_candy_get_effect()399 extern "C" int eye_candy_get_effect()
400 {
401   return current_effect.effect;
402 }
403 
eye_candy_adjust_z(float offset)404 void eye_candy_adjust_z(float offset)
405 {
406   current_effect.position.z += offset;
407   change_eye_candy_effect();
408 }
409 
draw_bounds_on_minimap()410 extern "C" void draw_bounds_on_minimap()
411 {
412   glDisable(GL_TEXTURE_2D);
413   glEnable(GL_BLEND);
414   for (std::vector<EffectDefinition>::iterator iter = effects.begin(); iter != effects.end(); iter++)
415     draw_bound(*iter, false);
416   if (eye_candy_ready_to_add)
417     draw_bound(current_effect, true);
418   glDisable(GL_BLEND);
419   glEnable(GL_TEXTURE_2D);
420 }
421 
draw_bound(EffectDefinition & eff,bool selected)422 void draw_bound(EffectDefinition& eff, bool selected)
423 {
424   int x0, y0, y1, width, height, tile_size;
425   get_minimap_dimensions(&x0, &y0, &width, &height);
426   y1 = y0 + height;
427   tile_size = width / tile_map_size_x;
428 
429   int scale = min2i(window_width, window_height) / 256;
430   glLineWidth(1.3 * scale);
431 
432   if (selected)
433     glColor4f(0.65, 0.55, 0.45, 0.7);
434   else
435     glColor4f(0.65, 0.55, 0.45, 0.25);
436 
437   glBegin(GL_LINE_LOOP);
438   if (eff.bounds.elements.size() >= 2)
439   {
440     std::vector<ec::SmoothPolygonElement>::const_iterator prev_iter = eff.bounds.elements.begin() + (eff.bounds.elements.size() - 1);
441     std::vector<ec::SmoothPolygonElement>::const_iterator next_iter = eff.bounds.elements.begin();
442     bool wrapped = false;
443     for (float f = 0; f < 2 * ec::PI; f += (2 * ec::PI) / 360.0)
444     {
445       if ((f > next_iter->angle) && (!wrapped))
446       {
447         prev_iter = next_iter;
448         next_iter++;
449         if (next_iter == eff.bounds.elements.end())
450         {
451           wrapped = true;
452           next_iter = eff.bounds.elements.begin();
453         }
454       }
455       float percent;
456       if (wrapped)
457         percent = (f - prev_iter->angle) / (next_iter->angle + (2 * ec::PI) - prev_iter->angle);
458       else if (f > prev_iter->angle)
459         percent = (f - prev_iter->angle) / (next_iter->angle - prev_iter->angle);
460       else
461         percent = (f + 2 * ec::PI - prev_iter->angle) / (next_iter->angle + (2 * ec::PI) - prev_iter->angle);
462       const float dist = prev_iter->radius * (1.0 - percent) + next_iter->radius * percent;
463       const float temp_x = x0 + ((eff.position.x - dist * sin(f)) * tile_size) / 3;
464       const float temp_y = y1 - ((eff.position.y + dist * cos(f)) * tile_size) / 3;
465       glVertex2f(temp_x, temp_y);
466     }
467   }
468   glEnd();
469 
470   if (selected)
471   {
472     glColor4f(1.0, 1.0, 1.0, 0.7);
473     glBegin(GL_QUADS);
474     for (std::vector<ec::SmoothPolygonElement>::const_iterator iter = eff.bounds.elements.begin(); iter != eff.bounds.elements.end(); iter++)
475     {
476       const float temp_x = x0 + ((eff.position.x - iter->radius * sin(iter->angle)) * tile_size) / 3;
477       const float temp_y = y1 - ((eff.position.y + iter->radius * cos(iter->angle)) * tile_size) / 3;
478       glVertex2f(temp_x - 2.0 * scale, temp_y - 2.0 * scale);
479       glVertex2f(temp_x - 2.0 * scale, temp_y + 2.0 * scale);
480       glVertex2f(temp_x + 2.0 * scale, temp_y + 2.0 * scale);
481       glVertex2f(temp_x + 2.0 * scale, temp_y - 2.0 * scale);
482     }
483 
484     glColor4f(1.0, 0.8, 0.6, 1.0);
485     const float temp_x = x0 + (eff.position.x * tile_size) / 3;
486     const float temp_y = y1 - (eff.position.y * tile_size) / 3;
487     glVertex2f(temp_x - 2.0 * scale, temp_y - 2.0 * scale);
488     glVertex2f(temp_x - 2.0 * scale, temp_y + 2.0 * scale);
489     glVertex2f(temp_x + 2.0 * scale, temp_y + 2.0 * scale);
490     glVertex2f(temp_x + 2.0 * scale, temp_y - 2.0 * scale);
491     glEnd();
492   }
493 }
494 
find_bounds_index(float x,float y)495 bool find_bounds_index(float x, float y)
496 {
497   if ((current_effect.position.x == -1.0) && (current_effect.position.y == -1.0))
498   {
499     last_ec_index = -1;
500     return false;
501   }
502 
503   if ((fabs(x - current_effect.position.x) < 9.0) && (fabs(y - current_effect.position.y) < 9.0))
504   {
505     last_ec_index = -1;
506     return true;
507   }
508 
509   for (int i = 0; i < (int)current_effect.bounds.elements.size(); i++)
510   {
511     std::vector<ec::SmoothPolygonElement>::const_iterator iter = current_effect.bounds.elements.begin() + i;
512     const float temp_x = current_effect.position.x - iter->radius * sin(iter->angle);
513     const float temp_y = current_effect.position.y + iter->radius * cos(iter->angle);
514     if ((fabs(x - temp_x) < 9.0) && (fabs(y - temp_y) < 9.0))
515     {
516       last_ec_index = i;
517       return true;
518     }
519   }
520 
521   float cur_angle = angle_to(current_effect.position.x, current_effect.position.y, x, y).angle;
522   last_ec_index = current_effect.bounds.elements.size();
523   for (int i = 0; i < (int)current_effect.bounds.elements.size(); i++)
524   {
525     const float angle = current_effect.bounds.elements[i].angle;
526     if (cur_angle < angle)
527     {
528       last_ec_index = i;
529       break;
530     }
531   }
532 
533   return false;
534 }
535 
angle_to(float start_x,float start_y,float end_x,float end_y)536 ec::SmoothPolygonElement angle_to(float start_x, float start_y, float end_x, float end_y)
537 {
538   const float diff_x = -(end_x - start_x);
539   const float diff_y = end_y - start_y;
540   float angle = atan2(diff_x, diff_y);
541   if (angle < 0)
542     angle += 2.0 * ec::PI;
543   const float dist = sqrt(diff_x * diff_x + diff_y * diff_y);
544   return ec::SmoothPolygonElement(angle, dist);
545 }
546 
draw_eye_candy_obj_info()547 void draw_eye_candy_obj_info()
548 {
549   unsigned char str[128];
550   int x_menu,y_menu;
551   if (cur_mode!=mode_eye_candy || !eye_candy_confirmed)
552     return;
553 
554   x_menu=0;
555   y_menu=window_height-72;
556   //draw a black rectangle
557   glEnable(GL_BLEND);
558   glBlendFunc(GL_ONE,GL_SRC_ALPHA);
559   glDisable(GL_TEXTURE_2D);
560   glBegin(GL_QUADS);
561   glColor4f(0.0f,0.0f,0.0f,0.5f);
562   glVertex3i(x_menu,y_menu+70,0);
563   glVertex3i(x_menu,y_menu,0);
564   glVertex3i(x_menu+600,y_menu,0);
565   glVertex3i(x_menu+600,y_menu+70,0);
566   glColor3f(1.0f,1.0f,1.0f);
567   glEnd();
568   glEnable(GL_TEXTURE_2D);
569   glDisable(GL_BLEND);
570 
571   x_menu+=2;
572   y_menu+=2;
573 
574   sprintf((char *)str, "X Pos: %03.2f",current_effect.position.x);
575   draw_string(x_menu,y_menu,str,1);
576 
577   y_menu+=17;
578   sprintf((char *)str, "Y Pos: %03.2f",current_effect.position.y);
579   draw_string(x_menu,y_menu,str,1);
580 
581   y_menu+=17;
582   sprintf((char *)str, "Z Pos: %03.2f",current_effect.position.z);
583   draw_string(x_menu,y_menu,str,1);
584 /////////////////////////////////////////////////
585   x_menu+=15*12;
586   y_menu-=17*2;
587 
588   sprintf((char *)str, "Angle   : %03.2f",current_effect.angle);
589   draw_string(x_menu,y_menu,str,1);
590 
591   y_menu+=17;
592   sprintf((char *)str, "Density : %03.2f",current_effect.density);
593   draw_string(x_menu,y_menu,str,1);
594 
595   y_menu+=17;
596   sprintf((char *)str, "Scale   : %03.2f",current_effect.scale);
597   draw_string(x_menu,y_menu,str,1);
598 /////////////////////////////////////////////////
599   x_menu+=17*12;
600   y_menu-=17*2;
601 
602   sprintf((char *)str, "Hue       : %03.2f",current_effect.hue);
603   draw_string(x_menu,y_menu,str,1);
604 
605   y_menu+=17;
606   sprintf((char *)str, "Saturation: %03.2f",current_effect.saturation);
607   draw_string(x_menu,y_menu,str,1);
608 
609   y_menu+=17;
610   sprintf((char *)str, "Height    : %03.2f",current_effect.base_height);
611   draw_string(x_menu,y_menu,str,1);
612 }
613 
draw_eye_candy_selectors()614 void draw_eye_candy_selectors()
615 {
616   glEnable(GL_COLOR);
617   glEnable(GL_LIGHTING);
618   glDisable(GL_TEXTURE_2D);
619   glColor4f(0.5, 0.5, 0.5, 1.0);
620   int i=0;
621   if (eye_candy_ready_to_add)
622     draw_eye_candy_selector(&current_effect, i);
623   i++;
624   for (std::vector<EffectDefinition>::const_iterator iter = effects.begin(); iter != effects.end(); iter++, i++)
625     draw_eye_candy_selector(&(*iter), i);
626   glDisable(GL_COLOR);
627   glDisable(GL_LIGHTING);
628   glEnable(GL_TEXTURE_2D);
629 }
630 
draw_eye_candy_selector(const EffectDefinition * const effect,const int i)631 void draw_eye_candy_selector(const EffectDefinition*const effect, const int i)
632 {
633   glPushMatrix();
634   glTranslatef(effect->position.x, effect->position.y, effect->position.z);
635   glLoadName (MAX_OBJ_3D + i);
636   glBegin(GL_QUADS);
637   {
638     // Front Face
639     glNormal3f(0.0, 0.0, 1.0);
640     glVertex3f(-0.15f, -0.15f,  0.15f);
641     glVertex3f( 0.15f, -0.15f,  0.15f);
642     glVertex3f( 0.15f,  0.15f,  0.15f);
643     glVertex3f(-0.15f,  0.15f,  0.15f);
644     // Back Face
645     glNormal3f(0.0, 0.0, -1.0);
646     glVertex3f(-0.15f, -0.15f, -0.15f);
647     glVertex3f(-0.15f,  0.15f, -0.15f);
648     glVertex3f( 0.15f,  0.15f, -0.15f);
649     glVertex3f( 0.15f, -0.15f, -0.15f);
650     // Top Face
651     glNormal3f(0.0, 1.0, 0.0);
652     glVertex3f(-0.15f,  0.15f, -0.15f);
653     glVertex3f(-0.15f,  0.15f,  0.15f);
654     glVertex3f( 0.15f,  0.15f,  0.15f);
655     glVertex3f( 0.15f,  0.15f, -0.15f);
656     // Bottom Face
657     glNormal3f(0.0, -1.0, 0.0);
658     glVertex3f(-0.15f, -0.15f, -0.15f);
659     glVertex3f( 0.15f, -0.15f, -0.15f);
660     glVertex3f( 0.15f, -0.15f,  0.15f);
661     glVertex3f(-0.15f, -0.15f,  0.15f);
662     // Right face
663     glNormal3f(1.0, 0.0, 0.0);
664     glVertex3f( 0.15f, -0.15f, -0.15f);
665     glVertex3f( 0.15f,  0.15f, -0.15f);
666     glVertex3f( 0.15f,  0.15f,  0.15f);
667     glVertex3f( 0.15f, -0.15f,  0.15f);
668     // Left Face
669     glNormal3f(-1.0, 0.0, 0.0);
670     glVertex3f(-0.15f, -0.15f, -0.15f);
671     glVertex3f(-0.15f, -0.15f,  0.15f);
672     glVertex3f(-0.15f,  0.15f,  0.15f);
673     glVertex3f(-0.15f,  0.15f, -0.15f);
674   }
675   glEnd();
676   glPopMatrix();
677 }
678 
select_eye_candy_effect(int i)679 void select_eye_candy_effect(int i)
680 {
681   if (i == MAX_OBJ_3D)	// The current selection
682     return;
683 
684   std::vector<EffectDefinition>::iterator iter = effects.begin() + (i - MAX_OBJ_3D - 1);
685   if (current_effect.reference)
686   {
687     ec_recall_effect(current_effect.reference);
688     current_effect.reference = NULL;
689   }
690   current_effect = *iter;
691   effects.erase(iter);
692   eye_candy_ready_to_add = 1;
693 }
694 
kill_eye_candy_effect()695 void kill_eye_candy_effect()
696 {
697   if (current_effect.reference)
698   {
699     ec_recall_effect(current_effect.reference);
700     current_effect.reference = NULL;
701   }
702   eye_candy_ready_to_add = 0;
703 }
704 
get_eye_candy_count()705 int get_eye_candy_count()
706 {
707   return effects.size();
708 }
709 
deserialize_eye_candy_effect(particles_io * data)710 void deserialize_eye_candy_effect(particles_io* data)
711 {
712   const unsigned char*const code = (const unsigned char*const)data->file_name + 5;
713 
714 //  std::cout << "Deserialize" << std::endl;
715 
716   EffectDefinition dest;
717 
718   unsigned char raw_code[54];
719   int i = 0;
720 
721   while (i < 18)
722   {
723     raw_code[i * 3]     = ((code[i * 4 + 0] - ' ') >> 0) | ((code[i * 4 + 1] - ' ') << 6);
724     raw_code[i * 3 + 1] = ((code[i * 4 + 1] - ' ') >> 2) | ((code[i * 4 + 2] - ' ') << 4);
725     raw_code[i * 3 + 2] = ((code[i * 4 + 2] - ' ') >> 4) | ((code[i * 4 + 3] - ' ') << 2);
726     i++;
727   }
728 
729   int bounds_count = raw_code[1];
730   if (bounds_count > 19)
731     bounds_count = 19;
732   for (i = 0; i < bounds_count; i++)
733   {
734     const float angle = raw_code[i * 2 + 2] * (2 * ec::PI) / 256.0f;
735     const float dist = raw_code[i * 2 + 3];
736     dest.bounds.elements.push_back(ec::SmoothPolygonElement(angle, dist));
737   }
738 
739   dest.position.x = data->x_pos;
740   dest.position.y = data->y_pos;
741   dest.position.z = data->z_pos;
742 
743   switch (raw_code[0])
744   {
745     case 0x00:	// Campfire
746     {
747       const float hue = raw_code[41] / 256.0;
748       const float saturation = raw_code[42] / 16.0;
749       const float scale = raw_code[43] + raw_code[44] / 256.0;
750       dest.effect = 0x00;
751       dest.hue = hue;
752       dest.saturation = saturation;
753       dest.scale = scale;
754       dest.reference = ec_create_campfire(dest.position.x, dest.position.y, dest.position.z, hue, saturation, 10, scale);
755       break;
756     }
757     case 0x01:	// Cloud
758     {
759       const float hue = raw_code[41] / 256.0;
760       const float saturation = raw_code[42] / 16.0;
761       const float density = raw_code[43] + raw_code[44] / 256.0;
762       dest.effect = 0x01;
763       dest.hue = hue;
764       dest.saturation = saturation;
765       dest.density = density;
766       dest.reference = ec_create_cloud(dest.position.x, dest.position.y, dest.position.z, hue, saturation, density, (ec_bounds)(&dest.bounds), 10);
767       break;
768     }
769     case 0x02:	// Fireflies
770     {
771       const float hue = raw_code[41] / 256.0;
772       const float saturation = raw_code[42] / 16.0;
773       const float density = raw_code[43] + raw_code[44] / 256.0;
774       const float scale = raw_code[45] + raw_code[46] / 256.0;
775       dest.effect = 0x02;
776       dest.hue = hue;
777       dest.saturation = saturation;
778       dest.scale = scale;
779       dest.density = density;
780       dest.reference = ec_create_fireflies(dest.position.x, dest.position.y, dest.position.z, hue, saturation, density, scale, (ec_bounds)(&dest.bounds));
781       break;
782     }
783     case 0x03:	// Fountain
784     {
785       const float hue = raw_code[41] / 256.0;
786       const float saturation = raw_code[42] / 16.0;
787       const float scale = raw_code[43] + raw_code[44] / 256.0;
788       const float base_height = raw_code[45] * 8.0 + raw_code[46] / 32.0;
789       const int backlit = raw_code[47];
790       dest.effect = 0x03;
791       dest.hue = hue;
792       dest.saturation = saturation;
793       dest.scale = scale;
794       dest.base_height = base_height;
795       dest.reference = ec_create_fountain(dest.position.x, dest.position.y, dest.position.z, hue, saturation, base_height, backlit, scale, 10);
796       break;
797     }
798     case 0x04:	// Lamp
799     {
800       const float hue = raw_code[41] / 256.0;
801       const float saturation = raw_code[42] / 16.0;
802       const float scale = raw_code[43] + raw_code[44] / 256.0;
803       dest.effect = 0x04;
804       dest.hue = hue;
805       dest.saturation = saturation;
806       dest.scale = scale;
807       dest.reference = ec_create_lamp(dest.position.x, dest.position.y, dest.position.z, hue, saturation, scale, 10);
808       break;
809     }
810     case 0x05:	// Magic protection
811     {
812       const float hue = raw_code[41] / 256.0;
813       const float saturation = raw_code[42] / 16.0;
814       const float scale = raw_code[43] + raw_code[44] / 256.0;
815       dest.effect = 0x05;
816       dest.hue = hue;
817       dest.saturation = saturation;
818       dest.scale = scale;
819       dest.reference = ec_create_ongoing_magic_protection(dest.position.x, dest.position.y, dest.position.z, hue, saturation, 10, scale);
820       break;
821     }
822     case 0x06:	// Shield
823     {
824       const float hue = raw_code[41] / 256.0;
825       const float saturation = raw_code[42] / 16.0;
826       const float scale = raw_code[43] + raw_code[44] / 256.0;
827       dest.effect = 0x06;
828       dest.hue = hue;
829       dest.saturation = saturation;
830       dest.scale = scale;
831       dest.reference = ec_create_ongoing_shield(dest.position.x, dest.position.y, dest.position.z, hue, saturation, 10, scale);
832       break;
833     }
834     case 0x07:	// Magic immunity
835     {
836       const float hue = raw_code[41] / 256.0;
837       const float saturation = raw_code[42] / 16.0;
838       const float scale = raw_code[43] + raw_code[44] / 256.0;
839       dest.effect = 0x07;
840       dest.hue = hue;
841       dest.saturation = saturation;
842       dest.scale = scale;
843       dest.reference = ec_create_ongoing_magic_immunity(dest.position.x, dest.position.y, dest.position.z, hue, saturation, 10, scale);
844       break;
845     }
846     case 0x08:	// Poison
847     {
848       const float hue = raw_code[41] / 256.0;
849       const float saturation = raw_code[42] / 16.0;
850       const float scale = raw_code[43] + raw_code[44] / 256.0;
851       dest.effect = 0x08;
852       dest.hue = hue;
853       dest.saturation = saturation;
854       dest.scale = scale;
855       dest.reference = ec_create_ongoing_poison(dest.position.x, dest.position.y, dest.position.z, hue, saturation, 10, scale);
856       break;
857     }
858     case 0x09:	// Smoke
859     {
860       const float hue = raw_code[41] / 256.0;
861       const float saturation = raw_code[42] / 16.0;
862       const float density = raw_code[43] + raw_code[44] / 256.0;
863       dest.effect = 0x09;
864       dest.hue = hue;
865       dest.saturation = saturation;
866       dest.density = density;
867       dest.reference = ec_create_smoke(dest.position.x, dest.position.y, dest.position.z, hue, saturation, density, 10);
868       break;
869     }
870     case 0x0A:	// Teleporter
871     {
872       const float hue = raw_code[41] / 256.0;
873       const float saturation = raw_code[42] / 16.0;
874       const float scale = raw_code[43] + raw_code[44] / 256.0;
875       dest.effect = 0x0A;
876       dest.hue = hue;
877       dest.saturation = saturation;
878       dest.scale = scale;
879       dest.reference = ec_create_teleporter(dest.position.x, dest.position.y, dest.position.z, hue, saturation, scale, 10);
880       break;
881     }
882     case 0x0B:	// Leaves
883     {
884       const float hue = raw_code[41] / 256.0;
885       const float saturation = raw_code[42] / 16.0;
886       const float density = raw_code[43] + raw_code[44] / 256.0;
887       const float scale = raw_code[45] + raw_code[46] / 256.0;
888       dest.effect = 0x0B;
889       dest.hue = hue;
890       dest.saturation = saturation;
891       dest.scale = scale;
892       dest.density = density;
893       dest.reference = ec_create_wind_leaves(dest.position.x, dest.position.y, dest.position.z, hue, saturation, scale, density, (ec_bounds)(&dest.bounds), 1.0, 0.0, 0.0);
894       break;
895     }
896     case 0x0C:	// Petals
897     {
898       const float hue = raw_code[41] / 256.0;
899       const float saturation = raw_code[42] / 16.0;
900       const float density = raw_code[43] + raw_code[44] / 256.0;
901       const float scale = raw_code[45] + raw_code[46] / 256.0;
902       dest.effect = 0x0C;
903       dest.hue = hue;
904       dest.saturation = saturation;
905       dest.scale = scale;
906       dest.density = density;
907       dest.reference = ec_create_wind_petals(dest.position.x, dest.position.y, dest.position.z, hue, saturation, scale, density, (ec_bounds)(&dest.bounds), 1.0, 0.0, 0.0);
908       break;
909     }
910     case 0x0D:	// Waterfall
911     {
912       const float hue = raw_code[41] / 256.0;
913       const float saturation = raw_code[42] / 16.0;
914       const float density = raw_code[43] + raw_code[44] / 256.0;
915       const float base_height = raw_code[45] * 8.0 + raw_code[46] / 32.0;
916       const float angle = raw_code[47] * ec::PI / 128.0;
917       dest.effect = 0x0D;
918       dest.hue = hue;
919       dest.saturation = saturation;
920       dest.density = density;
921       dest.base_height = base_height;
922       dest.angle = angle;
923 //      dest.reference = ec_create_waterfall(dest.position.x, dest.position.y, dest.position.z, hue, saturation);
924       break;
925     }
926     case 0x0E:	// Bees
927     {
928       const float hue = raw_code[41] / 256.0;
929       const float saturation = raw_code[42] / 16.0;
930       const float density = raw_code[43] + raw_code[44] / 256.0;
931       const float scale = raw_code[45] + raw_code[46] / 256.0;
932       dest.effect = 0x0E;
933       dest.hue = hue;
934       dest.saturation = saturation;
935       dest.scale = scale;
936       dest.density = density;
937 //      dest.reference = ec_create_bees(dest.position.x, dest.position.y, dest.position.z, hue, saturation);
938       break;
939     }
940     case 0x0F:	// Portal
941     {
942       const float hue = raw_code[41] / 256.0;
943       const float saturation = raw_code[42] / 16.0;
944       const float scale = raw_code[43] + raw_code[44] / 256.0;
945       const float angle = raw_code[45] * ec::PI / 128.0;
946       dest.effect = 0x0F;
947       dest.hue = hue;
948       dest.saturation = saturation;
949       dest.scale = scale;
950       dest.angle = angle;
951 //      dest.reference = ec_create_portal(dest.position.x, dest.position.y, dest.position.z, hue, saturation);
952       break;
953     }
954     case 0x10:	// Candle
955     {
956       const float hue = raw_code[41] / 256.0;
957       const float saturation = raw_code[42] / 16.0;
958       const float scale = raw_code[43] + raw_code[44] / 256.0;
959       dest.effect = 0x10;
960       dest.hue = hue;
961       dest.saturation = saturation;
962       dest.scale = scale;
963       dest.reference = ec_create_candle(dest.position.x, dest.position.y, dest.position.z, hue, saturation, scale, 10);
964       break;
965     }
966   }
967   effects.push_back(dest);
968 }
969 
serialize_eye_candy_effect(int index,particles_io * data)970 void serialize_eye_candy_effect(int index, particles_io* data)
971 {
972 //  std::cout << "Serialize" << std::endl;
973 
974   memset((char*)data, 0, sizeof(particles_io));
975 
976   std::string unformatted_data(80, '\0');
977   unformatted_data[0] = effects[index].effect;
978   unformatted_data[1] = effects[index].bounds.elements.size();
979   if (unformatted_data[1] > 19)
980     unformatted_data[1] = 19;
981   for (int i = 0; i < unformatted_data[1]; i++)
982   {
983     unformatted_data[i * 2 + 2] = (char)((unsigned char)(effects[index].bounds.elements[i].angle / (2 * ec::PI) * 256.0f));
984     unformatted_data[i * 2 + 3] = (char)((unsigned char)(effects[index].bounds.elements[i].radius));
985   }
986   switch (effects[index].effect)
987   {
988     case 0:    // Fire
989       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
990       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
991       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
992       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
993       break;
994     case 1:    // Cloud/Fog
995       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
996       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
997       unformatted_data[43] = (char)((unsigned char)(effects[index].density));
998       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].density * 256.0) % 256));
999       break;
1000     case 2:    // Fireflies
1001       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1002       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1003       unformatted_data[43] = (char)((unsigned char)(effects[index].density));
1004       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].density * 256.0) % 256));
1005       unformatted_data[45] = (char)((unsigned char)(effects[index].scale));
1006       unformatted_data[46] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1007       break;
1008     case 3:    // Fountain
1009       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1010       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1011       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1012       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1013       unformatted_data[47] = 0; 	// Backlit
1014       break;
1015     case 4:    // Lamp/Torch
1016       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1017       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1018       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1019       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1020       break;
1021     case 5:    // Magic Protection
1022       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1023       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1024       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1025       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1026       break;
1027     case 6:    // Shield
1028       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1029       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1030       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1031       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1032       break;
1033     case 7:    // Magic Immunity
1034       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1035       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1036       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1037       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1038       break;
1039     case 8:    // Poison
1040       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1041       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1042       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1043       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1044       break;
1045     case 9:    // Smoke
1046       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1047       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1048       unformatted_data[43] = (char)((unsigned char)(effects[index].density));
1049       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].density * 256.0) % 256));
1050       break;
1051     case 10:  // Teleporter
1052       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1053       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1054       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1055       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1056       break;
1057     case 11:  // Leaves
1058       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1059       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1060       unformatted_data[43] = (char)((unsigned char)(effects[index].density));
1061       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].density * 256.0) % 256));
1062       unformatted_data[45] = (char)((unsigned char)(effects[index].scale));
1063       unformatted_data[46] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1064       break;
1065     case 12:  // Flower Petals
1066       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1067       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1068       unformatted_data[43] = (char)((unsigned char)(effects[index].density));
1069       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].density * 256.0) % 256));
1070       unformatted_data[45] = (char)((unsigned char)(effects[index].scale));
1071       unformatted_data[46] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1072       break;
1073     case 13:  // Waterfall
1074       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1075       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1076       unformatted_data[43] = (char)((unsigned char)(effects[index].density));
1077       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].density * 256.0) % 256));
1078       unformatted_data[45] = (char)((unsigned char)(effects[index].base_height / 8.0));
1079       unformatted_data[46] = (char)((unsigned char)((int)(effects[index].base_height * 32.0) % 256));
1080       unformatted_data[47] = (char)((unsigned char)(effects[index].angle * 256.0));
1081       break;
1082     case 14:  // Bees
1083       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1084       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1085       unformatted_data[43] = (char)((unsigned char)(effects[index].density));
1086       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].density * 256.0) % 256));
1087       unformatted_data[45] = (char)((unsigned char)(effects[index].scale));
1088       unformatted_data[46] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1089       break;
1090     case 15:  // Portal
1091       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1092       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1093       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1094       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1095       unformatted_data[45] = (char)((unsigned char)(effects[index].angle * 256.0));
1096       break;
1097     case 16:    // Candle
1098       unformatted_data[41] = (char)((unsigned char)(effects[index].hue * 256.0));
1099       unformatted_data[42] = (char)((unsigned char)(effects[index].saturation * 16.0));
1100       unformatted_data[43] = (char)((unsigned char)(effects[index].scale));
1101       unformatted_data[44] = (char)((unsigned char)((int)(effects[index].scale * 256.0) % 256));
1102       break;
1103   }
1104 
1105   std::string data_str = "ec://";
1106   for (int i = 0; i < 18; i++)
1107   {
1108     data_str += ' ' + (char)((((unsigned char)unformatted_data[i * 3 + 0] & 0x3F)));
1109     data_str += ' ' + (char)((((unsigned char)unformatted_data[i * 3 + 0] & 0xC0) >> 6) | (((unsigned char)unformatted_data[i * 3 + 1] & 0x0F) << 2));
1110     data_str += ' ' + (char)((((unsigned char)unformatted_data[i * 3 + 1] & 0xF0) >> 4) | (((unsigned char)unformatted_data[i * 3 + 2] & 0x03) << 4));
1111     data_str += ' ' + (char)((((unsigned char)unformatted_data[i * 3 + 2] & 0xFC) >> 2));
1112   }
1113 
1114   sprintf(data->file_name, "%s", data_str.c_str());
1115   data->x_pos = effects[index].position.x;
1116   data->y_pos = effects[index].position.y;
1117   data->z_pos = effects[index].position.z;
1118 }
1119 
destroy_all_eye_candy()1120 void destroy_all_eye_candy()
1121 {
1122   for (std::vector<EffectDefinition>::iterator iter = effects.begin(); iter != effects.end(); iter++)
1123   {
1124     if (iter->reference)
1125     {
1126       ec_recall_effect(iter->reference);
1127       iter->reference = NULL;
1128     }
1129   }
1130   effects.clear();
1131 }
1132 
1133 #endif // EYE_CANDY
1134