浏览代码

Merge branch 'develop' into develop-tmp

Mark Sibly 7 年之前
父节点
当前提交
56591b069f

+ 2 - 0
.gitignore

@@ -60,3 +60,5 @@ Mollusk.exe
 
 .com.apple.timemachine.supported
 
+.mx2
+

+ 14 - 0
VERSIONS.TXT

@@ -1,4 +1,18 @@
 
+***** Monkey-v2018.06 *****
+
+Added Timeout property to HttpRequest.
+
+Implemented HttpRequest on all targets - only GET tested.
+
+Added cheezy godrays effect - see mojo3d/tests/pbhspheres.monkey2
+
+Fixed deprecated warnings in android project template.
+
+Updated android SDK to: Android Studio 3.1.2 ; Android SDK 27 (Oreo 8.1) ; NDK 16.1.4479499 ; Android SDK Tools 26.1.1
+
+Point/spot light now render quads.
+
 ***** Monkey-v2018.05 Mx2cc-v1.1.13 Ted2go-2.10 *****
 
 Added simple support for .hdr pixmap/texture/image loading (wont work on android).

+ 42 - 16
bananas/httprequest/httprequest_test.monkey2

@@ -3,43 +3,69 @@ Namespace myapp
 
 #Import "<std>"
 #Import "<mojo>"
+#Import "<mojox>"
 #Import "<httprequest>"
 
 Using std..
 Using mojo..
+Using mojox..
 Using httprequest..
 
 Class MyWindow Extends Window
 	
-	Field req:HttpRequest
-
 	Method New( title:String="HttpRequest demo",width:Int=640,height:Int=480,flags:WindowFlags=Null )
 
 		Super.New( title,width,height,flags )
+
+		Layout="letterbox"		
+		
+		Local label:=New Label
 		
-		req=New HttpRequest( "GET","http://www.blitzbasic.com",Lambda()
+		Local req:=New HttpRequest
+		
+		req.Timeout=10
+
+		req.ReadyStateChanged=Lambda()
 		
-			Print "Ready state changed to "+Int( req.ReadyState )
+			label.Text="Ready state changed to "+Int( req.ReadyState )+" status="+req.Status
 			
-			If req.ReadyState=4 
-				Print "ReponseText="+req.ResponseText
-				Print "Status="+req.Status
-			Endif
+			If req.ReadyState=ReadyState.Done Print "Request response:~n"+req.ResponseText
+		End
 		
-		End )
+	#If __TARGET__="emscripten"
+		Const url:="test.txt"
+	#else
+		Const url:="https://www.github.com"
+	#endif
 		
-		New Fiber( Lambda()
+		req.Open( "GET",url )
 		
-			req.Send()
-			
-		End )
+		Local button:=New Button( "CANCEL!" )
+		
+		button.Clicked+=Lambda()
+		
+			req.Cancel()
+		End
+		
+		Local dockingView:=New DockingView
+		
+		dockingView.AddView( label,"top" )
+		
+		dockingView.ContentView=button
+		
+		ContentView=dockingView
+		
+		req.Send()
 	End
-
+	
 	Method OnRender( canvas:Canvas ) Override
 	
-		App.RequestRender()
+		App.RequestRender()	'need this for ios?
+	End
 	
-		canvas.DrawText( "Hello World!",Width/2,Height/2,.5,.5 )
+	Method OnMeasure:Vec2i() Override
+		
+		Return New Vec2i( 320,240 )
 	End
 	
 End

+ 48 - 0
modules/emscripten/emscripten.monkey2

@@ -7,6 +7,7 @@ Namespace emscripten
 #Import "<sdl2>"
 
 #Import "<emscripten.h>"
+#Import "<emscripten/fetch.h>"
 
 Extern
 
@@ -34,4 +35,51 @@ Function emscripten_set_canvas_size:Void( width:Int,height:Int )
 Function emscripten_get_canvas_size:Void( width:Int Ptr,height:Int Ptr,fullScreen:Int Ptr )
 Function emscripten_get_now:Double()
 
