Reset Light Sources

Here is a simple macro which gives you the power to easily reset your light sources within a SOLIDWORKS Part or Assembly model by deleting the current light sources and adding back the ‘default’ (user specified) light sources.

Option Explicit
Sub main()
 
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swModelDocExt As SldWorks.ModelDocExtension
 
    ' Get SolidWorks Application
    Set swApp = Application.SldWorks
    ' Get active model document
    Set swModel = swApp.ActiveDoc
 
    ' Check for active document and if document is a Assembly or Part
    If swModel Is Nothing Then End
    If swModel.GetType <> swDocASSEMBLY And swModel.GetType <> swDocPART Then End
    Set swModelDocExt = swModel.Extension
 
    ' Delete current lights
    DeleleteLights swModel

    ' Add a directional light source
    SetAmbiantLightSource swModel, True, RGB(255, 255, 255), 0.3
    AddDirectionalLight swModel, "Directional1", True, RGB(255, 255, 255), 0.1, 0.3, 0.3, True, 90, 45
    AddDirectionalLight swModel, "Directional2", True, RGB(255, 255, 255), 0, 0.1, 0.3, True, -154.41, 37.77
    AddDirectionalLight swModel, "Directional3", True, RGB(255, 255, 255), 0, 0.2, 0.3, True, -101.07, 19.94
 
    ' Rebuild model to show light
    swModelDocExt.EditRebuildAll
 
End Sub

Function DeleleteLights(swModel As SldWorks.ModelDoc2)
    Dim i As Integer
    For i = swModel.GetLightSourceCount - 1 To 0 Step -1
        swModel.DeleteLightSource i
    Next i
End Function

Function AddDirectionalLight( _
    swModel As SldWorks.ModelDoc2, _
    LightName As String, _
    OnInSolidWorks As Boolean, _
    Color As Long, _
    Ambient As Double, _
    Brightness As Double, _
    Specularity As Double, _
    LockToModel As Boolean, _
    Longitude As Double, _
    Latitude As Double _
    )
    Dim X As Double, Y As Double, Z As Double
                             
    GetCartesianCoordinates Longitude, Latitude, X, Y, Z
 
    swModel.AddLightSource LightName, 4, LightName
    swModel.SetLightSourcePropertyValuesVB LightName, 4, Brightness, Color, 1, X, Y, Z, 0, 0, 0, 0, 0, 0, 0, Ambient, Specularity, 0, Not OnInSolidWorks
    swModel.LockLightToModel swModel.GetLightSourceCount - 1, LockToModel

End Function

Function GetCartesianCoordinates(ByVal Longitude As Double, ByVal Latitude As Double, ByRef X As Double, ByRef Y As Double, ByRef Z As Double)
    Longitude = (Longitude * (3.14159265359 / 180))
    Latitude = (Latitude * (3.14159265359 / 180))
    X = Cos(Latitude) * Sin(Longitude)
    Z = Cos(Latitude) * Cos(Longitude)
    Y = Sin(Latitude)
End Function

Function SetAmbiantLightSource(swModel As SldWorks.ModelDoc2, OnInSolidWorks As Boolean, Color As Long, Ambient As Double)
    swModel.SetLightSourcePropertyValuesVB swModel.GetLightSourceName(0), 1, 0, Color, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Ambient, 0, 0, Not OnInSolidWorks
End Function

Thank you. I was just going to start asking about / looking for such a macro. oa

I wrote a similar one that deletes all lights and sets ambient to 1. Now all our parts that are the same material look the same.

I find 1 to be a bit too bright, but I am doing the same thing.

Stefan

Your Reset Light Sources works well, is just what I need. I tried to add some lines to turn the background to “none”, but clearly I don’t know what I’m doing. Could you suggess some lines to add, maybe also set the rest of the “scene” basics?

Thanks

Dwight

What doesn’t work:

Sub main()

Dim swApp As SldWorks.SldWorks
Dim swModel As SldWorks.ModelDoc2
Dim swModelDocExt As SldWorks.ModelDocExtension

’ Get SolidWorks Application
Set swApp = Application.SldWorks
’ Get active model document
Set swModel = swApp.ActiveDoc

