BGE: Add new world API KX_WorldInfo (KX_Scene)
[blender.git] / source / gameengine / Ketsji / KX_WorldInfo.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file gameengine/Ketsji/KX_WorldInfo.cpp
29  *  \ingroup ketsji
30  */
31
32
33 #include "KX_WorldInfo.h"
34 #include "KX_PythonInit.h"
35 #include "KX_PyMath.h"
36 #include "RAS_IRasterizer.h"
37 #include "GPU_material.h"
38
39 /* This little block needed for linking to Blender... */
40 #ifdef WIN32
41 #include "BLI_winstuff.h"
42 #endif
43
44 /* This list includes only data type definitions */
45 #include "DNA_scene_types.h"
46 #include "DNA_world_types.h"
47
48 #include "BLI_math.h"
49
50 #include "BKE_global.h"
51 #include "BKE_scene.h"
52 /* end of blender include block */
53
54
55 KX_WorldInfo::KX_WorldInfo(Scene *blenderscene, World *blenderworld)
56 {
57         if (blenderworld) {
58                 m_name = blenderworld->id.name + 2;
59                 m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene);
60                 m_hasworld = true;
61                 m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false);
62                 m_misttype = blenderworld->mistype;
63                 m_miststart = blenderworld->miststa;
64                 m_mistdistance = blenderworld->mistdist;
65                 m_mistintensity = blenderworld->misi;
66                 setMistColor(blenderworld->horr, blenderworld->horg, blenderworld->horb);
67                 setBackColor(blenderworld->horr, blenderworld->horg, blenderworld->horb);
68                 setAmbientColor(blenderworld->ambr, blenderworld->ambg, blenderworld->ambb);
69         }
70         else {
71                 m_hasworld = false;
72         }
73 }
74
75 KX_WorldInfo::~KX_WorldInfo()
76 {
77 }
78
79 const STR_String& KX_WorldInfo::GetName()
80 {
81         return m_name;
82 }
83
84 bool KX_WorldInfo::hasWorld()
85 {
86         return m_hasworld;
87 }
88
89 bool KX_WorldInfo::hasMist()
90 {
91         return m_hasmist;
92 }
93
94 float KX_WorldInfo::getBackColorRed()
95 {
96         return m_backgroundcolor[0];
97 }
98
99 float KX_WorldInfo::getBackColorGreen()
100 {
101         return m_backgroundcolor[1];
102 }
103
104 float KX_WorldInfo::getBackColorBlue()
105 {
106         return m_backgroundcolor[2];
107 }
108
109 float KX_WorldInfo::getAmbientColorRed()
110 {
111         return m_ambientcolor[0];
112 }
113
114 float KX_WorldInfo::getAmbientColorGreen()
115 {
116         return m_ambientcolor[1];
117 }
118
119 float KX_WorldInfo::getAmbientColorBlue()
120 {
121         return m_ambientcolor[2];
122 }
123
124 short KX_WorldInfo::getMistType()
125 {
126         return m_misttype;
127 }
128
129 float KX_WorldInfo::getMistStart()
130 {
131         return m_miststart;
132 }
133
134 float KX_WorldInfo::getMistDistance()
135 {
136         return m_mistdistance;
137 }
138
139 float KX_WorldInfo::getMistIntensity()
140 {
141         return m_mistintensity;
142 }
143
144 float KX_WorldInfo::getMistColorRed()
145 {
146         return m_mistcolor[0];
147 }
148
149 float KX_WorldInfo::getMistColorGreen()
150 {
151         return m_mistcolor[1];
152 }
153
154 float KX_WorldInfo::getMistColorBlue()
155 {
156         return m_mistcolor[2];
157 }
158
159 void KX_WorldInfo::setBackColor(float r, float g, float b)
160 {
161         m_backgroundcolor[0] = r;
162         m_backgroundcolor[1] = g;
163         m_backgroundcolor[2] = b;
164
165         if (m_do_color_management) {
166                 linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor);
167         }
168         else {
169                 copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor);
170         }
171 }
172
173 void KX_WorldInfo::setMistType(short type)
174 {
175         m_misttype = type;
176 }
177
178 void KX_WorldInfo::setUseMist(bool enable)
179 {
180         m_hasmist = enable;
181 }
182
183 void KX_WorldInfo::setMistStart(float d)
184 {
185         m_miststart = d;
186 }
187
188 void KX_WorldInfo::setMistDistance(float d)
189 {
190         m_mistdistance = d;
191 }
192
193 void KX_WorldInfo::setMistIntensity(float intensity)
194 {
195         m_mistintensity = intensity;
196 }
197 void KX_WorldInfo::setMistColor(float r, float g, float b)
198 {
199         m_mistcolor[0] = r;
200         m_mistcolor[1] = g;
201         m_mistcolor[2] = b;
202
203         if (m_do_color_management) {
204                 linearrgb_to_srgb_v3_v3(m_con_mistcolor, m_mistcolor);
205         }
206         else {
207                 copy_v3_v3(m_con_mistcolor, m_mistcolor);
208         }
209 }
210
211 void KX_WorldInfo::setAmbientColor(float r, float g, float b)
212 {
213         m_ambientcolor[0] = r;
214         m_ambientcolor[1] = g;
215         m_ambientcolor[2] = b;
216
217         if (m_do_color_management) {
218                 linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor);
219         }
220         else {
221                 copy_v3_v3(m_con_ambientcolor, m_ambientcolor);
222         }
223 }
224
225 void KX_WorldInfo::UpdateBackGround()
226 {
227         if (m_hasworld) {
228                 RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer();
229
230                 if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) {
231                         m_rasterizer->SetBackColor(m_con_backgroundcolor);
232                         GPU_horizon_update_color(m_backgroundcolor);
233                 }
234         }
235 }
236
237 void KX_WorldInfo::UpdateWorldSettings()
238 {
239         if (m_hasworld) {
240                 RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer();
241
242                 if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) {
243                         m_rasterizer->SetAmbientColor(m_con_ambientcolor);
244                         GPU_ambient_update_color(m_ambientcolor);
245
246                         if (m_hasmist) {
247                                 m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor);
248                                 GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor);
249                                 m_rasterizer->EnableFog(true);
250                                 GPU_mist_update_enable(true);
251                         }
252                         else {
253                                 m_rasterizer->EnableFog(false);
254                                 GPU_mist_update_enable(false);
255                         }
256                 }
257         }
258 }
259
260 #ifdef WITH_PYTHON
261
262 /* -------------------------------------------------------------------------
263  * Python functions
264  * ------------------------------------------------------------------------- */
265 PyObject *KX_WorldInfo::py_repr(void)
266 {
267         return PyUnicode_From_STR_String(GetName());
268 }
269
270 /* -------------------------------------------------------------------------
271  * Python Integration Hooks
272  * ------------------------------------------------------------------------- */
273 PyTypeObject KX_WorldInfo::Type = {
274         PyVarObject_HEAD_INIT(NULL, 0)
275         "KX_WorldInfo",
276         sizeof(PyObjectPlus_Proxy),
277         0,
278         py_base_dealloc,
279         0,
280         0,
281         0,
282         0,
283         py_base_repr,
284         0,0,0,0,0,0,0,0,0,
285         Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
286         0,0,0,0,0,0,0,
287         Methods,
288         0,
289         0,
290         &PyObjectPlus::Type,
291         0,0,0,0,0,0,
292         py_base_new
293 };
294
295 PyMethodDef KX_WorldInfo::Methods[] = {
296         {NULL,NULL} /* Sentinel */
297 };
298
299 PyAttributeDef KX_WorldInfo::Attributes[] = {
300         KX_PYATTRIBUTE_BOOL_RW("mist_enable", KX_WorldInfo, m_hasmist),
301         KX_PYATTRIBUTE_FLOAT_RW("mist_start", 0.0f, 10000.0f, KX_WorldInfo, m_miststart),
302         KX_PYATTRIBUTE_FLOAT_RW("mist_distance", 0.001f, 10000.0f, KX_WorldInfo, m_mistdistance),
303         KX_PYATTRIBUTE_FLOAT_RW("mist_intensity", 0.0f, 1.0f, KX_WorldInfo, m_mistintensity),
304         KX_PYATTRIBUTE_SHORT_RW("mist_type", 0, 2, true, KX_WorldInfo, m_misttype),
305         KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst),
306         KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_LINEAR", KX_WorldInfo, pyattr_get_mist_typeconst),
307         KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_INV_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst),
308         KX_PYATTRIBUTE_RW_FUNCTION("mist_color", KX_WorldInfo, pyattr_get_mist_color, pyattr_set_mist_color),
309         KX_PYATTRIBUTE_RW_FUNCTION("background_color", KX_WorldInfo, pyattr_get_back_color, pyattr_set_back_color),
310         KX_PYATTRIBUTE_RW_FUNCTION("ambient_color", KX_WorldInfo, pyattr_get_ambient_color, pyattr_set_ambient_color),
311         { NULL } /* Sentinel */
312 };
313
314 /* Attribute get/set functions */
315
316 #ifdef USE_MATHUTILS
317
318 /*----------------------mathutils callbacks ----------------------------*/
319
320 /* subtype */
321 #define MATHUTILS_VEC_CB_MIST_COLOR 1
322 #define MATHUTILS_VEC_CB_BACK_COLOR 2
323 #define MATHUTILS_VEC_CB_AMBIENT_COLOR 3
324
325 static unsigned char mathutils_world_vector_cb_index = -1; /* index for our callbacks */
326
327 static int mathutils_world_generic_check(BaseMathObject *bmo)
328 {
329         KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
330         if (self == NULL)
331                 return -1;
332                 
333         return 0;
334 }
335
336 static int mathutils_world_vector_get(BaseMathObject *bmo, int subtype)
337 {
338         KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
339         if (self == NULL)
340                 return -1;
341
342         switch (subtype) {
343                 case MATHUTILS_VEC_CB_MIST_COLOR:
344                         copy_v3_v3(bmo->data, self->m_mistcolor);
345                         break;
346                 case MATHUTILS_VEC_CB_BACK_COLOR:
347                         copy_v3_v3(bmo->data, self->m_backgroundcolor);
348                         break;
349                 case MATHUTILS_VEC_CB_AMBIENT_COLOR:
350                         copy_v3_v3(bmo->data, self->m_ambientcolor);
351                         break;
352         default:
353                 return -1;
354         }
355         return 0;
356 }
357
358 static int mathutils_world_vector_set(BaseMathObject *bmo, int subtype)
359 {
360         KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
361
362         if (self == NULL)
363                 return -1;
364
365         switch (subtype) {
366                 case MATHUTILS_VEC_CB_MIST_COLOR:
367                         self->setMistColor(bmo->data[0], bmo->data[1], bmo->data[2]);
368                         break;
369                 case MATHUTILS_VEC_CB_BACK_COLOR:
370                         self->setBackColor(bmo->data[0], bmo->data[1], bmo->data[2]);
371                         break;
372                 case MATHUTILS_VEC_CB_AMBIENT_COLOR:
373                         self->setAmbientColor(bmo->data[0], bmo->data[1], bmo->data[2]);
374                         break;
375         default:
376                 return -1;
377         }
378         return 0;
379 }
380
381 static int mathutils_world_vector_get_index(BaseMathObject *bmo, int subtype, int index)
382 {
383         KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
384
385         if (self == NULL)
386                 return -1;
387
388         switch (subtype) {
389                 case MATHUTILS_VEC_CB_MIST_COLOR:
390                 {
391                         const float *color = self->m_mistcolor;
392                         bmo->data[index] = color[index];
393                 }
394                 break;
395                 case MATHUTILS_VEC_CB_BACK_COLOR:
396                 {
397                         const float *color = self->m_backgroundcolor;
398                         bmo->data[index] = color[index];
399                 }
400                         break;
401                 case MATHUTILS_VEC_CB_AMBIENT_COLOR:
402                 {
403                         const float *color = self->m_ambientcolor;
404                         bmo->data[index] = color[index];
405                 }
406                 break;
407         default:
408                 return -1;
409         }
410         return 0;
411 }
412
413 static int mathutils_world_vector_set_index(BaseMathObject *bmo, int subtype, int index)
414 {
415         KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user);
416
417         if (self == NULL)
418                 return -1;
419
420         float color[4];
421         switch (subtype) {
422                 case MATHUTILS_VEC_CB_MIST_COLOR:
423                         copy_v3_v3(color, self->m_mistcolor);
424                         color[index] = bmo->data[index];
425                         self->setMistColor(color[0], color[1], color[2]);
426                 break;
427                 case MATHUTILS_VEC_CB_BACK_COLOR:
428                         copy_v3_v3(color, self->m_backgroundcolor);
429                         color[index] = bmo->data[index];
430                         self->setBackColor(color[0], color[1], color[2]);
431                 break;
432                 case MATHUTILS_VEC_CB_AMBIENT_COLOR:
433                         copy_v3_v3(color, self->m_ambientcolor);
434                         color[index] = bmo->data[index];
435                         self->setAmbientColor(color[0], color[1], color[2]);
436                         break;
437         default:
438                 return -1;
439         }
440         return 0;
441 }
442
443 static Mathutils_Callback mathutils_world_vector_cb = {
444         mathutils_world_generic_check,
445         mathutils_world_vector_get,
446         mathutils_world_vector_set,
447         mathutils_world_vector_get_index,
448         mathutils_world_vector_set_index
449 };
450
451 void KX_WorldInfo_Mathutils_Callback_Init()
452 {
453         // register mathutils callbacks, ok to run more than once.
454         mathutils_world_vector_cb_index = Mathutils_RegisterCallback(&mathutils_world_vector_cb);
455 }
456 #endif // USE_MATHUTILS
457
458
459 PyObject *KX_WorldInfo::pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
460 {
461         PyObject *retvalue;
462
463         const char* type = attrdef->m_name;
464
465         if (!strcmp(type, "KX_MIST_QUADRATIC")) {
466                 retvalue = PyLong_FromLong(KX_MIST_QUADRATIC);
467         } 
468         else if (!strcmp(type, "KX_MIST_LINEAR")) {
469                 retvalue = PyLong_FromLong(KX_MIST_LINEAR);
470         } 
471         else if (!strcmp(type, "KX_MIST_INV_QUADRATIC")) {
472                 retvalue = PyLong_FromLong(KX_MIST_INV_QUADRATIC);
473         }
474         else {
475                 /* should never happen */
476                 PyErr_SetString(PyExc_TypeError, "invalid mist type");
477                 retvalue = NULL;
478         }
479
480         return retvalue;
481 }
482
483 PyObject *KX_WorldInfo::pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
484 {
485 #ifdef USE_MATHUTILS
486         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_MIST_COLOR);
487 #else
488         KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
489         return PyObjectFrom(MT_Vector3(self->m_mistcolor));
490 #endif
491 }
492
493 int KX_WorldInfo::pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
494 {
495         KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
496
497         MT_Vector3 color;
498         if (PyVecTo(value, color))
499         {
500                 self->setMistColor(color[0], color[1], color[2]);
501                 return PY_SET_ATTR_SUCCESS;
502         }
503         return PY_SET_ATTR_FAIL;
504 }
505
506 PyObject *KX_WorldInfo::pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
507 {
508
509 #ifdef USE_MATHUTILS
510         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_BACK_COLOR);
511 #else
512         KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
513         return PyObjectFrom(MT_Vector3(self->m_backgroundcolor));
514 #endif
515 }
516
517 int KX_WorldInfo::pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
518 {
519         KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
520
521         MT_Vector3 color;
522         if (PyVecTo(value, color))
523         {
524                 self->setBackColor(color[0], color[1], color[2]);
525                 return PY_SET_ATTR_SUCCESS;
526         }
527         return PY_SET_ATTR_FAIL;
528 }
529
530 PyObject *KX_WorldInfo::pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
531 {
532 #ifdef USE_MATHUTILS
533         return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_AMBIENT_COLOR);
534 #else
535         KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
536         return PyObjectFrom(MT_Vector3(self->m_ambientcolor));
537 #endif
538 }
539
540 int KX_WorldInfo::pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
541 {
542         KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v);
543
544         MT_Vector3 color;
545         if (PyVecTo(value, color))
546         {
547                 self->setAmbientColor(color[0], color[1], color[2]);
548                 return PY_SET_ATTR_SUCCESS;
549         }
550         return PY_SET_ATTR_FAIL;
551 }
552
553 #endif /* WITH_PYTHON */