+Struct emscripten_fetch_t
+	
+	Field id:UInt
+	Field userData:Void Ptr
+	Field url:CString
+	Field data:libc.char_t Ptr
+	Field numBytes:ULong
+	Field dataOffset:ULong
+	Field totalBytes:ULong
+	Field readyState:UShort
+	Field status:Short
+End
+
+Const EMSCRIPTEN_FETCH_LOAD_TO_MEMORY:UInt
+Const EMSCRIPTEN_FETCH_STREAM_DATA:UInt
+Const EMSCRIPTEN_FETCH_PERSIST_FILE:UInt
+Const EMSCRIPTEN_FETCH_APPEND:UInt
+Const EMSCRIPTEN_FETCH_REPLACE:UInt
+Const EMSCRIPTEN_FETCH_NO_DOWNLOAD:UInt
+Const EMSCRIPTEN_FETCH_SYNCHRONOUS:UInt
+Const EMSCRIPTEN_FETCH_WAITABLE:UInt
+
+Struct emscripten_fetch_attr_t
+	
+	Field requestMethod:libc.char_t Ptr
+	Field userData:Void Ptr
+	Field onsuccess:Void( fetch:emscripten_fetch_t ptr )
+	Field onerror:Void( fetch:emscripten_fetch_t ptr )
+	Field onprogress:Void( fetch:emscripten_fetch_t Ptr )
+	Field attributes:UInt
+	Field timeoutMSecs:UInt
+	Field withCredentials:Bool
+	Field destinationPath:CString
+	Field userName:CString
+	Field password:CString
+	Field requestHeaders:CString Ptr
+	Field overridenMimeType:CString
+	Field requestData:CString
+	Field requestDataSize:UInt
+End
+
+Function emscripten_fetch_attr_init( attr:emscripten_fetch_attr_t Ptr )
+
+Function emscripten_fetch:emscripten_fetch_t Ptr( attr:emscripten_fetch_attr_t Ptr,url:CString )
+
+Function emscripten_fetch_close( fetch:emscripten_fetch_t Ptr )
+
 #Endif

二进制
modules/httprequest/bin/wget.exe


+ 115 - 2
modules/httprequest/httprequest.monkey2

@@ -1,12 +1,125 @@
 
 Namespace httprequest
 
-#If __TARGET__="android"
+#Import "<std>"
 
-#Import "httprequest_android"
+Using std..
+
+#If __TARGET__="windows" Or __TARGET__="linux"
+
+#Import "httprequest_desktop"
+
+#Import "bin/wget.exe"
 
 #Else If __TARGET__="macos" Or  __TARGET__="ios"
 
 #Import "httprequest_ios"
 
+#Elseif __TARGET__="emscripten"
+
+#Import "httprequest_emscripten"
+
+#Elseif __TARGET__="android"
+
+#Import "httprequest_android"
+
 #Endif
+
+Enum ReadyState
+	Unsent=0
+	Opened=1
+	HeadersReceived=2
+	Loading=3
+	Done=4
+	Error=5
+End
+
+Class HttpRequestBase
+	
+	Field ReadyStateChanged:Void()
+	
+	Property Timeout:Float()
+		
+		Return _timeout
+		
+	Setter( timeout:Float )
+		
+		_timeout=timeout
+	End
+	
+	Property ReadyState:ReadyState()
+		
+		Return _readyState
+	End
+	
+	Property ResponseText:String()
+		
+		Return _response
+	End
+	
+	Property Status:Int()
+		
+		Return _status
+	End
+	
+	Method Open( req:String,url:String )
+		
+		OnOpen( req,url )
+	End
+	
+	Method SetHeader( header:String,value:String )
+		
+		OnSetHeader( header,value )
+	End
+	
+	Method Send( text:String="" )
+		
+		OnSend( text )
+	End
+	
+	Method Cancel()
+		
+		OnCancel()
+	End
+	
+	Protected
+	
+	Field _readyState:ReadyState
+	Field _timeout:Float=60.0
+	Field _response:String
+	Field _status:Int=-1
+	Field _req:String
+	Field _url:String
+	
+	Method New()
+		
+		_readyState=ReadyState.Unsent
+		_timeout=10
+		_status=-1
+	End
+	
+	Method OnOpen( req:String,url:String ) Virtual
+		_req=req
+		_url=url
+		SetReadyState( ReadyState.Opened )
+	End
+
+	Method OnSetHeader( header:String,value:String ) Virtual
+	End
+	
+	Method OnSend( text:String ) Abstract
+	
+	Method OnCancel() Virtual
+	End
+	
+	Method SetReadyState( readyState:ReadyState )
+		
+		If readyState=_readyState Return
+		
+		_readyState=readyState
+		
+		ReadyStateChanged()
+	End
+	
+End
+

+ 63 - 139
modules/httprequest/httprequest_android.monkey2

@@ -21,174 +21,102 @@ Global onReadyStateChanged:Void(jobject,Int)="bbHttpRequest::onReadyStateChanged
 
 Global onResponseReceived:Void(jobject,String,Int,Int)="bbHttpRequest::onResponseReceived"
 
-private
-
-Function OnMainFiber( func:Void() )
-	
-	If Fiber.Current()=Fiber.Main() func() Else App.Idle+=func
-	
-End
-
 Public
 
-Enum ReadyState
-	
-	Unsent=0
-	Opened=1
-	HeadersReceived=2
-	Loading=3
-	Done=4
-	Error=5
-
-End
-
-Class HttpRequest
-	
-	Field ReadyStateChanged:Void()
+Class HttpRequest Extends HttpRequestBase
 	
 	Method New()
+		
+		Init()
 
 		Local env:=Android_JNI_GetEnv()
 		
-		Init( env )
-		
 		Local obj:=env.AllocObject( _class )
 		
 		_obj=env.NewGlobalRef( obj )
 		
-		Insert()
+		_requests.Add( Self )
 	End
 	