’ Check for active document and if document is a Assembly or Part
If swModel Is Nothing Then End
If swModel.GetType <> swDocASSEMBLY And swModel.GetType <> swDocPART Then End
Set swModelDocExt = swModel.Extension

’ Delete current lights
DeleleteLights swModel

’ Add a directional light source
SetAmbiantLightSource swModel, True, RGB(255, 255, 255), 0.5
AddDirectionalLight swModel, “Directional1”, True, RGB(255, 255, 255), 0, 0.5, 0.3, False, -20, 30
AddDirectionalLight swModel, “Directional2”, True, RGB(255, 255, 255), 0, 0.1, 0.3, False, -180, 45

’ Set Background to none
Set Scene.BackgroundType = “none”

’ Rebuild model to show light
swModelDocExt.EditRebuildAll

End Sub

Replace

Set Scene.BackgroundType = “none”

with

Dim swConfig As SldWorks.Configuration
Set swConfig = swModel.GetActiveConfiguration

Dim Scene As SldWorks.SWScene
Set Scene = swConfig.GetScene

Scene.BackgroundType = 0

Thanks very much, Deepak, that worked just right.

Dwight

Actually, not quite. All works except that the . . .

Scene.BackgroundType = 0

. . . does work but doesn’t stick. If I change configurations, the background will revert to its previous state. I searched a little, got a clue, and found that . . .

Scene.BackgroundType = swSceneBackgroundType_e.swBackgroundType_None

. . . works and does stick.

Dwight

But . . . you have to do that for each configuration. That seems odd because when you open the scene properties window and edit it there, the setting applies to all the configurations. I didn’t know you could even have different scenes for different configurations.

Dwight

Hi Dwight, use this code instead. It will set the Scene background type to none for each configuration.

    Dim vConfigName As Variant
    For Each vConfigName In swModel.GetConfigurationNames
        swModel.GetConfigurationByName(vConfigName).GetScene.BackgroundType = 0
    Next vConfigName

It’s bit strange indeed, because display states can also have different scene settings, but via the API there are no scene option under the display states.
changing the scene via the configuration seems to override all linked display states.

Stefan

Thanks, that does it, works efficiently.

Dwight

This is failing for me in many cases (Run-time error ‘91’:Object variable or With block variable not set). I tried to dive in a little and quickly got lost. I’ll try to follow up on a hint if anyone has a hint.

Thanks

Dwight

Do the parts that fail have more than 1 configuration?

Dwight, have you set swModel to something earlier?

    Dim swApp                   As SldWorks.SldWorks
    Dim swModel                 As SldWorks.ModelDoc2
    Dim vConfigName 		As Variant

    Set swApp = Application.SldWorks
    Set swModel = swApp.ActiveDoc
    For Each vConfigName In swModel.GetConfigurationNames
        swModel.GetConfigurationByName(vConfigName).GetScene.BackgroundType = 0
    Next vConfigName

Yes. Here’s the whole thing . . .

Option Explicit

Sub main()
 
    Dim swApp As SldWorks.SldWorks
    Dim swModel As SldWorks.ModelDoc2
    Dim swModelDocExt As SldWorks.ModelDocExtension
 
    ' Get SolidWorks Application
    Set swApp = Application.SldWorks
    ' Get active model document
    Set swModel = swApp.ActiveDoc
 
    ' Check for active document and if document is a Assembly or Part
    If swModel Is Nothing Then End
    If swModel.GetType <> swDocASSEMBLY And swModel.GetType <> swDocPART Then End
    Set swModelDocExt = swModel.Extension
 
    ' Delete current lights
    DeleleteLights swModel

    ' Add a directional light source
    SetAmbiantLightSource swModel, True, RGB(255, 255, 255), 0.6
    AddDirectionalLight swModel, "Directional1", True, RGB(255, 255, 255), 0, 0.4, 0.3, False, -20, 25
    AddDirectionalLight swModel, "Directional2", True, RGB(255, 255, 255), 0, 0.1, 0.3, False, -180, 45
    
    ' Set background to none
    Dim vConfigName As Variant
    For Each vConfigName In swModel.GetConfigurationNames
        swModel.GetConfigurationByName(vConfigName).GetScene.BackgroundType = 0
    Next vConfigName
   
    ' Rebuild model to show light
    swModelDocExt.EditRebuildAll
 
End Sub

