RemovePaint does not update view

RemovePaint does not update view

htlcnn
Enthusiast Enthusiast
1,026 Views
7 Replies
Message 1 of 8

RemovePaint does not update view

htlcnn
Enthusiast
Enthusiast

I wrote a script to let user select beams and columns, then I use doc.RemovePaint to remove painted materials on all of their faces. Script run successfully and material is deleted from schedule. But the view is not updated, until I run the script again. Please see the screencast.

 

 

 

Here is my code:

# -*- coding: utf-8 -*-

import sys
import clr
clr.AddReference('RevitAPI')
import Autodesk

import rpw
from rpw import doc, uidoc
from System.Collections.Generic import List

def get_faces(element):
    op = Autodesk.Revit.DB.Options()
    op.View = doc.ActiveView
    geometries = element.Geometry[op]
    for g in geometries:
        if type(g) == Autodesk.Revit.DB.Solid and g.Faces.Size > 0:
            return g.Faces


class CategoriesFilter(Autodesk.Revit.UI.Selection.ISelectionFilter):
    def __init__(self, names):
        self.names = names
    def AllowElement(self, element):
        return element.Category.Name in self.names


def select_by_category(prompt='Pick Objects', *names):
    references = uidoc.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element,
                                           CategoriesFilter(names), prompt)
    return [rpw.db.Element.from_id(reference.ElementId) for reference in references]


selected_elements = rpw.ui.Selection().elements
if not selected_elements:
    try:
        selected_elements = select_by_category('Pick Elements', 'Structural Framing', 'Structural Columns')
    except Autodesk.Revit.Exceptions.OperationCanceledException:
        sys.exit()

with rpw.db.Transaction('Remove Paint on all faces'):
    for e in selected_elements:
        faces = get_faces(e)
        for face in faces:
            doc.RemovePaint(e.Id, face)

Am I missing any step?

0 Likes
1,027 Views
7 Replies
Replies (7)
Message 2 of 8

Revitalizer
Advisor
Advisor

Hi,

 

there is a UIDocument.RefreshActiveView() method which you could call after your transaction.

There is also a Document.Regenerate() but since it is called automatically on a transaction's commit, I think that's not necessary.

 

But...

I don't know Python, but I don't see any transaction commit in your code, may this be the cause ?

 

 

Revitalizer




Rudolf Honke
Software Developer
Mensch und Maschine





0 Likes
Message 3 of 8

htlcnn
Enthusiast
Enthusiast

Hi Revitalizer,

 

I tried to use UIDocument.RefreshActiveView() but the result was the same.

 

I use revitpythonwrapper Transaction context which automatically starts and commits transaction. It's just something to make the code more "pythonic". I used rpw.db.Transaction in my other scripts and had no issue.

 

Anyway, I tried to switch to original Transaction but still no change.

Here is my new code:

# -*- coding: utf-8 -*-

import sys
import clr
clr.AddReference('RevitAPI')
import Autodesk

import rpw
from rpw import doc, uidoc

def get_faces(element):
    op = Autodesk.Revit.DB.Options()
    op.View = doc.ActiveView
    geometries = element.Geometry[op]
    for g in geometries:
        if type(g) == Autodesk.Revit.DB.Solid and g.Faces.Size > 0:
            return g.Faces


class CategoriesFilter(Autodesk.Revit.UI.Selection.ISelectionFilter):
    def __init__(self, names):
        self.names = names
    def AllowElement(self, element):
        return element.Category.Name in self.names


def select_by_category(prompt='Pick Objects', *names):
    references = uidoc.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element,
                                           CategoriesFilter(names), prompt)
    return [rpw.db.Element.from_id(reference.ElementId) for reference in references]


selected_elements = rpw.ui.Selection().elements
if not selected_elements:
    try:
        selected_elements = select_by_category('Pick Elements', 'Structural Framing', 'Structural Columns')
    except Autodesk.Revit.Exceptions.OperationCanceledException:
        sys.exit()

