Browse Source

WIP jsonifier loading stuff...

Mark Sibly 7 years ago
parent
commit
03e5d99fa1

+ 6 - 8
modules/mojo3d/scene/entities/model.monkey2

@@ -126,7 +126,7 @@ Class Model Extends Renderable
 		
 		
 		Local editing:=scene.Editing
 		Local editing:=scene.Editing
 		
 		
-		scene.Editing=False
+		If editing scene.Jsonifier.BeginLoading()
 		
 		
 		Local model:Model
 		Local model:Model
 		
 		
@@ -134,14 +134,12 @@ Class Model Extends Renderable
 			
 			
 			model=loader.LoadModel( path )
 			model=loader.LoadModel( path )
 			
 			
-			If Not model Continue
-			
-			If editing scene.Jsonifier.AddInstance( model,"mojo3d.Model.Load",New Variant[]( path )  )
-				
-			Exit
+			If model Exit
 		Next
 		Next
-
-		scene.Editing=editing
+		
+		If editing scene.Jsonifier.EndLoading()
+		
+		If editing scene.Jsonifier.AddInstance( model,"mojo3d.Model.Load",New Variant[]( path )  )
 		
 		
 		Return model
 		Return model
 	End
 	End

+ 19 - 10
modules/mojo3d/scene/entities/sprite.monkey2

@@ -27,12 +27,13 @@ Class Sprite Extends Renderable
 		Name="Sprite"
 		Name="Sprite"
 		
 		
 		AddInstance()
 		AddInstance()
+		
+		Visible=True
 	End
 	End
 
 
 	Method New( material:Material,parent:Entity=Null )
 	Method New( material:Material,parent:Entity=Null )
-		Self.New( parent )
 		
 		
-		_material=material
+		Super.New( parent )
 		
 		
 		Name="Sprite"
 		Name="Sprite"
 		Material=material
 		Material=material
@@ -42,6 +43,17 @@ Class Sprite Extends Renderable
 		Visible=True
 		Visible=True
 	End
 	End
 
 
+	Method New( sprite:Sprite,parent:Entity )
+		
+		Super.New( sprite,parent )
+		
+		_material=sprite._material
+		_handle=sprite._handle
+		_mode=sprite._mode
+		
+		AddInstance( sprite )
+	End
+	
 	#rem monkeydoc Copies the sprite.
 	#rem monkeydoc Copies the sprite.
 	#end	
 	#end	
 	Method Copy:Sprite( parent:Entity=Null ) Override
 	Method Copy:Sprite( parent:Entity=Null ) Override
@@ -58,6 +70,7 @@ Class Sprite Extends Renderable
 	This must currently be an instance of a SpriteMaterial.
 	This must currently be an instance of a SpriteMaterial.
 	
 	
 	#end	
 	#end	
+	[jsonify=1]
 	Property Material:Material()
 	Property Material:Material()
 		
 		
 		Return _material
 		Return _material
@@ -70,6 +83,7 @@ Class Sprite Extends Renderable
 	#rem monkeydoc Rect within texture to draw.
 	#rem monkeydoc Rect within texture to draw.
 	
 	
 	#end	
 	#end	
+	[jsonify=1]
 	Property TextureRect:Rectf()
 	Property TextureRect:Rectf()
 		
 		
 		Return _textureRect
 		Return _textureRect
@@ -84,6 +98,7 @@ Class Sprite Extends Renderable
 	Defaults to 0.5,0.5.
 	Defaults to 0.5,0.5.
 	
 	
 	#end
 	#end
+	[jsonify=1]
 	Property Handle:Vec2f()
 	Property Handle:Vec2f()
 		
 		
 		Return _handle
 		Return _handle
@@ -98,6 +113,7 @@ Class Sprite Extends Renderable
 	Defaults to SpriteMode.Billboard.
 	Defaults to SpriteMode.Billboard.
 	
 	
 	#end
 	#end
+	[jsonify=1]
 	Property Mode:SpriteMode()
 	Property Mode:SpriteMode()
 		
 		
 		Return _mode
 		Return _mode
@@ -109,15 +125,8 @@ Class Sprite Extends Renderable
 	
 	
 	Protected
 	Protected
 
 
-	Method New( sprite:Sprite,parent:Entity )
-		Super.New( sprite,parent )
-		
-		_material=sprite._material
-		_handle=sprite._handle
-		_mode=sprite._mode
-	End
-	
 	Method OnRender( rq:RenderQueue ) Override
 	Method OnRender( rq:RenderQueue ) Override
+		
 		rq.AddSpriteOp( Self )
 		rq.AddSpriteOp( Self )
 	End
 	End
 	
 	

