Skip to content

Commit

Permalink
Rough in ged opendb/closedb callbacks, cleanup
Browse files Browse the repository at this point in the history
The opendb command was repeating a lot of the work of the closedb
command - just have opendb call closedb first if needed.

As a first cut, give applications a chance to take action both
immediately before and immediately after the open and close operations
take place - it's conceivable they'll want to record info about the old
state, and they'll almost always want to respond to the new data from a
successful open.
  • Loading branch information
starseeker committed Aug 29, 2023
1 parent 9094488 commit 246dd70
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 81 deletions.
9 changes: 9 additions & 0 deletions include/ged/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,15 @@ struct ged {
void (*ged_create_vlist_display_list_callback)(struct display_list *); /**< @brief function to call after all vlist created that loops through creating display list for each solid */
void (*ged_destroy_vlist_callback)(unsigned int, int); /**< @brief function to call after freeing a vlist */

/* Functions related to database open/close - if the parent application
* needs to take any action upon database opening or closing, it should
* register these callbacks so GED's opendb/closedb commands trigger
* the correct logic. */
void (*ged_pre_opendb_callback)(struct ged *, void *);
void (*ged_post_opendb_callback)(struct ged *, void *);
void (*ged_pre_closedb_callback)(struct ged *, void *);
void (*ged_post_closedb_callback)(struct ged *, void *);
void *ged_db_callback_udata;

/* Functions assigned to ged_subprocess init_clbk and end_clbk
* slots when the ged_subprocess is created. TODO - eventually
Expand Down
29 changes: 22 additions & 7 deletions src/libged/close/close.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,48 @@
#include <string.h>

#include "bu/cmd.h"
#include "bg/lod.h"

#include "../ged_private.h"


extern "C" int
ged_close_core(struct ged *gedp, int UNUSED(argc), const char **UNUSED(argv))
{
GED_CHECK_DATABASE_OPEN(gedp, BRLCAD_ERROR);
// If we don't have an open database, this is a no-op
if (!gedp->dbip)
return BRLCAD_OK;

// If the caller has work to do first, trigger it
if (gedp->ged_pre_closedb_callback)
(*gedp->ged_pre_closedb_callback)(gedp, gedp->ged_db_callback_udata);

/* set result while we still have the info */
bu_vls_sprintf(gedp->ged_result_str, "closed %s", gedp->dbip->dbi_filename);

rt_new_material_head(MATER_NULL);

/* Clear any geometry displayed in application views.
* TODO - properly speaking, we should only be zapping geometry data here
* and not clearing all scene objects... */
const char *av[2];
av[0] = "zap";
av[1] = (char *)0;
ged_exec(gedp, 1, (const char **)av);

/* close current database */
if (gedp->dbip) {
if (gedp->dbip)
db_close(gedp->dbip);
}
gedp->dbip = NULL;

/* Clean up any old acceleration states, if present */
const char *use_dbi_state = getenv("LIBGED_DBI_STATE");
if (use_dbi_state) {
if (gedp->dbi_state)
delete gedp->dbi_state;
}
if (use_dbi_state && gedp->dbi_state)
delete gedp->dbi_state;
gedp->dbi_state = NULL;
if (gedp->ged_lod)
bg_mesh_lod_context_destroy(gedp->ged_lod);
gedp->ged_lod = NULL;

/* Terminate any ged subprocesses */
if (gedp != GED_NULL) {
Expand All @@ -74,6 +85,10 @@ ged_close_core(struct ged *gedp, int UNUSED(argc), const char **UNUSED(argv))
bu_ptbl_reset(&gedp->ged_subp);
}

// If the caller has work to do after close, trigger it
if (gedp->ged_post_closedb_callback)
(*gedp->ged_post_closedb_callback)(gedp, gedp->ged_db_callback_udata);

return BRLCAD_OK;
}

Expand Down
7 changes: 5 additions & 2 deletions src/libged/ged.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,11 @@ ged_init(struct ged *gedp)
gedp->fbs_open_client_handler = NULL;
gedp->fbs_close_client_handler = NULL;

gedp->ged_opendb_callback = NULL;
gedp->ged_closedb_callback = NULL;
gedp->ged_pre_opendb_callback = NULL;
gedp->ged_post_opendb_callback = NULL;
gedp->ged_pre_closedb_callback = NULL;
gedp->ged_post_closedb_callback = NULL;
gedp->ged_db_callback_udata = NULL;

gedp->ged_subprocess_init_callback = NULL;
gedp->ged_subprocess_end_callback = NULL;
Expand Down
117 changes: 45 additions & 72 deletions src/libged/open/open.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
extern "C" int
ged_reopen_core(struct ged *gedp, int argc, const char *argv[])
{
struct db_i *new_dbip;
static const char *usage = "[filename]";

GED_CHECK_ARGC_GT_0(gedp, argc, BRLCAD_ERROR);
Expand All @@ -50,88 +49,62 @@ ged_reopen_core(struct ged *gedp, int argc, const char *argv[])
return BRLCAD_OK;
}

