Skip to content

refactor: Rewrite Loader in C# #2647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 64 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
0ecc3de
feat: add pyRevitAssemblyBuilder project to the Loader solution
romangolev Apr 10, 2025
723821c
feat: make assembly put dlls in a correct folder, scanning all availa…
romangolev Apr 11, 2025
355f92e
feat: implement recursive UI builder
romangolev Apr 11, 2025
847c246
fix: UIManagerServite to handle stacked pulldowns correctly
romangolev Apr 14, 2025
fc104aa
feat: update build dlls
romangolev Apr 14, 2025
f659f49
feat: replace DI architecture with plain intantiating of services. re…
romangolev Apr 16, 2025
c916a4a
feat: implement pyRevitExtensionParser csproject
romangolev Apr 18, 2025
aa4fc9d
feat: update dlls
romangolev Apr 18, 2025
aea0787
feat: change unique id to mimic pythonic one, add logic to CommandTyp…
romangolev Apr 18, 2025
41a5955
feat: change assembly generation module to Roslyn
romangolev Apr 20, 2025
2fc4643
feat: mvp c# loader
romangolev Apr 21, 2025
81efe9a
fix: move enums to parser, simplify code by removing wraps
romangolev Apr 23, 2025
3886911
undate binaries
romangolev Apr 23, 2025
038fd01
Switch for .net core Desktop connector API
jmcouffin Apr 11, 2025
e93db34
fix: is_schedule
leyarx Apr 11, 2025
ae30736
Update pyrevit-hosts.json 2026.0.1
jmcouffin Apr 14, 2025
bb06cdc
Update Directory.Build.targets
jmcouffin Apr 14, 2025
987570d
upd
nodatasheet Feb 8, 2024
4ead9b0
add Associated to Others to select_family_parameters
nodatasheet Apr 12, 2025
b6dda98
cleanup
nodatasheet Apr 12, 2025
2972ffc
Update __init__.py
jmcouffin Apr 14, 2025
0ba9785
Adding exitscript option to SelectFromList from pyrevit.forms
iorhanV Apr 10, 2025
52b9424
Update __init__.py - exitscritp handeled in show method
jmcouffin Apr 14, 2025
7f5eadb
Bump golang.org/x/crypto
dependabot[bot] Apr 14, 2025
3fb7b20
fixes commit f81f483
jmcouffin Apr 16, 2025
db6510d
Update __init__.py
jmcouffin Apr 16, 2025
736cfed
Update go.mod mongodb driver
jmcouffin Apr 16, 2025
6ccc8c1
Update go.mod
jmcouffin Apr 16, 2025
8ae818e
missing comma in the docs for CommandSwitchWindow
jonatanjacobsson Apr 17, 2025
4e98317
feat: add pyRevitAssemblyBuilder project to the Loader solution
romangolev Apr 10, 2025
80f6ccf
feat: make assembly put dlls in a correct folder, scanning all availa…
romangolev Apr 11, 2025
1d6da91
feat: implement recursive UI builder
romangolev Apr 11, 2025
fa8fc2b
fix: UIManagerServite to handle stacked pulldowns correctly
romangolev Apr 14, 2025
ba7d564
feat: update build dlls
romangolev Apr 14, 2025
6964633
feat: replace DI architecture with plain intantiating of services. re…
romangolev Apr 16, 2025
46bdaa9
feat: implement pyRevitExtensionParser csproject
romangolev Apr 18, 2025
0546001
feat: update dlls
romangolev Apr 18, 2025
cffdb8a
feat: change unique id to mimic pythonic one, add logic to CommandTyp…
romangolev Apr 18, 2025
b686515
feat: change assembly generation module to Roslyn
romangolev Apr 20, 2025
33b3d75
feat: mvp c# loader
romangolev Apr 21, 2025
18ecf76
fix: move enums to parser, simplify code by removing wraps
romangolev Apr 23, 2025
e8e445a
undate binaries
romangolev Apr 23, 2025
4acf0a9
feat: add a switcher in settings to be able to toglle between python …
romangolev Apr 24, 2025
84ee64b
update dlls
romangolev Apr 24, 2025
1c90cac
merge conflict
romangolev Apr 24, 2025
1b92a55
fix: remove unused dlls
romangolev Apr 25, 2025
f408e57
feat: get back ILPack method for generating assemblies, make a switch…
romangolev Apr 25, 2025
869ed85
update dlls
romangolev Apr 25, 2025
27ca06d
feat: implement availability class generator
romangolev May 3, 2025
2f9b799
fix: improve parsing logic, move command collector to ParsedExtension…
romangolev May 3, 2025
88f0223
upd dlls
romangolev May 3, 2025
b202aa1
feat: parse bundle.yaml and reorder UI Components
romangolev May 6, 2025
525f2f6
fix: use Display name insted of truncated Name for ParsedComponents
romangolev May 7, 2025
3e8596d
feat: add testing bench for parser; add support for slideout
romangolev May 14, 2025
3ca0f22
fix: make sure UI is generated correctly and buttons are executed
romangolev May 15, 2025
faaa8e6
add 2 swichable parameters to settings
romangolev Jun 12, 2025
f785799
fix: clean-up and use config files only
romangolev Jun 16, 2025
aef99de
feat: add support for PanelButtons
romangolev Jun 24, 2025
1f65b01
update dlls
romangolev Jun 24, 2025
1a6ff56
feat: parse title and name with ExtensionParser
romangolev Jul 5, 2025
b46c55b
chore: make a parser for extensions, move config to ExtensionParser
romangolev Jul 6, 2025
b999f2f
fix: read parsed data from script.py correctly
romangolev Jul 8, 2025
ad13740
chore: support parsing for some other configs, split config in 2 files
romangolev Jul 8, 2025
185b0e2
chore: refactor ExtensionParser and implement the logic for loading c…
romangolev Jul 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified bin/netcore/engines/IPY342/pyRevitLoader.dll
Binary file not shown.
Binary file modified bin/netcore/engines/IPY342/pyRevitRunner.dll
Binary file not shown.
Binary file modified bin/netcore/pyRevitLabs.PyRevit.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added bin/netfx/engines/IPY342/System.ValueTuple.dll
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file modified bin/netfx/engines/IPY342/pyRevitLoader.dll
Binary file not shown.
Binary file modified bin/netfx/engines/IPY342/pyRevitRunner.dll
Binary file not shown.
Binary file modified bin/netfx/pyRevitLabs.PyRevit.dll
Binary file not shown.
Binary file modified bin/pyRevitLabs.PyRevit.dll
Binary file not shown.
2 changes: 0 additions & 2 deletions dev/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Library</OutputType>
<!-- <TargetFramework>net48</TargetFramework>-->
<!-- <TargetFrameworks>net48;net8.0-windows</TargetFrameworks>-->
<PlatformTarget>x64</PlatformTarget>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
Expand Down
6 changes: 6 additions & 0 deletions dev/pyRevitLabs/pyRevitLabs.PyRevit/PyRevitConsts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ public static class PyRevitConsts {
public const string BundleScriptGrasshopperXPostfix = ".ghx";
public const string BundleScriptRevitFamilyPostfix = ".rfa";

// loader settings
public const string ConfigsNewLoaderKey = "new_loader";
public const bool ConfigsNewLoaderDefault = false;
public const string ConfigsUseRoslynKey = "use_roslyn_loader";
public const bool ConfigsUseRoslynDefault = false;

// theme
public static SolidColorBrush PyRevitAccentBrush = new SolidColorBrush(Color.FromArgb(0xFF, 0xf3, 0x9c, 0x12));
public static SolidColorBrush PyRevitBackgroundBrush = new SolidColorBrush(Color.FromArgb(0xFF, 0x2c, 0x3e, 0x50));
Expand Down
4 changes: 2 additions & 2 deletions dev/pyRevitLoader/Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PropertyGroup Condition="'$(MSBuildProjectName)' != 'pyRevitAssemblyBuilder'">
<UseRevit>true</UseRevit>
<UseWpf>true</UseWpf>
<UseWindowsForms>true</UseWindowsForms>
<UseAssemblyBuilder>true</UseAssemblyBuilder>
<TargetFrameworks>net48;net8.0-windows</TargetFrameworks>

<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
</PropertyGroup>

Expand Down
31 changes: 24 additions & 7 deletions dev/pyRevitLoader/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<None Remove="obj\**" />
</ItemGroup>

<ItemGroup Condition="$(UseRunner)=='' OR $(UseRunner)==False">
<ItemGroup Condition="$(UseLoader)==True">
<Compile Include="..\Source\PyRevitLoaderApplication.cs" Link="Source\PyRevitLoaderApplication.cs"/>
<Compile Include="..\Source\ScriptExecutor.cs" Link="Source\ScriptExecutor.cs"/>
</ItemGroup>
Expand All @@ -17,7 +17,7 @@
<Compile Include="..\Source\ScriptExecutor.cs" Link="Source\ScriptExecutor.cs"/>
</ItemGroup>

<ItemGroup Condition="$(IronPythonVersion.Contains('PR'))">
<ItemGroup Condition="'$(UseIronPython)' != 'false' AND $(IronPythonVersion.Contains('PR'))">
<Reference Include="IronPython" HintPath="$(PyRevitEnginesDir)\$(IronPythonVersion)\pyRevitLabs.IronPython.dll"/>
<Reference Include="IronPython.Modules" HintPath="$(PyRevitEnginesDir)\$(IronPythonVersion)\pyRevitLabs.IronPython.Modules.dll"/>
<Reference Include="IronPython.SQLite" HintPath="$(PyRevitEnginesDir)\$(IronPythonVersion)\pyRevitLabs.IronPython.SQLite.dll"/>
Expand All @@ -26,22 +26,39 @@
<Reference Include="Microsoft.Scripting" HintPath="$(PyRevitEnginesDir)\$(IronPythonVersion)\pyRevitLabs.Microsoft.Scripting.dll"/>
</ItemGroup>

<ItemGroup Condition="!$(IronPythonVersion.Contains('PR'))">
<ItemGroup Condition="'$(UseIronPython)' != 'false' AND !$(IronPythonVersion.Contains('PR'))">
<PackageReference Include="IronPython" Version="$(Version)"/>
</ItemGroup>

<ItemGroup>
<Reference Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" Include="Microsoft.CSharp"/>
</ItemGroup>

<ItemGroup>

<ItemGroup Condition="'$(UseAssemblyBuilder)' == 'true'">
<ProjectReference Include="..\pyRevitAssemblyBuilder\pyRevitAssemblyBuilder.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(UseExtensionParser)' == 'true'">
<ProjectReference Include="..\pyRevitExtensionParser\pyRevitExtensionParser.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(UseIronPython)' != 'false'">
<EmbeddedResource Include="$(IronPythonStdLibDir)\$(IronPythonStdLib)"/>
</ItemGroup>


<ItemGroup Condition="'$(UseRoslyn)' == 'true'">
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.13.0" />
</ItemGroup>

<ItemGroup Condition="'$(UseILPack)' == 'true'">
<PackageReference Include="Lokad.ILPack" Version="0.3.0" ExcludeAssets="runtime" />
</ItemGroup>

<Target Name="Deploy" AfterTargets="AfterBuild">
<ItemGroup>
<AllFilesToCopy Include="$(TargetDir)\**\*.dll"
Exclude="$(TargetDir)\**\Xceed.Wpf.AvalonDock.dll" />
Exclude="$(TargetDir)\**\Xceed.Wpf.AvalonDock.dll"
Condition="'$(IsTestProject)' != 'true'"/>
</ItemGroup>
<Copy SourceFiles="@(AllFilesToCopy)"
DestinationFolder="$(PyRevitEnginesDir)\$(IronPythonVersion)" />
Expand Down
82 changes: 79 additions & 3 deletions dev/pyRevitLoader/Source/PyRevitLoaderApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
using System.Reflection;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;
using pyRevitAssemblyBuilder.AssemblyMaker;
using pyRevitAssemblyBuilder.SessionManager;
using pyRevitExtensionParser.Config;

/* Note:
* It is necessary that this code object do not have any references to IronPython.
Expand All @@ -28,7 +31,21 @@ Result IExternalApplication.OnStartup(UIControlledApplication application)

try
{
return ExecuteStartupScript(application);
// we need a UIApplication object to assign as `__revit__` in python...
var versionNumber = application.ControlledApplication.VersionNumber;
var fieldName = int.Parse(versionNumber) >= 2017 ? "m_uiapplication" : "m_application";
var fi = application.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);

var uiApplication = (UIApplication)fi.GetValue(application);

var executor = new ScriptExecutor(uiApplication);
var result = ExecuteStartupScript(application);
if (result == Result.Failed)
{
TaskDialog.Show("Error Loading pyRevit", executor.Message);
}

return result;
}
catch (Exception ex)
{
Expand All @@ -49,11 +66,28 @@ private static void LoadAssembliesInFolder(string folder)
}
catch
{

}
}
}

private static Result ExecuteStartupScript(UIControlledApplication uiControlledApplication)
{
// defy the method of loading the assembly
// based on the config file setup
var config = PyRevitConfig.Load();
switch (config.NewLoader)
{
case true when config.NewLoaderRoslyn:
return ExecuteStartUpCsharp(uiControlledApplication, AssemblyBuildStrategy.Roslyn);
case true:
return ExecuteStartUpCsharp(uiControlledApplication, AssemblyBuildStrategy.ILPack);
default:
return ExecuteStartUpPython(uiControlledApplication);
}
}

public static Result ExecuteStartUpPython(UIControlledApplication uiControlledApplication)
{
// we need a UIApplication object to assign as `__revit__` in python...
var versionNumber = uiControlledApplication.ControlledApplication.VersionNumber;
Expand All @@ -76,18 +110,60 @@ private static Result ExecuteStartupScript(UIControlledApplication uiControlledA

return result;
}
public static Result ExecuteStartUpCsharp(UIControlledApplication uiControlledApplication, AssemblyBuildStrategy loadingMethod)
{
try
{
var versionNumber = uiControlledApplication.ControlledApplication.VersionNumber;
var fieldName = int.Parse(versionNumber) >= 2017 ? "m_uiapplication" : "m_application";
var fi = uiControlledApplication.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
var uiApplication = (UIApplication)fi.GetValue(uiControlledApplication);

// Instantiate all services
var assemblyBuilder = new AssemblyBuilderService(versionNumber, loadingMethod);
var extensionManager = new ExtensionManagerService();
var hookManager = new HookManager();
var uiManager = new UIManagerService(uiApplication);

var sessionManager = new SessionManagerService(
assemblyBuilder,
extensionManager,
hookManager,
uiManager
);

sessionManager.LoadSession();

// execute light version of StartupScript python script
Result result = Result.Succeeded;
var startupScript = GetStartupScriptPath();
if (startupScript != null)
{
var executor = new ScriptExecutor(uiApplication); // uiControlledApplication);
result = executor.ExecuteScript(startupScript);
if (result == Result.Failed)
{
TaskDialog.Show("Error Loading pyRevit", executor.Message);
}
}
return Result.Succeeded;
}
catch (Exception ex)
{
TaskDialog.Show("Error Starting pyRevit Session", ex.ToString());
return Result.Failed;
}
}
private static string GetStartupScriptPath()
{
var loaderDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var dllDir = Path.GetDirectoryName(loaderDir);
return Path.Combine(dllDir, string.Format("{0}.py", Assembly.GetExecutingAssembly().GetName().Name));
}

Result IExternalApplication.OnShutdown(UIControlledApplication application)
{
// FIXME: deallocate the python shell...
return Result.Succeeded;
}
}
}
}
Loading