#include <cmath>
#include <msp/core/maputils.h>
#include <msp/datafile/collection.h>
+#include <msp/fs/utils.h>
#include <msp/interpolate/bezierspline.h>
+#include <msp/strings/format.h>
#include "animation.h"
#include "animationeventobserver.h"
#include "armature.h"
Animation::~Animation()
{
+ for(vector<TimedKeyFrame>::iterator i=keyframes.begin(); i!=keyframes.end(); ++i)
+ if(i->owned)
+ delete i->keyframe;
for(vector<Curve *>::iterator i=curves.begin(); i!=curves.end(); ++i)
delete *i;
}
TimedKeyFrame tkf;
tkf.time = t;
tkf.keyframe = kf;
- if(!owned)
- tkf.keyframe.keep();
tkf.control = c;
+ tkf.owned = owned;
keyframes.push_back(tkf);
{
RefPtr<KeyFrame> kf = new KeyFrame;
if(coll)
- load_sub(*kf, get_collection());
+ {
+ KeyFrame::Loader ldr(*kf, get_collection());
+ ldr.set_inline_base_name(format("%s/%d.kframe", FS::basename(get_source()), obj.keyframes.size()));
+ load_sub_with(ldr);
+ }
else
load_sub(*kf);
struct TimedKeyFrame
{
Time::TimeDelta time;
- RefPtr<const KeyFrame> keyframe;
+ const KeyFrame *keyframe;
bool control;
+ bool owned;
};
struct Event
#include <msp/datafile/collection.h>
+#include <msp/fs/utils.h>
#include "keyframe.h"
#include "pose.h"
void KeyFrame::set_pose(const Pose &p)
{
pose = &p;
- pose.keep();
}
add("scaling", &Loader::scaling);
}
+void KeyFrame::Loader::set_inline_base_name(const string &n)
+{
+ inline_base_name = n;
+}
+
void KeyFrame::Loader::pose(const string &n)
{
obj.pose = &get_collection().get<Pose>(n);
- obj.pose.keep();
}
void KeyFrame::Loader::pose_inline()
{
RefPtr<Pose> p = new Pose;
load_sub(*p, get_collection());
- obj.pose = p;
+ get_collection().add((inline_base_name.empty() ? FS::basename(get_source()) : inline_base_name)+".pose", p.get());
+ obj.pose = p.release();
}
void KeyFrame::Loader::position(float x, float y, float z)
public:
class Loader: public DataFile::CollectionObjectLoader<KeyFrame>
{
+ private:
+ std::string inline_base_name;
+
public:
Loader(KeyFrame &);
Loader(KeyFrame &, Collection &);
private:
void init();
+ public:
+ void set_inline_base_name(const std::string &);
+
+ private:
void pose(const std::string &);
void pose_inline();
void position(float, float, float);
private:
Transform transform;
UniformMap uniforms;
- RefPtr<const Pose> pose;
+ const Pose *pose;
public:
KeyFrame();
const Transform &get_transform() const { return transform; }
Matrix get_matrix() const { return transform.to_matrix(); }
const UniformMap &get_uniforms() const { return uniforms; }
- const Pose *get_pose() const { return pose.get(); }
+ const Pose *get_pose() const { return pose; }
};
} // namespace GL
#include <msp/core/maputils.h>
#include <msp/datafile/collection.h>
+#include <msp/fs/utils.h>
#include "bindable.h"
#include "gl.h"
#include "font.h"
void Font::set_texture(const Texture2D &t)
{
texture = &t;
- texture.keep();
}
const Texture2D &Font::get_texture() const
{
RefPtr<Texture2D> tex = new Texture2D;
load_sub(*tex);
- obj.texture = tex;
+ get_collection().add(FS::basename(get_source())+".tex2d", tex.get());
+ obj.texture = tex.release();
}
void Font::Loader::texture_ref(const string &name)
{
obj.texture = &get_collection().get<Texture2D>(name);
- obj.texture.keep();
}
typedef std::map<CodePair, float> KerningMap;
typedef std::map<CodePair, unsigned> LigatureMap;
- RefPtr<const Texture2D> texture;
+ const Texture2D *texture;
float native_size;
float ascent;
float descent;
Sequence::Step &step = sequence.add_step(i->tag, *renderable);
step.set_blend(i->blend.get());
step.set_depth_test(i->depth_test.get());
- step.set_lighting(i->lighting.get());
+ step.set_lighting(i->lighting);
}
const SequenceTemplate::PostProcessorArray &postprocs = tmpl.get_postprocessors();
stp.tag = tag;
stp.slot_name = rend;
if(coll)
- load_sub(stp, *coll);
+ {
+ Step::Loader ldr(stp, *coll);
+ ldr.set_inline_base_name(format("%s/%d.step", get_source(), obj.steps.size()));
+ load_sub_with(ldr);
+ }
else
load_sub(stp);
add("scene", &Loader::scene);
}
+void SequenceTemplate::Step::Loader::set_inline_base_name(const string &n)
+{
+ inline_base_name = n;
+}
+
void SequenceTemplate::Step::Loader::blend_predefined(const string &name)
{
const Blend *bln = 0;
{
RefPtr<Lighting> lightn = new Lighting;
load_sub(*lightn);
- obj.lighting = lightn;
+ get_collection().add(inline_base_name+".lightn", lightn.get());
+ obj.lighting = lightn.release();
}
void SequenceTemplate::Step::Loader::lighting(const string &name)
{
obj.lighting = &get_collection().get<Lighting>(name);
- obj.lighting.keep();
}
void SequenceTemplate::Step::Loader::object(const string &name)
{
class Loader: public DataFile::CollectionObjectLoader<Step>
{
+ private:
+ std::string inline_base_name;
+
public:
Loader(Step &);
Loader(Step &, Collection &);
private:
void init();
+ public:
+ void set_inline_base_name(const std::string &);
+
+ private:
void blend(BlendFactor, BlendFactor);
void blend_predefined(const std::string &);
void depth_test(Predicate);
};
std::string tag;
- RefPtr<Lighting> lighting;
+ const Lighting *lighting;
RefPtr<const DepthTest> depth_test;
RefPtr<const Blend> blend;
std::string slot_name;
#include <stdexcept>
#include <cmath>
#include <msp/core/algorithm.h>
+#include <msp/fs/utils.h>
#include "error.h"
#include "light.h"
#include "lighting.h"
set_fog_density(0.0f);
}
-Lighting::~Lighting()
-{
- for(vector<Light *>::iterator i=owned_data.begin(); i!=owned_data.end(); ++i)
- delete *i;
-}
-
void Lighting::set_ambient(const Color &a)
{
ambient = a;
{
RefPtr<Light> lgt = new Light;
load_sub(*lgt);
- obj.attach(*lgt);
- obj.owned_data.push_back(lgt.release());
+ get_collection().add(format("%s/%d.light", FS::basename(get_source()), obj.lights.size()), lgt.get());
+ obj.attach(*lgt.release());
}
void Lighting::Loader::light_inline_index(unsigned)
Color fog_color;
float fog_density;
std::vector<AttachedLight> lights;
- std::vector<Light *> owned_data;
mutable ProgramData shdata;
public:
Lighting();
- ~Lighting();
/** Sets the ambient lighting color. Affects all surfaces in the scene. */
void set_ambient(const Color &);
extra_spec["use_image_based_lighting"] = true;
shprog = material->create_compatible_shader(extra_spec);
- shprog.keep();
if(shdata)
- shdata = new ProgramData(*shdata, shprog.get());
+ shdata = new ProgramData(*shdata, shprog);
shprog_from_material = true;
}
void RenderPass::set_shader_program(const Program *prog, const ProgramData *data)
{
shprog = prog;
- shprog.keep();
shprog_from_material = false;
shdata = (data ? new ProgramData(*data) : 0);
}
void RenderPass::set_material(const Material *mat)
{
material = mat;
- material.keep();
maybe_create_material_shader();
set_material_textures();
}
{
for(vector<TextureSlot>::const_iterator i=textures.begin(); i!=textures.end(); ++i)
renderer.set_texture(i->tag, i->texture, i->sampler);
- renderer.set_material(material.get());
- renderer.set_shader_program(shprog.get(), shdata.get());
+ renderer.set_material(material);
+ renderer.set_shader_program(shprog, shdata.get());
renderer.set_reverse_winding(back_faces);
}
add("texunit", &Loader::texunit_named);
}
+void RenderPass::Loader::set_inline_base_name(const string &n)
+{
+ inline_base_name = n;
+}
+
void RenderPass::Loader::finish()
{
if(obj.material)
{
Material::GenericLoader ldr(coll);
load_sub_with(ldr);
- obj.material = ldr.get_material();
+ RefPtr<Material> mat = ldr.get_material();
+ get_collection().add(inline_base_name+".mat", mat.get());
+ obj.material = mat.release();
obj.set_material_textures();
}
void RenderPass::Loader::material(const string &name)
{
obj.material = &get_collection().get<Material>(name);
- obj.material.keep();
obj.set_material_textures();
}
void RenderPass::Loader::shader(const string &n)
{
obj.shprog = &get_collection().get<Program>(get_shader_name(n));
- obj.shprog.keep();
obj.shprog_from_material = false;
if(obj.shdata)
- obj.shdata = new ProgramData(*obj.shdata, obj.shprog.get());
+ obj.shdata = new ProgramData(*obj.shdata, obj.shprog);
}
void RenderPass::Loader::texture(const string &n)
if(!obj.shprog || obj.shprog_from_material)
throw runtime_error("Shader is required for uniforms");
if(!obj.shdata)
- obj.shdata = new ProgramData(obj.shprog.get());
+ obj.shdata = new ProgramData(obj.shprog);
else if(obj.shdata.refcount()>1)
obj.shdata = new ProgramData(*obj.shdata);
load_sub(*obj.shdata);
class Loader: public DataFile::CollectionObjectLoader<RenderPass>
{
private:
+ std::string inline_base_name;
+
static ActionMap shared_actions;
public:
Loader(RenderPass &);
Loader(RenderPass &, Collection &);
-
private:
virtual void init_actions();
+
+ public:
+ void set_inline_base_name(const std::string &);
+
+ private:
virtual void finish();
static std::string get_shader_name(const std::string &);
TextureSlot(Tag t): tag(t), texture(0), sampler(0) { }
};
- RefPtr<const Program> shprog;
+ const Program *shprog;
bool shprog_from_material;
RefPtr<ProgramData> shdata;
std::map<Tag, Tag> uniform_slots;
- RefPtr<const Material> material;
+ const Material *material;
std::string material_slot;
std::vector<TextureSlot> textures;
bool back_faces;
public:
void set_shader_program(const Program *, const ProgramData *);
- const Program *get_shader_program() const { return shprog.get(); }
+ const Program *get_shader_program() const { return shprog; }
const ProgramData *get_shader_data() const { return shdata.get(); }
Tag get_slotted_uniform_tag(Tag) const;
void set_material(const Material *);
- const Material *get_material() const { return material.get(); }
+ const Material *get_material() const { return material; }
const std::string &get_material_slot_name() const { return material_slot; }
void set_texture(Tag, const Texture *, const Sampler * = 0);
Tag get_texture_tag(const std::string &) const;
#include <msp/core/refptr.h>
#include <msp/datafile/collection.h>
+#include <msp/fs/utils.h>
#include <msp/strings/format.h>
#include "material.h"
#include "program.h"
add("pass", &Loader::pass);
}
+void Technique::Loader::set_inline_base_name(const string &n)
+{
+ inline_base_name = n;
+}
+
void Technique::Loader::inherit(const string &n)
{
obj.passes = get_collection().get<Technique>(n).get_passes();
{
RenderPass p;
if(coll)
- load_sub(p, get_collection());
+ {
+ RenderPass::Loader ldr(p, get_collection());
+ ldr.set_inline_base_name(format("%s/%s.pass", (inline_base_name.empty() ? FS::basename(get_source()) : inline_base_name), n));
+ load_sub_with(ldr);
+ }
else
load_sub(p);
class Loader: public Msp::DataFile::CollectionObjectLoader<Technique>
{
private:
+ std::string inline_base_name;
+
static ActionMap shared_actions;
public:
Loader(Technique &);
Loader(Technique &, Collection &);
-
private:
virtual void init_actions();
+ public:
+ void set_inline_base_name(const std::string &);
+
+ private:
void inherit(const std::string &);
void pass(const std::string &);
};
#include <msp/datafile/collection.h>
+#include <msp/fs/utils.h>
#include <msp/strings/format.h>
#include "error.h"
#include "material.h"
void Object::set_mesh(unsigned i, const Mesh *m)
{
- RefPtr<const Mesh> &ptr = get_lod(i, "Object::set_mesh").mesh;
+ const Mesh *&ptr = get_lod(i, "Object::set_mesh").mesh;
if(i==0 && ptr && lod0_watched)
if(ResourceManager *rm = ptr->get_manager())
rm->unobserve_resource(*ptr, *this);
ptr = m;
- ptr.keep();
lod0_watched = false;
if(i==0 && m)
if(i>=lods.size())
return 0;
- return lods[i].mesh.get();
+ return lods[i].mesh;
}
void Object::set_technique(unsigned i, const Technique *t)
{
- RefPtr<const Technique> &ptr = get_lod(i, "Object::set_technique").technique;
- ptr = t;
- ptr.keep();
+ get_lod(i, "Object::set_technique").technique = t;
}
const Technique *Object::get_technique(unsigned i) const
if(i>=lods.size())
return 0;
- return lods[i].technique.get();
+ return lods[i].technique;
}
void Object::render(Renderer &renderer, Tag tag) const
if(!pass)
return;
- const Mesh *mesh = lods.front().mesh.get();
+ const Mesh *mesh = lods.front().mesh;
if (!mesh)
throw logic_error("no mesh");
if(!pass)
return;
- const Mesh *mesh = lods[lod].mesh.get();
+ const Mesh *mesh = lods[lod].mesh;
if (!mesh)
throw logic_error("no mesh");
const RenderPass *Object::get_pass(Tag tag, unsigned lod) const
{
- const Technique *tech = lods[lod].technique.get();
+ const Technique *tech = lods[lod].technique;
if(!tech)
throw logic_error("no technique");
return tech->find_pass(tag);
void Object::resource_loaded(Resource &res)
{
- if(&res==lods.front().mesh.get() && bounding_sphere.is_empty())
+ if(&res==lods.front().mesh && bounding_sphere.is_empty())
update_bounding_sphere();
}
void Object::resource_removed(Resource &res)
{
- if(&res==lods.front().mesh.get())
+ if(&res==lods.front().mesh)
lod0_watched = false;
}
{
RefPtr<Mesh> msh = new Mesh;
load_sub(*msh);
- lod.mesh = msh;
+ get_collection().add(format("%s/lod%d.mesh", FS::basename(get_source()), index), msh.get());
+ lod.mesh = msh.release();
}
void Object::LodLoader::technique(const string &n)
void Object::LodLoader::technique_inline()
{
RefPtr<Technique> tech = new Technique;
- if(coll)
- load_sub(*tech, get_collection());
- else
- load_sub(*tech);
- lod.technique = tech;
+ Technique::Loader ldr(*tech, get_collection());
+ string name = format("%s/lod%d.tech", FS::basename(get_source()), index);
+ ldr.set_inline_base_name(name);
+ load_sub(*tech, get_collection());
+ get_collection().add(name, tech.get());
+ lod.technique = tech.release();
}
} // namespace GL
private:
struct LevelOfDetail
{
- RefPtr<const Mesh> mesh;
- RefPtr<const Technique> technique;
+ const Mesh *mesh;
+ const Technique *technique;
};
std::vector<LevelOfDetail> lods;
#include <msp/datafile/collection.h>
+#include <msp/fs/utils.h>
#include "camera.h"
#include "objectinstance.h"
#include "occludedscene.h"
namespace Msp {
namespace GL {
-Scene::~Scene()
-{
- for(vector<Renderable *>::iterator i=owned_data.begin(); i!=owned_data.end(); ++i)
- delete *i;
-}
-
bool Scene::setup_frustum(const Renderer &renderer) const
{
const Camera *camera = renderer.get_camera();
{
RefPtr<ObjectInstance> inst = new ObjectInstance(get_collection().get<GL::Object>(n));
load_sub(*inst);
- obj.add(*inst);
+ get_collection().add(format("%s/%d.inst", FS::basename(get_source()), inst_counter++), inst.get());
if(content && !t.empty())
(*content)[t] = inst.get();
- obj.owned_data.push_back(inst.release());
+ obj.add(*inst.release());
}
void Scene::Loader::scene(const string &n)
private:
ContentMap *content;
+ unsigned inst_counter;
public:
Loader(Scene &, Collection &);
typedef TypeRegistry<GenericLoader::CreateScene, GenericLoader &> SceneRegistry;
protected:
- // XXX If a loaded renderable is removed from the scene it needs to be removed from here as well
- std::vector<Renderable *> owned_data;
mutable Matrix culling_matrix;
mutable Vector4 frustum_edges[6];
Scene(const Scene &);
Scene &operator=(const Scene &);
public:
- virtual ~Scene();
+ virtual ~Scene() { }
virtual void add(Renderable &) = 0;
virtual void remove(Renderable &) = 0;
Sequence::~Sequence()
{
+ for(vector<PostProcStep>::iterator i=postproc.begin(); i!=postproc.end(); ++i)
+ if(i->owned)
+ delete i->postproc;
delete target[0];
delete target[1];
delete target_ms;
void Sequence::add_postprocessor(PostProcessor &pp)
{
- add_postprocessor(&pp, true);
+ add_postprocessor(&pp, false);
}
void Sequence::add_postprocessor_owned(PostProcessor *pp)
{
- add_postprocessor(pp, false);
+ add_postprocessor(pp, true);
}
-void Sequence::add_postprocessor(PostProcessor *pp, bool keep)
+void Sequence::add_postprocessor(PostProcessor *pp, bool owned)
{
- postproc.push_back(pp);
- if(keep)
- postproc.back().keep();
+ postproc.push_back(PostProcStep(pp, owned));
try
{
create_targets(0);
}
catch(...)
{
+ if(!owned)
+ delete pp;
postproc.pop_back();
throw;
}
out_fbo->bind();
const Texture2D &color = target[j]->get_target_texture(RENDER_COLOR);
const Texture2D &depth = target[j]->get_target_texture(RENDER_DEPTH);
- postproc[i]->render(renderer, color, depth);
+ postproc[i].postproc->render(renderer, color, depth);
}
}
}
DEPRECATED typedef Step Pass;
private:
+ struct PostProcStep
+ {
+ PostProcessor *postproc;
+ bool owned;
+
+ PostProcStep(PostProcessor *pp, bool o): postproc(pp), owned(o) { }
+ };
+
std::vector<Step> steps;
const Camera *camera;
- std::vector<RefPtr<PostProcessor> > postproc;
+ std::vector<PostProcStep> postproc;
unsigned width;
unsigned height;
bool hdr;