Function DeleleteLights(swModel As SldWorks.ModelDoc2)
    Dim i As Integer
    For i = swModel.GetLightSourceCount - 1 To 0 Step -1
        swModel.DeleteLightSource i
    Next i
End Function

Function AddDirectionalLight( _
    swModel As SldWorks.ModelDoc2, _
    LightName As String, _
    OnInSolidWorks As Boolean, _
    Color As Long, _
    Ambient As Double, _
    Brightness As Double, _
    Specularity As Double, _
    LockToModel As Boolean, _
    Longitude As Double, _
    Latitude As Double _
    )
    Dim X As Double, Y As Double, Z As Double
                             
    GetCartesianCoordinates Longitude, Latitude, X, Y, Z
 
    swModel.AddLightSource LightName, 4, LightName
    swModel.SetLightSourcePropertyValuesVB LightName, 4, Brightness, Color, 1, X, Y, Z, 0, 0, 0, 0, 0, 0, 0, Ambient, Specularity, 0, Not OnInSolidWorks
    swModel.LockLightToModel swModel.GetLightSourceCount - 1, LockToModel

End Function

Function GetCartesianCoordinates(ByVal Longitude As Double, ByVal Latitude As Double, ByRef X As Double, ByRef Y As Double, ByRef Z As Double)
    Longitude = (Longitude * (3.14159265359 / 180))
    Latitude = (Latitude * (3.14159265359 / 180))
    X = Cos(Latitude) * Sin(Longitude)
    Z = Cos(Latitude) * Cos(Longitude)
    Y = Sin(Latitude)
End Function

Function SetAmbiantLightSource(swModel As SldWorks.ModelDoc2, OnInSolidWorks As Boolean, Color As Long, Ambient As Double)
    swModel.SetLightSourcePropertyValuesVB swModel.GetLightSourceName(0), 1, 0, Color, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Ambient, 0, 0, Not OnInSolidWorks
End Function

Based on the error, it is trying to perform an action on something with an invalid index. If I give you three apples, and then tell you to take the 4th apple and cut it in half, you’re going to look at me like I’m stupid.

My guess is it is one of these lines:

   For i = swModel.GetLightSourceCount - 1 To 0 Step -1
        swModel.DeleteLightSource i
    Next i

Somehow “i” would have to get an invalid value. I tried to get this to fail, but couldn’t.

    For Each vConfigName In swModel.GetConfigurationNames
        swModel.GetConfigurationByName(vConfigName).GetScene.BackgroundType = 0
    Next vConfigName

Somehow the code is referencing a configuration that doesn’t exist.

Function SetAmbiantLightSource(swModel As SldWorks.ModelDoc2, OnInSolidWorks As Boolean, Color As Long, Ambient As Double)
    swModel.SetLightSourcePropertyValuesVB swModel.GetLightSourceName(0), 1, 0, Color, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, Ambient, 0, 0, Not OnInSolidWorks
End Function

This could create an error if an invalid value was passed to the function.


The code should stop and highlight the line where the error occurs, which would help sort out the issues. (You might have to have the editor open for that to happen.) Knowing where the problem lies would help diagnose the issue.

I was able to get it to fail with an assembly. It is failing here, but I cannot figure out why:

For Each vConfigName In swModel.GetConfigurationNames
        swModel.GetConfigurationByName(vConfigName).GetScene.BackgroundType = 0
    Next vConfigName

SPerman

Thanks very much for digging into this. All the code for changing the lights was taken from another macro. I just added the part that sets the background to zero.

I find now that it works on some models with more than one configuration and not on others with more than one configuration. I use the edit function offered in Solidworks, which opens Microsoft Visual Basic. When it fails, I can F8 step by step, and it stops the first time it hits the GetConfigurationByName line. In the window showing “Locals” the vConfigName equals “Default”, which is one of the configiurations.

I will try to get a better idea which files work and which don’t.

Dwight

At this point, my recommendation would be to break this down into smaller steps, to try and understand what exactly is failing.


For Each vConfigName In swModel.GetConfigurationNames
swModel.GetConfigurationByName(vConfigName).GetScene.BackgroundType = 0
Next vConfigName

This could be broken into:
Get configuration
Get scene
Set background

All 3 of those things are happening in a single line, which is efficient, but difficult to debug.

Good luck!