-	Method New( req:String,url:String,readyStateChanged:Void()=Null )
-		Self.New()
-		
-		ReadyStateChanged=readyStateChanged
-		
-		Open( req,url )
-	End
+	Protected
 	
-	Property ReadyState:ReadyState()
+	Method OnOpen( req:String,url:String ) Override
 		
-		Return Cast<ReadyState>( _readyState )
-
-	End
+		If Not _obj Return
 	
-	Property ResponseText:String()
-		
-		Return _response
-	End
+		Local env:=Android_JNI_GetEnv()
 	
-	Property Status:Int()
-		
-		Return _status
+		env.CallVoidMethod( _obj,_open,New Variant[]( req,url ) )
 	End
 	
-	Method Discard()
-		
-		Remove()
+	Method OnSetHeader( header:String,value:String ) Override
 		
+		If Not _obj Return
+	
 		Local env:=Android_JNI_GetEnv()
-		
-		env.DeleteGlobalRef( _obj )
-		
-	End
 	
-	Method Open( req:String,url:String )
-		
-		OnMainFiber( Lambda()
-		
-			Local env:=Android_JNI_GetEnv()
-		
-			env.CallVoidMethod( _obj,_open,New Variant[]( req,url ) )
-		End )
+		env.CallVoidMethod( _obj,_setHeader,New Variant[]( header,value ) )
 	End
 	
-	Method SetHeader( header:String,value:String )
-		
-		OnMainFiber( Lambda()
-
-			Local env:=Android_JNI_GetEnv()
+	Method OnSend( text:String ) Override
 		
-			env.CallVoidMethod( _obj,_setHeader,New Variant[]( header,value ) )
-		End )
-	End
+		If Not _obj Return
 	
-	Method Send()
+		Local env:=Android_JNI_GetEnv()
 		
-		Send( "" )
+		Local timeout:=Int( _timeout * 1000 )
+	
+		env.CallVoidMethod( _obj,_send,New Variant[]( text,timeout ) )
 	End
 	
-	Method Send( text:String )
-		
-		OnMainFiber( Lambda()
-
-			Local env:=Android_JNI_GetEnv()
+	Method OnCancel() Override
 		
-			env.CallVoidMethod( _obj,_send,New Variant[]( text ) )
+		If Not _obj Return
 		
-		End )
+		Local env:=Android_JNI_GetEnv()
 		
+		env.CallVoidMethod( _obj,_cancel,Null )
 	End
 	
 	Private
 	
-	Global _list:HttpRequest
-	
-	Field _succ:HttpRequest
 	Field _obj:jobject
-	Field _readyState:Int
-	Field _response:String
-	Field _status:int
-	
-	Method New( peer:jobject )
-		_obj=peer
-	End
-	
-	Method Insert()
-		_succ=_list
-		_list=Self
-	End
-	
-	Method Remove()
-		local inst:=_list,pred:HttpRequest=Null
-		While inst
-			If inst=Self
-				If pred
-					pred._succ=_succ
-				Else
-					_list=_succ
-				Endif
-				Return
-			Endif
-			pred=inst
-			inst=inst._succ
-		Wend
-	End
 	
 	Global _class:jclass
 	Global _open:jmethodID
 	Global _setHeader:jmethodID
 	Global _send:jmethodID
+	Global _cancel:jmethodID
 	
-	Function OnReadyStateChanged( obj:jobject,state:Int )
+	Global _requests:=New Stack<HttpRequest>
+	
+	Method Close()
+		
+		If Not _obj Return
+		
+		_requests.Remove( Self )
 		
 		Local env:=Android_JNI_GetEnv()
 		
-		Local inst:=_list
+		env.DeleteGlobalRef( _obj )
 		
-		While inst
+		_obj=Null
+	End
+	
+	Function OnReadyStateChanged( obj:jobject,state:Int )
+		
+		Local env:=Android_JNI_GetEnv()
+		
+		For Local request:=Eachin _requests
 			
-			If env.IsSameObject( obj,inst._obj )
-				
-				inst._readyState=state
+			If Not env.IsSameObject( obj,request._obj ) Continue
 				
-				inst.ReadyStateChanged()
-				
-				Return
-			Endif
+			request.SetReadyState( Cast<ReadyState>( state ) )
+
+			If state=4 Or state=5 request.Close()
 			
-			inst=inst._succ
-		Wend
+			Exit
+		Next
 		
 	End
 	
@@ -196,28 +124,25 @@ Class HttpRequest
 
 		Local env:=Android_JNI_GetEnv()
 		
-		Local inst:=_list
-		
-		While inst
+		For Local request:=Eachin _requests
 			
-			If env.IsSameObject( obj,inst._obj )
-				
-				inst._response=response
-				
-				inst._status=status
+			If Not env.IsSameObject( obj,request._obj ) Continue
 				
-				inst._readyState=state
-				
-				inst.ReadyStateChanged()
+			request._response=response
 			
