Views > Viewpoints
Viewpoint Sync
Copies viewpoint folders from one Navisworks file to another through a package: export the folders here, import them there into the folder you choose, skipping, replacing or keeping both when a name exists.
Status
Launched Ran inside Navisworks at least once with no error logged; nobody checked the result yet.
The public ask
No public source is on record for this tool.
Events it listens to
None. It runs only when you click it.
Files
Paths are relative to the Playground.extension folder.
Views.tab/Viewpoints.panel/Viewpoint_Sync.pushbutton/bundle.yamlViews.tab/Viewpoints.panel/Viewpoint_Sync.pushbutton/icon.dark.pngViews.tab/Viewpoints.panel/Viewpoint_Sync.pushbutton/icon.pngViews.tab/Viewpoints.panel/Viewpoint_Sync.pushbutton/icon.small.dark.pngViews.tab/Viewpoints.panel/Viewpoint_Sync.pushbutton/icon.small.pngViews.tab/Viewpoints.panel/Viewpoint_Sync.pushbutton/script.py
Install
- Only this tool. In Navisworks, click pyNavis > Playground, search for Viewpoint Sync, tick it and click Install.
- The whole extension. Download
Playground.extension.zip, unzip it, put thePlayground.extensionfolder in%APPDATA%\pyNavis\extensions\, and click pyNavis > Reload. Viewpoint Sync is on the Views tab, Viewpoints panel.
You need pyNavis 1.3.0 or later.
Tried it? Tell us whether it worked or not. That report is what moves a tool up the status ladder.
ReportSource
The tool's own files, word for word as published in pynavis/Playground. Paths are relative to the Playground.extension folder.
script.py
The script that runs on a click.
Views.tab/Viewpoints.panel/Viewpoint_Sync.pushbutton/script.py View on GitHub"""Copies saved-viewpoint folders between Navisworks files through a viewpoint package."""
import os
from namo import progress, ui, vp_common, vp_sync, vpexport
from pynavis import forms, output, script, toast
TITLE = 'Viewpoint Sync'
ACTIONS = ['Export package', 'Import package']
DEFAULTS = {'target': '', 'keep_paths': True, 'policy': 'skip', 'clip': True, 'comments': True}
def export_package(document):
rows = vp_common.view_rows(document)
if not rows:
toast.info('No saved viewpoints', 'Save some viewpoints, then export a package.')
return
folders = vp_common.folder_paths(rows)
table = [{'value': path, 'cells': [vp_common.folder_label(path), count]} for path, count in folders]
picked = ui.choose('%s: folders to export' % TITLE, table, ['Folder', 'Viewpoints'],
checked=[path for path, _c in folders], ok='Next',
prompt='A folder takes its subfolders with it. (top level) is the viewpoints '
'outside any folder.')
if picked is None:
return
chosen = vp_common.select_rows(rows, {'mode': 'folders', 'folders': picked})
if not chosen:
toast.info('Nothing to export', 'The chosen folders hold no viewpoints.')
return
path = forms.save_file(filter='Playground viewpoint packages (*.nvp.json)|*.nvp.json',
default_name=vp_sync.package_path_default(document), title=TITLE)
if path is None:
return
if not path.lower().endswith('.nvp.json'):
path = (path[:-5] if path.lower().endswith('.json') else path) + '.nvp.json'
try:
vpexport.write_package(path, vpexport.records_from(chosen, document, include_clip=True), document)
except (IOError, OSError) as error:
toast.error('Could not write the package', '%s. Check the folder is writable, then try again.' % error)
return
toast.success('Exported %s' % vp_common.plural(len(chosen), 'viewpoint'),
'%s. Open the other model and choose Import package.' % path)
def import_package(document):
path = forms.open_file(filter='Viewpoint packages and Navisworks XML (*.nvp.json;*.json;*.xml)|'
'*.nvp.json;*.json;*.xml', title=TITLE)
if path is None:
return
try:
records, units_from, notes = vpexport.read_file(path)
except ValueError as error:
toast.error('Could not read the package', str(error))
return
if not records:
toast.info('The file holds no viewpoints', notes[0] if notes else os.path.basename(path))
return
counts = vpexport.folder_counts(records)
table = [{'value': folder, 'cells': [vp_common.folder_label(folder), count]} for folder, count in counts]
picked = ui.choose('%s: folders to import' % TITLE, table, ['Folder', 'Viewpoints'],
checked=[folder for folder, _c in counts], ok='Next')
if picked is None:
return
chosen = vp_sync.chosen(records, picked)
if not chosen:
toast.info('No folders chosen', 'Tick at least one folder, then import the package again.')
return
cfg = script.get_config(DEFAULTS)
units = str(document.Units)
same = abs(vp_common.unit_factor(units_from, units) - 1.0) < 1e-12
intro = '%s from %s.' % (vp_common.plural(len(chosen), 'viewpoint'), os.path.basename(path))
if not same:
intro += ' The package is in %s and will be converted to %s.' % (units_from.lower(), units.lower())
values = ui.form(TITLE, vp_sync.import_fields(cfg), intro=intro, ok='Import')
if values is None:
return
cfg.update(values)
script.save_config(cfg)
steps = vp_sync.plan(chosen, values['target'], values['policy'], vp_sync.existing_lookup(document),
values['keep_paths'])
counts_now = vp_sync.plan_counts(steps)
if counts_now['replace'] and not forms.confirm('%s\n\nReplaced viewpoints lose their own camera, section and '
'comments. One Ctrl+Z undoes the import.'
% vp_sync.plan_sentence(steps), TITLE):
return
outcome = progress.run(TITLE, lambda report: vp_sync.apply(document, steps, units_from, values['clip'],
values['comments'], report), 'Importing')
if outcome is progress.CANCELLED:
return
results, stopped = outcome
if results:
output.set_title('%s: import report' % TITLE)
output.print_md('## Imported from %s' % os.path.basename(path))
for note in notes:
output.print_md(note)
output.print_table(vp_sync.report_rows(results), ['Folder', 'Name', 'Result'])
level, message, detail = vp_sync.summary(results, stopped, len(steps))
toast.show(level, message, detail)
def run():
document = vp_common.active_doc()
if not vp_common.has_models(document):
toast.info('No model open', 'Open or append a model, then run Viewpoint Sync again.')
return
action = forms.ask_options(None, ACTIONS, title=TITLE)
if action == ACTIONS[0]:
export_package(document)
elif action == ACTIONS[1]:
import_package(document)
run()
Library modules this tool uses
From the shared namo library, which installs with every tool. Each name opens the module on GitHub.
namo.progressGlue between pyNavis' cancellable progress window and Playground's progress callbacks.namo.uiWPF building blocks for Playground tools, themed from the pyNavis design system.namo.vp_commonShared helpers for the Views tools (Viewpoints, Capture and Navigate panels).namo.vp_syncViewpoint Sync: copy saved-viewpoint folders between Navisworks files through a package (namo.vpexport records in a .nvp.json file; a Navisworks viewpoint .xml is read too).namo.vpexportSaved viewpoints out of Navisworks, as plain records, as Navisworks viewpoint exchange XML, and as a Playground package (.nvp.json) that Viewpoint Sync reads back.
bundle.yaml
The bundle contract: the keys pyNavis reads for this tool.
Views.tab/Viewpoints.panel/Viewpoint_Sync.pushbutton/bundle.yaml View on GitHubtitle: Viewpoint\nSync
tooltip: Copies viewpoint folders from one Navisworks file to another through a package: export the folders here, import them there into the folder you choose, skipping, replacing or keeping both when a name exists.
context: doc