t = Autodesk.Revit.DB.Transaction(doc, 'Remove Paint on all faces')
t.Start()
for e in selected_elements:
    faces = get_faces(e)
    for face in faces:
        doc.RemovePaint(e.Id, face)
t.Commit()

uidoc.RefreshActiveView()

Thanks!

 

0 Likes
Message 4 of 8

FAIR59
Advisor
Advisor

It might be interesting to know how you paint the faces in the first place. In the UI (in the project environment) you can only paint the faces of system families, wall, floors etc. Unless this a new feature of Revit 2018 that I'm not aware of. 

0 Likes
Message 5 of 8

htlcnn
Enthusiast
Enthusiast

@FAIR59 I can paint structural framing instances when there are at least two intersecting ones. In the video I use doc.Paint to paint on the faces of intersecting beams. Here is my Paint code:

 

# -*- coding: utf-8 -*-

import sys
import clr
clr.AddReference('RevitAPI')
import Autodesk

import rpw
from rpw import doc, uidoc
from rpw.ui.forms import FlexForm, ComboBox, Label, Button

def get_faces(element):
    op = Autodesk.Revit.DB.Options()
    geometries = element.Geometry[op]
    for g in geometries:
        if type(g) == Autodesk.Revit.DB.Solid and g.Faces.Size > 0:
            return g.Faces


class CategoriesFilter(Autodesk.Revit.UI.Selection.ISelectionFilter):
    def __init__(self, names):
        self.names = names
    def AllowElement(self, element):
        return element.Category.Name in self.names


def select_by_category(prompt='Pick Objects', *names):
    references = uidoc.Selection.PickObjects(Autodesk.Revit.UI.Selection.ObjectType.Element,
                                           CategoriesFilter(names), prompt)
    return [rpw.db.Element.from_id(reference.ElementId) for reference in references]

materials = rpw.db.Collector(of_class='Material')
components = [
              Label('Select materials to paint to all faces:'),
              ComboBox('material_id', {m.Name: m.Id for m in materials}),
              Button('Paint All Faces'),
             ]
ff = FlexForm('Paint All Faces', components)


selected_elements = rpw.ui.Selection().elements
if not selected_elements:
    try:
        selected_elements = select_by_category('Pick Elements', 'Structural Framing', 'Structural Columns')
    except Autodesk.Revit.Exceptions.OperationCanceledException:
        sys.exit()

ff.show()
if ff.values:
    with rpw.db.Transaction('Paint faces'):
        for e in selected_elements:
            faces = get_faces(e)
            for face in faces:
                doc.Paint(e.Id, face, ff.values['material_id'])
else:
    sys.exit()
0 Likes
Message 6 of 8

RPTHOMAS108
Mentor
Mentor

Try calling Doc.Regenerate directly after Doc.Paint, which as Revitalizer noted should automatically be called after a transaction.

 

I believe this regeneration method needs to be called within a transaction since it's purpose is to update element information that has not yet been commited. This may rule out an issue with the python transaction context, which I'm also not familiar with.

 

Try it without the wrapper by explicitly ending the transaction yourself, see if that helps (try:/except:/else: structure).

 

 

0 Likes
Message 7 of 8

htlcnn
Enthusiast
Enthusiast

@RPTHOMAS108 as I described, my Paint code worked without doc.Regenerate (please see the video at the first post), but RemovePaint didn't behave the same. I also tried to add doc.Regenerate() before Transaction.Commit(), but there was no change, the graphics still stayed the same until I ran RemovePaint the second time.

0 Likes
Message 8 of 8

Revitalizer
Advisor
Advisor

Hi,

 

another idea:

 

Use a TransactionGroup,

execute your 'remove paint' transaction, then

either do some sort of dummy transaction or

repeat your first transaction.

 

 

Revitalizer




Rudolf Honke
Software Developer
Mensch und Maschine





0 Likes