-			Endif
-
-			inst=inst._succ
-		wend
+			request._status=status
+			
+			request.SetReadyState( Cast<ReadyState>( state ) )
+			
+			Exit
+		Next
 	End
 	
-	Function Init( env:JNIEnv )
+	Function Init()
+		
 		If _class Return
+
+		Local env:=Android_JNI_GetEnv()
 	
 		_class=env.FindClass( "com/monkey2/lib/Monkey2HttpRequest" )
 		If Not _class RuntimeError( "Can't find com.monkey2.lib.Monkey2HttpRequest class" )
@@ -225,14 +150,13 @@ Class HttpRequest
 		_open=env.GetMethodID( _class,"open","(Ljava/lang/String;Ljava/lang/String;)V" )
 		
 		_setHeader=env.GetMethodID( _class,"setHeader","(Ljava/lang/String;Ljava/lang/String;)V" )
-	
-		_send=env.GetMethodID( _class,"send","(Ljava/lang/String;)V" )
+		
+		_send=env.GetMethodID( _class,"send","(Ljava/lang/String;I)V" )
+
+		_cancel=env.GetMethodID( _class,"cancel","()V" )
 		
 		onReadyStateChanged=OnReadyStateChanged
 		
 		onResponseReceived=OnResponseReceived
 	End
-	
 End
-
-		

+ 85 - 0
modules/httprequest/httprequest_desktop.monkey2

@@ -0,0 +1,85 @@
+
+Namespace httprequest
+
+Function Hello()
+End
+
+Class HttpRequest Extends HttpRequestBase
+	
+	Method New()
+	End
+	
+	Protected
+	
+	Method OnSend( text:String ) Override
+		
+		Global id:=0
+		
+		id+=1
+		
+		_tmp=GetEnv( "TMP" )+"\wget-"+id+".txt"
+		
+	#if __TARGET__="windows"
+		Local post_data:=_req="POST" ? " -post-data=~q"+text+"~q" Else ""
+		Local cmd:="wget -q -T "+_timeout+" -O ~q"+_tmp+"~q --method="+_req+post_data+" ~q"+_url+"~q"
+	#else
+		Local cmd:="curl -s -m "+timeout+" -o ~q"+_tmp+"~q ~q"+url+"~q"
+	#endif
+		
+		_process=New Process
+		
+		_process.Finished=Lambda()
+		
+			If Not _process Return
+		
+			If _process.ExitCode=0
+				
+				_response=LoadString( _tmp )
+				
+				DeleteFile( _tmp )
+				
+				_status=200
+				
+				_process=Null
+				
+				SetReadyState( ReadyState.Done )
+				
+			Else
+				
+				DeleteFile( _tmp )
+				
+				_status=404
+				
+				_process=Null
+				
+				SetReadyState( ReadyState.Error )
+				
+			Endif
+		End
+		
+		SetReadyState( ReadyState.Loading )
+		
+		_process.Start( cmd )
+	End
+	
+	Method OnCancel() Override
+		
+		If Not _process Return
+
+		DeleteFile( _tmp )
+		
+		_process.Terminate()
+		
+		_process=Null
+		
+		_status=-1
+
+		SetReadyState( ReadyState.Error )
+	End
+	
+	Private
+	
+	Field _process:Process
+	
+	Field _tmp:String
+End

+ 100 - 0
modules/httprequest/httprequest_emscripten.monkey2

@@ -0,0 +1,100 @@
+
+Namespace httprequest
+
+#Import "<emscripten>"
+
+Using emscripten..
+
+Class HttpRequest Extends HttpRequestBase
+	
+	Method New()
+	End
+	
+	Protected
+	
+	Method OnSend( text:String ) Override
+		
+		Local attr:emscripten_fetch_attr_t
+		
+		emscripten_fetch_attr_init( Varptr attr )
+		
+		_req.ToCString( attr.requestMethod,4 )
+		attr.attributes=EMSCRIPTEN_FETCH_LOAD_TO_MEMORY
+		attr.onsuccess=FetchSuccess
+		attr.onerror=FetchError
+		
+		SetReadyState( ReadyState.Loading )
+		
+		_fetch=emscripten_fetch( Varptr attr,_url )
+		
+		_sending.Add( Self )
+	End
+	
+	Method OnCancel() Override
+		
+		If Not _fetch Return
+		
+		Close()
+		
+		SetReadyState( ReadyState.Error )
+	End
+	
+	Private
+	
+	Field _fetch:emscripten_fetch_t Ptr
+	
+	Global _sending:=New Stack<HttpRequest>
+	
+	Method Close()
+		
+		If Not _fetch Return
+		
+		_sending.Remove( Self )
+		
+		emscripten_fetch_close( _fetch )
+		
+		_fetch=Null
+	End
+	
+	Method Success()
+		
+		_response=String.FromCString( _fetch->data,_fetch->numBytes )
+		
+		_status=_fetch->status
+		
+		SetReadyState( ReadyState.Done )
+		
+		Close()
+	End
+	
+	Method Error()
+		
+		_status=_fetch->status
+		
+		SetReadyState( ReadyState.Error )
+		
+		Close()
+	End
+	
+	Function FindRequest:HttpRequest( fetch:emscripten_fetch_t Ptr )
+
+		For Local request:=Eachin _sending
+
+			If request._fetch=fetch Return request
+		Next
+		
+		Return Null
+	End
+	
+	Function FetchSuccess( fetch:emscripten_fetch_t Ptr )
+		
+		FindRequest( fetch )?.Success()
+	End
+	
+	Function FetchError( fetch:emscripten_fetch_t Ptr )
+
+		FindRequest( fetch )?.Error()
+	End
+		
+	
+End