+ 137 - 78
modules/mojo3d/scene/jsonifier/jsonifier.monkey2

@@ -2,64 +2,91 @@ Namespace mojo3d.jsonifier
 
 
 Class Jsonifier
 Class Jsonifier
 
 
+Private
+	
+	Class Instance
+		Field id:Int
+		Field obj:Variant
+		Field ctor:Invocation
+		Field initialState:JsonObject
+		
+		Operator To:String()
+			Return "Instance(type="+obj.Type+" dynamic type="+obj.DynamicType+")"
+		End
+	End
+	
+	Field _loading:Int
+	Field _instLoading:Int
+	Field _instsByObj:=New Map<Object,Instance>
+	Field _insts:=New Stack<Instance>
+	
+Public
+
+	Method BeginLoading()
+		
+		_loading+=1
+
+		If _loading>1 Return
+
+		_instLoading=_insts.Length
+	End
+	
+	Method EndLoading()
+		
+		_loading-=1
+		
+		If _loading Return
+		
+		For Local i:=_instLoading Until _insts.Length
+			Local inst:=_insts[i]
+			Local tobj:=Cast<Object>( inst.obj )
+			inst.initialState=JsonifyState( tobj )
+		next
+	End
+	
 	Method AddInstance( obj:Variant,ctor:Invocation )
 	Method AddInstance( obj:Variant,ctor:Invocation )
 		
 		
 		Local tobj:=Cast<Object>( obj )
 		Local tobj:=Cast<Object>( obj )
 		
 		
-		Assert( Not _instsByObj.Contains( tobj ) )
-		
-		Local inst:=New Instance
+		Local inst:=_instsByObj[tobj]
+		If inst
+			If inst.ctor Print "Warning: overwriting instance ctor for "+inst
+			inst.ctor=ctor
+			Return
+		Endif
+			
+		inst=New Instance
+		inst.id=_insts.Length
 		inst.obj=obj
 		inst.obj=obj
-		inst.id="@"+String(_insts.Length)
-		inst.ctor=ctor
-		inst.initialState=JsonifyState( tobj )
 		
 		
-		_instsByObj[tobj]=inst
-		_instsById[inst.id]=inst
-
 		_insts.Add( inst )
 		_insts.Add( inst )
-	End
-
-	'ctor via ctor
-	Method AddInstance( obj:Variant,args:Variant[] )
-		
-		AddInstance( obj,New Invocation( obj.DynamicType,"New",Null,args ) )
-	end
-
-	'ctor via method call
-	Method AddInstance( obj:Variant,decl:String,inst:Variant,args:Variant[] )
+		_instsByObj[tobj]=inst
 		
 		
-		AddInstance( obj,New Invocation( decl,inst,args ) )
-	End
+		If _loading Return
 
 
-	'ctor via function call
-	Method AddInstance( obj:Variant,decl:String,args:Variant[] )
-		
-		AddInstance( obj,New Invocation( decl,Null,args ) )
+		inst.ctor=ctor
+		inst.initialState=JsonifyState( tobj )
 	End
 	End
-
+	
 	Method JsonifyInstances:JsonObject()
 	Method JsonifyInstances:JsonObject()
 		
 		
 		Local jobj:=New JsonObject
 		Local jobj:=New JsonObject
 		
 		
 		jobj["assetsDir"]=New JsonString( AssetsDir() )
 		jobj["assetsDir"]=New JsonString( AssetsDir() )
 		
 		
-		Local jinsts:=New JsonArray( _insts.Length )
+		Local jinsts:=New Stack<JsonValue>
 		
 		
 		For Local i:=0 Until _insts.Length
 		For Local i:=0 Until _insts.Length
 			
 			
-			Local jobj:=New JsonObject
+'			Print "Jsonifying "+i
 			
 			
 			Local inst:=_insts[i]
 			Local inst:=_insts[i]
 			Local tobj:=Cast<Object>( inst.obj )
 			Local tobj:=Cast<Object>( inst.obj )
+
+			'compute delta state
+			Local state:=JsonifyState( tobj )
 			
 			
-			jobj["id"]=New JsonString( inst.id )
-			
-			jobj["type"]=New JsonString( tobj.DynamicType.Name )
-			
-			jobj["ctor"]=Jsonify( inst.ctor )
-			
-			Local state:=JsonifyState( tobj ),dstate:=New JsonObject
+			Local dstate:=New JsonObject
 			
 			
 			For Local it:=Eachin state.All()
 			For Local it:=Eachin state.All()
 				
 				
