1 #include <msp/core/refptr.h>
2 #include <msp/datafile/collection.h>
3 #include <msp/fs/utils.h>
4 #include <msp/strings/format.h>
6 #include "programdata.h"
15 RenderPass &Technique::add_pass(Tag tag)
17 return insert_unique(passes, tag, RenderPass())->second;
20 bool Technique::has_pass(Tag tag) const
22 return passes.count(tag);
25 const RenderPass &Technique::get_pass(Tag tag) const
27 return get_item(passes, tag);
30 const RenderPass *Technique::find_pass(Tag tag) const
32 auto i = passes.find(tag);
33 return (i!=passes.end() ? &i->second : 0);
36 bool Technique::replace_texture(const string &slot, const Texture &tex)
38 bool replaced = false;
39 for(auto &kvp: passes)
41 Tag tag = kvp.second.get_texture_tag(slot);
44 kvp.second.set_texture(tag, &tex);
52 bool Technique::replace_material(const string &slot, const Material &mat)
54 bool replaced = false;
55 for(auto &kvp: passes)
57 const string &pass_slot = kvp.second.get_material_slot_name();
58 if(!pass_slot.empty() && pass_slot==slot)
60 kvp.second.set_material(&mat);
68 bool Technique::replace_uniforms(const ProgramData &shdata)
70 bool replaced = false;
71 const vector<Tag> &uniform_tags = shdata.get_uniform_tags();
72 for(auto &kvp: passes)
74 RefPtr<ProgramData> new_shdata;
75 for(Tag t: uniform_tags)
77 Tag tag = kvp.second.get_slotted_uniform_tag(t);
82 new_shdata = new ProgramData(*kvp.second.get_shader_data());
84 new_shdata->copy_uniform(shdata, tag);
89 kvp.second.set_shader_program(kvp.second.get_shader_program(), new_shdata.get());
95 bool Technique::has_shaders() const
97 for(const auto &kvp: passes)
98 if(kvp.second.get_shader_program())
103 void Technique::set_debug_name(const string &name)
106 for(auto &kvp: passes)
107 kvp.second.set_debug_name(format("%s [pass:%s]", name, kvp.first.str()));
114 DataFile::Loader::ActionMap Technique::Loader::shared_actions;
116 Technique::Loader::Loader(Technique &t):
117 DataFile::CollectionObjectLoader<Technique>(t, 0)
119 set_actions(shared_actions);
122 Technique::Loader::Loader(Technique &t, Collection &c):
123 DataFile::CollectionObjectLoader<Technique>(t, &c)
125 set_actions(shared_actions);
128 void Technique::Loader::init_actions()
130 add("inherit", &Loader::inherit);
131 add("pass", &Loader::pass);
134 void Technique::Loader::set_inline_base_name(const string &n)
136 inline_base_name = n;
139 void Technique::Loader::inherit(const string &n)
141 obj.passes = get_collection().get<Technique>(n).get_passes();
142 InheritLoader ldr(obj, get_collection());
146 void Technique::Loader::pass(const string &n)
151 RenderPass::Loader ldr(p, get_collection());
152 ldr.set_inline_base_name(format("%s/%s.pass", (inline_base_name.empty() ? FS::basename(get_source()) : inline_base_name), n));
158 if(!p.get_shader_program())
159 throw logic_error("no shader program in pass");
161 insert_unique(obj.passes, n, p);
165 Technique::InheritLoader::InheritLoader(Technique &t, Collection &c):
166 DataFile::CollectionObjectLoader<Technique>(t, &c)
168 add("material", &InheritLoader::material);
169 add("texture", &InheritLoader::texture);
170 add("uniforms", &InheritLoader::uniforms);
173 void Technique::InheritLoader::material(const string &slot, const string &name)
175 const Material &mat = get_collection().get<Material>(name);
176 if(obj.replace_material(slot, mat))
179 // For backwards compatibility
180 RenderPass &pass = get_item(obj.passes, slot);
181 if(const Material *base_mat = pass.get_material())
183 for(auto &kvp: obj.passes)
184 if(kvp.second.get_material()==base_mat)
185 kvp.second.set_material(&mat);
188 pass.set_material(&mat);
191 void Technique::InheritLoader::texture(const string &slot, const string &name)
193 if(!obj.replace_texture(slot, get_collection().get<Texture>(name)))
194 throw key_error(slot);
197 void Technique::InheritLoader::uniforms()
201 obj.replace_uniforms(shdata);