Jump to content
GreenSock

attaboy

Members
  • Posts

    39
  • Joined

  • Last visited

Posts posted by attaboy

  1. I replaced the first line of code below with what I thought would work but nothing happens I press the button and nothing not even a error message.

     

    //TweenLite.to(bio, 3, {transformAroundCenter:{x:450, y:400, scaleX:1, scaleY:1, delay:1}, rotation:1440, ease:Back.easeOut, easeParams:[.7]});
    TweenLite.to(bio, 3, {transformAroundPoint:{point:new Point(383,307), scaleX:1, scaleY:1, rotation:1440, pointIsLocal:true}, ease:Back.easeOut, easeParams:[.7]});

  2. I have a MC that can be viewed here http://www.jimslounge.com/erikMay27/testBio4.swf It rotates around center as I wanted it to do. When I added a scrolling text field I get this http://www.jimslounge.com/erikMay27/testBio5.swf the center of the MC changes as the 800 px high text field scrolls. I was wondering if there was anyway I could transformAroundCenter using the center of the MC as it was before adding the TextField.

     

    import com.greensock.*;
    import com.greensock.easing.*;
    import com.greensock.plugins.*;
    import com.droolpigs.*;
    
    TweenPlugin.activate([TransformAroundPointPlugin, TransformAroundCenterPlugin, ShortRotationPlugin]);
    
    var textAS:TextAutoScroll = new TextAutoScroll("bio.txt", 30, 420, 700, 800);
    var bio:Bio2 = new Bio2();
    bio.scaleX =.001;
    bio.scaleY =.001;
    bio.x=450;
    bio.y=400;
    bio.addChild(textAS);
    
    // dragdrop stuff
    		bio.addEventListener(MouseEvent.MOUSE_DOWN, drag);
    		bio.addEventListener(MouseEvent.MOUSE_UP, drop);
    
    	load_btn.addEventListener(MouseEvent.CLICK, loadAbout);
    	unload_btn.addEventListener(MouseEvent.CLICK, unloadAbout);
    
    	function drag(e:MouseEvent):void {
    		e.currentTarget.startDrag();
    	}
    
    	function drop(e:MouseEvent):void {
    		e.currentTarget.stopDrag();
    	}
    
    function loadAbout(e:MouseEvent):void {
    addChild(bio);
    
    TweenLite.to(bio, 3, {transformAroundCenter:{x:450, y:400, scaleX:1, scaleY:1, delay:1}, rotation:1440, ease:Back.easeOut, easeParams:[.7]});
    }
    
    function unloadAbout(e:MouseEvent):void {
    if(bio){
    TweenLite.to(bio, 2.5, {transformAroundCenter:{x:450, y:400, scaleX:.001, scaleY:.001}, rotation:-1440, onComplete:removeit});
    }
    }
    
    function removeit():void {
    removeChild(bio);
    } 
    

  3. I have a slide show which greensock helped me with he pretty much rewrote it it's very cool the way he did it . It slices and splices in arrays (please excuse my ignorant explanation I haven't gotten around to examining how it works in detail. My only issue with it is I don't think it scales well. I feed in 182 images with a combined total of 10.4 meg when the swf loads it uses 124 meg then it adds about 1.25 meg memory as each image is displayed until it reaches 293 meg at which point gc kicks in and keeps it there.

     

    import com.greensock.*;
    import com.greensock.easing.*;
    import com.greensock.loading.*;
    import flash.display.*;
    import flash.geom.*;
    import com.greensock.events.LoaderEvent;
    import com.greensock.loading.display.ContentDisplay;
    
    var duration:Number = .5;
    var timeline:TimelineMax;
    var bars:Bars = new Bars();
    bars.cacheAsBitmap = true;
    holderBG.addChild(bars);
    
    createTimeline();
    
    function createTimeline():void {
    timeline = new TimelineMax({repeat:1, repeatDelay:5, yoyo:true, onComplete:showRandom, paused:true});
    for (var count:int = 1; count <= 10; count++) {
    	var mc:MovieClip = bars["bar" + count];
    	timeline.insert(TweenMax.from(mc, duration, {x:"64", alpha:0, ease:Cubic.easeOut}), (count - 1) * 0.1);
    }
    }
    
    var xmlLoader:XMLLoader = new XMLLoader("bioPics-data.xml", {onComplete:onXMLLoadComplete, autoDispose:true});;
    xmlLoader.load();
    var images:Array;
    var displayQueue:Array; //same as "images" array initially, but each time we show a random image, we remove it from this array so that we can make sure the same image never shows twice in a row. We repopulate the array by slicing the images array once displayQueue is empty.
    var curSlide:ContentDisplay;
    
    function onXMLLoadComplete(e:Event):void {
    var queue:LoaderMax = new LoaderMax({maxConnections:1});
    var nativeHolderSize:Rectangle = holderBG.getBounds(holderBG);
    for each (var image:XML in xmlLoader.content.image) {
    	queue.append( new ImageLoader(image.@src, {centerRegistration:true, width:nativeHolderSize.width, height:nativeHolderSize.height, scaleMode:"proportionalInside"}) );
    }
    images = queue.content; //a LoaderMax's "content" is an array of all of its child loaders' content. In this case, a bunch of ContentDisplay objects.
    displayQueue = images.slice();
    
    //choose a random image to load first...
    var randomIndex:int = int(Math.random() * displayQueue.length);
    displayQueue[randomIndex].loader.prioritize(false); //ensures that it is first in the loading queue
    displayQueue[randomIndex].loader.addEventListener(LoaderEvent.COMPLETE, startSlideshow, false, 0, true); //we just want to wait for the first one to load before beginning. The rest can load in the background.
    displayQueue.splice(randomIndex, 1);
    
    queue.load();
    }
    
    function startSlideshow(event:LoaderEvent):void {
    displaySlide(event.target.content);
    }
    
    function showRandom():void {
    if (displayQueue.length == 0) {
    	displayQueue = images.slice();
    }
    var randomIndex:int = int(Math.random() * displayQueue.length);
    displaySlide( displayQueue[randomIndex] );
    displayQueue.splice(randomIndex, 1);
    }
    
    function displaySlide(slide:ContentDisplay):void {
    if (curSlide != null) {
    	holderBG.removeChild(curSlide);
    }
    curSlide = slide;
    holderBG.addChild(slide);
    slide.cacheAsBitmap = true;
    slide.mask = bars;
    bars.width = slide.rawContent.width;
    bars.height = slide.rawContent.height;
    timeline.restart();
    }

    any ideas?

    I was hoping to use this on a larger slide show I support it presents about 1000 images that average about 150k.

  4. Thanks for the help I think we're getting close. I removed some extraneous code and tried to implement your changes.

    Here's what I have now:

     

    //// this is timeline code within a MovieClip////
    
    import com.greensock.*;
    import com.greensock.easing.*;
    import com.greensock.loading.*;
    import flash.display.*;
    import flash.utils.*;
    import flash.events.*;
    import flash.net.*;
    import flash.text.*;
    import flash.geom.*;
    
    var bars:Bars = new Bars();
    var n:int = 0;
    var intCurrentSlide:int;
    var req:URLRequest; 
    var holder:Sprite = new Sprite();
    var loader:ImageLoader;
    var rand:int;
    var nxtNum:int;
    var picNum:String;
    var slideCount:int;
    var xmlLoader:URLLoader;   // slideshow xml loader
    var xmlSlideshow:XML;  // slideshow xml
    var strXMLPath:String = "bioPics-data.xml";
    var slideName:String;
    var duration:Number=.5;
    var prevSlide:String;
    var timeline:TimelineMax;
    
    createTimeline();
    
    xmlLoader = new URLLoader();   
    xmlLoader.addEventListener(Event.COMPLETE, onXMLLoadComplete);
    xmlLoader.load(new URLRequest(strXMLPath));
    
    function onXMLLoadComplete(e:Event):void {
    	xmlLoader.removeEventListener(Event.COMPLETE, onXMLLoadComplete);
    	xmlSlideshow = new XML(e.target.data);     // create new xml with the received data
    	slideCount = xmlSlideshow..image.length();   // get total slide count
    	loadSlide();
    }
    
    function createTimeline():void{
    timeline =new TimelineMax({repeat:1,repeatDelay:5,yoyo:true,onComplete:loadSlide, paused:true});
    for (var count:int = 1; count <=10; count++) {
    	var mc:MovieClip=bars["bar"+count];
    	timeline.append(TweenMax.from(mc, duration, {x:"64", alpha:0, ease:Cubic.easeOut}), -.4);
    	}
    }
    
    function loadSlide():void {
    	rand = Math.ceil(Math.random()* slideCount - 1);
    [b]		loader = new ImageLoader(slideName, {onInit:displaySlide, centerRegistration:true, container:holder});			
    	// the assignment of loader seems to be where I'm getting hung up this is the line 54 in error msg.[/b]
    	loader.load();
    }
    
    function displaySlide(e:Event):void {
    	trace("in displaySlide");
       var bounds:Rectangle = holder.getBounds(holder.parent);
       bars.x = bounds.x;  //bars is a MC in the library
       bars.y = bounds.y;
       bars.cacheAsBitmap = true;
       holder.cacheAsBitmap = true;
       holder.mask = bars;
       bars.width = holder.width;
       bars.height = holder.height;
       holderBG.addChild(holder);  //holderBG is a MC that's placed on stage at author time
       holderBG.addChild(bars);
       timeline.restart();
       }

     

    When I run it I get this error:

    TypeError: Error #1009: Cannot access a property or method of a null object reference.

    at com.greensock.loading.core::LoaderItem/_setRequestURL()[C]

    at com.greensock.loading.core::LoaderItem()[C]

    at com.greensock.loading.core::DisplayObjectLoader()[C]

    at com.greensock.loading::ImageLoader()[C]

    at Bio2/loadSlide()[bio2]

    at Bio2/onXMLLoadComplete()[bio2]

    at flash.events::EventDispatcher/dispatchEventFunction()

    at flash.events::EventDispatcher/dispatchEvent()

    at flash.net::URLLoader/onComplete()

  5. I'm very new to everything greensock. I built a slideshow with a greensock tween the tween is way cool. You can see the slideshow by going here:

    http://www.droolpigs.com/ and clicking the About Us button. The slideshow is fine except that every now and then a slide doesn't align. I was told that I might be able to fix the problem by using loaderMax.

    this is my original code:

    		import com.greensock.*;
    		import com.greensock.easing.*;
    	import flash.display.*;
    	import flash.utils.*;
    	import flash.events.*;
    	import flash.net.*;
    	import flash.text.*;
    
    	var myFont:Font3 = new Font3();
    	var extReq:URLRequest = new URLRequest("bio.txt");
    	var extLoader:URLLoader = new URLLoader();
    	var myFormat:TextFormat = new TextFormat();
    ///		
    	var tf:TextField = new TextField();
    	var tf3:TextField = new TextField();
    	var msk:Sprite = new Sprite();
    	var tl:TimelineMax = new TimelineMax({repeat:-1});	
    ///
    //		var bio:Bio = new Bio();
    		var bars:Bars = new Bars();
    	var n:int = 0;
    	var intCurrentSlide:int;
    	var req:URLRequest; 
      		var holder:Sprite = new Sprite();
    //		var holderBG:HolderBG = new HolderBG();
    	var loader:Loader;
    	var rand:int;
    	var nxtNum:int;
    	var picNum:String;
    	var slideCount:int;
    	var xmlLoader:URLLoader;   // slideshow xml loader
    	var xmlSlideshow:XML;  // slideshow xml
    	var strXMLPath:String = "bioPics-data.xml";
    	var slideName:String;
          var history:Array = new Array();
    		var duration:Number=.5;
    	var prevSlide:String;
    	var timeline:TimelineMax;
    //////////		
    
    	xmlLoader = new URLLoader();   
    	xmlLoader.addEventListener(Event.COMPLETE, onXMLLoadComplete);
    	xmlLoader.load(new URLRequest(strXMLPath));
    
    ///////////// text setup ////////////////////
    tf.x =-285;
    //tf.y =655;
    tf.y=700;
    tf.width = 700;
    tf.height = 800;
    tf.multiline=true;
    tf.wordWrap=true;
    tf.condenseWhite=true;
    
    //tf2
    
    tf3.x =-285;
    tf3.y =660;
    tf3.width = 700;
    tf3.height = 20;
    tf3.htmlText = 'Contact links and Email:      droolpigs.com | myspace site      droolpigs@gmail.com | invisibleblindman@hotmail.com';
    
    addChild(tf);
    addChild(tf3);
    
    
    msk.graphics.beginFill(0x000000);
    msk.graphics.drawRect(0, 0, 700, 165);
    msk.x = -285;
    msk.y = 485;
    msk.graphics.endFill();
    
    extLoader.addEventListener(Event.COMPLETE, textReady);
    
    myFormat.font = myFont.fontName;
    myFormat.color = "0xffaa00";
    //0x77ffaa
    
    
    myFormat.size = 18;
    myFormat.leading = 2.5;
    
    tf.defaultTextFormat=myFormat;
    tf.embedFonts=true;
    tf.alpha=1;
    
    extLoader.load(extReq);
    
    function textReady(e:Event):void {
    tf.cacheAsBitmap=true;
    	msk.cacheAsBitmap=true;
    tf.mask=msk;
    addChild(msk);
    tf.htmlText=e.target.data;
    }
    
    tl.insert( new TweenLite(tf, 70, {y:"-940", ease:Linear.easeNone}) );
    //////////////text setup////////////////////////	
    
    		createTimeline();
    
    	function onXMLLoadComplete(e:Event):void {
    			xmlLoader.removeEventListener(Event.COMPLETE, onXMLLoadComplete);
    			xmlSlideshow = new XML(e.target.data);     // create new xml with the received data
    			slideCount = xmlSlideshow..image.length();   // get total slide count
    			loadSlide();
    	}
    
    
    		function loadSlide():void {
     			prevSlide=history[history.length-1];
    		rand = Math.ceil(Math.random()* slideCount - 1);  
    			loader = new Loader();
    			req = new URLRequest(xmlSlideshow..@src[rand]);
    			loader.contentLoaderInfo.addEventListener(Event.INIT, displaySlide);
    			loader.load(req);
    		slideName = xmlSlideshow..@src[rand].toString();
    
    	if(slideName != prevSlide){
    				history.push(slideName); 
    			loader.load(new URLRequest(xmlSlideshow..@src[rand]));
    
    		}else{
    			loadSlide();
    			}
    	}
    
         	function createTimeline():void{
           timeline =new TimelineMax({repeat:1,repeatDelay:5,yoyo:true,onComplete:loadSlide, paused:true});
           for (var count:int = 1; count <=10; count++) {
               var mc:MovieClip=bars["bar"+count];
               timeline.append(TweenMax.from(mc, duration, {x:"64", alpha:0, ease:Cubic.easeOut}), -.4);
            	}
           }
    
    	function displaySlide(e:Event = null):void {
    		loader.contentLoaderInfo.removeEventListener(Event.INIT, displaySlide);
    		if (holderBG.holder)
    		{
    		holderBG.removeChild(holder);
    		holderBG.holder = null;
    		}
    //			trace ("holder.numChildren "+holder.numChildren);
    			if(holder.numChildren > 0){holder.removeChildAt(0);}
     			holder.addChild(loader.content);
    
    		// center the pic
    		holder.x=holderBG.width/2 - holder.width/2;
    		holder.y=holderBG.height/2 - holder.height/2;
    		// make the mask position over the pic
    		 bars.x=holder.x;
    		 bars.y=holder.y;
    			 bars.cacheAsBitmap=true;
     			holder.cacheAsBitmap=true;
    			holder.mask=bars;
    		 bars.width = holder.width;
    			 bars.height = holder.height;
    		 holderBG.addChild(holder);
    			 holderBG.addChild(bars);
    		timeline.restart();		}

    and this is my feeble attempt to load the slides with loaderMax .

     

    import com.greensock.*;

    import com.greensock.easing.*;

    import com.greensock.loading.ImageLoader;

    import flash.display.*;

    import flash.utils.*;

    import flash.events.*;

    import flash.net.*;

    import flash.text.*;

     

    var myFont:Font3 = new Font3();

    var extReq:URLRequest = new URLRequest("bio.txt");

    var extLoader:URLLoader = new URLLoader();

    var myFormat:TextFormat = new TextFormat();

     

    var bars:Bars = new Bars();

    var n:int = 0;

    var intCurrentSlide:int;

    var req:URLRequest;

    var holder:Sprite = new Sprite();

    // var holderBG:HolderBG = new HolderBG();

    var loader:Loader;

    var rand:int;

    var nxtNum:int;

    var picNum:String;

    var slideCount:int;

    var xmlLoader:URLLoader; // slideshow xml loader

    var xmlSlideshow:XML; // slideshow xml

    var strXMLPath:String = "bioPics-data.xml";

    var slideName:String;

    var history:Array = new Array();

    var duration:Number=.5;

    var prevSlide:String;

    var timeline:TimelineMax;

    //////////

    xmlLoader = new URLLoader();

    xmlLoader.addEventListener(Event.COMPLETE, onXMLLoadComplete);

    xmlLoader.load(new URLRequest(strXMLPath));

     

     

    createTimeline();

     

    function onXMLLoadComplete(e:Event):void {

    xmlLoader.removeEventListener(Event.COMPLETE, onXMLLoadComplete);

    xmlSlideshow = new XML(e.target.data); // create new xml with the received data

    slideCount = xmlSlideshow..image.length(); // get total slide count

    loadSlide();

    }

     

     

    function loadSlide():void {

    prevSlide=history[history.length-1];

    rand = Math.ceil(Math.random()* slideCount - 1);

    var image:ImageLoader = new ImageLoader(xmlSlideshow..@src[rand],

    {container:this,

    x:275, y:240,

    width:600, height:300,

    scaleMode:"proportionalInside",

    centerRegistration:true,

    // blendMode:"overlay",

    bgColor:0x000000,

    rotation:0});

     

    image.load();

    holderBG.addChild(image);

    holderBG.addChild(bars);

     

    // bars.x=image.container.x;

    // bars.y=image.container.y;

    // bars.cacheAsBitmap=true;

    // image.cacheAsBitmap=true;

    // image.mask=bars;

    // bars.width = image.width;

    // bars.height = image.height;

     

    timeline.restart();

     

     

     

    }

     

    function createTimeline():void{

    timeline =new TimelineMax({repeat:1,repeatDelay:5,yoyo:true,onComplete:loadSlide, paused:true});

    for (var count:int = 1; count <=10; count++) {

    var mc:MovieClip=bars["bar"+count];

    timeline.append(TweenMax.from(mc, duration, {x:"64", alpha:0, ease:Cubic.easeOut}), -.4);

    }

    }

     

    Apparently I can't treat the loaderMax instance as a display object and I don't know how to put the tween inside loaderMax.

  6. oops that was dumb.

    I changed to this

     

    import com.demos.*;

     

    var displayImage:ImageLoader_Enhanced = new ImageLoader_Enhanced();

    addChild(displayImage);

     

    but still nothing.

    I also tried as a document class, same blank screen.

     

    it would be nice if there were demo fla's

  7. I copied the code for ImageLoader_Enhanced class form a LoaderMax tutorial I found on the GreenSock site

    this is the code:

    package com.demos {
    
    import com.greensock.loading.ImageLoader;
    import flash.display.Sprite;
    
    public class ImageLoader_Enhanced extends Sprite {
    
    	public function ImageLoader_Enhanced() {
    		var image:ImageLoader = new ImageLoader("bio_pics/0001.jpg",
    												 {container:this,
    												 	x:30, y:100,
    													width:750, height:350,
    													scaleMode:"proportionalInside",
    													centerRegistration:true,
    													blendMode:"overlay",
    													bgColor:0x000000,
    													rotation:0});
    		image.load();
    	}
    }
    }

     

    I created a folder in my com folder called demos and put it there as ImageLoader_Enhanced.as

    I then created a Fla in the same folder as the com and bio_pics folders. In that FLA I run this code:

     

    import com.demos.*;
    
    var displayImage:ImageLoader_Enhanced = new ImageLoader_Enhanced();
    displayImage;

     

    I get no error message so I guess it works but no image is displayed.

  8. I'm trying but it's not working. I still cant get a seamless transition. As soon as it repeats it blanks out the text on stage. Isn't there a way to make textfield1 position below textfield2 as soon as it's moved beyond the mask? I've done that using a timer and as3 before it was pretty simple.

     

    here's the output: http://www.jimslounge.com/textScroll2.swf

     

    here's the code:

     

    import com.greensock.*;
    import com.greensock.easing.*;
    import com.greensock.plugins.*;
    import flash.events.*;
    import flash.net.*;
    import flash.text.*;
    import flash.display.*;
    
    var myFont:Font2 = new Font2();
    var extLoader:URLLoader = new URLLoader();
    var req:URLRequest = new URLRequest("bio.txt");
    var tf1:TextField = new TextField();
    var tf2:TextField = new TextField();
    var tf3:TextField = new TextField();
    var msk1:Sprite = new Sprite();
    var msk2:Sprite = new Sprite();
    var myFormat:TextFormat = new TextFormat();
    var tl:TimelineMax = new TimelineMax({repeat:-1});
    
    tf1.x =50;
    tf1.y =250;
    tf1.width = 650;
    tf1.height = 500;
    tf1.multiline=true;
    tf1.wordWrap=true;
    tf1.condenseWhite=true;
    
    tf2.x =50;
    tf2.y =750;
    tf2.width = 650;
    tf2.height = 500;
    tf2.multiline=true;
    tf2.wordWrap=true;
    tf2.condenseWhite=true;
    
    tf3.x =50;
    tf3.y =253;
    tf3.width = 650;
    tf3.height = 20;
    tf3.htmlText = 'droolpigs.com | myspace site';
    
    this.addChildAt(tf1, 0);
    this.addChildAt(tf2, 0);
    addChild(tf3);
    
    
    msk1.graphics.beginFill(0x000000);
    msk1.graphics.drawRect(0, 0, 650, 170);
    msk1.x = 50;
    msk1.y = 80;
    msk1.graphics.endFill();
    
    msk2.graphics.beginFill(0x000000);
    msk2.graphics.drawRect(0, 0, 650, 170);
    msk2.x = 50;
    msk2.y = 80;
    msk2.graphics.endFill();
    
    
    extLoader.addEventListener(Event.COMPLETE, textReady);
    
    myFormat.font = myFont.fontName;
    myFormat.size = 14;
    myFormat.leading = 2.5;
    
    tf1.defaultTextFormat=myFormat;
    tf1.embedFonts=true;
    tf1.alpha=1;
    tf2.defaultTextFormat=myFormat;
    tf2.embedFonts=true;
    tf2.alpha=1;
    
    extLoader.load(req);
    
    function textReady(e:Event):void {
    tf1.cacheAsBitmap=true;
    tf2.cacheAsBitmap=true;
    	msk1.cacheAsBitmap=true;
    msk2.cacheAsBitmap=true;
    tf1.mask=msk1;
    tf2.mask=msk2;
    addChild(msk1);
    addChild(msk2);
    tf1.htmlText=e.target.data;
    tf2.htmlText=e.target.data;
    
    }
    
    tl.insertMultiple( TweenMax.allTo([tf1, tf2], 20, {y:"-1000", ease:Linear.easeNone}));

  9. It starts out too fast and ends up too slow. You can see it here http://www.jimslounge.com/textScroll2.swf

    here's the code:

     

    import com.greensock.*;
    import com.greensock.easing.*;
    import com.greensock.plugins.*;
    import flash.events.*;
    import flash.net.*;
    import flash.text.*;
    import flash.display.*;
    
    var myFont:Font2 = new Font2();
    var extLoader:URLLoader = new URLLoader();
    var req:URLRequest = new URLRequest("bio.txt");
    var tf:TextField = new TextField();
    var msk:Sprite = new Sprite();
    var myFormat:TextFormat = new TextFormat();
    var timeline:TimelineMax;
    
    tf.x =50;
    tf.y =80;
    tf.width = 300;
    tf.height = 1300;
    tf.multiline=true;
    tf.wordWrap=true;
    tf.condenseWhite=true;
    
    addChild(tf);
    
    	msk.graphics.beginFill(0x000000);
    	msk.graphics.drawRect(0, 0, 300, 150);
    	msk.x = 50;
    	msk.y = 80;
    	msk.graphics.endFill();
    
    
    
    extLoader.addEventListener(Event.COMPLETE, textReady);
    
    myFormat.font = myFont.fontName;
    myFormat.size = 14;
    myFormat.leading = 2.5;
    
    tf.defaultTextFormat=myFormat;
    tf.embedFonts=true;
    tf.alpha=1;
    
    extLoader.load(req);
    
    function textReady(e:Event):void {
    tf.cacheAsBitmap=true;
    msk.cacheAsBitmap=true;
    	tf.mask=msk;
    tf.htmlText=e.target.data;
    addChild(msk);
    }
    TweenLite.to(tf, 50, {y:-1400});
    

×