user-preferences for addons. currently unused, example & docs still to come.

This commit is contained in:
Campbell Barton 2012-12-29 10:24:42 +00:00
parent 18f134304c
commit 79c2571e56
11 changed files with 309 additions and 4 deletions

@ -1162,7 +1162,8 @@ class USERPREF_PT_addons(Panel):
continue
# Addon UI Code
box = col.column().box()
col_box = col.column()
box = col_box.box()
colsub = box.column()
row = colsub.row()
@ -1225,6 +1226,25 @@ class USERPREF_PT_addons(Panel):
for i in range(4 - tot_row):
split.separator()
# Show addon user preferences
if is_enabled:
addon_preferences = userpref.addons[module_name].preferences
if addon_preferences is not None:
draw = getattr(addon_preferences, "draw", None)
if draw is not None:
addon_preferences_class = type(addon_preferences)
box_prefs = col_box.box()
box_prefs.label("Preferences:")
addon_preferences_class.layout = box_prefs
try:
draw(context)
except:
import traceback
traceback.print_exc()
box_prefs.label(text="Error (see console)", icon='ERROR')
del addon_preferences_class.layout
# Append missing scripts
# First collect scripts that are used but have no script file.
module_names = {mod.__name__ for mod, info in addons}

@ -0,0 +1,42 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#ifndef __BKE_ADDON_H__
#define __BKE_ADDON_H__
#include "RNA_types.h"
typedef struct bAddonPrefType {
/* type info */
char idname[64]; // best keep the same size as BKE_ST_MAXNAME
/* RNA integration */
ExtensionRNA ext;
} bAddonPrefType;
bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet);
void BKE_addon_pref_type_add(bAddonPrefType *apt);
void BKE_addon_pref_type_remove(bAddonPrefType *apt);
void BKE_addon_pref_type_init(void);
void BKE_addon_pref_type_free(void);
#endif /* __BKE_ADDON_H__ */

