Merge with trunk, revision 28528 - 28976.
[blender.git] / source / blender / editors / space_logic / logic_ops.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28 #include <stddef.h>
29
30 #include "DNA_object_types.h"
31 #include "DNA_scene_types.h"
32 #include "DNA_sensor_types.h"
33 #include "DNA_controller_types.h"
34 #include "DNA_actuator_types.h"
35
36 #include "BLI_blenlib.h"
37
38 #include "BKE_context.h"
39 #include "BKE_main.h"
40 #include "BKE_sca.h"
41
42 #include "ED_object.h"
43 #include "ED_screen.h"
44
45 #include "RNA_access.h"
46 #include "RNA_define.h"
47 #include "RNA_enum_types.h"
48
49 #include "WM_api.h"
50 #include "WM_types.h"
51
52 #include "logic_intern.h"
53
54 /* ************* Generic Operator Helpers ************* */
55
56 static int edit_sensor_poll(bContext *C)
57 {
58         PointerRNA ptr= CTX_data_pointer_get_type(C, "sensor", &RNA_Sensor);
59
60         if (ptr.data && ((ID*)ptr.id.data)->lib) return 0;
61         return 1;
62 }
63
64 static int edit_controller_poll(bContext *C)
65 {
66         PointerRNA ptr= CTX_data_pointer_get_type(C, "controller", &RNA_Controller);
67
68         if (ptr.data && ((ID*)ptr.id.data)->lib) return 0;
69         return 1;
70 }
71
72 static int edit_actuator_poll(bContext *C)
73 {
74         PointerRNA ptr= CTX_data_pointer_get_type(C, "actuator", &RNA_Actuator);
75
76         if (ptr.data && ((ID*)ptr.id.data)->lib) return 0;
77         return 1;
78 }
79
80 /* this is the nice py-api-compatible way to do it, like modifiers, 
81    but not entirely working yet..
82  
83 static void edit_sensor_properties(wmOperatorType *ot)
84 {
85         RNA_def_string(ot->srna, "sensor", "", 32, "Sensor", "Name of the sensor to edit");
86         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the object the sensor belongs to");
87 }
88
89 static int edit_sensor_invoke_properties(bContext *C, wmOperator *op)
90 {
91         PointerRNA ptr= CTX_data_pointer_get_type(C, "sensor", &RNA_Sensor);
92         
93         if (RNA_property_is_set(op->ptr, "sensor") && RNA_property_is_set(op->ptr, "object") )
94                 return 1;
95         
96         if (ptr.data) {
97                 bSensor *sens = ptr.data;
98                 Object *ob = ptr.id.data;
99                 
100                 RNA_string_set(op->ptr, "sensor", sens->name);
101                 RNA_string_set(op->ptr, "object", ob->id.name+2);
102                 return 1;
103         }
104         
105         return 0;
106 }
107
108 static bSensor *edit_sensor_property_get(bContext *C, wmOperator *op, Object *ob)
109 {
110         char sensor_name[32];
111         char ob_name[32];
112         bSensor *sens;
113         
114         RNA_string_get(op->ptr, "sensor", sensor_name);
115         RNA_string_get(op->ptr, "object", ob_name);
116         
117         ob = BLI_findstring(&(CTX_data_main(C)->object), ob_name, offsetof(ID, name) + 2);
118         if (!ob)
119                 return NULL;
120         
121         sens = BLI_findstring(&(ob->sensors), sensor_name, offsetof(bSensor, name));    
122         return sens;
123 }
124  */
125 /*
126 static void edit_controller_properties(wmOperatorType *ot)
127 {
128         RNA_def_string(ot->srna, "controller", "", 32, "Controller", "Name of the controller to edit");
129         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the object the controller belongs to");
130 }
131
132 static int edit_controller_invoke_properties(bContext *C, wmOperator *op)
133 {
134         PointerRNA ptr= CTX_data_pointer_get_type(C, "controller", &RNA_Controller);
135         
136         if (RNA_property_is_set(op->ptr, "controller") && RNA_property_is_set(op->ptr, "object") )
137                 return 1;
138         
139         if (ptr.data) {
140                 bController *cont = ptr.data;
141                 Object *ob = ptr.id.data;
142                 
143                 RNA_string_set(op->ptr, "controller", cont->name);
144                 RNA_string_set(op->ptr, "object", ob->id.name+2);
145                 return 1;
146         }
147         
148         return 0;
149 }
150
151 static bController *edit_controller_property_get(bContext *C, wmOperator *op, Object *ob)
152 {
153         char controller_name[32];
154         char ob_name[32];
155         bController *cont;
156         
157         RNA_string_get(op->ptr, "controller", controller_name);
158         RNA_string_get(op->ptr, "object", ob_name);
159         
160         ob = BLI_findstring(&(CTX_data_main(C)->object), ob_name, offsetof(ID, name) + 2);
161         if (!ob)
162                 return NULL;
163         
164         cont = BLI_findstring(&(ob->controllers), controller_name, offsetof(bController, name));        
165         return cont;
166 }
167
168 static void edit_actuator_properties(wmOperatorType *ot)
169 {
170         RNA_def_string(ot->srna, "actuator", "", 32, "Actuator", "Name of the actuator to edit");
171         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the object the actuator belongs to");
172 }
173
174 static int edit_actuator_invoke_properties(bContext *C, wmOperator *op)
175 {
176         PointerRNA ptr= CTX_data_pointer_get_type(C, "actuator", &RNA_Actuator);
177         
178         if (RNA_property_is_set(op->ptr, "actuator") && RNA_property_is_set(op->ptr, "object") )
179                 return 1;
180         
181         if (ptr.data) {
182                 bActuator *act = ptr.data;
183                 Object *ob = ptr.id.data;
184                 
185                 RNA_string_set(op->ptr, "actuator",act->name);
186                 RNA_string_set(op->ptr, "object", ob->id.name+2);
187                 return 1;
188         }
189         
190         return 0;
191 }
192
193 static bController *edit_actuator_property_get(bContext *C, wmOperator *op, Object *ob)
194 {
195         char actuator_name[32];
196         char ob_name[32];
197         bActuator *act;
198         
199         RNA_string_get(op->ptr, "actuator", actuator_name);
200         RNA_string_get(op->ptr, "object", ob_name);
201         
202         ob = BLI_findstring(&(CTX_data_main(C)->object), ob_name, offsetof(ID, name) + 2);
203         if (!ob)
204                 return NULL;
205         
206         cont = BLI_findstring(&(ob->actuators), actuator_name, offsetof(bActuator, name));      
207         return act;
208 }
209 */
210
211 /* ************* Add/Remove Sensor Operator ************* */
212
213 static int sensor_remove_exec(bContext *C, wmOperator *op)
214 {
215         /*      Object *ob;
216         bSensor *sens = edit_sensor_property_get(C, op, ob);    */
217         PointerRNA ptr = CTX_data_pointer_get_type(C, "sensor", &RNA_Sensor);
218         Object *ob= ptr.id.data;
219         bSensor *sens= ptr.data;
220         
221         if (!sens)
222                 return OPERATOR_CANCELLED;
223         
224         BLI_remlink(&(ob->sensors), sens);
225         free_sensor(sens);
226         
227         WM_event_add_notifier(C, NC_LOGIC, NULL);
228         
229         return OPERATOR_FINISHED;
230 }
231
232
233 /* commented along with above stuff
234  static int sensor_remove_invoke(bContext *C, wmOperator *op, wmEvent *event)
235 {
236         if (edit_sensor_invoke_properties(C, op))
237                 return sensor_remove_exec(C, op);
238         else
239                 return OPERATOR_CANCELLED;
240 }
241  */
242
243 void LOGIC_OT_sensor_remove(wmOperatorType *ot)
244 {
245         ot->name= "Remove Sensor";
246         ot->description= "Remove a sensor from the active object";
247         ot->idname= "LOGIC_OT_sensor_remove";
248         
249         //ot->invoke= sensor_remove_invoke;
250         ot->exec= sensor_remove_exec;
251         ot->poll= edit_sensor_poll;
252         
253         /* flags */
254         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
255         //edit_sensor_properties(ot);
256 }
257
258 static int sensor_add_exec(bContext *C, wmOperator *op)
259 {
260         Object *ob = ED_object_active_context(C);
261         bSensor *sens;
262         PointerRNA sens_ptr;
263         PropertyRNA *prop;
264         const char *sens_name;
265         int type= RNA_enum_get(op->ptr, "type");
266         char name[32];
267
268         sens= new_sensor(type);
269         BLI_addtail(&(ob->sensors), sens);
270         
271         /* set the sensor name based on rna type enum */
272         RNA_pointer_create((ID *)ob, &RNA_Sensor, sens, &sens_ptr);
273         prop = RNA_struct_find_property(&sens_ptr, "type");
274
275         RNA_string_get(op->ptr, "name", name);
276         if(BLI_strnlen(name, 32) < 1){
277                 RNA_property_enum_name(C, &sens_ptr, prop, RNA_property_enum_get(&sens_ptr, prop), &sens_name);
278                 BLI_strncpy(sens->name, sens_name, sizeof(sens->name));
279         }
280         else
281                 BLI_strncpy(sens->name, name, sizeof(sens->name));
282
283         make_unique_prop_names(C, sens->name);
284         ob->scaflag |= OB_SHOWSENS;
285
286         WM_event_add_notifier(C, NC_LOGIC, NULL);
287         
288         return OPERATOR_FINISHED;
289 }
290
291 void LOGIC_OT_sensor_add(wmOperatorType *ot)
292 {
293         PropertyRNA *prop;
294         
295         /* identifiers */
296         ot->name= "Add Sensor";
297         ot->description = "Add a sensor to the active object";
298         ot->idname= "LOGIC_OT_sensor_add";
299         
300         /* api callbacks */
301         ot->invoke= WM_menu_invoke;
302         ot->exec= sensor_add_exec;
303         ot->poll= ED_operator_object_active_editable;
304         
305         /* flags */
306         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
307         
308         /* properties */
309         prop= RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, SENS_ALWAYS, "Type", "Type of sensor to add");
310         RNA_def_enum_funcs(prop, rna_Sensor_type_itemf);
311         prop= RNA_def_string(ot->srna, "name", "", 32, "Name", "Name of the Sensor to add");
312 }
313
314 /* ************* Add/Remove Controller Operator ************* */
315
316 static int controller_remove_exec(bContext *C, wmOperator *op)
317 {
318         /*      Object *ob;
319         bController *cont = edit_controller_property_get(C, op, ob);    */
320         PointerRNA ptr = CTX_data_pointer_get_type(C, "controller", &RNA_Controller);
321         Object *ob= ptr.id.data;
322         bController *cont= ptr.data;
323         
324         if (!cont)
325                 return OPERATOR_CANCELLED;
326         
327         BLI_remlink(&(ob->controllers), cont);
328         unlink_controller(cont);
329         free_controller(cont);
330         
331         WM_event_add_notifier(C, NC_LOGIC, NULL);
332         
333         return OPERATOR_FINISHED;
334 }
335
336
337 /* commented along with above stuff
338  static int controller_remove_invoke(bContext *C, wmOperator *op, wmEvent *event)
339 {
340         if (edit_controller_invoke_properties(C, op))
341                 return controller_remove_exec(C, op);
342         else
343                 return OPERATOR_CANCELLED;
344 }
345  */
346
347 void LOGIC_OT_controller_remove(wmOperatorType *ot)
348 {
349         ot->name= "Remove Controller";
350         ot->description= "Remove a controller from the active object";
351         ot->idname= "LOGIC_OT_controller_remove";
352         
353         //ot->invoke= controller_remove_invoke;
354         ot->exec= controller_remove_exec;
355         ot->poll= edit_controller_poll;
356         
357         /* flags */
358         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
359         //edit_controller_properties(ot);
360 }
361
362 static int controller_add_exec(bContext *C, wmOperator *op)
363 {
364         Object *ob = ED_object_active_context(C);
365         bController *cont;
366         PointerRNA cont_ptr;
367         PropertyRNA *prop;
368         const char *cont_name;
369         int type= RNA_enum_get(op->ptr, "type");
370         int bit;
371         char name[32];
372         
373         cont= new_controller(type);
374         BLI_addtail(&(ob->controllers), cont);
375         
376         /* set the controller name based on rna type enum */
377         RNA_pointer_create((ID *)ob, &RNA_Controller, cont, &cont_ptr);
378         prop = RNA_struct_find_property(&cont_ptr, "type");
379
380         RNA_string_get(op->ptr, "name", name);
381         if(BLI_strnlen(name, 32) < 1){
382                 RNA_property_enum_name(C, &cont_ptr, prop, RNA_property_enum_get(&cont_ptr, prop), &cont_name);
383                 BLI_strncpy(cont->name, cont_name, sizeof(cont->name));
384         }
385         else
386                 BLI_strncpy(cont->name, name, sizeof(cont->name));
387
388         make_unique_prop_names(C, cont->name);
389         /* set the controller state mask from the current object state.
390          A controller is always in a single state, so select the lowest bit set
391          from the object state */
392         for (bit=0; bit<OB_MAX_STATES; bit++) {
393                 if (ob->state & (1<<bit))
394                         break;
395         }
396         cont->state_mask = (1<<bit);
397         if (cont->state_mask == 0) {
398                 /* shouldn't happen, object state is never 0 */
399                 cont->state_mask = 1;
400         }
401         
402         ob->scaflag |= OB_SHOWCONT;
403         
404         WM_event_add_notifier(C, NC_LOGIC, NULL);
405         
406         return OPERATOR_FINISHED;
407 }
408
409 void LOGIC_OT_controller_add(wmOperatorType *ot)
410 {
411         PropertyRNA *prop;
412         
413         /* identifiers */
414         ot->name= "Add Controller";
415         ot->description = "Add a controller to the active object";
416         ot->idname= "LOGIC_OT_controller_add";
417         
418         /* api callbacks */
419         ot->invoke= WM_menu_invoke;
420         ot->exec= controller_add_exec;
421         ot->poll= ED_operator_object_active_editable;
422         
423         /* flags */
424         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
425         
426         /* properties */
427         prop= RNA_def_enum(ot->srna, "type", controller_type_items, CONT_LOGIC_AND, "Type", "Type of controller to add");
428         prop= RNA_def_string(ot->srna, "name", "", 32, "Name", "Name of the Controller to add");
429 }
430
431 /* ************* Add/Remove Actuator Operator ************* */
432
433 static int actuator_remove_exec(bContext *C, wmOperator *op)
434 {
435         /*      Object *ob;
436         bActuator *cont = edit_actuator_property_get(C, op, ob);        */
437         PointerRNA ptr = CTX_data_pointer_get_type(C, "actuator", &RNA_Actuator);
438         Object *ob= ptr.id.data;
439         bActuator *act= ptr.data;
440         
441         if (!act)
442                 return OPERATOR_CANCELLED;
443         
444         BLI_remlink(&(ob->actuators), act);
445         unlink_actuator(act);
446         free_actuator(act);
447         
448         WM_event_add_notifier(C, NC_LOGIC, NULL);
449         
450         return OPERATOR_FINISHED;
451 }
452
453
454 /* commented along with above stuff
455  static int actuator_remove_invoke(bContext *C, wmOperator *op, wmEvent *event)
456 {
457         if (edit_actuator_invoke_properties(C, op))
458                 return actuator_remove_exec(C, op);
459         else
460                 return OPERATOR_CANCELLED;
461 }
462  */
463
464 void LOGIC_OT_actuator_remove(wmOperatorType *ot)
465 {
466         ot->name= "Remove Actuator";
467         ot->description= "Remove a actuator from the active object";
468         ot->idname= "LOGIC_OT_actuator_remove";
469         
470         //ot->invoke= actuator_remove_invoke;
471         ot->exec= actuator_remove_exec;
472         ot->poll= edit_actuator_poll;
473         
474         /* flags */
475         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
476         //edit_controller_properties(ot);
477 }
478
479 static int actuator_add_exec(bContext *C, wmOperator *op)
480 {
481         Object *ob = ED_object_active_context(C);
482         bActuator *act;
483         PointerRNA act_ptr;
484         PropertyRNA *prop;
485         const char *act_name;
486         char  name[32];
487         //XXX RNA_string_get is not using maxlen, it's using UserPreferencesFilePaths_python_scripts_directory_get instead (what limits the string copy to 160 chars in this case and CRASHES Blender).
488         int type= RNA_enum_get(op->ptr, "type");
489
490         act= new_actuator(type);
491         BLI_addtail(&(ob->actuators), act);
492         
493         /* set the actuator name based on rna type enum */
494         RNA_pointer_create((ID *)ob, &RNA_Actuator, act, &act_ptr);
495         prop = RNA_struct_find_property(&act_ptr, "type");
496
497         RNA_string_get(op->ptr, "name", name);
498         if (BLI_strnlen(name, 32) < 1){
499                 RNA_property_enum_name(C, &act_ptr, prop, RNA_property_enum_get(&act_ptr, prop), &act_name);
500                 BLI_strncpy(act->name, act_name, sizeof(act->name));
501         }
502         else
503                 BLI_strncpy(act->name, name, sizeof(act->name));
504
505         make_unique_prop_names(C, act->name);
506         ob->scaflag |= OB_SHOWACT;
507         
508         WM_event_add_notifier(C, NC_LOGIC, NULL);
509         
510         return OPERATOR_FINISHED;
511 }
512
513 void LOGIC_OT_actuator_add(wmOperatorType *ot)
514 {
515         PropertyRNA *prop;
516         
517         /* identifiers */
518         ot->name= "Add Actuator";
519         ot->description = "Add a actuator to the active object";
520         ot->idname= "LOGIC_OT_actuator_add";
521         
522         /* api callbacks */
523         ot->invoke= WM_menu_invoke;
524         ot->exec= actuator_add_exec;
525         ot->poll= ED_operator_object_active_editable;
526         
527         /* flags */
528         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
529         
530         /* properties */
531         prop= RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, CONT_LOGIC_AND, "Type", "Type of actuator to add");
532         RNA_def_enum_funcs(prop, rna_Actuator_type_itemf);
533         prop= RNA_def_string(ot->srna, "name", "", 32, "Name", "Name of the Actuator to add");
534 }
535
536 void ED_operatortypes_logic(void)
537 {
538         WM_operatortype_append(LOGIC_OT_sensor_remove);
539         WM_operatortype_append(LOGIC_OT_sensor_add);
540         WM_operatortype_append(LOGIC_OT_controller_remove);
541         WM_operatortype_append(LOGIC_OT_controller_add);
542         WM_operatortype_append(LOGIC_OT_actuator_remove);
543         WM_operatortype_append(LOGIC_OT_actuator_add);
544 }