@@ -69,12 +96,19 @@ Class Jsonifier
 				If CompareJson( x,y )<>0 dstate[it.Key]=x
 				If CompareJson( x,y )<>0 dstate[it.Key]=x
 			Next
 			Next
 			
 			
-			jobj["state"]=dstate
+			If Not inst.ctor And dstate.Empty Continue
+			
+			Local jobj:=New JsonObject
+			jobj["type"]=New JsonString( tobj.DynamicType.Name )	'not actually used, cool for debug
+			
+			jobj["id"]=New JsonNumber( inst.id )
+			If inst.ctor jobj["ctor"]=Jsonify( inst.ctor )
+			If Not dstate.Empty jobj["state"]=dstate
 				
 				
-			jinsts[i]=jobj
+			jinsts.Add( jobj )
 		Next
 		Next
 
 
-		jobj["instances"]=jinsts
+		jobj["instances"]=New JsonArray( jinsts )
 		
 		
 		Return jobj
 		Return jobj
 	End
 	End
@@ -86,44 +120,73 @@ Class Jsonifier
 		If jobj.Contains( "assetsDir" ) SetAssetsDir( jobj.GetString( "assetsDir" ) )
 		If jobj.Contains( "assetsDir" ) SetAssetsDir( jobj.GetString( "assetsDir" ) )
 		
 		
 		Local jinsts:=jobj.GetArray( "instances" )
 		Local jinsts:=jobj.GetArray( "instances" )
+
+		Local jobjsById:=New IntMap<JsonObject>
 		
 		
 		For Local i:=0 Until jinsts.Length
 		For Local i:=0 Until jinsts.Length
 			
 			
 			Local jobj:=jinsts.GetObject( i )
 			Local jobj:=jinsts.GetObject( i )
+			Assert( jobj.Contains( "id" ) )
 			
 			
-			Local obj:Variant
-						
-			If i<_insts.Length
-				
-				obj=_insts[i].obj
-			Else
-				Local ctor:=Cast<Invocation>( Dejsonify( jobj["ctor"],Typeof<Invocation> ) )
+			Local id:=jobj.GetNumber( "id" )
+			Assert( Not jobjsById.Contains( id ) )
 			
 			
-				obj=ctor.Execute()
-			Endif
-
-			_dejsonified.Add( obj )
+			jobjsById[id]=jobj
+		Next
+		
+		'copy of insts alreday created (ie: initial Scene)
+		Local tinsts:=_insts.ToArray(),id:=0
+		
+		For Local i:=0 Until jinsts.Length
 			
 			
-			Local tobj:=Cast<Object>( obj )
+			Local jobj:=jinsts.GetObject( i )
+			If Not jobj.Contains( "ctor" ) Continue
 			
 			
-			'set value type state only on this pass.
-			If jobj.Contains( "state" ) DejsonifyState( tobj,jobj.GetObject( "state" ),tobj.DynamicType,False )
-		Next
+			Local ctor:=Cast<Invocation>( Dejsonify( jobj["ctor"],Typeof<Invocation> ) )
+			ctor.Execute()
+			
+			For Local j:=id Until _insts.Length
+				
+				If Not jobjsById.Contains( j ) Continue
 
 
-		'set reference type state - do this on a second pass 'coz of forward refs. Probably wont always work?
-		For Local i:=0 Until _dejsonified.Length
+				Local jobj:=jobjsById[j]
+				Local tobj:=Cast<Object>( _insts[j].obj )
+				If jobj.Contains( "state" ) DejsonifyState( tobj,jobj.GetObject( "state" ),tobj.DynamicType,False )
+			Next
 			
 			
-			Local jobj:=jinsts.GetObject( i )
+			id=_insts.Length
 			
 			
-			Local obj:=_dejsonified[i]
+		Next
+		
+		'set reference type state - do this on a second pass 'coz of forward refs. Probably wont always work?
+		For Local i:=0 Until _insts.Length
 			
 			
-			Local tobj:=Cast<Object>( obj )
+			If Not jobjsById.Contains( i ) Continue
 			
 			
+			Local jobj:=jobjsById[i]
+			Local tobj:=Cast<Object>( _insts[i].obj )
 			If jobj.Contains( "state" ) DejsonifyState( tobj,jobj.GetObject( "state" ),tobj.DynamicType,True )
 			If jobj.Contains( "state" ) DejsonifyState( tobj,jobj.GetObject( "state" ),tobj.DynamicType,True )
 		Next
 		Next
 		
 		
 		SetAssetsDir( assetsDir )
 		SetAssetsDir( assetsDir )
 	End
 	End
