Skip to content

Commit 2d52379

Browse files
committed
Implement async_flatten_done
1 parent b5c35e6 commit 2d52379

File tree

2 files changed

+87
-13
lines changed

2 files changed

+87
-13
lines changed

render_pipeline/rppanda/showbase/loader.hpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,16 @@ class ShowBase;
5858
class RENDER_PIPELINE_DECL Loader : public DirectObject
5959
{
6060
public:
61+
using CallbackType = std::function<void(std::vector<NodePath>&)>;
62+
6163
/**
6264
* Returned by loadModel when used asynchronously. This class is
6365
* modelled after Future, and can be awaited.
6466
*/
6567
class RENDER_PIPELINE_DECL Callback
6668
{
6769
public:
68-
Callback(Loader* loader, int num_objects,
69-
const std::function<void(std::vector<NodePath>&)>& callback);
70+
Callback(Loader* loader, int num_objects, const CallbackType& callback);
7071

7172
void got_object(size_t index, NodePath object);
7273

@@ -87,7 +88,7 @@ class RENDER_PIPELINE_DECL Loader : public DirectObject
8788

8889
Loader* loader_;
8990
std::vector<NodePath> objects_;
90-
std::function<void(std::vector<NodePath>&)> callback_;
91+
CallbackType callback_;
9192
std::unordered_set<AsyncTask*> requests_;
9293
std::vector<AsyncTask*> request_list_;
9394
};
@@ -116,13 +117,11 @@ class RENDER_PIPELINE_DECL Loader : public DirectObject
116117

117118
std::shared_ptr<Callback> load_model_async(const Filename& model_path, const LoaderOptions& loader_options={},
118119
boost::optional<bool> no_cache=boost::none, bool allow_instance=false, boost::optional<bool> ok_missing=boost::none,
119-
const std::function<void(std::vector<NodePath>&)>& callback={},
120-
boost::optional<int> priority=boost::none);
120+
const CallbackType& callback={}, boost::optional<int> priority=boost::none);
121121

122122
std::shared_ptr<Callback> load_model_async(const std::vector<Filename>& model_list, const LoaderOptions& loader_options={},
123123
boost::optional<bool> no_cache=boost::none, bool allow_instance=false, boost::optional<bool> ok_missing=boost::none,
124-
const std::function<void(std::vector<NodePath>&)>& callback={},
125-
boost::optional<int> priority = boost::none);
124+
const CallbackType& callback={}, boost::optional<int> priority = boost::none);
126125

127126
void unload_model(NodePath model);
128127
void unload_model(ModelRoot* model);
@@ -230,6 +229,25 @@ class RENDER_PIPELINE_DECL Loader : public DirectObject
230229

231230
void unload_shader(const Filename& shader_path);
232231

232+
/**
233+
* Performs a model.flattenStrong() operation in a sub-thread
234+
* (if threading is compiled into Panda). The model may be a
235+
* single NodePath, or it may be a list of NodePaths.
236+
*
237+
* Each model is duplicated and flattened in the sub-thread.
238+
*
239+
* If inPlace is True, then when the flatten operation completes,
240+
* the newly flattened copies are automatically dropped into the
241+
* scene graph, in place the original models.
242+
*
243+
* If a callback is specified, then it is called after the
244+
* operation is finished, receiving the flattened model (or a
245+
* list of flattened models).
246+
*/
247+
std::shared_ptr<Callback> async_flatten_strong(NodePath model, const CallbackType& callback = {});
248+
std::shared_ptr<Callback> async_flatten_strong(const std::vector<NodePath>& model_list, const CallbackType& callback = {});
249+
std::shared_ptr<Callback> async_flatten_strong_in_place(std::vector<NodePath>& model_list, const CallbackType& callback = {});
250+
233251
private:
234252
class Impl;
235253
std::unique_ptr<Impl> impl_;

src/rppanda/showbase/loader.cpp

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737

3838
#include "render_pipeline/rppanda/showbase/loader.hpp"
3939

40+
#include <nodePathCollection.h>
4041
#include <audioManager.h>
4142
#include <loader.h>
4243
#include <audioLoadRequest.h>
@@ -46,6 +47,7 @@
4647
#include <dynamicTextFont.h>
4748
#include <texturePool.h>
4849
#include <shaderPool.h>
50+
#include <modelFlattenRequest.h>
4951

5052
#include <fmt/ostream.h>
5153

@@ -64,6 +66,12 @@ class Loader::Impl
6466
void pre_load_model(LoaderOptions& this_options, bool& this_ok_missing,
6567
boost::optional<bool> no_cache, bool allow_instance, boost::optional<bool> ok_missing);
6668

