@@ -16,6 +16,7 @@ namespace GhPython.Component
1616{
1717 public abstract class ScriptingAncestorComponent : SafeComponent
1818 {
19+ static bool g_resources_unpacked = false ;
1920 private readonly StringList m_py_output = new StringList ( ) ; // python output stream is piped here
2021 internal static GrasshopperDocument m_document = new GrasshopperDocument ( ) ;
2122 internal ComponentIOMarshal m_marshal ;
@@ -38,9 +39,81 @@ protected ScriptingAncestorComponent()
3839 {
3940 }
4041
41- public override void AddRuntimeMessage ( GH_RuntimeMessageLevel level , string text )
42+ private static void UnpackScriptResources ( )
4243 {
43- base . AddRuntimeMessage ( level , text ) ;
44+ if ( g_resources_unpacked )
45+ return ;
46+ Guid python_plugin_id = new Guid ( "814d908a-e25c-493d-97e9-ee3861957f49" ) ;
47+ var plugin = Rhino . PlugIns . PlugIn . Find ( python_plugin_id ) ;
48+ if ( plugin == null )
49+ return ;
50+
51+ g_resources_unpacked = true ;
52+
53+ // Unpack ghcomponents.py to the Python plug directory
54+ string settings_directory = plugin . SettingsDirectory ;
55+ string marker_file = Path . Combine ( settings_directory , "ghpy_version.txt" ) ;
56+ try
57+ {
58+ if ( File . Exists ( marker_file ) )
59+ {
60+ string text = File . ReadAllText ( marker_file ) ;
61+ Version markedversion = new Version ( text ) ;
62+ Version this_version = typeof ( ZuiPythonComponent ) . Assembly . GetName ( ) . Version ;
63+ if ( markedversion == this_version )
64+ {
65+ #if ! DEBUG
66+ // everything looks good, bail out
67+ return ;
68+ #endif
69+ }
70+ }
71+ }
72+ catch ( Exception ex )
73+ {
74+ HostUtils . ExceptionReport ( ex ) ;
75+ }
76+
77+ try
78+ {
79+ // if we get to here, we need to unpack the resources
80+ if ( ! Directory . Exists ( settings_directory ) )
81+ Directory . CreateDirectory ( settings_directory ) ;
82+ string ghpython_package_dir = Path . Combine ( settings_directory , "lib" , "ghpython" ) ;
83+ if ( Directory . Exists ( ghpython_package_dir ) )
84+ Directory . Delete ( ghpython_package_dir , true ) ;
85+ Directory . CreateDirectory ( ghpython_package_dir ) ;
86+ System . Reflection . Assembly a = typeof ( ZuiPythonComponent ) . Assembly ;
87+ string [ ] names = a . GetManifestResourceNames ( ) ;
88+
89+ const string prefix = "GhPython.package." ;
90+
91+ foreach ( string name in names )
92+ {
93+ if ( ! name . StartsWith ( prefix , StringComparison . InvariantCultureIgnoreCase ) )
94+ continue ;
95+
96+ Stream resource_stream = a . GetManifestResourceStream ( name ) ;
97+ if ( resource_stream == null )
98+ continue ;
99+ StreamReader stream = new StreamReader ( resource_stream ) ;
100+ string s = stream . ReadToEnd ( ) ;
101+ stream . Close ( ) ;
102+ string filename = name . Replace ( prefix , "" ) ;
103+ string path = Path . Combine ( ghpython_package_dir , filename ) ;
104+ File . WriteAllText ( path , s ) ;
105+ }
106+
107+ // Write the marker file at the very end to ensure that we actually got to this point.
108+ // If an exception occured for some reason like a file was in use, then the plug-in
109+ // will just attempt to unpack the resources next time.
110+ string str = a . GetName ( ) . Version . ToString ( ) ;
111+ File . WriteAllText ( marker_file , str ) ;
112+ }
113+ catch ( Exception ex )
114+ {
115+ HostUtils . DebugString ( "Exception while unpacking resources: " + ex . Message ) ;
116+ }
44117 }
45118
46119 protected override void Initialize ( )
@@ -53,6 +126,7 @@ protected override void Initialize()
53126 m_py = PythonScript . Create ( ) ;
54127 if ( m_py != null )
55128 {
129+ UnpackScriptResources ( ) ;
56130 SetScriptTransientGlobals ( ) ;
57131 m_py . Output = m_py_output . Write ;
58132 m_py . SetVariable ( "__name__" , "__main__" ) ;
@@ -243,16 +317,16 @@ private static Param_String ConstructOutOutputParam()
243317
244318 #region Solving
245319
246- protected override void SafeSolveInstance ( IGH_DataAccess DA )
320+ protected override void SafeSolveInstance ( IGH_DataAccess da )
247321 {
248322 if ( m_py == null )
249323 {
250- DA . SetData ( 0 , "No Python engine available. This component needs Rhino v5" ) ;
324+ da . SetData ( 0 , "No Python engine available. This component needs Rhino v5" ) ;
251325 return ;
252326 }
253327
254328 if ( ! HiddenOutOutput )
255- DA . DisableGapLogic ( 0 ) ;
329+ da . DisableGapLogic ( 0 ) ;
256330
257331 m_py_output . Reset ( ) ;
258332
@@ -277,7 +351,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
277351 for ( int i = showing_code_input ? 1 : 0 ; i < Params . Input . Count ; i ++ )
278352 {
279353 string varname = Params . Input [ i ] . NickName ;
280- object o = m_marshal . GetInput ( DA , i ) ;
354+ object o = m_marshal . GetInput ( da , i ) ;
281355 m_py . SetVariable ( varname , o ) ;
282356 m_py . SetIntellisenseVariable ( varname , o ) ;
283357 }
@@ -291,7 +365,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
291365 else
292366 {
293367 script = null ;
294- DA . GetData ( 0 , ref script ) ;
368+ da . GetData ( 0 , ref script ) ;
295369 }
296370
297371 if ( string . IsNullOrWhiteSpace ( script ) )
@@ -325,7 +399,7 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
325399 {
326400 string varname = Params . Output [ i ] . NickName ;
327401 object o = m_py . GetVariable ( varname ) ;
328- m_marshal . SetOutput ( o , DA , i ) ;
402+ m_marshal . SetOutput ( o , da , i ) ;
329403 }
330404 }
331405 else
@@ -336,15 +410,15 @@ protected override void SafeSolveInstance(IGH_DataAccess DA)
336410 catch ( Exception ex )
337411 {
338412 AddErrorNicely ( m_py_output , ex ) ;
339- SetFormErrorOrClearIt ( DA , m_py_output ) ;
413+ SetFormErrorOrClearIt ( da , m_py_output ) ;
340414 throw ;
341415 }
342416 finally
343417 {
344418 if ( rhdoc != null && prevEnabled != rhdoc . Views . RedrawEnabled )
345419 rhdoc . Views . RedrawEnabled = true ;
346420 }
347- SetFormErrorOrClearIt ( DA , m_py_output ) ;
421+ SetFormErrorOrClearIt ( da , m_py_output ) ;
348422 }
349423
350424 private bool AddLocalPath ( out string location )
0 commit comments