+	'ctor via ctor
+	Method AddInstance( obj:Variant,args:Variant[] )
+		
+		AddInstance( obj,New Invocation( obj.DynamicType,"New",Null,args ) )
+	end
+
+	'ctor via method call
+	Method AddInstance( obj:Variant,decl:String,inst:Variant,args:Variant[] )
+		
+		AddInstance( obj,New Invocation( decl,inst,args ) )
+	End
+
+	'ctor via function call
+	Method AddInstance( obj:Variant,decl:String,args:Variant[] )
+		
+		AddInstance( obj,New Invocation( decl,Null,args ) )
+	End
 	
 	
 	Method Jsonify:JsonValue( value:Variant )
 	Method Jsonify:JsonValue( value:Variant )
 		
 		
@@ -131,7 +194,7 @@ Class Jsonifier
 		
 		
 		Local type:=value.Type
 		Local type:=value.Type
 		Assert( type )
 		Assert( type )
-		
+
 		'handle primitive types
 		'handle primitive types
 		Select type
 		Select type
 		Case Typeof<Bool>
 		Case Typeof<Bool>
@@ -152,7 +215,7 @@ Class Jsonifier
 			Local obj:=Cast<Object>( value )
 			Local obj:=Cast<Object>( value )
 			If Not obj Return JsonValue.NullValue
 			If Not obj Return JsonValue.NullValue
 			Local inst:=_instsByObj[obj]
 			Local inst:=_instsByObj[obj]
-			If inst Return New JsonString( inst.id )
+			If inst Return New JsonString( "@"+inst.id )
 		Case "Enum"
 		Case "Enum"
 			Return New JsonNumber( value.EnumValue )
 			Return New JsonNumber( value.EnumValue )
 		End
 		End
@@ -164,6 +227,11 @@ Class Jsonifier
 		Next
 		Next
 
 
 		Select type.Kind
 		Select type.Kind
+		Case "Unknown"
+			Local obj:=Cast<Object>( value )
+			If Not obj Return JsonValue.NullValue
+			Local inst:=_instsByObj[obj]
+			If inst Return New JsonString( "@"+inst.id )
 		Case "Class"
 		Case "Class"
 			Return JsonValue.NullValue
 			Return JsonValue.NullValue
 		Case "Array"
 		Case "Array"
@@ -207,9 +275,8 @@ Class Jsonifier
 				Return type.NullValue
 				Return type.NullValue
 			Elseif jvalue.IsString
 			Elseif jvalue.IsString
 				Local id:=Int( jvalue.ToString().Slice( 1 ) )
 				Local id:=Int( jvalue.ToString().Slice( 1 ) )
-				Assert( id>=0 And id<_dejsonified.Length,"Dejsonify error" )
-				Local inst:=_dejsonified[id]
-				Return inst
+				Assert( id>=0 And id<_insts.Length,"Dejsonify error" )
+				Return _insts[id].obj
 			Endif
 			Endif
 		Case "Enum"
 		Case "Enum"
 			Return type.MakeEnum( jvalue.ToNumber() )
 			Return type.MakeEnum( jvalue.ToNumber() )
@@ -222,6 +289,12 @@ Class Jsonifier
 		Next
 		Next
 
 
 		Select type.Kind
 		Select type.Kind
+		Case "Unknown"
+			If jvalue.IsString
+				Local id:=Int( jvalue.ToString().Slice( 1 ) )
+				Assert( id>=0 And id<_insts.Length,"Dejsonify error" )
+				Return _insts[id].obj
+			Endif
 		Case "Class"
 		Case "Class"
 			Return type.NullValue
 			Return type.NullValue
 		Case "Array"
 		Case "Array"
@@ -242,20 +315,6 @@ Class Jsonifier
 	
 	
 	Private
 	Private
 	
 	
-	Class Instance
-		Field obj:Variant
-		Field id:String
-		Field ctor:Invocation
-		Field initialState:JsonObject
-	End
-	
-	Field _insts:=New Stack<Instance>
-	
-	Field _instsByObj:=New Map<Object,Instance>
-	Field _instsById:=New StringMap<Instance>
-	
-	Field _dejsonified:=New Stack<Variant>
-	
 	Method JsonifyState:JsonObject( obj:Object )
 	Method JsonifyState:JsonObject( obj:Object )
 		
 		
 		Local jobj:=New JsonObject
 		Local jobj:=New JsonObject
@@ -300,7 +359,7 @@ Class Jsonifier
 			
 			
 			Local type:=d.Type
 			Local type:=d.Type
 			
 			
