source: tags/ms_r16q4/SL/ITEM_SHADER/item_shader.cxx

Last change on this file was 15429, checked in by westram, 7 years ago
  • fix unit-tests for stabs-format
File size: 25.1 KB
Line 
1// ============================================================ //
2//                                                              //
3//   File      : item_shader.cxx                                //
4//   Purpose   :                                                //
5//                                                              //
6//   Coded by Ralf Westram (coder@reallysoft.de) in June 2016   //
7//   http://www.arb-home.de/                                    //
8//                                                              //
9// ============================================================ //
10
11#include "item_shader.h"
12#include <arbdb.h>
13
14#define is_assert(cond) arb_assert(cond)
15
16// --------------------------------------------------------------------------------
17// test my interface
18
19#ifdef UNIT_TESTS
20#ifndef TEST_UNIT_H
21#include <test_unit.h>
22#endif
23
24struct DummyPlugin: public ShaderPlugin {
25    DummyPlugin() : ShaderPlugin("dummy", "test crash dummy") {}
26    ShadedValue shade(GBDATA */*gb_item*/) const OVERRIDE { return NULL; }
27    static void reshade() {}
28    int get_dimension() const OVERRIDE { return 0; }
29    void init_specific_awars(AW_root *) OVERRIDE {}
30    bool customizable() const OVERRIDE { return false; }
31    void customize(AW_root */*awr*/) OVERRIDE { is_assert(0); }
32    char *store_config() const OVERRIDE { return NULL; }
33    void load_or_reset_config(const char *) OVERRIDE {}
34    void activate(bool /*on*/) OVERRIDE {}
35};
36
37void TEST_shader_interface();
38TEST_PUBLISH(TEST_shader_interface);
39void TEST_shader_interface() {
40    GB_shell  shell;
41    GBDATA   *gb_main = GB_open("nosuch.arb", "c");
42
43    {
44        const char    *SHADY   = "lady";
45        AW_root       *NOROOT  = NULL;
46        AW_gc_manager *NOGCMAN = NULL;
47
48        BoundItemSel      sel(gb_main, SPECIES_get_selector());
49        ItemShader   *shader = registerItemShader(NOROOT, NOGCMAN, sel, SHADY, "undescribed", "", DummyPlugin::reshade, 0);
50        TEST_REJECT_NULL(shader);
51
52        const ItemShader *unknown = findItemShader("unknown");
53        TEST_EXPECT_NULL(unknown);
54
55        const ItemShader *found = findItemShader(SHADY);
56        TEST_EXPECT_EQUAL(found, shader);
57
58        // check shader plugins
59        shader->register_plugin(new DummyPlugin);
60        TEST_EXPECT(shader->activate_plugin  ("dummy"));        TEST_EXPECT_EQUAL(shader->active_plugin_name(), "dummy");
61        TEST_REJECT(shader->activate_plugin  ("unregistered")); TEST_EXPECT_EQUAL(shader->active_plugin_name(), "dummy");
62        TEST_EXPECT(shader->activate_plugin  ("field"));        TEST_EXPECT_EQUAL(shader->active_plugin_name(), "field");
63        TEST_EXPECT(shader->deactivate_plugin());               TEST_EXPECT_EQUAL(shader->active_plugin_name(), NO_PLUGIN_SELECTED);
64        TEST_REJECT(shader->deactivate_plugin());
65
66        // clean-up
67        destroyAllItemShaders();
68    }
69    GB_close(gb_main);
70}
71
72#endif // UNIT_TESTS
73
74// --------------------------------------------------------------------------------
75// implementation
76
77#include "field_shader.h"
78
79#include <awt_config_manager.hxx>
80
81#include <aw_root.hxx>
82#include <aw_window.hxx>
83#include <aw_awar.hxx>
84#include <aw_preset.hxx>
85#include <aw_select.hxx>
86#include <aw_msg.hxx>
87
88#include <arb_strarray.h>
89
90#include <vector>
91#include <string>
92#include <algorithm>
93
94
95using namespace std;
96
97typedef vector<ShaderPluginPtr> Plugins;
98
99#define AWAR_SELECTED_PLUGIN shader_awar("plugin")
100#define AWAR_SHOW_DIMENSION  tmp_shader_awar("dimension")
101
102#define AWAR_GUI_RANGE           tmp_shader_awar("range")
103#define AWAR_GUI_OVERLAY_GROUPS  tmp_shader_awar("groups")
104#define AWAR_GUI_OVERLAY_MARKED  tmp_shader_awar("marked")
105#define AWAR_GUI_PHASE_FREQ      tmp_shader_awar("phase")
106#define AWAR_GUI_PHASE_ALTER     tmp_shader_awar("alternate")
107#define AWAR_GUI_PHASE_PRESHIFT  tmp_shader_awar("preshift")
108#define AWAR_GUI_PHASE_POSTSHIFT tmp_shader_awar("postshift")
109
110#define AWAR_PLUGIN_RANGE           plugin_awar("range")
111#define AWAR_PLUGIN_OVERLAY_GROUPS  plugin_awar("groups")
112#define AWAR_PLUGIN_OVERLAY_MARKED  plugin_awar("marked")
113#define AWAR_PLUGIN_PHASE_FREQ      plugin_awar("phase")
114#define AWAR_PLUGIN_PHASE_ALTER     plugin_awar("alternate")
115#define AWAR_PLUGIN_PHASE_PRESHIFT  plugin_awar("preshift")
116#define AWAR_PLUGIN_PHASE_POSTSHIFT plugin_awar("postshift")
117
118// ----------------------
119//      ShaderPlugin
120
121void ShaderPlugin::init_awars(AW_root *awr, const char *awar_prefix_) {
122    is_assert(awar_prefix.empty()); // called twice?
123    awar_prefix = string(awar_prefix_) + '/' + get_id();
124
125    if (awr) {
126        // common awars for all shader plugins:
127        awr->awar_string(AWAR_PLUGIN_RANGE,           "");  // => will use first available color-range (for dimension reported by actual plugin)
128        awr->awar_int   (AWAR_PLUGIN_OVERLAY_GROUPS,  0);
129        awr->awar_int   (AWAR_PLUGIN_OVERLAY_MARKED,  0);
130        awr->awar_float (AWAR_PLUGIN_PHASE_FREQ,      1.0);
131        awr->awar_int   (AWAR_PLUGIN_PHASE_ALTER,     0);
132        awr->awar_float (AWAR_PLUGIN_PHASE_PRESHIFT,  0.0);
133        awr->awar_float (AWAR_PLUGIN_PHASE_POSTSHIFT, 0.0);
134
135        init_specific_awars(awr);
136    }
137}
138
139bool ShaderPlugin::overlay_marked() const {
140    return AW_root::SINGLETON->awar(AWAR_PLUGIN_OVERLAY_MARKED)->read_int();
141}
142bool ShaderPlugin::overlay_color_groups() const {
143    return AW_root::SINGLETON->awar(AWAR_PLUGIN_OVERLAY_GROUPS)->read_int();
144}
145
146// -------------------------
147//      ItemShader_impl
148
149#define SKIP_TMP_PREFIX 4
150
151class ItemShader_impl : public ItemShader {
152    Plugins plugins;
153    string  help_id;
154    string  awar_prefix;
155
156    RefPtr<AW_gc_manager>         gcman;
157    RefPtr<AW_window>             aw_cfg;            // config window
158    RefPtr<AW_option_menu_struct> range_option_menu; // color-range selector in config window
159
160    ShaderPluginPtr find_plugin(const string& plugin_id) const;
161
162    void setup_new_dimension();
163    void init_config_definition(AWT_config_definition& cdef, bool add_selected_plugin) const;
164
165public:
166    ItemShader_impl(AW_gc_manager *gcman_, const string& id_, const string& description_, const string& help_id_, ReshadeCallback rcb, int undef_gc) :
167        ItemShader(id_, description_, rcb, undef_gc),
168        help_id(help_id_),
169        awar_prefix(GBS_global_string("tmp/shader/%s", get_id().c_str())),
170        gcman(gcman_),
171        aw_cfg(NULL),
172        range_option_menu(NULL)
173    {}
174
175    void register_plugin(ShaderPluginPtr plugin) OVERRIDE;
176    bool activate_plugin(const string& plugin_id) OVERRIDE;
177    bool activate_plugin_impl(const string& plugin_id);
178    std::string active_plugin_name() const OVERRIDE {
179        if (active_plugin.isSet()) return active_plugin->get_id();
180        return NO_PLUGIN_SELECTED;
181    }
182
183    const char *shader_awar(const char *name) const {
184        return GBS_global_string("%s/%s", awar_prefix.c_str()+SKIP_TMP_PREFIX, name);
185    }
186    const char *tmp_shader_awar(const char *name) const {
187        return GBS_global_string("%s/%s", awar_prefix.c_str(), name);
188    }
189
190    void init_awars(AW_root *awr);
191    void init() OVERRIDE;
192
193    void check_dimension_change() OVERRIDE;
194
195    void popup_config_window(AW_root *awr) OVERRIDE;
196
197    static void trigger_reshade_cb(AW_root*,ItemShader_impl *shader) { shader->trigger_reshade_callback(SIMPLE_RESHADE); }
198
199    void configure_active_plugin(AW_root *awr) {
200        if (active_plugin.isSet()) {
201            if (active_plugin->customizable()) active_plugin->customize(awr);
202            else aw_message(GBS_global_string("Nothing to configure for '%s'", active_plugin->get_description().c_str()));
203        }
204        else aw_message("Please select a shader");
205    }
206    static void configure_active_plugin_cb(AW_window *aww, ItemShader_impl *shader) { shader->configure_active_plugin(aww->get_root()); }
207
208    void selected_plugin_changed_cb(AW_root *awr) {
209        AW_awar *awar_plugin = awr->awar(AWAR_SELECTED_PLUGIN);
210        if (!activate_plugin_impl(awar_plugin->read_char_pntr())) {
211            awar_plugin->write_string(NO_PLUGIN_SELECTED);
212        }
213    }
214    static void selected_plugin_changed_cb(AW_root *awr, ItemShader_impl *shader) { shader->selected_plugin_changed_cb(awr); }
215
216    void selected_range_changed_cb(AW_root *awr) {
217        AW_activateColorRange(gcman, awr->awar(AWAR_GUI_RANGE)->read_char_pntr());
218        trigger_reshade_callback(SIMPLE_RESHADE);
219    }
220    static void selected_range_changed_cb(AW_root *awr, ItemShader_impl *shader) { shader->selected_range_changed_cb(awr); }
221
222    void configure_colors_cb(AW_window *aww) { AW_popup_gc_color_range_window(aww, gcman); }
223    static void configure_colors_cb(AW_window *aww, ItemShader_impl *shader) { shader->configure_colors_cb(aww); }
224
225    void phase_changed_cb(AW_root *awr) {
226        phaser = Phaser(awr->awar(AWAR_GUI_PHASE_FREQ)->read_float(),
227                        awr->awar(AWAR_GUI_PHASE_ALTER)->read_int(),
228                        awr->awar(AWAR_GUI_PHASE_PRESHIFT)->read_float(),
229                        awr->awar(AWAR_GUI_PHASE_POSTSHIFT)->read_float());
230        trigger_reshade_callback(SIMPLE_RESHADE);
231    }
232    static void phase_changed_cb(AW_root *awr, ItemShader_impl *shader) { shader->phase_changed_cb(awr); }
233
234    void reset_phasing_cb(AW_root *awr) const {
235        DelayReshade here(this);
236        awr->awar(AWAR_GUI_PHASE_FREQ)->reset_to_default();
237        awr->awar(AWAR_GUI_PHASE_ALTER)->reset_to_default();
238        awr->awar(AWAR_GUI_PHASE_PRESHIFT)->reset_to_default();
239        awr->awar(AWAR_GUI_PHASE_POSTSHIFT)->reset_to_default();
240    }
241    static void reset_phasing_cb(AW_window *aww, const ItemShader_impl *shader) { shader->reset_phasing_cb(aww->get_root()); }
242
243    char *store_config_cb() const;
244    void  load_or_reset_config_cb(const char *cfgstr);
245
246    static char *store_config_cb(ItemShader_impl *shader) { return shader->store_config_cb(); }
247    static void load_or_reset_config_cb(const char *cfgstr, ItemShader_impl *shader) { return shader->load_or_reset_config_cb(cfgstr); }
248};
249
250struct has_id {
251    string id;
252    explicit has_id(const char *id_) : id(id_) {}
253    explicit has_id(const string& id_) : id(id_) {}
254
255    bool operator()(const ItemShader_impl& shader) { return shader.get_id() == id; }
256    bool operator()(const ShaderPluginPtr& plugin) { return plugin->get_id() == id; }
257};
258
259
260// --------------------------------
261//      shader plugin registry
262
263ShaderPluginPtr ItemShader_impl::find_plugin(const string& plugin_id) const {
264    Plugins::const_iterator found = find_if(plugins.begin(), plugins.end(), has_id(plugin_id));
265    return found == plugins.end() ? ShaderPluginPtr() : *found;
266}
267
268void ItemShader_impl::register_plugin(ShaderPluginPtr plugin) {
269    is_assert(find_plugin(plugin->get_id()).isNull()); // attempt to register two plugins with same name!
270    plugins.push_back(plugin);
271
272    plugin->announce_shader(this);
273    plugin->init_awars(AW_root::SINGLETON, awar_prefix.c_str()+SKIP_TMP_PREFIX);
274}
275
276bool ItemShader_impl::activate_plugin_impl(const string& plugin_id) {
277    bool            changed    = false;
278    ShaderPluginPtr prevActive = active_plugin;
279    if (plugin_id == NO_PLUGIN_SELECTED) {
280        if (active_plugin.isSet()) {
281            active_plugin.SetNull();
282            changed = true;
283        }
284    }
285    else {
286        ShaderPluginPtr found = find_plugin(plugin_id);
287        if (found.isSet()) {
288            active_plugin = found;
289            changed       = true;
290        }
291    }
292    if (changed) {
293        if (prevActive.isSet()) prevActive->activate(false);
294        if (active_plugin.isSet()) active_plugin->activate(true);
295
296        DelayReshade here(this);
297
298        AW_root *awr = AW_root::SINGLETON;
299        if (awr) {
300            if (active_plugin.isSet()) {
301                // map common GUI awars to awars of active plugin:
302                awr->awar(AWAR_GUI_RANGE)          ->map(active_plugin->AWAR_PLUGIN_RANGE);
303                awr->awar(AWAR_GUI_OVERLAY_MARKED) ->map(active_plugin->AWAR_PLUGIN_OVERLAY_MARKED);
304                awr->awar(AWAR_GUI_OVERLAY_GROUPS) ->map(active_plugin->AWAR_PLUGIN_OVERLAY_GROUPS);
305                awr->awar(AWAR_GUI_PHASE_FREQ)     ->map(active_plugin->AWAR_PLUGIN_PHASE_FREQ);
306                awr->awar(AWAR_GUI_PHASE_ALTER)    ->map(active_plugin->AWAR_PLUGIN_PHASE_ALTER);
307                awr->awar(AWAR_GUI_PHASE_PRESHIFT) ->map(active_plugin->AWAR_PLUGIN_PHASE_PRESHIFT);
308                awr->awar(AWAR_GUI_PHASE_POSTSHIFT)->map(active_plugin->AWAR_PLUGIN_PHASE_POSTSHIFT);
309                check_dimension_change();
310            }
311            else {
312                // unmap GUI awars:
313                awr->awar(AWAR_GUI_RANGE)          ->unmap();
314                awr->awar(AWAR_GUI_OVERLAY_MARKED) ->unmap();
315                awr->awar(AWAR_GUI_OVERLAY_GROUPS) ->unmap();
316                awr->awar(AWAR_GUI_PHASE_FREQ)     ->unmap();
317                awr->awar(AWAR_GUI_PHASE_ALTER)    ->unmap();
318                awr->awar(AWAR_GUI_PHASE_PRESHIFT) ->unmap();
319                awr->awar(AWAR_GUI_PHASE_POSTSHIFT)->unmap();
320                setup_new_dimension();
321            }
322        }
323        trigger_reshade_callback(SIMPLE_RESHADE);
324    }
325    return changed;
326}
327bool ItemShader_impl::activate_plugin(const string& plugin_id) {
328    AW_root *awr = AW_root::SINGLETON;
329    if (!awr) {
330        return activate_plugin_impl(plugin_id);
331    }
332
333    AW_awar *awar_plugin = awr->awar(AWAR_SELECTED_PLUGIN);
334    awar_plugin->write_string(plugin_id.c_str());
335
336    return (strcmp(awar_plugin->read_char_pntr(), plugin_id.c_str()) == 0);
337}
338
339// --------------------------
340//      dimension change
341
342void ItemShader_impl::setup_new_dimension() {
343    AW_root *awr = AW_root::SINGLETON;
344    int      dim = active_plugin.isSet() ? active_plugin->get_dimension() : 0;
345
346    AW_awar *awar_range = awr->awar(AWAR_GUI_RANGE);
347
348    if (dim>0) {
349        // auto-select another color-range (if selected does not match dimension)
350
351        ConstStrArray ids, names;
352        AW_getColorRangeNames(gcman, dim, ids, names);
353        aw_assert(!ids.empty()); // no range defined with dimension 'dim' // @@@ check during ItemShader-setup!
354
355        const char *selected_range_id  = awar_range->read_char_pntr();
356        bool        seen_selected      = false;
357
358        if (aw_cfg) aw_cfg->clear_option_menu(range_option_menu);
359        for (unsigned i = 0; i<ids.size(); ++i) {
360            if (aw_cfg) aw_cfg->insert_option(names[i], "", ids[i]);
361            if (!seen_selected && strcmp(selected_range_id, ids[i]) == 0) { // check if awar-value exists
362                seen_selected = true;
363            }
364        }
365        if (aw_cfg) aw_cfg->update_option_menu();
366
367        if (!seen_selected) selected_range_id = ids[0]; // autoselect first color-range
368
369        awar_range->write_string(selected_range_id);
370        AW_activateColorRange(gcman, selected_range_id);
371    }
372    else {
373        if (aw_cfg) {
374            aw_cfg->clear_option_menu(range_option_menu);
375            aw_cfg->insert_option("<none>", "", "");
376            aw_cfg->update_option_menu();
377        }
378        awar_range->write_string("");
379    }
380
381    awr->awar(AWAR_SHOW_DIMENSION)->write_int(dim);
382}
383void ItemShader_impl::check_dimension_change() {
384    aw_assert(active_plugin.isSet());
385
386    int wanted_dim = active_plugin->get_dimension();
387    if (wanted_dim>0) {
388        int         range_dim;
389        /*const char *range_id = */ AW_getActiveColorRangeID(gcman, &range_dim);
390
391        int awar_dim = AW_root::SINGLETON->awar(AWAR_SHOW_DIMENSION)->read_int();
392
393        if (wanted_dim != range_dim || wanted_dim != awar_dim) { // active color-range has wrong dimension (or config window needs update)
394            setup_new_dimension();
395        }
396    }
397}
398
399// ---------------------------------------
400//      store / restore shader config
401
402void ItemShader_impl::init_config_definition(AWT_config_definition& cdef, bool add_selected_plugin) const {
403    if (add_selected_plugin) cdef.add(AWAR_SELECTED_PLUGIN, "plugin");
404
405    cdef.add(AWAR_GUI_RANGE,           "range");
406    cdef.add(AWAR_GUI_OVERLAY_GROUPS,  "overlay_groups");
407    cdef.add(AWAR_GUI_OVERLAY_MARKED,  "overlay_marked");
408    cdef.add(AWAR_GUI_PHASE_FREQ,      "phase_frequency");
409    cdef.add(AWAR_GUI_PHASE_ALTER,     "phase_alternate");
410    cdef.add(AWAR_GUI_PHASE_PRESHIFT,  "phase_preshift");
411    cdef.add(AWAR_GUI_PHASE_POSTSHIFT, "phase_postshift");
412}
413
414char *ItemShader_impl::store_config_cb() const {
415    char     *cfgstr = NULL;
416    GB_ERROR  error  = NULL;
417
418    AWT_config_definition cdef;
419    init_config_definition(cdef, true);
420    {
421        AWT_config cfg(&cdef);
422        error = cfg.parseError();
423
424        if (!error) {
425            if (active_plugin.isSet()) {
426                char *plugin_setup = active_plugin->store_config();
427                if (plugin_setup) {
428                    cfg.set_entry("plugin_setup", plugin_setup);
429                    free(plugin_setup);
430                }
431            }
432            cfgstr = cfg.config_string();
433        }
434    }
435
436    aw_message_if(error);
437
438    return cfgstr ? cfgstr : strdup("");
439}
440
441void ItemShader_impl::load_or_reset_config_cb(const char *stored) {
442    GB_ERROR error = NULL;
443
444    AWT_config_definition cdef;
445    init_config_definition(cdef, stored);
446
447    if (stored) {
448        AWT_config cfg(stored);
449        error = cfg.parseError();
450
451        if (!error) {
452            char *plugin_setup = nulldup(cfg.get_entry("plugin_setup"));
453            cfg.delete_entry("plugin_setup"); // avoids wrong error message about unsupported entry 'plugin_setup'
454
455            const char      *saved_pluginname = cfg.get_entry("plugin");
456            ShaderPluginPtr  targetPlugin     = saved_pluginname ? find_plugin(saved_pluginname) : active_plugin;
457
458            {
459                DelayReshade here(this);
460                if (plugin_setup) {
461                    if (targetPlugin.isSet()) {
462                        // restore plugin specific settings
463                        targetPlugin->load_or_reset_config(plugin_setup);
464                    }
465                    else {
466                        error = "Failed to restore plugin-specific settings (unknown plugin)";
467                    }
468                }
469
470                // activate saved plugin before restoring its settings
471                // (otherwise settings of the previously selected plugin may get modified)
472                if (targetPlugin.isSet()) activate_plugin(targetPlugin->get_id());
473
474                // now restore all settings (into GUI-awars mapped to active config)
475                cfg.write_to_awars(cdef.get_mapping(), true);
476            }
477            free(plugin_setup);
478        }
479    }
480    else { // reset
481        DelayReshade here(this);
482        if (active_plugin.isSet()) active_plugin->load_or_reset_config(NULL); // reset selected plugin-config first
483        cdef.reset();                                                         // will NOT touch selected plugin (ie. its only a partial restore)
484    }
485    aw_message_if(error);
486}
487
488// ------------------------
489//      user-interface
490
491static void global_colorgroup_use_changed_cb(AW_root *awr, ItemShader_impl *shader) {
492    awr->awar(shader->AWAR_GUI_OVERLAY_GROUPS)->write_int(awr->awar(AW_get_color_groups_active_awarname())->read_int());
493}
494
495void ItemShader_impl::init() {
496    // initialize ItemShader
497    // - activate plugin stored in AWAR
498
499    is_assert(!plugins.empty()); // you have to register all plugins before calling init
500
501    first_range_gc = AW_getFirstRangeGC(gcman);
502    selected_plugin_changed_cb(AW_root::SINGLETON, this);
503}
504
505void ItemShader_impl::init_awars(AW_root *awr) {
506    RootCallback Reshade_cb       = makeRootCallback(ItemShader_impl::trigger_reshade_cb, this);
507    RootCallback PhaseChanged_cb  = makeRootCallback(ItemShader_impl::phase_changed_cb, this);
508    RootCallback PluginChanged_cb = makeRootCallback(ItemShader_impl::selected_plugin_changed_cb, this);
509    RootCallback RangeChanged_cb  = makeRootCallback(ItemShader_impl::selected_range_changed_cb, this);
510
511    awr->awar_string(AWAR_SELECTED_PLUGIN,     NO_PLUGIN_SELECTED)->add_callback(PluginChanged_cb);
512    awr->awar_int   (AWAR_SHOW_DIMENSION,      -1);
513    awr->awar_string(AWAR_GUI_RANGE,           "") ->add_callback(RangeChanged_cb);
514    awr->awar_int   (AWAR_GUI_OVERLAY_GROUPS,  0)  ->add_callback(Reshade_cb);
515    awr->awar_int   (AWAR_GUI_OVERLAY_MARKED,  0)  ->add_callback(Reshade_cb);
516    awr->awar_float (AWAR_GUI_PHASE_FREQ,      1.0)->set_minmax(0.01, 100.0)->add_callback(PhaseChanged_cb);
517    awr->awar_float (AWAR_GUI_PHASE_PRESHIFT,  0.0)->set_minmax(0.0,    1.0)->add_callback(PhaseChanged_cb);
518    awr->awar_float (AWAR_GUI_PHASE_POSTSHIFT, 0.0)->set_minmax(0.0,    1.0)->add_callback(PhaseChanged_cb);
519    awr->awar_int   (AWAR_GUI_PHASE_ALTER,     0)  ->add_callback(PhaseChanged_cb);
520
521    const char *awarname_global_colorgroups = AW_get_color_groups_active_awarname();
522    awr->awar(awarname_global_colorgroups)->add_callback(makeRootCallback(global_colorgroup_use_changed_cb, this));
523}
524
525void ItemShader_impl::popup_config_window(AW_root *awr) {
526    if (!aw_cfg) {
527        AW_window_simple *aws = new AW_window_simple;
528        {
529            string wid = GBS_global_string("shader_cfg_%s", get_id().c_str());
530            aws->init(awr, wid.c_str(), get_description().c_str());
531        }
532        aws->load_xfig("item_shader_cfg.fig");
533
534        aws->button_length(8);
535
536        aws->at("close");
537        aws->callback(AW_POPDOWN);
538        aws->create_button("CLOSE", "CLOSE", "O");
539
540        aws->at("help");
541        aws->callback(makeHelpCallback(help_id.c_str()));
542        aws->create_button("HELP", "HELP");
543
544        aws->at("plugin");
545        AW_selection_list *sel = aws->create_selection_list(AWAR_SELECTED_PLUGIN, true);
546        sel->insert_default("<No shading>", NO_PLUGIN_SELECTED);
547        for (Plugins::iterator p = plugins.begin(); p != plugins.end(); ++p) {
548            const ShaderPlugin& plugged = **p;
549            sel->insert(plugged.get_description().c_str(), plugged.get_id().c_str());
550        }
551        sel->update();
552
553        aws->at("plugin_cfg");
554        aws->callback(makeWindowCallback(ItemShader_impl::configure_active_plugin_cb, this));
555        aws->create_autosize_button("configure", "Configure");
556
557        aws->at("range");
558        range_option_menu = aws->create_option_menu(AWAR_GUI_RANGE, false);
559        aws->insert_option("<none>", "", "");
560        aws->update_option_menu();
561
562        aws->at("color_cfg");
563        aws->callback(makeWindowCallback(ItemShader_impl::configure_colors_cb, this));
564        aws->create_autosize_button("color_cfg", "Color setup");
565
566        aws->at("groups");
567        aws->create_toggle(AWAR_GUI_OVERLAY_GROUPS);
568
569        aws->at("marked");
570        aws->create_toggle(AWAR_GUI_OVERLAY_MARKED);
571
572        aws->auto_space(5,5);
573        const int FIELDSIZE    = 12;
574        const int SCALERLENGTH = 400;
575
576        aws->at("alt");
577        aws->create_toggle(AWAR_GUI_PHASE_ALTER);
578
579        aws->at("dim");
580        aws->create_button(0, AWAR_SHOW_DIMENSION, 0, "+");
581
582        aws->at("reset");
583        aws->callback(makeWindowCallback(ItemShader_impl::reset_phasing_cb, this));
584        aws->create_button("reset", "RESET", "R");
585
586        aws->at("freq");      aws->create_input_field_with_scaler(AWAR_GUI_PHASE_FREQ,      FIELDSIZE, SCALERLENGTH, AW_SCALER_EXP_LOWER);
587        aws->at("preshift");  aws->create_input_field_with_scaler(AWAR_GUI_PHASE_PRESHIFT,  FIELDSIZE, SCALERLENGTH, AW_SCALER_LINEAR);
588        aws->at("postshift"); aws->create_input_field_with_scaler(AWAR_GUI_PHASE_POSTSHIFT, FIELDSIZE, SCALERLENGTH, AW_SCALER_LINEAR);
589
590        aws->at("cfg");
591        AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, get_id().c_str(),
592                                  makeStoreConfigCallback(ItemShader_impl::store_config_cb, this),
593                                  makeRestoreConfigCallback(ItemShader_impl::load_or_reset_config_cb, this));
594
595        aws->window_fit();
596
597        aw_cfg = aws;
598
599        setup_new_dimension();
600    }
601    aw_cfg->activate();
602}
603
604// -------------------------
605//      shader registry
606
607typedef vector<ItemShader_impl> Shaders;
608
609static Shaders registered;
610
611ItemShader *registerItemShader(AW_root *awr, AW_gc_manager *gcman, BoundItemSel& itemtype, const char *unique_id, const char *description, const char *help_id, ReshadeCallback reshade_cb, int undef_gc) {
612    /*! create a new ItemShader
613     *
614     * @param awr             the application root
615     * @param gcman           gc-manager used for shading
616     * @param itemtype        type of item
617     * @param unique_id       unique ID
618     * @param description     short description used ia. as title of config window (eg. "Tree shading")
619     * @param help_id         helpfile
620     * @param reshade_cb      callback which updates the shading + refreshes the display
621     * @param undef_gc        GC reported for undefined ShadedValue
622     *
623     * (Note: the reshade_cb may be called very often! best is to trigger a temp. DB-awar like AWAR_TREE_RECOMPUTE)
624     */
625    if (findItemShader(unique_id)) {
626        is_assert(0); // duplicate shader id
627        return NULL;
628    }
629
630    registered.push_back(ItemShader_impl(gcman, unique_id, description, help_id, reshade_cb, undef_gc));
631    ItemShader_impl& new_shader = registered.back();
632    if (awr) new_shader.init_awars(awr);
633    new_shader.register_plugin(makeItemFieldShader(itemtype));
634    return &new_shader;
635}
636
637const ItemShader *findItemShader(const char *id) {
638    Shaders::iterator found = find_if(registered.begin(), registered.end(), has_id(id));
639    return found == registered.end() ? NULL : &*found;
640}
641
642void destroyAllItemShaders() {
643    registered.clear();
644}
645
Note: See TracBrowser for help on using the repository browser.