1 #include <msp/core/refptr.h>
2 #include <msp/datafile/collection.h>
3 #include <msp/fs/utils.h>
4 #include <msp/strings/format.h>
7 #include "programdata.h"
17 RenderPass &Technique::add_pass(Tag tag)
19 return insert_unique(passes, tag, RenderPass())->second;
22 bool Technique::has_pass(Tag tag) const
24 return passes.count(tag);
27 const RenderPass &Technique::get_pass(Tag tag) const
29 return get_item(passes, tag);
32 const RenderPass *Technique::find_pass(Tag tag) const
34 auto i = passes.find(tag);
35 return (i!=passes.end() ? &i->second : 0);
38 bool Technique::replace_texture(const string &slot, const Texture &tex)
40 bool replaced = false;
41 for(auto &kvp: passes)
43 Tag tag = kvp.second.get_texture_tag(slot);
46 kvp.second.set_texture(tag, &tex);
54 bool Technique::replace_material(const string &slot, const Material &mat)
56 bool replaced = false;
57 for(auto &kvp: passes)
59 const string &pass_slot = kvp.second.get_material_slot_name();
60 if(!pass_slot.empty() && pass_slot==slot)
62 kvp.second.set_material(&mat);
70 bool Technique::replace_uniforms(const ProgramData &shdata)
72 bool replaced = false;
73 const vector<Tag> &uniform_tags = shdata.get_uniform_tags();
74 for(auto &kvp: passes)
76 RefPtr<ProgramData> new_shdata;
77 for(Tag t: uniform_tags)
79 Tag tag = kvp.second.get_slotted_uniform_tag(t);
84 new_shdata = new ProgramData(*kvp.second.get_shader_data());
86 new_shdata->uniform(tag, shdata.get_uniform(t));
91 kvp.second.set_shader_program(kvp.second.get_shader_program(), new_shdata.get());
97 bool Technique::has_shaders() const
99 for(const auto &kvp: passes)
100 if(kvp.second.get_shader_program())
105 void Technique::set_debug_name(const string &name)
108 for(auto &kvp: passes)
109 kvp.second.set_debug_name(format("%s [pass:%s]", name, kvp.first.str()));
116 DataFile::Loader::ActionMap Technique::Loader::shared_actions;
118 Technique::Loader::Loader(Technique &t):
119 DataFile::CollectionObjectLoader<Technique>(t, 0)
121 set_actions(shared_actions);
124 Technique::Loader::Loader(Technique &t, Collection &c):
125 DataFile::CollectionObjectLoader<Technique>(t, &c)
127 set_actions(shared_actions);
130 void Technique::Loader::init_actions()
132 add("inherit", &Loader::inherit);
133 add("pass", &Loader::pass);
136 void Technique::Loader::set_inline_base_name(const string &n)
138 inline_base_name = n;
141 void Technique::Loader::inherit(const string &n)
143 obj.passes = get_collection().get<Technique>(n).get_passes();
144 InheritLoader ldr(obj, get_collection());
148 void Technique::Loader::pass(const string &n)
153 RenderPass::Loader ldr(p, get_collection());
154 ldr.set_inline_base_name(format("%s/%s.pass", (inline_base_name.empty() ? FS::basename(get_source()) : inline_base_name), n));
160 if(!p.get_shader_program())
161 throw logic_error("no shader program in pass");
163 insert_unique(obj.passes, n, p);
167 Technique::InheritLoader::InheritLoader(Technique &t, Collection &c):
168 DataFile::CollectionObjectLoader<Technique>(t, &c)
170 add("material", &InheritLoader::material);
171 add("texture", &InheritLoader::texture);
172 add("uniforms", &InheritLoader::uniforms);
175 void Technique::InheritLoader::material(const string &slot, const string &name)
177 const Material &mat = get_collection().get<Material>(name);
178 if(obj.replace_material(slot, mat))
181 // For backwards compatibility
182 RenderPass &pass = get_item(obj.passes, slot);
183 if(const Material *base_mat = pass.get_material())
185 for(auto &kvp: obj.passes)
186 if(kvp.second.get_material()==base_mat)
187 kvp.second.set_material(&mat);
190 pass.set_material(&mat);
193 void Technique::InheritLoader::texture(const string &slot, const string &name)
195 if(!obj.replace_texture(slot, get_collection().get<Texture>(name)))
196 throw key_error(slot);
199 void Technique::InheritLoader::uniforms()
203 obj.replace_uniforms(shdata);