-			Local isinst:=type.Kind="Class"
+			Local isinst:=type.Kind="Class" Or type.Kind="Unknown"
 			
 			
 			If Not isinst And type.Kind="Array" And type.ElementType.Kind="Class" isinst=True
 			If Not isinst And type.Kind="Array" And type.ElementType.Kind="Class" isinst=True
 				
 				

+ 26 - 0
modules/mojo3d/scene/jsonifier/jsonifierexts.monkey2

@@ -1,5 +1,31 @@
 Namespace mojo3d.jsonifier
 Namespace mojo3d.jsonifier
 
 
+Class MojoJsonifierExt Extends JsonifierExt
+	
+	Const Instance:=New MojoJsonifierExt
+
+	Method Jsonify:JsonValue( value:Variant,jsonifier:Jsonifier ) Override
+		
+		Select value.Type
+		Case Typeof<TextureFlags>
+			Return New JsonNumber( Int( Cast<TextureFlags>( value ) ) )
+		End
+		
+		Return Null
+	End
+
+	Method Dejsonify:Variant( jvalue:JsonValue,type:TypeInfo,jsonifier:Jsonifier ) Override
+		
+		Select type
+		Case Typeof<TextureFlags>
+			Return Cast<TextureFlags>( Int( jvalue.ToNumber() ) )
+		End
+		
+		Return Null
+	End
+	
+End
+
 Class StdJsonifierExt Extends JsonifierExt
 Class StdJsonifierExt Extends JsonifierExt
 	
 	
 	Const Instance:=New StdJsonifierExt
 	Const Instance:=New StdJsonifierExt

+ 25 - 0
modules/mojo3d/scene/material.monkey2

@@ -122,6 +122,24 @@ Class Material Extends Resource
 		Return GetOpaqueShader()
 		Return GetOpaqueShader()
 	End
 	End
 	
 	
+	Function LoadTexture:Texture( path:String,textureFlags:TextureFlags,flipy:Bool=False )
+		
+		Local scene:=Scene.GetCurrent()
+		
+		Return scene.LoadTexture( path,textureFlags,flipy )
+	End
+	
+	Function LoadTexture:Texture( path:String,name:String,textureFlags:TextureFlags,flipy:Bool=False )
+		
+		Local scene:=Scene.GetCurrent()
+		
+		Local texture:=scene.LoadTexture( path+"/"+name+".png",textureFlags,flipy )
+		
+		If Not texture texture=scene.LoadTexture( path+"/"+name+".jpg",textureFlags,flipy )
+			
+		Return texture
+	End
+	
 	Protected
 	Protected
 	
 	
 	Method New()
 	Method New()
@@ -143,6 +161,13 @@ Class Material Extends Resource
 		TextureMatrix=material.TextureMatrix
 		TextureMatrix=material.TextureMatrix
 	End
 	End
 	
 	
+	Method AddInstance()
+
+		Local scene:=Scene.GetCurrent()
+		
+		If scene.Editing scene.Jsonifier.AddInstance( Self,New Variant[0] )
+	End
+	
 	Method AddInstance( args:Variant[] )
 	Method AddInstance( args:Variant[] )
 		
 		
 		Local scene:=Scene.GetCurrent()
 		Local scene:=Scene.GetCurrent()

+ 37 - 28
modules/mojo3d/scene/materials/pbrmaterial.monkey2

@@ -30,6 +30,30 @@ Public
 #end
 #end
 Class PbrMaterial Extends Material
 Class PbrMaterial Extends Material
 	
 	
+	Private
+	
+	Method Init( boned:Bool )
+		
+		_boned=boned
+
+		Uniforms.DefaultTexture=Texture.ColorTexture( Color.White )
+		
+		ColorTexture=Null
+		EmissiveTexture=Null
+		MetalnessTexture=Null
+		RoughnessTexture=Null
+		OcclusionTexture=Null
+		NormalTexture=Null
+		
+		ColorFactor=Color.White
+		EmissiveFactor=Color.Black
+		MetalnessFactor=1.0
+		RoughnessFactor=1.0
+	End
+	
+	Public
+	
+	
 	#rem monkeydoc Creates a new pbr material.
 	#rem monkeydoc Creates a new pbr material.
 	
 	
 	All properties default to white or '1' except for emissive factor which defaults to black. 
 	All properties default to white or '1' except for emissive factor which defaults to black. 
@@ -47,26 +71,14 @@ Class PbrMaterial Extends Material
 	#end
 	#end
 	Method New( boned:Bool=False )
 	Method New( boned:Bool=False )
 		
 		