/* set database filename */
if (argc == 2) {
const char *av[2];
struct db_i *old_dbip = gedp->dbip;
struct mater *old_materp = rt_material_head();
struct mater *new_materp;

// TODO - need to look more carefully at material_head and what
// its expected behavior is through a dbip change...
rt_new_material_head(MATER_NULL);
if (argc != 2) {
bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
return BRLCAD_ERROR;
}

if ((new_dbip = _ged_open_dbip(argv[1], 0)) == DBI_NULL) {
/* Restore RT's material head */
rt_new_material_head(old_materp);
/* Before proceeding with the full open logic, see if
* we can actually open what the caller provided */
struct db_i *new_dbip = NULL;
struct mater *old_materp = rt_material_head();
if ((new_dbip = _ged_open_dbip(argv[1], 0)) == DBI_NULL) {
/* Restore RT's material head */
rt_new_material_head(old_materp);

bu_vls_printf(gedp->ged_result_str, "ged_reopen_core: failed to open %s\n", argv[1]);
return BRLCAD_ERROR;
}
bu_vls_printf(gedp->ged_result_str, "ged_reopen_core: failed to open %s\n", argv[1]);
return BRLCAD_ERROR;
}

av[0] = "zap";
/* Close current database, if we have one */
if (gedp->dbip) {
const char *av[2];
av[0] = "closedb";
av[1] = (char *)0;
ged_exec(gedp, 1, (const char **)av);
}

new_materp = rt_material_head();
/* If the caller has work to do before open, trigger it */
if (gedp->ged_pre_opendb_callback)
(*gedp->ged_pre_opendb_callback)(gedp, gedp->ged_db_callback_udata);

gedp->dbip = old_dbip;
rt_new_material_head(old_materp);
/* Set up the new database info in gedp */
gedp->dbip = new_dbip;
rt_new_material_head(rt_material_head());

/* close current database */
if (gedp->dbip)
db_close(gedp->dbip);
gedp->dbip = NULL;
const char *use_dbi_state = getenv("LIBGED_DBI_STATE");
if (use_dbi_state) {
if (gedp->dbi_state)
delete gedp->dbi_state;
}
gedp->dbi_state = NULL;

/* Terminate any ged subprocesses */
if (gedp != GED_NULL) {
for (size_t i = 0; i < BU_PTBL_LEN(&gedp->ged_subp); i++) {
struct ged_subprocess *rrp = (struct ged_subprocess *)BU_PTBL_GET(&gedp->ged_subp, i);
if (!rrp->aborted) {
bu_terminate(bu_process_pid(rrp->p));
rrp->aborted = 1;
}
bu_ptbl_rm(&gedp->ged_subp, (long *)rrp);
BU_PUT(rrp, struct ged_subprocess);
}
bu_ptbl_reset(&gedp->ged_subp);
}

gedp->dbip = new_dbip;

rt_new_material_head(new_materp);

/* New database open, need to initialize reference counts */
db_update_nref(gedp->dbip, &rt_uniresource);


// LoD context creation (DbiState initialization can use info
// stored here, so do this first)
if (gedp->ged_lod)
bg_mesh_lod_context_destroy(gedp->ged_lod);
gedp->ged_lod = bg_mesh_lod_context_create(argv[1]);

// Set up the DbiState container for fast structure access
if (use_dbi_state)
gedp->dbi_state = new DbiState(gedp);

// Set the view units, if we have a view
if (gedp->ged_gvp) {
gedp->ged_gvp->gv_base2local = gedp->dbip->dbi_base2local;
gedp->ged_gvp->gv_local2base = gedp->dbip->dbi_local2base;
}
/* New database open, need to initialize reference counts */
db_update_nref(gedp->dbip, &rt_uniresource);

return BRLCAD_OK;
// LoD context creation (DbiState initialization can use info
// stored here, so do this first)
gedp->ged_lod = bg_mesh_lod_context_create(argv[1]);

// If enabled, set up the DbiState container for fast structure access
const char *use_dbi_state = getenv("LIBGED_DBI_STATE");
if (use_dbi_state)
gedp->dbi_state = new DbiState(gedp);

// Set the view units, if we have a view
if (gedp->ged_gvp) {
gedp->ged_gvp->gv_base2local = gedp->dbip->dbi_base2local;
gedp->ged_gvp->gv_local2base = gedp->dbip->dbi_local2base;
}

bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", argv[0], usage);
return BRLCAD_ERROR;
// If the caller has work to do after open, trigger it
if (gedp->ged_post_opendb_callback)
(*gedp->ged_post_opendb_callback)(gedp, gedp->ged_db_callback_udata);

return BRLCAD_OK;
}

extern "C" {
Expand Down

0 comments on commit 246dd70

Please sign in to comment.