synched with trunk at revision 34793
[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_sensor_types.h"
32 #include "DNA_controller_types.h"
33 #include "DNA_actuator_types.h"
34
35 #include "BLI_blenlib.h"
36
37 #include "BKE_context.h"
38 #include "BKE_main.h"
39 #include "BKE_sca.h"
40
41 #include "ED_object.h"
42 #include "ED_screen.h"
43
44 #include "RNA_access.h"
45 #include "RNA_define.h"
46 #include "RNA_enum_types.h"
47
48 #include "WM_api.h"
49 #include "WM_types.h"
50
51 #include "logic_intern.h"
52
53 /* ************* Generic Operator Helpers ************* */
54
55 static int edit_sensor_poll(bContext *C)
56 {
57         PointerRNA ptr= CTX_data_pointer_get_type(C, "sensor", &RNA_Sensor);
58
59         if (ptr.data && ((ID*)ptr.id.data)->lib) return 0;
60         return 1;
61 }
62
63 static int edit_controller_poll(bContext *C)
64 {
65         PointerRNA ptr= CTX_data_pointer_get_type(C, "controller", &RNA_Controller);
66
67         if (ptr.data && ((ID*)ptr.id.data)->lib) return 0;
68         return 1;
69 }
70
71 static int edit_actuator_poll(bContext *C)
72 {
73         PointerRNA ptr= CTX_data_pointer_get_type(C, "actuator", &RNA_Actuator);
74
75         if (ptr.data && ((ID*)ptr.id.data)->lib) return 0;
76         return 1;
77 }
78
79 static void edit_sensor_properties(wmOperatorType *ot)
80 {
81         RNA_def_string(ot->srna, "sensor", "", 32, "Sensor", "Name of the sensor to edit");
82         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the object the sensor belongs to");
83 }
84
85 static int edit_sensor_invoke_properties(bContext *C, wmOperator *op)
86 {
87         PointerRNA ptr= CTX_data_pointer_get_type(C, "sensor", &RNA_Sensor);
88         
89         if (RNA_property_is_set(op->ptr, "sensor") && RNA_property_is_set(op->ptr, "object") )
90                 return 1;
91         
92         if (ptr.data) {
93                 bSensor *sens = ptr.data;
94                 Object *ob = ptr.id.data;
95                 
96                 RNA_string_set(op->ptr, "sensor", sens->name);
97                 RNA_string_set(op->ptr, "object", ob->id.name+2);
98                 return 1;
99         }
100         
101         return 0;
102 }
103
104 static Object *edit_object_property_get(bContext *C, wmOperator *op)
105 {
106         char ob_name[32];
107         Object *ob;
108
109         RNA_string_get(op->ptr, "object", ob_name);
110
111         /* if ob_name is valid try to find the object with this name
112         otherwise gets the active object */
113         if (BLI_strnlen(ob_name, 32) > 0)
114                 ob = BLI_findstring(&(CTX_data_main(C)->object), ob_name, offsetof(ID, name) + 2);
115         else
116                 ob= ED_object_active_context(C);
117
118         return ob;
119 }
120
121 static bSensor *edit_sensor_property_get(bContext *C, wmOperator *op, Object **ob)
122 {
123         char sensor_name[32];
124         bSensor *sens;
125         
126         RNA_string_get(op->ptr, "sensor", sensor_name);
127
128         *ob= edit_object_property_get(C, op);
129         if (!*ob) return NULL;
130         
131         sens = BLI_findstring(&((*ob)->sensors), sensor_name, offsetof(bSensor, name)); 
132         return sens;
133 }
134
135 static void edit_controller_properties(wmOperatorType *ot)
136 {
137         RNA_def_string(ot->srna, "controller", "", 32, "Controller", "Name of the controller to edit");
138         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the object the controller belongs to");
139 }
140
141 static int edit_controller_invoke_properties(bContext *C, wmOperator *op)
142 {
143         PointerRNA ptr= CTX_data_pointer_get_type(C, "controller", &RNA_Controller);
144         
145         if (RNA_property_is_set(op->ptr, "controller") && RNA_property_is_set(op->ptr, "object") )
146                 return 1;
147         
148         if (ptr.data) {
149                 bController *cont = ptr.data;
150                 Object *ob = ptr.id.data;
151                 
152                 RNA_string_set(op->ptr, "controller", cont->name);
153                 RNA_string_set(op->ptr, "object", ob->id.name+2);
154                 return 1;
155         }
156         
157         return 0;
158 }
159
160 static bController *edit_controller_property_get(bContext *C, wmOperator *op, Object **ob)
161 {
162         char controller_name[32];
163         bController *cont;
164         
165         RNA_string_get(op->ptr, "controller", controller_name);
166
167         *ob= edit_object_property_get(C, op);
168         if (!*ob) return NULL;
169         
170         cont = BLI_findstring(&((*ob)->controllers), controller_name, offsetof(bController, name));     
171         return cont;
172 }
173
174 static void edit_actuator_properties(wmOperatorType *ot)
175 {
176         RNA_def_string(ot->srna, "actuator", "", 32, "Actuator", "Name of the actuator to edit");
177         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the object the actuator belongs to");
178 }
179
180 static int edit_actuator_invoke_properties(bContext *C, wmOperator *op)
181 {
182         PointerRNA ptr= CTX_data_pointer_get_type(C, "actuator", &RNA_Actuator);
183         
184         if (RNA_property_is_set(op->ptr, "actuator") && RNA_property_is_set(op->ptr, "object") )
185                 return 1;
186         
187         if (ptr.data) {
188                 bActuator *act = ptr.data;
189                 Object *ob = ptr.id.data;
190                 
191                 RNA_string_set(op->ptr, "actuator",act->name);
192                 RNA_string_set(op->ptr, "object", ob->id.name+2);
193                 return 1;
194         }
195         
196         return 0;
197 }
198
199 static bActuator *edit_actuator_property_get(bContext *C, wmOperator *op, Object **ob)
200 {
201         char actuator_name[32];
202         bActuator *act;
203         
204         RNA_string_get(op->ptr, "actuator", actuator_name);
205
206         *ob= edit_object_property_get(C, op);
207         if (!*ob) return NULL;
208         
209         act = BLI_findstring(&((*ob)->actuators), actuator_name, offsetof(bActuator, name));    
210         return act;
211 }
212
213 static int logicbricks_move_property_get(wmOperator *op)
214 {
215         int type = RNA_enum_get(op->ptr, "direction");
216
217         if (type == 1)
218                 return TRUE;
219         else
220                 return FALSE;
221 }
222
223 /* ************* Add/Remove Sensor Operator ************* */
224
225 static int sensor_remove_exec(bContext *C, wmOperator *op)
226 {
227         Object *ob=NULL;
228         bSensor *sens = edit_sensor_property_get(C, op, &ob);
229         
230         if (!sens)
231                 return OPERATOR_CANCELLED;
232         
233         BLI_remlink(&(ob->sensors), sens);
234         free_sensor(sens);
235         
236         WM_event_add_notifier(C, NC_LOGIC, NULL);
237         
238         return OPERATOR_FINISHED;
239 }
240
241  static int sensor_remove_invoke(bContext *C, wmOperator *op, wmEvent *event)
242 {
243         if (edit_sensor_invoke_properties(C, op))
244                 return sensor_remove_exec(C, op);
245         else
246                 return OPERATOR_CANCELLED;
247 }
248
249 void LOGIC_OT_sensor_remove(wmOperatorType *ot)
250 {
251         ot->name= "Remove Sensor";
252         ot->description= "Remove a sensor from the active object";
253         ot->idname= "LOGIC_OT_sensor_remove";
254         
255         ot->invoke= sensor_remove_invoke;
256         ot->exec= sensor_remove_exec;
257         ot->poll= edit_sensor_poll;
258         
259         /* flags */
260         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
261         edit_sensor_properties(ot);
262 }
263
264 static int sensor_add_exec(bContext *C, wmOperator *op)
265 {
266         Object *ob;
267         bSensor *sens;
268         PointerRNA sens_ptr;
269         PropertyRNA *prop;
270         const char *sens_name;
271         char name[32];
272         int type= RNA_enum_get(op->ptr, "type");
273
274         ob= edit_object_property_get(C, op);
275         if (!ob)
276                 return OPERATOR_CANCELLED;
277
278         sens= new_sensor(type);
279         BLI_addtail(&(ob->sensors), sens);
280         
281         /* set the sensor name based on rna type enum */
282         RNA_pointer_create((ID *)ob, &RNA_Sensor, sens, &sens_ptr);
283         prop = RNA_struct_find_property(&sens_ptr, "type");
284
285         RNA_string_get(op->ptr, "name", name);
286         if(BLI_strnlen(name, 32) < 1){
287                 RNA_property_enum_name(C, &sens_ptr, prop, RNA_property_enum_get(&sens_ptr, prop), &sens_name);
288                 BLI_strncpy(sens->name, sens_name, sizeof(sens->name));
289         }
290         else
291                 BLI_strncpy(sens->name, name, sizeof(sens->name));
292
293         make_unique_prop_names(C, sens->name);
294         ob->scaflag |= OB_SHOWSENS;
295
296         WM_event_add_notifier(C, NC_LOGIC, NULL);
297         
298         return OPERATOR_FINISHED;
299 }
300
301 void LOGIC_OT_sensor_add(wmOperatorType *ot)
302 {
303         PropertyRNA *prop;
304         
305         /* identifiers */
306         ot->name= "Add Sensor";
307         ot->description = "Add a sensor to the active object";
308         ot->idname= "LOGIC_OT_sensor_add";
309         
310         /* api callbacks */
311         ot->invoke= WM_menu_invoke;
312         ot->exec= sensor_add_exec;
313         ot->poll= ED_operator_object_active_editable;
314         
315         /* flags */
316         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
317         
318         /* properties */
319         prop= RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, SENS_ALWAYS, "Type", "Type of sensor to add");
320         RNA_def_enum_funcs(prop, rna_Sensor_type_itemf);
321         RNA_def_string(ot->srna, "name", "", 32, "Name", "Name of the Sensor to add");
322         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the Object to add the Sensor to");
323 }
324
325 /* ************* Add/Remove Controller Operator ************* */
326
327 static int controller_remove_exec(bContext *C, wmOperator *op)
328 {
329         Object *ob = NULL;
330         bController *cont = edit_controller_property_get(C, op, &ob);
331         
332         if (!cont)
333                 return OPERATOR_CANCELLED;
334         
335         BLI_remlink(&(ob->controllers), cont);
336         unlink_controller(cont);
337         free_controller(cont);
338         
339         WM_event_add_notifier(C, NC_LOGIC, NULL);
340         
341         return OPERATOR_FINISHED;
342 }
343
344  static int controller_remove_invoke(bContext *C, wmOperator *op, wmEvent *event)
345 {
346         if (edit_controller_invoke_properties(C, op))
347                 return controller_remove_exec(C, op);
348         else
349                 return OPERATOR_CANCELLED;
350 }
351
352 void LOGIC_OT_controller_remove(wmOperatorType *ot)
353 {
354         ot->name= "Remove Controller";
355         ot->description= "Remove a controller from the active object";
356         ot->idname= "LOGIC_OT_controller_remove";
357         
358         ot->invoke= controller_remove_invoke;
359         ot->exec= controller_remove_exec;
360         ot->poll= edit_controller_poll;
361         
362         /* flags */
363         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
364         edit_controller_properties(ot);
365 }
366
367 static int controller_add_exec(bContext *C, wmOperator *op)
368 {
369         Object *ob;
370         bController *cont;
371         PointerRNA cont_ptr;
372         PropertyRNA *prop;
373         const char *cont_name;
374         int bit;
375         char name[32];
376         int type= RNA_enum_get(op->ptr, "type");
377
378         ob= edit_object_property_get(C, op);
379         if(!ob)
380                 return OPERATOR_CANCELLED;
381         
382         cont= new_controller(type);
383         BLI_addtail(&(ob->controllers), cont);
384         
385         /* set the controller name based on rna type enum */
386         RNA_pointer_create((ID *)ob, &RNA_Controller, cont, &cont_ptr);
387         prop = RNA_struct_find_property(&cont_ptr, "type");
388
389         RNA_string_get(op->ptr, "name", name);
390         if(BLI_strnlen(name, 32) < 1){
391                 RNA_property_enum_name(C, &cont_ptr, prop, RNA_property_enum_get(&cont_ptr, prop), &cont_name);
392                 BLI_strncpy(cont->name, cont_name, sizeof(cont->name));
393         }
394         else
395                 BLI_strncpy(cont->name, name, sizeof(cont->name));
396
397         make_unique_prop_names(C, cont->name);
398         /* set the controller state mask from the current object state.
399          A controller is always in a single state, so select the lowest bit set
400          from the object state */
401         for (bit=0; bit<OB_MAX_STATES; bit++) {
402                 if (ob->state & (1<<bit))
403                         break;
404         }
405         cont->state_mask = (1<<bit);
406         if (cont->state_mask == 0) {
407                 /* shouldn't happen, object state is never 0 */
408                 cont->state_mask = 1;
409         }
410         
411         ob->scaflag |= OB_SHOWCONT;
412         
413         WM_event_add_notifier(C, NC_LOGIC, NULL);
414         
415         return OPERATOR_FINISHED;
416 }
417
418 void LOGIC_OT_controller_add(wmOperatorType *ot)
419 {
420         /* identifiers */
421         ot->name= "Add Controller";
422         ot->description = "Add a controller to the active object";
423         ot->idname= "LOGIC_OT_controller_add";
424         
425         /* api callbacks */
426         ot->invoke= WM_menu_invoke;
427         ot->exec= controller_add_exec;
428         ot->poll= ED_operator_object_active_editable;
429         
430         /* flags */
431         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
432         
433         /* properties */
434         RNA_def_enum(ot->srna, "type", controller_type_items, CONT_LOGIC_AND, "Type", "Type of controller to add");
435         RNA_def_string(ot->srna, "name", "", 32, "Name", "Name of the Controller to add");
436         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the Object to add the Controller to");
437 }
438
439 /* ************* Add/Remove Actuator Operator ************* */
440
441 static int actuator_remove_exec(bContext *C, wmOperator *op)
442 {
443         Object *ob=NULL;
444         bActuator *act = edit_actuator_property_get(C, op, &ob);
445         
446         if (!act)
447                 return OPERATOR_CANCELLED;
448         
449         BLI_remlink(&(ob->actuators), act);
450         unlink_actuator(act);
451         free_actuator(act);
452         
453         WM_event_add_notifier(C, NC_LOGIC, NULL);
454         
455         return OPERATOR_FINISHED;
456 }
457
458 static int actuator_remove_invoke(bContext *C, wmOperator *op, wmEvent *event)
459 {
460         if (edit_actuator_invoke_properties(C, op))
461                 return actuator_remove_exec(C, op);
462         else
463                 return OPERATOR_CANCELLED;
464 }
465
466 void LOGIC_OT_actuator_remove(wmOperatorType *ot)
467 {
468         ot->name= "Remove Actuator";
469         ot->description= "Remove a actuator from the active object";
470         ot->idname= "LOGIC_OT_actuator_remove";
471         
472         ot->invoke= actuator_remove_invoke;
473         ot->exec= actuator_remove_exec;
474         ot->poll= edit_actuator_poll;
475         
476         /* flags */
477         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
478         edit_actuator_properties(ot);
479 }
480
481 static int actuator_add_exec(bContext *C, wmOperator *op)
482 {
483         Object *ob;
484         bActuator *act;
485         PointerRNA act_ptr;
486         PropertyRNA *prop;
487         const char *act_name;
488         char  name[32];
489         int type= RNA_enum_get(op->ptr, "type");
490                 
491         ob= edit_object_property_get(C, op);
492         if(!ob)
493                 return OPERATOR_CANCELLED;
494
495         act= new_actuator(type);
496         BLI_addtail(&(ob->actuators), act);
497         
498         /* set the actuator name based on rna type enum */
499         RNA_pointer_create((ID *)ob, &RNA_Actuator, act, &act_ptr);
500         prop = RNA_struct_find_property(&act_ptr, "type");
501
502         RNA_string_get(op->ptr, "name", name);
503         if (BLI_strnlen(name, 32) < 1){
504                 RNA_property_enum_name(C, &act_ptr, prop, RNA_property_enum_get(&act_ptr, prop), &act_name);
505                 BLI_strncpy(act->name, act_name, sizeof(act->name));
506         }
507         else
508                 BLI_strncpy(act->name, name, sizeof(act->name));
509
510         make_unique_prop_names(C, act->name);
511         ob->scaflag |= OB_SHOWACT;
512         
513         WM_event_add_notifier(C, NC_LOGIC, NULL);
514         
515         return OPERATOR_FINISHED;
516 }
517
518 void LOGIC_OT_actuator_add(wmOperatorType *ot)
519 {
520         PropertyRNA *prop;
521         
522         /* identifiers */
523         ot->name= "Add Actuator";
524         ot->description = "Add a actuator to the active object";
525         ot->idname= "LOGIC_OT_actuator_add";
526         
527         /* api callbacks */
528         ot->invoke= WM_menu_invoke;
529         ot->exec= actuator_add_exec;
530         ot->poll= ED_operator_object_active_editable;
531         
532         /* flags */
533         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
534         
535         /* properties */
536         prop= RNA_def_enum(ot->srna, "type", DummyRNA_NULL_items, CONT_LOGIC_AND, "Type", "Type of actuator to add");
537         RNA_def_enum_funcs(prop, rna_Actuator_type_itemf);
538         RNA_def_string(ot->srna, "name", "", 32, "Name", "Name of the Actuator to add");
539         RNA_def_string(ot->srna, "object", "", 32, "Object", "Name of the Object to add the Actuator to");
540 }
541
542 /* ************* Move Logic Bricks Operator ************* */
543 static EnumPropertyItem logicbricks_move_direction[] ={
544                 {1, "UP", 0, "Move Up", ""},
545                 {2, "DOWN", 0, "Move Down", ""},
546                 {0, NULL, 0, NULL, NULL}};
547
548
549 static int sensor_move_exec(bContext *C, wmOperator *op)
550 {
551         Object *ob=NULL;
552         bSensor *sens= edit_sensor_property_get(C, op, &ob);
553         int move_up= logicbricks_move_property_get(op);
554         
555         if (!sens)
556                 return OPERATOR_CANCELLED;
557
558         sca_move_sensor(sens, ob, move_up);
559
560         WM_event_add_notifier(C, NC_LOGIC, NULL);
561         
562         return OPERATOR_FINISHED;
563 }
564
565 static int sensor_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
566 {
567         if (edit_sensor_invoke_properties(C, op)) {
568                 return sensor_move_exec(C, op);
569         }
570         else
571                 return OPERATOR_CANCELLED;
572 }
573
574 void LOGIC_OT_sensor_move(wmOperatorType *ot)
575 {
576         /* identifiers */
577         ot->name= "Move Sensor";
578         ot->description = "Move Densor";
579         ot->idname= "LOGIC_OT_sensor_move";
580         
581         /* api callbacks */
582         ot->invoke= sensor_move_invoke;
583         ot->exec= sensor_move_exec;
584         ot->poll= edit_sensor_poll;
585         
586         /* flags */
587         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
588         
589         /* properties */
590         edit_sensor_properties(ot);
591         RNA_def_enum(ot->srna, "direction", logicbricks_move_direction, 1, "Direction", "Move Up or Down");
592 }
593
594 static int controller_move_exec(bContext *C, wmOperator *op)
595 {
596         Object *ob=NULL;
597         bController *cont= edit_controller_property_get(C, op, &ob);
598         int move_up= logicbricks_move_property_get(op);
599         
600         if (!cont)
601                 return OPERATOR_CANCELLED;
602
603         sca_move_controller(cont, ob, move_up);
604
605         WM_event_add_notifier(C, NC_LOGIC, NULL);
606         
607         return OPERATOR_FINISHED;
608 }
609
610 static int controller_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
611 {
612         if (edit_controller_invoke_properties(C, op)) {
613                 return controller_move_exec(C, op);
614         }
615         else
616                 return OPERATOR_CANCELLED;
617 }
618
619 void LOGIC_OT_controller_move(wmOperatorType *ot)
620 {
621         /* identifiers */
622         ot->name= "Move Controller";
623         ot->description = "Move Controller";
624         ot->idname= "LOGIC_OT_controller_move";
625         
626         /* api callbacks */
627         ot->invoke= controller_move_invoke;
628         ot->exec= controller_move_exec;
629         ot->poll= edit_controller_poll;
630         
631         /* flags */
632         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
633         
634         /* properties */
635         edit_controller_properties(ot);
636         RNA_def_enum(ot->srna, "direction", logicbricks_move_direction, 1, "Direction", "Move Up or Down");
637 }
638
639 static int actuator_move_exec(bContext *C, wmOperator *op)
640 {
641         Object *ob=NULL;
642         bActuator *act = edit_actuator_property_get(C, op, &ob);
643         int move_up= logicbricks_move_property_get(op);
644
645         if (!act)
646                 return OPERATOR_CANCELLED;
647
648         sca_move_actuator(act, ob, move_up);
649
650         WM_event_add_notifier(C, NC_LOGIC, NULL);
651         
652         return OPERATOR_FINISHED;
653 }
654
655 static int actuator_move_invoke(bContext *C, wmOperator *op, wmEvent *event)
656 {
657         if (edit_actuator_invoke_properties(C, op)) {
658                 return actuator_move_exec(C, op);
659         }
660         else
661                 return OPERATOR_CANCELLED;
662 }
663
664 void LOGIC_OT_actuator_move(wmOperatorType *ot)
665 {
666         /* identifiers */
667         ot->name= "Move Actuator";
668         ot->description = "Move Actuator";
669         ot->idname= "LOGIC_OT_actuator_move";
670         
671         /* api callbacks */
672         ot->invoke= actuator_move_invoke;
673         ot->exec= actuator_move_exec;
674         ot->poll= edit_actuator_poll;
675         
676         /* flags */
677         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
678         
679         /* properties */
680         edit_actuator_properties(ot);
681         RNA_def_enum(ot->srna, "direction", logicbricks_move_direction, 1, "Direction", "Move Up or Down");
682 }
683
684
685 void ED_operatortypes_logic(void)
686 {
687         WM_operatortype_append(LOGIC_OT_sensor_remove);
688         WM_operatortype_append(LOGIC_OT_sensor_add);
689         WM_operatortype_append(LOGIC_OT_sensor_move);
690         WM_operatortype_append(LOGIC_OT_controller_remove);
691         WM_operatortype_append(LOGIC_OT_controller_add);
692         WM_operatortype_append(LOGIC_OT_controller_move);
693         WM_operatortype_append(LOGIC_OT_actuator_remove);
694         WM_operatortype_append(LOGIC_OT_actuator_add);
695         WM_operatortype_append(LOGIC_OT_actuator_move);
696 }