@@ -17,6 +17,7 @@ namespace GhPython.Component
1717{
1818 public abstract class ScriptingAncestorComponent : SafeComponent
1919 {
20+ static bool g_resources_unpacked = false ;
2021 private readonly StringList m_py_output = new StringList ( ) ; // python output stream is piped here
2122 internal static GrasshopperDocument m_document = new GrasshopperDocument ( ) ;
2223 internal ComponentIOMarshal m_marshal ;
@@ -39,9 +40,81 @@ protected ScriptingAncestorComponent()
3940 {
4041 }
4142
42- public override void AddRuntimeMessage ( GH_RuntimeMessageLevel level , string text )
43+ private static void UnpackScriptResources ( )
4344 {
44- base . AddRuntimeMessage ( level , text ) ;
45+ if ( g_resources_unpacked )
46+ return ;
47+ Guid python_plugin_id = new Guid ( "814d908a-e25c-493d-97e9-ee3861957f49" ) ;
48+ var plugin = Rhino . PlugIns . PlugIn . Find ( python_plugin_id ) ;
49+ if ( plugin == null )
50+ return ;
51+
52+ g_resources_unpacked = true ;
53+
54+ // Unpack ghcomponents.py to the Python plug directory
55+ string settings_directory = plugin . SettingsDirectory ;
56+ string marker_file = Path . Combine ( settings_directory , "ghpy_version.txt" ) ;
57+ try
58+ {
59+ if ( File . Exists ( marker_file ) )
60+ {
61+ string text = File . ReadAllText ( marker_file ) ;
62+ Version markedversion = new Version ( text ) ;
63+ Version this_version = typeof ( ZuiPythonComponent ) . Assembly . GetName ( ) . Version ;
64+ if ( markedversion == this_version )
65+ {
66+ #if ! DEBUG
67+ // everything looks good, bail out
68+ return ;
69+ #endif
70+ }
71+ }
72+ }
73+ catch ( Exception ex )
74+ {
75+ HostUtils . ExceptionReport ( ex ) ;
76+ }
77+
78+ try
79+ {
80+ // if we get to here, we need to unpack the resources
81+ if ( ! Directory . Exists ( settings_directory ) )
82+ Directory . CreateDirectory ( settings_directory ) ;
83+ string ghpython_package_dir = Path . Combine ( settings_directory , "lib" , "ghpython" ) ;
84+ if ( Directory . Exists ( ghpython_package_dir ) )
85+ Directory . Delete ( ghpython_package_dir , true ) ;
86+ Directory . CreateDirectory ( ghpython_package_dir ) ;
87+ System . Reflection . Assembly a = typeof ( ZuiPythonComponent ) . Assembly ;
88+ string [ ] names = a . GetManifestResourceNames ( ) ;
89+
90+ const string prefix = "GhPython.package." ;
91+
92+ foreach ( string name in names )
93+ {
94+ if ( ! name . StartsWith ( prefix , StringComparison . InvariantCultureIgnoreCase ) )
95+ continue ;
96+
97+ Stream resource_stream = a . GetManifestResourceStream ( name ) ;
98+ if ( resource_stream == null )
99+ continue ;
100+ StreamReader stream = new StreamReader ( resource_stream ) ;
101+ string s = stream . ReadToEnd ( ) ;
102+ stream . Close ( ) ;
103+ string filename = name . Replace ( prefix , "" ) ;
104+ string path = Path . Combine ( ghpython_package_dir , filename ) ;
105+ File . WriteAllText ( path , s ) ;
106+ }
107+
108+ // Write the marker file at the very end to ensure that we actually got to this point.
109+ // If an exception occured for some reason like a file was in use, then the plug-in
110+ // will just attempt to unpack the resources next time.
111+ string str = a . GetName ( ) . Version . ToString ( ) ;
112+ File . WriteAllText ( marker_file , str ) ;
113+ }
114+ catch ( Exception ex )
115+ {
116+ HostUtils . DebugString ( "Exception while unpacking resources: " + ex . Message ) ;
117+ }
45118 }
46119
47120 protected override void Initialize ( )
@@ -54,6 +127,7 @@ protected override void Initialize()
54127 m_py = PythonScript . Create ( ) ;
55128 if ( m_py != null )
56129 {
130+ UnpackScriptResources ( ) ;
57131 SetScriptTransientGlobals ( ) ;
58132 m_py . Output = m_py_output . Write ;
59133 m_py . SetVariable ( "__name__" , "__main__" ) ;
@@ -244,16 +318,16 @@ private static Param_String ConstructOutOutputParam()
244318
245319 #region Solving
246320
247- protected override void SafeSolveInstance ( IGH_DataAccess DA )
321+ protected override void SafeSolveInstance ( IGH_DataAccess da )
248322 {
249323 if ( m_py == null )
250324 {
251- DA . SetData ( 0 , "No Python engine available. This component needs Rhino v5" ) ;
325+ da . SetData ( 0 , "No Python engine available. This component needs Rhino v5" ) ;
252326 return ;
253327 }
254328
255329 if ( ! HiddenOutOutput )
256- DA . DisableGapLogic ( 0 ) ;
330+ da . DisableGapLogic ( 0 ) ;
257331
258332 m_py_output . Reset ( ) ;
259333
@@ -278,7 +352,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
278352 for ( int i = showing_code_input ? 1 : 0 ; i < Params . Input . Count ; i ++ )
279353 {
280354 string varname = Params . Input [ i ] . NickName ;
281- object o = m_marshal . GetInput ( DA , i ) ;
355+ object o = m_marshal . GetInput ( da , i ) ;
282356 m_py . SetVariable ( varname , o ) ;
283357 m_py . SetIntellisenseVariable ( varname , o ) ;
284358 }
@@ -292,7 +366,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
292366 else
293367 {
294368 script = null ;
295- DA . GetData ( 0 , ref script ) ;
369+ da . GetData ( 0 , ref script ) ;
296370 }
297371
298372 if ( string . IsNullOrWhiteSpace ( script ) )
@@ -326,7 +400,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
326400 {
327401 string varname = Params . Output [ i ] . NickName ;
328402 object o = m_py . GetVariable ( varname ) ;
329- m_marshal . SetOutput ( o , DA , i ) ;
403+ m_marshal . SetOutput ( o , da , i ) ;
330404 }
331405 }
332406 else
@@ -337,15 +411,15 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
337411 catch ( Exception ex )
338412 {
339413 AddErrorNicely ( m_py_output , ex ) ;
340- SetFormErrorOrClearIt ( DA , m_py_output ) ;
414+ SetFormErrorOrClearIt ( da , m_py_output ) ;
341415 throw ;
342416 }
343417 finally
344418 {
345419 if ( rhdoc != null && prevEnabled != rhdoc . Views . RedrawEnabled )
346420 rhdoc . Views . RedrawEnabled = true ;
347421 }
348- SetFormErrorOrClearIt ( DA , m_py_output ) ;
422+ SetFormErrorOrClearIt ( da , m_py_output ) ;
349423 }
350424
351425 private bool AddLocalPath ( out string path )
0 commit comments