+ 56 - 23
modules/httprequest/httprequest_ios.monkey2

@@ -7,32 +7,65 @@ Namespace httprequest
 
 Extern
 
-Enum ReadyState="bbReadyState"
-	Unsent
-	Done
-	Error
-End
-
-Class HttpRequest="bbHttpRequest"
+Class bbHttpRequest
 	
-	Field ReadyStateChanged:Void()="readyStateChanged"
+	Field readyState:Int
+	Field response:String
+	Field status:Int
+	Field readyStateChanged:Void()
 	
-	Property ReadyState:ReadyState()="readyState"
-		
-	Property ResponseText:String()="responseText"
-		
-	Property Status:Int()="status"
+	Method open( req:String,url:String )
+	Method setHeader( name:String,value:String )
+	Method send( text:String,timeout:float )
+	Method cancel()
+End
+
+Public
+
+Class HttpRequest Extends HttpRequestBase
 
 	Method New()
+	
+		_peer=New bbHttpRequest
 		
-	Method New( req:String,url:String,readyStateChanged:Void()=Null )
-		
-	Method Open( req:String,url:String )="open"
-		
-	Method SetHeader( name:String,value:String )="setHeader"
-		
-	Method Send()="send"
-		
-	Method Send( text:String )="send"
-		
+		_peer.readyStateChanged=OnReadyStateChanged
+	End
+	
+	Protected
+	
+	Method OnReadyStateChanged()
+	
+		If _peer.readyState=4
+			_response=_peer.response
+			_status=_peer.status
+		Endif
+	
+		SetReadyState( Cast<ReadyState>( _peer.readyState ) )
+	End
+	
+	Method OnOpen( req:String,url:String ) Override
+	
+		_peer.open( req,url )
+	End
+	
+	Method OnSetHeader( name:String,value:String ) Override
+	
+		_peer.setHeader( name,value )
+	End
+	
+	Method OnSend( text:String ) Override
+	
+		_peer.send( text,_timeout )
+	End
+	
+	Method OnCancel() Override
+	
+		_peer.cancel()
+	End
+	
+	Private
+	
+	Field _peer:bbHttpRequest
+	
 End
+

+ 1 - 1
modules/httprequest/module.json

@@ -3,6 +3,6 @@
 	"about":"HttpRequest module",
 	"author":"Mark Sibly",
 	"version":"1.0.0",
-	"depends":["jni","std","sdl2","mojo"]
+	"depends":["libc","jni","std","sdl2","mojo"]
 }
 

+ 36 - 19
modules/httprequest/native/Monkey2HttpRequest.java

