Skip to content

Commit fba7bd3

Browse files
committed
UPBGE: Add component scritp generation.
To ease the definition of a component a button named "Create Component" is added. This button ask for a path module.Class and generates a script named module.py with a component class Class inside. This template class contains a start and update function commented and a definition block before the class for global game engine variable. If the file already exists an error is raised. The previous button named Add Component is now renamed Register Component.
1 parent 2c93233 commit fba7bd3

File tree

5 files changed

+155
-14
lines changed

5 files changed

+155
-14
lines changed

release/scripts/startup/bl_ui/space_logic.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,15 @@ def draw(self, context):
3939
st = context.space_data
4040

4141
row = layout.row()
42-
row.operator("logic.add_python_component", text="Add Component", icon="ZOOMIN")
42+
row.operator("logic.python_component_register", text="Register Component", icon="ZOOMIN")
43+
row.operator("logic.python_component_create", text="Create Component", icon="ZOOMIN")
4344

4445
for i, c in enumerate(game.components):
4546
box = layout.box()
4647
row = box.row()
4748
row.prop(c, "name", text="")
48-
row.operator("logic.component_reload", text="", icon='RECOVER_LAST').index = i
49-
row.operator("logic.component_remove", text="", icon='X').index = i
49+
row.operator("logic.python_component_reload", text="", icon='RECOVER_LAST').index = i
50+
row.operator("logic.python_component_remove", text="", icon='X').index = i
5051

5152
for prop in c.properties:
5253
row = box.row()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import bge
2+
from collections import OrderedDict
3+
4+
if not hasattr(bge, "__component__"):
5+
# Put shared definitions here executed only in game engine.
6+
# e.g:
7+
# scene = bge.logic.getCurrentScene()
8+
pass
9+
10+
class %Name%(bge.types.KX_PythonComponent):
11+
# Put your arguments here of the format ("key", default_value).
12+
# These values are exposed to the UI.
13+
args = OrderedDict([
14+
])
15+
16+
def start(self, args):
17+
# Put your initialization code here, args stores the values from the UI.
18+
# self.object is the owner object of this component.
19+
pass
20+
21+
def update(self):
22+
# Put your code executed every logic step here.
23+
# self.object is the owner object of this component.
24+
pass

source/blender/blenkernel/BKE_python_component.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extern "C" {
2828
#endif
2929

3030
struct PythonComponent *BKE_python_component_new(char *import, struct ReportList *reports, struct bContext *context);
31+
struct PythonComponent *BKE_python_component_create_file(char *import, struct ReportList *reports, struct bContext *context);
3132
void BKE_python_component_reload(struct PythonComponent *pc, struct ReportList *reports, struct bContext *context);
3233
void BKE_python_component_copy_list(struct ListBase *lbn, const struct ListBase *lbo);
3334
void BKE_python_component_free(struct PythonComponent *pc);

source/blender/blenkernel/intern/python_component.c

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,15 @@
2626
#include "BLI_listbase.h"
2727
#include "BLI_string.h"
2828
#include "BLI_path_util.h"
29+
#include "BLI_fileops.h"
2930
#include "MEM_guardedalloc.h"
3031

3132
#include "BKE_python_component.h"
3233
#include "BKE_report.h"
3334
#include "BKE_context.h"
3435
#include "BKE_main.h"
36+
#include "BKE_text.h"
37+
#include "BKE_appdir.h"
3538

3639
#include "RNA_types.h"
3740

@@ -505,6 +508,75 @@ PythonComponent *BKE_python_component_new(char *import, ReportList *reports, bCo
505508
return pc;
506509
}
507510

511+
PythonComponent *BKE_python_component_create_file(char *import, ReportList *reports, bContext *context)
512+
{
513+
char *classname;
514+
char *modulename;
515+
char filename[FILE_MAX];
516+
char respath[FILE_MAX];
517+
size_t filesize = 0;
518+
unsigned char *orgfilecontent;
519+
char *filecontent;
520+
Main *maggie = CTX_data_main(context);
521+
struct Text *text;
522+
PythonComponent *pc;
523+
524+
// Don't bother with an empty string
525+
if (strcmp(import, "") == 0) {
526+
BKE_report(reports, RPT_ERROR_INVALID_INPUT, "No component was specified.");
527+
return NULL;
528+
}
529+
530+
// Extract the module name and the class name.
531+
modulename = strtok(import, ".");
532+
classname = strtok(NULL, ".");
533+
534+
if (!classname) {
535+
BKE_report(reports, RPT_ERROR_INVALID_INPUT, "No component class name was specified.");
536+
return NULL;
537+
}
538+
539+
strcpy(filename, modulename);
540+
BLI_ensure_extension(filename, FILE_MAX, ".py");
541+
542+
if (BLI_findstring(&maggie->text, filename, offsetof(ID, name) + 2)) {
543+
BKE_reportf(reports, RPT_ERROR_INVALID_INPUT, "File %s already exists.", filename);
544+
return NULL;
545+
}
546+
547+
text = BKE_text_add(maggie, filename);
548+
549+
BLI_strncpy(respath, BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "templates_py"), sizeof(respath));
550+
BLI_path_append(respath, sizeof(respath), "python_component.py");
551+
552+
orgfilecontent = BLI_file_read_text_as_mem(respath, 0, &filesize);
553+
orgfilecontent[filesize] = '\0';
554+
555+
filecontent = BLI_str_replaceN((char *)orgfilecontent, "%Name%", classname);
556+
557+
BKE_text_write(text, (char *)filecontent);
558+
559+
MEM_freeN(filecontent);
560+
561+
pc = MEM_callocN(sizeof(PythonComponent), "PythonComponent");
562+
563+
// Copy module and class names.
564+
strcpy(pc->module, modulename);
565+
if (classname) {
566+
strcpy(pc->name, classname);
567+
}
568+
569+
// Try load the component.
570+
if (!load_component(pc, reports, CTX_data_main(context))) {
571+
BKE_python_component_free(pc);
572+
return NULL;
573+
}
574+
575+
BKE_reportf(reports, RPT_INFO, "File %s created.", filename);
576+
577+
return pc;
578+
}
579+
508580
void BKE_python_component_reload(PythonComponent *pc, ReportList *reports, bContext *context)
509581
{
510582
load_component(pc, reports, CTX_data_main(context));

source/blender/editors/space_logic/logic_ops.c

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,7 @@ static void LOGIC_OT_view_all(wmOperatorType *ot)
742742
}
743743