69+
/**
70+
* The asynchronous flatten operation has completed; quietly
71+
* drop in the new models.
72+
*/
73+
void async_flatten_done(const std::vector<NodePath>& models, const CallbackType& callback, std::vector<NodePath>& orig_model_list);
74+
6775
/**
6876
* A model or sound file or some such thing has just been
6977
* loaded asynchronously by the sub-thread. Add it to the list
@@ -116,6 +124,26 @@ void Loader::Impl::pre_load_model(LoaderOptions& this_options, bool& this_ok_mis
116124
this_options.set_flags(this_options.get_flags() | LoaderOptions::LF_allow_instance);
117125
}
118126

127+
void Loader::Impl::async_flatten_done(const std::vector<NodePath>& models, const CallbackType& callback, std::vector<NodePath>& orig_model_list)
128+
{
129+
rppanda_showbase_cat.debug() << "async_flatten_done" << std::endl;
130+
131+
if (models.size() != orig_model_list.size())
132+
rppanda_showbase_cat.error() << "async_flatten_done: Size is not same." << std::endl;
133+
134+
for (size_t k = 0, k_end = models.size(); k < k_end; ++k)
135+
{
136+
orig_model_list[k].get_children().detach();
137+
auto orig = orig_model_list[k].node();
138+
auto flat = models[k].node();
139+
orig->copy_all_properties(flat);
140+
flat->replace_node(orig);
141+
}
142+
143+
if (callback)
144+
callback(orig_model_list);
145+
}
146+
119147
void Loader::Impl::got_async_object(const Event* ev)
120148
{
121149
if (ev->get_num_parameters() != 1)
@@ -152,8 +180,7 @@ void Loader::Impl::got_async_object(const Event* ev)
152180

153181
// ************************************************************************************************
154182

155-
Loader::Callback::Callback(Loader* loader, int num_objects,
156-
const std::function<void(std::vector<NodePath>&)>& callback) : loader_(loader), callback_(callback)
183+
Loader::Callback::Callback(Loader* loader, int num_objects, const CallbackType& callback) : loader_(loader), callback_(callback)
157184
{
158185
objects_.resize(num_objects);
159186
}
@@ -265,17 +292,15 @@ std::vector<NodePath> Loader::load_model(const std::vector<Filename>& model_list
265292

266293
std::shared_ptr<Loader::Callback> Loader::load_model_async(const Filename& model_path, const LoaderOptions& loader_options,
267294
boost::optional<bool> no_cache, bool allow_instance, boost::optional<bool> ok_missing,
268-
const std::function<void(std::vector<NodePath>&)>& callback,
269-
boost::optional<int> priority)
295+
const CallbackType& callback, boost::optional<int> priority)
270296
{
271297
return load_model_async(std::vector<Filename>{model_path}, loader_options, no_cache,
272298
allow_instance, ok_missing, callback, priority);
273299
}
274300

275301
std::shared_ptr<Loader::Callback> Loader::load_model_async(const std::vector<Filename>& model_list, const LoaderOptions& loader_options,
276302
boost::optional<bool> no_cache, bool allow_instance, boost::optional<bool> ok_missing,
277-
const std::function<void(std::vector<NodePath>&)>& callback,
278-
boost::optional<int> priority)
303+
const CallbackType& callback, boost::optional<int> priority)
279304
{
280305
rppanda_showbase_cat.debug() << "Loading model: " << join_to_string(model_list) << std::endl;
281306

@@ -654,4 +679,35 @@ void Loader::unload_shader(const Filename& shader_path)
654679
ShaderPool::release_shader(shader_path);
655680
}
656681

682+
auto Loader::async_flatten_strong(NodePath model, const CallbackType& callback) -> std::shared_ptr<Callback>
683+
{
684+
return async_flatten_strong(std::vector<NodePath>{model}, callback);
685+
}
686+
687+
auto Loader::async_flatten_strong(const std::vector<NodePath>& model_list, const CallbackType& callback) -> std::shared_ptr<Callback>
688+
{
689+
auto cb = std::make_shared<Callback>(this, model_list.size(), callback);
690+
691+
size_t i = 0;
692+
for (const auto& model_path : model_list)
693+
{
694+
PT(ModelFlattenRequest) request = new ModelFlattenRequest(model_path.node());
695+
request->set_done_event(impl_->hook_);
696+
impl_->loader_->load_async(request);
697+
cb->requests_.insert(request);
698+
cb->request_list_.push_back(request);
699+
impl_->requests_.insert({ request.p(),{ cb, i } });
700+
i += 1;
701+
}
702+
703+
return cb;
704+
}
705+
706+
auto Loader::async_flatten_strong_in_place(std::vector<NodePath>& model_list, const CallbackType& callback) -> std::shared_ptr<Callback>
707+
{
708+
const auto& const_model_list = model_list;
709+
CallbackType new_callback = std::bind(&Impl::async_flatten_done, impl_.get(), std::placeholders::_1, callback, model_list);
710+
return async_flatten_strong(const_model_list, new_callback);
711+
}
712+
657713
}

0 commit comments

Comments
 (0)