Skip to content

Commit

Permalink
add apphandler events
Browse files Browse the repository at this point in the history
  • Loading branch information
ihm-tswow committed Aug 30, 2022
1 parent 1749528 commit d6a4bc6
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 0 deletions.
163 changes: 163 additions & 0 deletions bxx/app_handlers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
#include "app_handlers.hpp"

#include "python_object.hpp"
#include "exec.hpp"
#include "script.hpp"

#include "scene.hpp"

#include <fmt/core.h>

namespace bxx::app::handlers
{
void register_handler(std::string const& target, std::function<void(bxx::python_tuple const&)> func)
{
// todo: for some bizarre reason this stops working if i don't pass all varargs python-side,
// but everything is still in the first tuple once it reaches C++
size_t event_idx = lib_register_event([=](bxx::python_tuple const& tuple) {
func(tuple.get<python_tuple>(0));
return bxx::python_object();
});
exec({
fmt::format("@bpy.app.handlers.persistent"),
fmt::format("def event_{}_{}(*args):",get_script_index(),event_idx),
fmt::format(" fire_event({},{}, args)",get_script_index(),event_idx),
fmt::format("register_app_handler({}, bpy.app.handlers.{}, event_{}_{})", get_script_index(), target, get_script_index(), event_idx, target)
});
}

void depsgraph_update_pre(std::function<void(scene)> callback)
{
register_handler("depsgraph_update_pre", [=](python_tuple const& tup) {
callback(tup.get<python_object>(0));
});
}

void depsgraph_update_post(std::function<void(scene, python_object)> callback)
{
register_handler("depsgraph_update_post", [=](python_tuple const& tup) {
callback(tup.get<scene>(0), tup.get<python_object>(1));
});
}
void frame_change_pre(std::function<void(scene)> callback)
{
register_handler("frame_change_pre", [=](python_tuple const& tup) {
callback(tup.get<scene>(0));
});
}
void frame_change_post(std::function<void(scene, python_object)> callback)
{
register_handler("frame_change_post", [=](python_tuple const& tup) {
callback(tup.get<scene>(0), tup.get<python_object>(1));
});
}

void load_factory_preferences_post(std::function<void()> callback)
{
register_handler("load_factory_preferences_post", [=](python_tuple const& tup) {
callback();
});
}
void load_factory_startup_post(std::function<void()> callback)
{
register_handler("load_factory_startup_post", [=](python_tuple const& tup) {
callback();
});
}
void load_post(std::function<void()> callback)
{
register_handler("load_post", [=](python_tuple const& tup) {
callback();
});
}
void load_pre(std::function<void()> callback)
{
register_handler("load_pre", [=](python_tuple const& tup) {
callback();
});
}
void redo_pre(std::function<void(scene)> callback)
{
register_handler("redo_pre", [=](python_tuple const& tup) {
callback(tup.get<scene>(0));
});
}
void redo_post(std::function<void(scene)> callback)
{
register_handler("redo_post", [=](python_tuple const& tup) {
callback(tup.get<scene>(0));
});
}
void render_cancel(std::function<void()> callback)
{
register_handler("render_cancel", [=](python_tuple const& tup) {
callback();
});
}
void render_complete(std::function<void(scene)> callback)
{
register_handler("render_complete", [=](python_tuple const& tup) {
callback(tup.get<scene>(0));
});
}
void render_init(std::function<void()> callback)
{
register_handler("render_init", [=](python_tuple const& tup) {
callback();
});
}
void render_post(std::function<void(scene)> callback)
{
register_handler("render_post", [=](python_tuple const& tup) {
callback(tup.get<scene>(0));
});
}
void render_pre(std::function<void(scene)> callback)
{
register_handler("render_pre", [=](python_tuple const& tup) {
callback(tup.get<scene>(0));
});
}
void render_stats(std::function<void()> callback)
{
register_handler("render_stats", [=](python_tuple const& tup) {
callback();
});
}
void render_write(std::function<void()> callback)
{
register_handler("render_write", [=](python_tuple const& tup) {
callback();
});
}
void save_post(std::function<void()> callback)
{
register_handler("save_post", [=](python_tuple const& tup) {
callback();
});
}
void save_pre(std::function<void()> callback)
{
register_handler("save_pre", [=](python_tuple const& tup) {
callback();
});
}
void undo_post(std::function<void(scene)> callback)
{
register_handler("undo_post", [=](python_tuple const& tup) {
callback(tup.get<scene>(0));
});
}
void undo_pre(std::function<void(scene)> callback)
{
register_handler("undo_pre", [=](python_tuple const& tup) {
callback(tup.get<scene>(0));
});
}
void version_update(std::function<void()> callback)
{
register_handler("version_update", [=](python_tuple const& tup) {
callback();
});
}
}
40 changes: 40 additions & 0 deletions bxx/app_handlers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#pragma once

