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