744744
/* Component operators */
745-
static int component_add_exec(bContext *C, wmOperator *op)
745+
static int component_register_exec(bContext *C, wmOperator *op)
746746
{
747747
PythonComponent *pycomp;
748748
Object *ob = CTX_data_active_object(C);
@@ -770,20 +770,62 @@ static int component_add_exec(bContext *C, wmOperator *op)
770770
return OPERATOR_FINISHED;
771771
}
772772

773+
static int component_create_exec(bContext *C, wmOperator *op)
774+
{
775+
PythonComponent *pycomp;
776+
Object *ob = CTX_data_active_object(C);
777+
char import[MAX_NAME];
778+
779+
if (!ob) {
780+
return OPERATOR_CANCELLED;
781+
}
782+
783+
RNA_string_get(op->ptr, "component_name", import);
784+
pycomp = BKE_python_component_create_file(import, op->reports, C);
785+
786+
if(!pycomp) {
787+
return OPERATOR_CANCELLED;
788+
}
789+
790+
BLI_addtail(&ob->components, pycomp);
791+
WM_event_add_notifier(C, NC_LOGIC, NULL);
792+
793+
return OPERATOR_FINISHED;
794+
}
795+
773796
static int component_new_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
774797
{
775798
/* Better for user feedback. */
776799
return WM_operator_props_dialog_popup(C, op, 15 * UI_UNIT_X, UI_UNIT_Y);
777800
}
778801

779-
static void LOGIC_OT_component_add(wmOperatorType *ot)
802+
static void LOGIC_OT_python_component_register(wmOperatorType *ot)
780803
{
781804
ot->name = "Add Python Component";
782-
ot->idname = "LOGIC_OT_add_python_component";
805+
ot->idname = "LOGIC_OT_python_component_register";
783806
ot->description = "Add a python component to the selected object";
784807

785808
/* api callbacks */
786-
ot->exec = component_add_exec;
809+
ot->exec = component_register_exec;
810+
ot->invoke = component_new_invoke;
811+
ot->poll = ED_operator_object_active_editable;
812+
813+
/* flags */
814+
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
815+
816+
PropertyRNA *parm;
817+
parm = RNA_def_string(ot->srna, "component_name", "module.Component", 64, "Component", "The component class name with module (module.ComponentName)");
818+
RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
819+
}
820+
821+
static void LOGIC_OT_python_component_create(wmOperatorType *ot)
822+
{
823+
ot->name = "Create Python Component";
824+
ot->idname = "LOGIC_OT_python_component_create";
825+
ot->description = "Create a python component to the selected object";
826+
827+
/* api callbacks */
828+
ot->exec = component_create_exec;
787829
ot->invoke = component_new_invoke;
788830
ot->poll = ED_operator_object_active_editable;
789831

@@ -819,12 +861,12 @@ static int component_remove_exec(bContext *C, wmOperator *op)
819861
return OPERATOR_FINISHED;
820862
}
821863

822-
static void LOGIC_OT_component_remove(wmOperatorType *ot)
864+
static void LOGIC_OT_python_component_remove(wmOperatorType *ot)
823865
{
824866
/* identifiers */
825867
ot->name = "Remove Component";
826868
ot->description = "Remove Component";
827-
ot->idname = "LOGIC_OT_component_remove";
869+
ot->idname = "LOGIC_OT_python_component_remove";
828870

829871
/* api callbacks */
830872
ot->exec = component_remove_exec;
@@ -871,12 +913,12 @@ static int component_reload_exec(bContext *C, wmOperator *op)
871913
return OPERATOR_FINISHED;
872914
}
873915

874-
static void LOGIC_OT_component_reload(wmOperatorType *ot)
916+
static void LOGIC_OT_python_component_reload(wmOperatorType *ot)
875917
{
876918
/* identifiers */
877919
ot->name = "Reload Component";
878920
ot->description = "Reload Component";
879-
ot->idname = "LOGIC_OT_component_reload";
921+
ot->idname = "LOGIC_OT_python_component_reload";
880922

881923
/* api callbacks */
882924
ot->exec = component_reload_exec;
@@ -903,9 +945,10 @@ void ED_operatortypes_logic(void)
903945
WM_operatortype_append(LOGIC_OT_actuator_add);
904946
WM_operatortype_append(LOGIC_OT_actuator_move);
905947

906-
WM_operatortype_append(LOGIC_OT_component_add);
907-
WM_operatortype_append(LOGIC_OT_component_remove);
908-
WM_operatortype_append(LOGIC_OT_component_reload);
948+
WM_operatortype_append(LOGIC_OT_python_component_register);
949+
WM_operatortype_append(LOGIC_OT_python_component_create);
950+
WM_operatortype_append(LOGIC_OT_python_component_remove);
951+
WM_operatortype_append(LOGIC_OT_python_component_reload);
909952

910953
WM_operatortype_append(LOGIC_OT_view_all);
911954
}

0 commit comments

Comments
 (0)