#include <functional>

namespace bxx
{
class python_object;
class python_tuple;
class scene;
namespace app::handlers
{
void depsgraph_update_pre(std::function<void(scene)> callback);
void depsgraph_update_post(std::function<void(scene, python_object)> callback);
void frame_change_pre(std::function<void(scene)> callback);
void frame_change_post(std::function<void(scene, python_object)> callback);
void load_factory_preferences_post(std::function<void()> callback);
void load_factory_startup_post(std::function<void()> callback);
void load_post(std::function<void()> callback);
void load_pre(std::function<void()> callback);
void redo_pre(std::function<void(scene)> callback);
void redo_post(std::function<void(scene)> callback);
// todo: unknown arguments
void render_cancel(std::function<void()> callback);
void render_complete(std::function<void(scene)> callback);
// todo: unknown arguments
void render_init(std::function<void()> callback);
void render_post(std::function<void(scene)> callback);
void render_pre(std::function<void(scene)> callback);
// todo: unknown arguments
void render_stats(std::function<void()> callback);
// todo: unknown arguments
void render_write(std::function<void()> callback);
void save_post(std::function<void()> callback);
void save_pre(std::function<void()> callback);
void undo_post(std::function<void(scene)> callback);
void undo_pre(std::function<void(scene)> callback);
void version_update(std::function<void()> callback);
void register_handler(std::string const& target, std::function<void(python_tuple const&)> callback);
}
}
5 changes: 5 additions & 0 deletions bxx/scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
#include "makesdna/DNA_scene_types.h"
#include "fmt/core.h"

bxx::scene::scene(python_object obj)
: m_raw(reinterpret_cast<bl_scene*>(obj.call<std::uint64_t>("as_pointer")))
{
}

std::string bxx::scene::get_name() const
{
return m_raw->id.name + 2;
Expand Down
1 change: 1 addition & 0 deletions bxx/scene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace bxx
{
public:
scene(bl_scene* raw);
scene(python_object obj);
void set_name(std::string const& name);
std::string get_name() const override;
std::string get_full_name() const override;
Expand Down
13 changes: 13 additions & 0 deletions core/core_cy.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ cdef extern void auto_reload_cxx();
# python objects we need to unregister with the scripts
registered_operators = {}
registered_property_groups = {}
registered_app_handlers = {}

# image buffers
cdef array.array cur_pixels # image buffer create temp
Expand Down Expand Up @@ -99,6 +100,11 @@ cdef void unregister_script(size_t script):
delattr(target,name)
registered_property_groups[script] = []

if script in registered_app_handlers:
for (target,func) in registered_app_handlers[script]:
target.remove(func)
registered_app_handlers[script] = []

def fire_event(script,event,*args):
return <object> core_fire_event(script,event,<PyObject*>args)

Expand All @@ -111,6 +117,12 @@ def register_property_group(script,target, name, property_group,is_collection):
else:
setattr(target,name,bpy.props.PointerProperty(type=property_group))

def register_app_handler(script, target, func):
target.append(func)
if not script in registered_app_handlers:
registered_app_handlers[script] = []
registered_app_handlers[script].append((target,func))

cdef float* create_image_buffer(unsigned long long id, int width ,int height):
global cur_pixels
cur_pixels = array.array('f',[0])
Expand Down Expand Up @@ -141,6 +153,7 @@ def build_context():
context['register_operator'] = register_operator
context['fire_event'] = fire_event
context['register_property_group'] = register_property_group
context['register_app_handler'] = register_app_handler
context['preferences'] = preferences
context['get_addon_name'] = get_addon_name
context['get_addon_path'] = get_addon_path
Expand Down

0 comments on commit d6a4bc6

Please sign in to comment.