@@ -9,6 +9,9 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
 import java.net.URL;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 public class Monkey2HttpRequest{
 
@@ -18,7 +21,7 @@ public class Monkey2HttpRequest{
 	
 	int readyState;
 	
-	boolean busy;
+	boolean sending;
 
     native void onNativeReadyStateChanged( int state );
     
@@ -47,28 +50,34 @@ public class Monkey2HttpRequest{
 			
 		}catch( IOException ex ){
 		
+			Log.v( TAG,ex.toString() );
+				
 			setReadyState( 5 );
 		}		
 	}
 	
 	void setHeader( String name,String value ){
 	
-		if( readyState!=1 || busy ) return;
+		if( readyState!=1 || sending ) return;
 	
 		connection.setRequestProperty( name,value );
 	}
 	
-	void send( final String text ){
+	void send( final String text,final int timeout ){
 	
-		if( readyState!=1 || busy ) return;
+		if( readyState!=1 || sending ) return;
+				
+		sending=true;
 		
-		busy=true;
+		new Thread( new Runnable(){
 		
-		new Thread( new Runnable() {
-
-			public void run() {
-
-				try {
+			public void run(){
+			
+				connection.setConnectTimeout( timeout );
+		
+				connection.setReadTimeout( timeout );
+				
+				try{
 				
 					if( text!=null && text.length()!=0 ){
 			
@@ -86,12 +95,12 @@ public class Monkey2HttpRequest{
 					
 					setReadyState( 3 );
 
-					byte[] buf = new byte[4096];
+					byte[] buf=new byte[4096];
 					ByteArrayOutputStream out=new ByteArrayOutputStream(1024);
-					for (; ; ) {
-						int n = in.read(buf);
-						if (n < 0) break;
-						out.write(buf, 0, n);
+					for( ;; ){
+						int n=in.read( buf );
+						if( n<0 ) break;
+						out.write( buf,0,n );
 					}
 					in.close();
 
@@ -103,14 +112,22 @@ public class Monkey2HttpRequest{
 					
 					readyState=4;
 					
-				} catch ( IOException ex) {
+				}catch( IOException ex ){
+				
+					Log.v( TAG,ex.toString() );
 				
 					setReadyState( 5 );
 				}
-				
-				busy=false;
+
+				connection.disconnect();
+
+				sending=false;
 			}
-			
 		} ).start();
 	}
+	
+	void cancel(){
+	
+		connection.disconnect();
+	}
 }

+ 9 - 19
modules/httprequest/native/httprequest.h

@@ -3,38 +3,28 @@
 
 #if __APPLE__
 
-enum class bbReadyState{
-	Unsent=0,
-	Done=4,
-	Error=5
-};
-
 struct bbHttpRequest : public bbObject{
 
 	struct Rep;	//NS stuff...
 		
 	Rep *_rep;
 	
-	bbString _response;
-	int _readyState=0;
-	int _status=-1;
-	int _recv=-1;
+	int readyState=0;
+	bbString response;
+	int status=-1;
 	
 	bbFunction<void()> readyStateChanged;
 	
 	bbHttpRequest();
-	
-	bbHttpRequest( bbString req,bbString url,bbFunction<void()> readyStateChanged );
-	
-	bbReadyState readyState();
-	bbString responseText();
-	int status();
+	~bbHttpRequest();
 	
 	void open( bbString req,bbString url );
 	void setHeader( bbString name,bbString value );
-	void send();
-	void send( bbString text );
-
+	void send( bbString text,float timeout );
+	void cancel();
+	
+	void setReadyState( int state );
+	
 	void gcMark();
 };
 	

+ 58 - 86
modules/httprequest/native/httprequest.mm

@@ -4,129 +4,101 @@
 #include "../../std/async/native/async.h"
 
 struct bbHttpRequest::Rep{
-	NSMutableURLRequest *_req;
-	NSString *_response;
-	int _status;	
-};
-
-namespace{
-
-	struct ReadyStateChangedEvent : public bbAsync::Event{
 
-		bbHttpRequest *req;
-		int state;
-
-		ReadyStateChangedEvent( bbHttpRequest *req,int state ):req( req ),state( state ){
-		}
-		
-		void dispatch(){
-		
-			if( state==req->_readyState ){
-		
-				if( req->_readyState==4 ){
-					req->_response=bbString( req->_rep->_response );
-					req->_status=req->_rep->_status;
-				}
-			
-				req->readyStateChanged();
-			}
-			
-			bbGC::release( req );
-			
-			delete this;
-		}
-	};
+	NSMutableURLRequest *_req=0;
 
-}
+	NSURLSessionDataTask *_dataTask=0;
+};
 
 bbHttpRequest::bbHttpRequest(){
 
 	_rep=new Rep;
 }
 
-bbHttpRequest::bbHttpRequest( bbString req,bbString url,bbFunction<void()> readyStateChanged ):bbHttpRequest(){
-
-	this->readyStateChanged=readyStateChanged;
+bbHttpRequest::~bbHttpRequest(){
 
-	open( req,url );
-}
-	
-bbReadyState bbHttpRequest::readyState(){
-	
-	return (bbReadyState)_readyState;
-}
-	
-bbString bbHttpRequest::responseText(){
+#if !__has_feature(objc_arc)
+	if( _rep->_req ) [_rep->_req release];
+#endif
 
-	return _response;
-}
-	
-int bbHttpRequest::status(){
-	
-	return _status;
+	delete _rep;
 }
 	
 void bbHttpRequest::open( bbString req,bbString url ){
 	
-	if( _readyState!=0 ) return;
+	if( readyState!=0 ) return;
 	
-	NSMutableURLRequest *nsreq=[[NSMutableURLRequest alloc] init];
+	_rep->_req=[[NSMutableURLRequest alloc] init];
 		
-	[nsreq setHTTPMethod:req.ToNSString()];
+	[_rep->_req setHTTPMethod:req.ToNSString()];
 	
-	[nsreq setURL:[NSURL URLWithString:url.ToNSString()]];
+	[_rep->_req setURL:[NSURL URLWithString:url.ToNSString()]];
 	
-	if( [nsreq respondsToSelector:@selector(setAllowsCellularAccess:)] ){
-		[nsreq setAllowsCellularAccess:YES];
+	if( [_rep->_req respondsToSelector:@selector(setAllowsCellularAccess:)] ){
+		[_rep->_req setAllowsCellularAccess:YES];
 	}
 	
-	_rep->_req=nsreq;
-		
-	_readyState=1;
+	setReadyState( 1 );
 }
 	
 void bbHttpRequest::setHeader( bbString name,bbString value ){
 	
-	if( _readyState!=1 ) return;
+	if( readyState!=1 ) return;
 		
 	[_rep->_req setValue:value.ToNSString() forHTTPHeaderField:name.ToNSString()];
 }
+
+void bbHttpRequest::send( bbString text,float timeout ){
 	
-void bbHttpRequest::send(){
+	if( readyState!=1 ) return;
 	
-	send( "" );
-}
+	NSURLSession *session=[NSURLSession sharedSession];
+		
+	_rep->_dataTask=[session dataTaskWithRequest:_rep->_req completionHandler:
 	
-void bbHttpRequest::send( bbString text ){
+	^( NSData *data,NSURLResponse *response,NSError *error ){
 	
-	if( _readyState!=1 ) return;
+		if( !error ){
 		
-	bbGC::retain( this );
-
-	_readyState=3;	//loading
-	
-    std::thread( [=](){
-
-		NSURLResponse *response=0;
-			
-		NSData *data=[NSURLConnection sendSynchronousRequest:_rep->_req returningResponse:&response error:0];
+			NSString *str=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
 		
-		if( data && response ){
+			this->response=bbString( str );
 			
-		  	_rep->_response=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
+#if !__has_feature(objc_arc)
+			[str release];
+#endif
+
+		    status=[(NSHTTPURLResponse*)response statusCode];
+		    
+		    setReadyState( 4 );
+		    
+		}else{
 		
-		    _rep->_status=[(NSHTTPURLResponse*)response statusCode];
-			    
-		    //_recv=[data length];
+			setReadyState( 5 );
 		}
 		
-		_readyState=4;	//loaded
-		
-		ReadyStateChangedEvent *ev=new ReadyStateChangedEvent( this,_readyState );
-		
-		ev->post();
-			
-	} ).detach();
+		bbGC::release( this );
+	}
+	
+	];
+	
+	[_rep->_dataTask resume];
+
+	bbGC::retain( this );
+	
+	setReadyState( 3 );
+}
+
+void bbHttpRequest::cancel(){
+
+	if( _rep->_dataTask ) [_rep->_dataTask cancel];
+}
+
+void bbHttpRequest::setReadyState( int state ){
+
+	readyState=state;
+	
+	readyStateChanged();
 }
 
 void bbHttpRequest::gcMark(){

+ 9 - 3
modules/mojo3d/assets/shaders/effects/godrays.glsl

@@ -62,10 +62,16 @@ void main(){
 		
 		fragColor+=sample;
 	}
+	
+	gl_FragColor=vec4( fragColor * m_Exposure,1.0 );
 
-	float depth=texture2D( r_DepthBuffer,v_BufferCoords * r_BufferCoordScale ).r;
+/*
+	float depth=texture2D( r_DepthBuffer,v_BufferCoords ).r;
+	
+//	depth=1.0;
 	
-//	gl_FragColor=vec4( v_SourceBufferCoords,0.0,1.0 );//fragColor*m_Exposure,1.0 );
+//	gl_FragColor=vec4( v_BufferCoords,0.0,1.0 );
 
-	gl_FragColor=vec4( depth,0.0,0.0,1.0 );//fragColor*m_Exposure,1.0 );
+	gl_FragColor=vec4( depth,0.0,0.0,1.0 );
+*/
 }

+ 26 - 24
modules/mojo3d/render/renderer.monkey2

@@ -235,17 +235,29 @@ When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be use
 		_gdevice.Shader=_deferredLightingShader
 		_gdevice.CullMode=CullMode.None
 		
-		_gdevice.RenderTarget=_renderTarget1
-		
 		_runiforms.SetMat4f( "InverseProjectionMatrix",_invProjMatrix )
 		
 		RenderQuad()
+	End
+	
+	Method RenderDeferredFog()
 		
-		_gdevice.RenderTarget=_renderTarget0
+		If _scene.FogColor.a=0 Return
+		
+		_gdevice.ColorMask=ColorMask.All
+		_gdevice.DepthMask=False
+		_gdevice.DepthFunc=DepthFunc.Always
+		_gdevice.BlendMode=BlendMode.Alpha
+		_gdevice.RenderPass=0
+		
+		_gdevice.Shader=_deferredFogShader
+		_gdevice.CullMode=CullMode.None
+		
+		RenderQuad()
 	End
 	
 	Method RenderOpaqueDeferred()
-
+		
 		_gdevice.ColorMask=ColorMask.All
 		_gdevice.DepthMask=True
 		_gdevice.DepthFunc=DepthFunc.LessEqual
@@ -254,11 +266,15 @@ When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be use
 		
 		RenderOpaqueOps()
 		
+		'only write to accum buffer only from now on...
+		_gdevice.RenderTarget=_renderTarget1
+		
 		For Local light:=Eachin _scene.Lights
 			
 			RenderDeferredLighting( light )
 		Next
 		
+		RenderDeferredFog()
 	End
 	
 	Method RenderOpaqueForward()
@@ -315,30 +331,10 @@ When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be use
 		
 	End
 	
-	Method RenderDeferredFog()
-		
-		If _scene.FogColor.a=0 Return
-		
-		_gdevice.ColorMask=ColorMask.All
-		_gdevice.DepthMask=False
-		_gdevice.DepthFunc=DepthFunc.Always
-		_gdevice.BlendMode=BlendMode.Alpha
-		_gdevice.RenderPass=0
-		
-		_gdevice.RenderTarget=_renderTarget1
-		_gdevice.Shader=_deferredFogShader
-		_gdevice.CullMode=CullMode.None
-		
-		RenderQuad()
-
-		_gdevice.RenderTarget=_renderTarget0
-	End
-	
 	Method RenderOpaque()
 		
 		If _deferred 
 			RenderOpaqueDeferred()
-			RenderDeferredFog()
 		Else 
 			RenderOpaqueForward()
 		Endif
@@ -355,6 +351,8 @@ When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be use
 	End
 
 	Method RenderTransparent()
+		
+		If _deferred _gdevice.RenderTarget=_renderTarget0
 
 		Local first:=True
 		
@@ -554,6 +552,8 @@ When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be use
 	
 	Method RenderPostEffects()
 		
+		If _deferred _gdevice.RenderTarget=_renderTarget1
+		
 		PostEffect.BeginRendering( _gdevice,_runiforms )
 		
 		For Local effect:=Eachin _scene.PostEffects
@@ -908,6 +908,8 @@ When a new renderer is created, the config setting `MOJO3D\_RENDERER` can be use
 		If _accumBuffer And size.x<=_accumBuffer.Size.x And size.y<=_accumBuffer.Size.y Return
 		
 		_accumBuffer?.Discard()
+		_colorBuffer?.Discard()
+		_normalBuffer?.Discard()
 		_depthBuffer?.Discard()
 		_renderTarget0?.Discard()
 		_renderTarget1?.Discard()

+ 14 - 13
modules/mojo3d/tests/effects.monkey2

@@ -31,7 +31,7 @@ Class MyWindow Extends Window
 		Super.New( title,width,height,flags )
 		
 		_scene=Scene.GetCurrent()
-		_scene.ClearColor=Color.Black
+		_scene.ClearColor=Color.Sky
 		
 		'create camera
 		'
@@ -46,18 +46,17 @@ Class MyWindow Extends Window
 
 		'create effects
 		'
+		_godrays=New GodraysEffect
+		_godrays.Enabled=false
+		_godrays.Light=_light
+
 		_bloom=New BloomEffect
-		_bloom.Enabled=True
+		_bloom.Enabled=False
 		_scene.AddPostEffect( _bloom )
 		
 		_mono=New MonochromeEffect
 		_mono.Enabled=False
 		_scene.AddPostEffect( _mono )
-
-		_godrays=New GodraysEffect
-		_godrays.Enabled=false
-		_godrays.Weight=4.0
-		_godrays.Light=_light
 		
 		_scene.AddPostEffect( _godrays )
 		
@@ -73,22 +72,24 @@ Class MyWindow Extends Window
 		
 		RequestRender()
 		
-		If Keyboard.KeyHit( Key.Key1 ) _bloom.Enabled=Not _bloom.Enabled
-		If Keyboard.KeyHit( Key.Key2 ) _mono.Enabled=Not _mono.Enabled
-		If Keyboard.KeyHit( Key.Key3 ) _godrays.Enabled=Not _godrays.Enabled
+		If Keyboard.KeyHit( Key.Key1 ) _godrays.Enabled=Not _godrays.Enabled
+		If Keyboard.KeyHit( Key.Key2 ) _bloom.Enabled=Not _bloom.Enabled
+		If Keyboard.KeyHit( Key.Key3 ) _mono.Enabled=Not _mono.Enabled
 		
 		_scene.Update()
 		
 		_scene.Render( canvas )
 		
-		canvas.DrawText( "(1) Bloom="+_bloom.Enabled,0,0 )
-		canvas.DrawText( "(2) Monochrome="+_mono.Enabled,0,16 )
-		canvas.DrawText( "(3) Godrays="+_godrays.Enabled,0,32 )
+		canvas.DrawText( "(1) Godrays="+_godrays.Enabled,0,0 )
+		canvas.DrawText( "(2) Bloom="+_bloom.Enabled,0,16 )
+		canvas.DrawText( "(3) Monochrome="+_mono.Enabled,0,32 )
 	End
 	
 End
 
 Function Main()
+	
+	SetConfig( "MOJO_OPENGL_PROFILE","es" )
 
 	New AppInstance
 	

+ 1 - 2
modules/mojo3d/tests/room.monkey2

@@ -60,9 +60,8 @@ Class MyWindow Extends Window
 		Local model:=Model.Load( "asset::fish.glb" )
 		model.Mesh.FitVertices( New Boxf( -1,1 ) )
 		
-		Local root:=New Entity
+		Local root:=New Pivot
 		root.AddComponent<RotateBehaviour>().Speed=New Vec3f( 0,.1,0 )
-		root.Visible=True
 		
 		For Local an:=0 Until 360 Step 9