-		_boned=boned
-		
-		Uniforms.DefaultTexture=Texture.ColorTexture( Color.White )
+		Init( boned )
 		
 		
-		ColorTexture=Null
-		EmissiveTexture=Null
-		MetalnessTexture=Null
-		RoughnessTexture=Null
-		OcclusionTexture=Null
-		NormalTexture=Null
-		
-		ColorFactor=Color.White
-		EmissiveFactor=Color.Black
-		MetalnessFactor=1.0
-		RoughnessFactor=1.0
+		AddInstance( New Variant[]( boned ) )
 	End
 	End
 	
 	
 	Method New( color:Color,metalness:Float=1.0,roughness:Float=1.0,boned:Bool=False )
 	Method New( color:Color,metalness:Float=1.0,roughness:Float=1.0,boned:Bool=False )
 		
 		
-		Self.New( boned )
+		Init( boned )
 		
 		
 		ColorFactor=color
 		ColorFactor=color
 		MetalnessFactor=metalness
 		MetalnessFactor=metalness
@@ -230,12 +242,13 @@ Class PbrMaterial Extends Material
 	#end
 	#end
 	Function Load:PbrMaterial( path:String,textureFlags:TextureFlags=TextureFlags.WrapST|TextureFlags.FilterMipmap )
 	Function Load:PbrMaterial( path:String,textureFlags:TextureFlags=TextureFlags.WrapST|TextureFlags.FilterMipmap )
 		
 		
-		Local material:=New PbrMaterial
+		Local scene:=Scene.GetCurrent(),editing:=scene.Editing
 		
 		
-		Local scene:=Scene.GetCurrent()
-		If scene.Editing 
-			scene.Jsonifier.AddInstance( material,"mojo3d.PbrMaterial.Load",New Variant[]( path,textureFlags ) )
+		If editing 
+			scene.Jsonifier.BeginLoading()
 		Endif
 		Endif
+
+		Local material:=New PbrMaterial
 		
 		
 		Local texture:=LoadTexture( path,"color",textureFlags )
 		Local texture:=LoadTexture( path,"color",textureFlags )
 		If texture
 		If texture
@@ -277,6 +290,11 @@ Class PbrMaterial Extends Material
 			If jobj.Contains( "roughnessFactor" ) material.RoughnessFactor=jobj.GetNumber( "roughnessFactor" )
 			If jobj.Contains( "roughnessFactor" ) material.RoughnessFactor=jobj.GetNumber( "roughnessFactor" )
 		Endif
 		Endif
 		
 		
+		If editing 
+			scene.Jsonifier.EndLoading()
+			scene.Jsonifier.AddInstance( material,"mojo3d.PbrMaterial.Load",New Variant[]( path,textureFlags ) )
+		Endif
+		
 		Return material
 		Return material
 	End
 	End
 	
 	
@@ -292,15 +310,6 @@ Class PbrMaterial Extends Material
 	
 	
 	Field _dirty:=True
 	Field _dirty:=True
 	
 	
-	Function LoadTexture:Texture( path:String,name:String,flags:TextureFlags,flipy:Bool=False )
-		
-		Local texture:=Texture.Load( path+"/"+name+".png",flags,flipy )
-		
-		If Not texture texture=Texture.Load( path+"/"+name+".jpg",flags,flipy )
-			
-		Return texture
-	End
-	
 	Method ValidateShaders()
 	Method ValidateShaders()
 		
 		
 		If Not _dirty Return
 		If Not _dirty Return

+ 18 - 3
modules/mojo3d/scene/materials/spritematerial.monkey2

@@ -16,11 +16,15 @@ Class SpriteMaterial Extends Material
 		ColorFactor=Color.White
 		ColorFactor=Color.White
 		
 		
 		AlphaDiscard=.5
 		AlphaDiscard=.5
+		
+		AddInstance()
 	End
 	End
 	
 	
 	Method New( material:SpriteMaterial )
 	Method New( material:SpriteMaterial )
 	
 	
 		Super.New( material )
 		Super.New( material )
+		
+		AddInstance( material )
 	End
 	End
 	
 	
 	#rem monkeydoc Creates a copy of the sprite material.
 	#rem monkeydoc Creates a copy of the sprite material.
@@ -61,6 +65,7 @@ Class SpriteMaterial Extends Material
 		Return GetOpaqueShader()
 		Return GetOpaqueShader()
 	End
 	End
 	
 	
+	[jsonify=1]
 	Property ColorTexture:Texture()
 	Property ColorTexture:Texture()
 		
 		
 		Return Uniforms.GetTexture( "ColorTexture" )
 		Return Uniforms.GetTexture( "ColorTexture" )
