Viewpoints panel

Speeds to Saved

Write the same speeds and field of view into saved viewpoints you pick, without loading any of them.

On the ribbonStacked button, Viewpoints panel
NeedsSaved viewpoints in the document
Alt+Z" shift="Opens the shared speeds window">

What it does#

A set of views handed over by someone else navigates the way they liked. This rewrites the ticked views with your numbers, each one copied, its camera edited and swapped back, so nothing is loaded and the whole run is one undo step.

How to use it#

  1. Press Alt+Z or click Speeds to Saved. The values about to be written are named at the top of the browser.
  2. Tick views or whole folders and click OK. The progress window can stop the run part way, keeping what was written.

Limitations#

  • Folders have no camera and animations keep theirs on their own cuts; both are counted and skipped.
  • On some Navisworks releases a view has to be rebuilt to take the change, and the toast says plainly when redlines and appearance overrides were not carried over.

Source#

The tool's own files, word for word as shipped in Viewpoints.panel/Speeds.stack/Speeds_to_Saved.pushbutton. Every pyNavis tool is an ordinary bundle: copy these into your own extension and change what you like.

script.py Runs on a click. View on GitHub
# -*- coding: utf-8 -*-
"""Writes the stored speeds and field of view into saved viewpoints you pick.

Apply Speeds beside this does the view on screen; this does views already saved
in the document, without loading any of them: each saved item is copied, its
camera edited, and the copy swapped back into place. The whole run lands as a
single undo step and can be stopped part way, keeping whatever was written.

The picking is the shared viewpoint browser the Deleter and Manager use. The
writing is lib/vpspeeds.py, which also records the two routes that look like
they should work and do not.
"""

import clr

import speeds
import vpspeeds

clr.AddReference('PyNavis.Runtime')
from System.Collections.Generic import List
from PyNavis.Runtime.Forms import ViewpointResetDialog, ViewpointRow

from pynavis import forms, script, settings, toast, viewpoints


def to_rows(snapshot):
    rows = List[ViewpointRow]()
    for row in snapshot:
        r = ViewpointRow()
        r.Guid = row['guid']
        r.Key = row['key']
        r.ParentKey = row['parent_key']
        r.Folder = row['folder']
        r.Name = row['name']
        r.Kind = row['kind']
        r.Depth = row['depth']
        r.IsFolder = row['is_folder']
        r.Comments = row['comments']
        rows.Add(r)
    return rows


def run():
    log = script.get_logger()
    values = speeds.normalise(settings.load(speeds.SETTINGS_KEY, speeds.DEFAULTS))
    wanted = speeds.summary(values)
    if not wanted:
        toast.info('Nothing to reset',
                   'All three are switched off in the settings (Shift+Click)')
        return

    snapshot = viewpoints.snapshot()
    if not snapshot:
        forms.alert('This document has no saved viewpoints.')
        return

    guids = ViewpointResetDialog.Show(to_rows(snapshot), wanted)
    if guids is None:
        return                                  # cancelled: say nothing

    guids = list(guids)
    if not guids:
        toast.info('Nothing to reset', 'No viewpoints were ticked')
        return

    # A cancellable window rather than the output bar: this can run over hundreds
    # of viewpoints, and a run with no way out is worse than a slow one. update()
    # returns False once Cancel is clicked, which is the whole cancel signal; it
    # also pumps, so the button can be clicked at all while this holds the UI
    # thread.
    running = [True]
    with forms.progress('Reset viewpoints', 'Starting') as bar:
        def tick(done, count):
            running[0] = bar.update(float(done) / count,
                                    'Resetting %d of %d' % (done, count))

        written, unchanged, errors, route, stopped = vpspeeds.apply(
            snapshot, guids, values,
            progress=tick, cancelled=lambda: not running[0])

    skipped = vpspeeds.dropped_kinds(snapshot, guids)
    notes = []
    if skipped['folder']:
        notes.append('%d folder(s) have no camera' % skipped['folder'])
    if skipped['animation']:
        notes.append('%d animation(s) keep theirs on their cuts' % skipped['animation'])
    if unchanged:
        notes.append('%d already matched' % unchanged)
    if route == vpspeeds.REBUILT:
        notes.append('redlines and appearance overrides were not carried over')

    log.info('reset %d viewpoint(s), %s: %s' % (written, route, wanted))

    if errors:
        toast.warning('Reset %d viewpoint(s), %d failed' % (written, len(errors)),
                      errors[0])
    elif stopped:
        toast.warning('Stopped after %d viewpoint(s)' % written,
                      'What was written is kept, and one undo takes it all back')
    elif written:
        detail = wanted if not notes else '%s. %s.' % (wanted, ', '.join(notes))
        toast.success('Reset %d viewpoint(s)' % written, detail)
    else:
        toast.info('Nothing to change',
                   '. '.join(notes) or 'Those viewpoints already match your settings')


if '__commandpath__' in globals():
    run()
config.py Runs on Shift+Click. View on GitHub
"""Shift+Click settings for both speed buttons.

The window itself is shared (extensions/pyNavis.extension/lib), because the
two buttons read one settings store.
"""

import speedsconfig

speedsconfig.edit()
bundle.yaml The bundle contract: the keys pyNavis reads for this tool. View on GitHub
title: Speeds to Saved
tooltip: Write the stored walk speed, turn speed and field of view into saved viewpoints you pick. Shift+Click to change them.
shortcut: Alt+Z
context: viewpoints