@ -58,6 +58,7 @@ set(SRC
intern/CCGSubSurf.c
intern/DerivedMesh.c
intern/action.c
intern/addon.c
intern/anim.c
intern/anim_sys.c
intern/armature.c
@ -152,6 +153,7 @@ set(SRC
BKE_DerivedMesh.h
BKE_action.h
BKE_addon.h
BKE_anim.h
BKE_animsys.h
BKE_armature.h

@ -0,0 +1,84 @@
/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Contributor(s): Campbell Barton
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <stddef.h>
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
#include "BLI_string.h"
#include "BKE_addon.h" /* own include */
#include "RNA_access.h"
#include "RNA_define.h"
#include "BLF_translation.h"
#include "MEM_guardedalloc.h"
static GHash *global_addonpreftype_hash = NULL;
bAddonPrefType *BKE_addon_pref_type_find(const char *idname, int quiet)
{
if (idname[0]) {
bAddonPrefType *apt;
apt = BLI_ghash_lookup(global_addonpreftype_hash, idname);
if (apt) {
return apt;
}
if (!quiet) {
printf("search for unknown addon-ref '%s'\n", idname);
}
}
else {
if (!quiet) {
printf("search for empty addon");
}
}
return NULL;
}
void BKE_addon_pref_type_add(bAddonPrefType *apt)
{
BLI_ghash_insert(global_addonpreftype_hash, (void *)apt->idname, apt);
}
void BKE_addon_pref_type_remove(bAddonPrefType *apt)
{
BLI_ghash_remove(global_addonpreftype_hash, (void *)apt->idname, NULL, (GHashValFreeFP)MEM_freeN);
}
void BKE_addon_pref_type_init(void)
{
BLI_assert(global_addonpreftype_hash == NULL);
global_addonpreftype_hash = BLI_ghash_str_new(__func__);
}
void BKE_addon_pref_type_free(void)
{
BLI_ghash_free(global_addonpreftype_hash, NULL, (GHashValFreeFP)MEM_freeN);
global_addonpreftype_hash = NULL;
}

@ -387,6 +387,7 @@ void BKE_userdef_free(void)
wmKeyMap *km;
wmKeyMapItem *kmi;
wmKeyMapDiffItem *kmdi;
bAddon *addon, *addon_next;
for (km = U.user_keymaps.first; km; km = km->next) {
for (kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) {
@ -407,11 +408,19 @@ void BKE_userdef_free(void)
BLI_freelistN(&km->items);
}
for (addon = U.addons.first; addon; addon = addon_next) {
addon_next = addon->next;
if (addon->prop) {
IDP_FreeProperty(addon->prop);
MEM_freeN(addon->prop);
}
MEM_freeN(addon);
}
BLI_freelistN(&U.uistyles);
BLI_freelistN(&U.uifonts);
BLI_freelistN(&U.themes);
BLI_freelistN(&U.user_keymaps);
BLI_freelistN(&U.addons);
}
/* handle changes in settings that need recalc */

@ -8646,6 +8646,7 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
wmKeyMap *keymap;
wmKeyMapItem *kmi;
wmKeyMapDiffItem *kmdi;
bAddon *addon;
bfd->user = user= read_struct(fd, bhead, "user def");
@ -8684,6 +8685,13 @@ static BHead *read_userdef(BlendFileData *bfd, FileData *fd, BHead *bhead)
direct_link_keymapitem(fd, kmi);
}
for (addon = user->addons.first; addon; addon = addon->next) {
addon->prop = newdataadr(fd, addon->prop);
if (addon->prop) {
IDP_DirectLinkProperty(addon->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd);
}
}
// XXX
user->uifonts.first = user->uifonts.last= NULL;

@ -850,8 +850,12 @@ static void write_userdef(WriteData *wd)
write_keymapitem(wd, kmi);
}
for (bext= U.addons.first; bext; bext=bext->next)
for (bext= U.addons.first; bext; bext=bext->next) {
writestruct(wd, DATA, "bAddon", 1, bext);
if (bext->prop) {
IDP_WriteProperty(bext->prop, wd);
}
}
for (style= U.uistyles.first; style; style= style->next) {
writestruct(wd, DATA, "uiStyle", 1, style);

@ -343,6 +343,7 @@ typedef struct bTheme {
typedef struct bAddon {
struct bAddon *next, *prev;
char module[64];
IDProperty *prop; /* User-Defined Properties on this Addon (for storing preferences) */
} bAddon;
typedef struct SolidLight {

@ -54,6 +54,7 @@ extern StructRNA RNA_ActionPoseMarkers;
extern StructRNA RNA_Actuator;
extern StructRNA RNA_ActuatorSensor;
extern StructRNA RNA_Addon;
extern StructRNA RNA_AddonPreferences;
extern StructRNA RNA_AdjustmentSequence;
extern StructRNA RNA_AlwaysSensor;
extern StructRNA RNA_AndController;

@ -47,6 +47,7 @@
#include "BLF_translation.h"
#include "BKE_sound.h"
#include "BKE_addon.h"
#ifdef WITH_CYCLES
static EnumPropertyItem compute_device_type_items[] = {
@ -67,6 +68,7 @@ static EnumPropertyItem compute_device_type_items[] = {
#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_idprop.h"
#include "GPU_draw.h"
@ -79,6 +81,8 @@ static EnumPropertyItem compute_device_type_items[] = {
#include "CCL_api.h"
#include "BKE_addon.h"
static void rna_userdef_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *UNUSED(ptr))
{
WM_main_add_notifier(NC_WINDOW, NULL);
@ -428,6 +432,103 @@ static EnumPropertyItem *rna_lang_enum_properties_itemf(bContext *UNUSED(C), Poi
}
#endif
static IDProperty *rna_AddonPref_idprops(PointerRNA *ptr, int create)
{
if (create && !ptr->data) {
IDPropertyTemplate val = {0};
ptr->data = IDP_New(IDP_GROUP, &val, "RNA_AddonPreferences group");
}
return ptr->data;
}
static PointerRNA rna_Addon_preferences_get(PointerRNA *ptr)
{
bAddon *addon = (bAddon *)ptr->data;
bAddonPrefType *apt = BKE_addon_pref_type_find(addon->module, TRUE);
if (apt) {
if (addon->prop == NULL) {
IDPropertyTemplate val = {0};
addon->prop = IDP_New(IDP_GROUP, &val, addon->module); /* name is unimportant */
}
return rna_pointer_inherit_refine(ptr, apt->ext.srna, addon->prop);
}
else {
return PointerRNA_NULL;
}
}
static void rna_AddonPref_unregister(Main *UNUSED(bmain), StructRNA *type)
{
bAddonPrefType *apt = RNA_struct_blender_type_get(type);
if (!apt)
return;
RNA_struct_free_extension(type, &apt->ext);
BKE_addon_pref_type_remove(apt);
RNA_struct_free(&BLENDER_RNA, type);
/* update while blender is running */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
}
static StructRNA *rna_AddonPref_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
{
bAddonPrefType *apt, dummyapt = {{'\0'}};
bAddon dummyaddon = {NULL};
PointerRNA dummyhtr;
// int have_function[1];
/* setup dummy header & header type to store static properties in */
RNA_pointer_create(NULL, &RNA_AddonPreferences, &dummyaddon, &dummyhtr);
/* validate the python class */
if (validate(&dummyhtr, data, NULL /* have_function */ ) != 0)
return NULL;
BLI_strncpy(dummyapt.idname, dummyaddon.module, sizeof(dummyapt.idname));
if (strlen(identifier) >= sizeof(dummyapt.idname)) {
BKE_reportf(reports, RPT_ERROR, "Registering addon-prefs class: '%s' is too long, maximum length is %d",
identifier, (int)sizeof(dummyapt.idname));
return NULL;
}
/* check if we have registered this header type before, and remove it */
apt = BKE_addon_pref_type_find(dummyaddon.module, TRUE);
if (apt) {
if (apt->ext.srna) {
rna_AddonPref_unregister(bmain, apt->ext.srna);
}
}
/* create a new header type */
apt = MEM_mallocN(sizeof(bAddonPrefType), "addonpreftype");
memcpy(apt, &dummyapt, sizeof(dummyapt));
BKE_addon_pref_type_add(apt);
apt->ext.srna = RNA_def_struct(&BLENDER_RNA, identifier, "AddonPreferences");
apt->ext.data = data;
apt->ext.call = call;
apt->ext.free = free;
RNA_struct_blender_type_set(apt->ext.srna, apt);
// apt->draw = (have_function[0]) ? header_draw : NULL;
/* update while blender is running */
WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
return apt->ext.srna;
}
/* placeholder, doesn't do anything useful yet */
static StructRNA *rna_AddonPref_refine(PointerRNA *ptr)
{
return (ptr->type) ? ptr->type : &RNA_AddonPreferences;
}
#else
static void rna_def_userdef_theme_ui_font_style(BlenderRNA *brna)
@ -2381,6 +2482,32 @@ static void rna_def_userdef_addon(BlenderRNA *brna)
prop = RNA_def_property(srna, "module", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Module", "Module name");
RNA_def_struct_name_property(srna, prop);
/* Collection active property */
prop = RNA_def_property(srna, "preferences", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "AddonPreferences");
RNA_def_property_pointer_funcs(prop, "rna_Addon_preferences_get", NULL, NULL, NULL);
}
static void rna_def_userdef_addon_pref(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "AddonPreferences", NULL);
RNA_def_struct_ui_text(srna, "Addon Preferences", "");
RNA_def_struct_sdna(srna, "bAddon"); /* WARNING: only a bAddon during registration */
RNA_def_struct_refine_func(srna, "rna_AddonPref_refine");
RNA_def_struct_register_funcs(srna, "rna_AddonPref_register", "rna_AddonPref_unregister", NULL);
RNA_def_struct_idprops_func(srna, "rna_AddonPref_idprops");
/* registration */
RNA_define_verify_sdna(0);
prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "module");
RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
RNA_define_verify_sdna(1);
}
@ -3736,6 +3863,7 @@ void RNA_def_userdef(BlenderRNA *brna)
rna_def_userdef_filepaths(brna);
rna_def_userdef_system(brna);
rna_def_userdef_addon(brna);
rna_def_userdef_addon_pref(brna);
}

@ -66,6 +66,7 @@
#include "BKE_node.h"
#include "BKE_report.h"
#include "BKE_addon.h"
#include "BKE_packedFile.h"
#include "BKE_sequencer.h" /* free seq clipboard */
#include "BKE_material.h" /* clear_matcopybuf */
@ -135,6 +136,9 @@ void WM_init(bContext *C, int argc, const char **argv)
wm_init_cursor_data();
}
GHOST_CreateSystemPaths();
BKE_addon_pref_type_init();
wm_operatortype_init();
WM_menutype_init();
WM_uilisttype_init();
@ -401,6 +405,8 @@ void WM_exit_ext(bContext *C, const short do_python)
ED_screen_exit(C, win, win->screen);
}
}
BKE_addon_pref_type_free();
wm_operatortype_free();
wm_dropbox_free();
WM_menutype_free();