@@ -70,6 +75,7 @@ Class SpriteMaterial Extends Material
 		Uniforms.SetTexture( "ColorTexture",texture )
 		Uniforms.SetTexture( "ColorTexture",texture )
 	End
 	End
 	
 	
+	[jsonify=1]
 	Property ColorFactor:Color()
 	Property ColorFactor:Color()
 	
 	
 		Return Uniforms.GetColor( "ColorFactor" )
 		Return Uniforms.GetColor( "ColorFactor" )
@@ -79,6 +85,7 @@ Class SpriteMaterial Extends Material
 		Uniforms.SetColor( "ColorFactor",color )
 		Uniforms.SetColor( "ColorFactor",color )
 	End
 	End
 	
 	
+	[jsonify=1]
 	Property AlphaDiscard:Float()
 	Property AlphaDiscard:Float()
 		
 		
 		Return Uniforms.GetFloat( "AlphaDiscard" )
 		Return Uniforms.GetFloat( "AlphaDiscard" )
@@ -92,14 +99,22 @@ Class SpriteMaterial Extends Material
 	#end	
 	#end	
 	Function Load:SpriteMaterial( path:String,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
 	Function Load:SpriteMaterial( path:String,textureFlags:TextureFlags=TextureFlags.FilterMipmap )
 		
 		
-		Local texture:=Texture.Load( path,textureFlags )
-		If Not texture texture=Texture.ColorTexture( Color.Magenta )
+		Local scene:=Scene.GetCurrent(),editing:=scene.Editing
+		
+		If editing scene.Jsonifier.BeginLoading()
+		
+		Local texture:=LoadTexture( path,textureFlags )
+		'If Not texture texture=Texture.ColorTexture( Color.Magenta )
 		
 		
 		Local material:=New SpriteMaterial
 		Local material:=New SpriteMaterial
 		material.ColorTexture=texture
 		material.ColorTexture=texture
 		
 		
+		If editing
+			scene.Jsonifier.EndLoading()
+			scene.Jsonifier.AddInstance( material,"mojo3d.SpriteMaterial.Load",New Variant[]( path,textureFlags ) )
+		Endif
+		
 		Return material
 		Return material
 	End
 	End
 	
 	
 End
 End
-

+ 63 - 67
modules/mojo3d/scene/scene.monkey2

@@ -10,9 +10,11 @@ Class Scene
 	If there is no current scene when a new scene is created, the new scene becomes the current scene.
 	If there is no current scene when a new scene is created, the new scene becomes the current scene.
 		
 		
 	#end
 	#end
-	Method New()
+	Method New( editable:Bool=False )
 		
 		
 		If Not _current _current=Self
 		If Not _current _current=Self
+			
+		_editable=editable
 		
 		
 		_clearColor=Color.Sky
 		_clearColor=Color.Sky
 
 
@@ -22,13 +24,14 @@ Class Scene
 		
 		
 		_world=New World( Self )
 		_world=New World( Self )
 		
 		
-		Local type:=TypeInfo.GetType( "mojo3d.Scene" )
-		If type And type.Kind="Class"
+		If _editable
+			Local type:=TypeInfo.GetType( "mojo3d.Scene" )
+			Assert( type And type.Kind="Class","mojo3d reflection must be enabled for editable scenes" )
 			_jsonifier=New Jsonifier
 			_jsonifier=New Jsonifier
-			_jsonifier.AddInstance( Self,New Variant[0] )
+			_jsonifier.AddInstance( Self,New Variant[]( true ) )
+			_editing=True
 		Endif
 		Endif
 		
 		
-		_editing=False
 	End
 	End
 	
 	
 	#rem monkeydoc The sky texture.
 	#rem monkeydoc The sky texture.
@@ -40,7 +43,7 @@ Class Scene
 	This must currently be a valid cubemap texture.
 	This must currently be a valid cubemap texture.
 	
 	
 	#end
 	#end
-'	[jsonify=1]
+	[jsonify=1]
 	Property SkyTexture:Texture()
 	Property SkyTexture:Texture()
 		
 		
 		Return _skyTexture
 		Return _skyTexture
@@ -61,7 +64,7 @@ Class Scene
 	This must currently be a valid cubemap texture.
 	This must currently be a valid cubemap texture.
 	
 	
 	#end
 	#end
-'	[jsonify=1]
+	[jsonify=1]
 	Property EnvTexture:Texture()
 	Property EnvTexture:Texture()
 		
 		
 		Return _envTexture
 		Return _envTexture
@@ -195,44 +198,6 @@ Class Scene
 		_csmSplits=splits.Slice( 0 )
 		_csmSplits=splits.Slice( 0 )
 	End
 	End
 	
 	
-	Property Editing:Bool()
-		
-		Return _editing
-	
-	Setter( editing:Bool )
-		
-		If editing And Not _jsonifier RuntimeError( "Scene is not editable" )
-		
-		_editing=editing
-	End
-	
-	Property Jsonifier:Jsonifier()
-		
-		Return _jsonifier
-	End
-	
-	Method PauseEditing()
-		
-		_editingPaused+=1
-	End
-	
-	Method ResumeEditing:Bool()
-		
-		_editingPaused-=1
-		
-		Return Editing
-	End
-	
-	Method LoadTexture:Texture( path:String,flags:TextureFlags,flipNormalY:Bool=False )
-		
-		Local texture:=Texture.Load( path,flags,flipNormalY )
-		If Not texture Return Null
-		
-		If Editing Jsonifier.AddInstance( texture,"mojo3d.Scene.LoadTexture",Self,New Variant[]( path,flags,flipNormalY ) )
-			
-		Return texture
-	End
-
 	#rem monkeydoc Finds an entity in the scene.
 	#rem monkeydoc Finds an entity in the scene.
 	
 	
 	Finds an entity in the scene with the given name.
 	Finds an entity in the scene with the given name.
@@ -320,6 +285,39 @@ Class Scene
 		Return _rootEntities.ToArray()
 		Return _rootEntities.ToArray()
 	End
 	End
 	
 	
+	'***** serialization stuff *****
+	
+	Property Editable:Bool()
+		
+		Return _editable
+	End
+	
+	Property Editing:Bool()
+		
+		Return _editing
+	
+	Setter( editing:Bool )
+		
+		If editing And Not _editable RuntimeError( "Scene is not editable" )
+		
+		_editing=editing
+	End
+	
+	Property Jsonifier:Jsonifier()
+		
+		Return _jsonifier
+	End
+	
+	Method LoadTexture:Texture( path:String,flags:TextureFlags,flipNormalY:Bool=False )
+		
+		Local texture:=Texture.Load( path,flags,flipNormalY )
+		If Not texture Return Null
+		
+		If Editing Jsonifier.AddInstance( texture,"mojo3d.Scene.LoadTexture",Self,New Variant[]( path,flags,flipNormalY ) )
+			
+		Return texture
+	End
+
 	#rem monkeydoc Saves the scene to a mojo3d scene file
 	#rem monkeydoc Saves the scene to a mojo3d scene file
 	#end
 	#end
 	Method Save( path:String )
 	Method Save( path:String )
@@ -332,6 +330,25 @@ Class Scene
 		
 		
 		SaveString( json,path )
 		SaveString( json,path )
 	End
 	End
+
+	#rem monkeydoc Loads a mojo3d scene file and makes it current
+	#end
+	Function Load:Scene( path:String )
+		
+		Local json:=LoadString( path )
+		If Not json Return Null
+		
+		Local jobj:=JsonObject.Parse( json )
+		If Not jobj Return Null
+		
+		Local scene:=New Scene( True )
+		
+		SetCurrent( scene )
+		
+		scene.Jsonifier.DejsonifyInstances( jobj )
+		
+		Return scene
+	End
 	
 	
 	#rem monkeydoc Sets the current scene.
 	#rem monkeydoc Sets the current scene.
 	
 	
@@ -355,25 +372,6 @@ Class Scene
 		Return _current
 		Return _current
 	End
 	End
 	
 	
-	#rem monkeydoc Loads a mojo3d scene file and makes it current
-	#end
-	Function Load:Scene( path:String )
-
-		Local json:=LoadString( path )
-		If Not json Return Null
-		
-		Local jobj:=JsonObject.Parse( json )
-		If Not jobj Return Null
-		
-		Local scene:=New Scene
-		
-		SetCurrent( scene )
-		
-		scene.Jsonifier.DejsonifyInstances( jobj )
-		
-		Return scene
-	End
-	
 	Internal
 	Internal
 
 
 	Property PostEffects:Stack<PostEffect>()
 	Property PostEffects:Stack<PostEffect>()
@@ -438,11 +436,9 @@ Class Scene
 	Field _world:World
 	Field _world:World
 	
 	
 	Field _jsonifier:Jsonifier
 	Field _jsonifier:Jsonifier
-	
+	Field _editable:Bool
 	Field _editing:Bool
 	Field _editing:Bool
 	
 	
-	Field _editingPaused:=0
-	
 	Method Update( elapsed:Float )
 	Method Update( elapsed:Float )
 		
 		
 		For Local e:=Eachin _rootEntities
 		For Local e:=Eachin _rootEntities