Go Back   kirupaForum > Flash > ActionScript 3

Reply
 
Thread Tools Display Modes
Old 07-11-2006, 06:36 PM   #76
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Approach to Depth Sorting

Because of how the display list works with ActionScript 3, some methods of depth sorting will no longer work. One in particular is sorting objects on the screen based on their y location. In ActionScript 1 and 2, you could simply tell the clip to swapDepths at its _y location and be done with it. With AS3, this is no longer possible since no gaps can exist within the depths display list ("array").

An approach to obtaining the same functionality in AS3 is possible through an sorted array. Store the objects you want to arrange in an array. Then sort that array based on the y properties of the display objects within. All you have to do after that is place them in the display list in the order sorted. Ex:
Code:
var sortedItems:Array = new Array(mc1, mc2, mc3);
function arrange():void {
	sortedItems.sortOn("y", Array.NUMERIC);
	var i:int = sortedItems.length;
	while(i--){
		if (getChildIndex(sortedItems[i]) != i) {
			setChildIndex(sortedItems[i], i);
		}
	}
}
Here the sortedItems array stores the display objects being sorted (mc1 - mc3). In the arrange function, that array is sorted based on their y properties and then added to the display list at their locations within the array (if not already there).

Though this is not quite as easy as swaping to the depth of the _y property, it still proves a fairly efficient means of sorting objects on the screen based on their y location.

__________________
senocular is offline   Reply With Quote
Old 07-12-2006, 12:39 AM   #77
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Deep Object Copies with ByteArray

Using the new ByteArray (flash.utils.ByteArray) class in ActionScript 3, you can now easily create deep object copies. By deep, I mean being able to create copies not of just a single object and all its references, but also all the objects it references. This means if you use this method to copy an array which references an object, that object will also be copied as part of the copy procedure. Such a copy (clone) method would look like the following:
Code:
function clone(source:Object):* {
	var copier:ByteArray = new ByteArray();
	copier.writeObject(source);
	copier.position = 0;
	return(copier.readObject());
}
Note: you may need to import flash.utils.ByteArray;

To use this function simply say:
Code:
newObjectCopy = clone(originalObject);
Though this will make a deep copy of your objects, be aware that it does not retain class association. So, if you try to copy a MyClass instance, the copy will no longer be recognized as being of MyClass. This method is best used with generic objects.

__________________
senocular is offline   Reply With Quote
Old 07-12-2006, 10:38 AM   #78
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Similarly Named Instance and Static Properties

In ActionScript 1, you could have static properties of a class with the same name as instance properties. ActionScript 2 then came along and added a restriction preventing you from being able to do that. Now, with ActionScript 3, it is now again possible to have static properties with the same name as instance properties.
Code:
package {
	
	import flash.display.Sprite;
	
	public class MyApp extends Sprite {
	
		private var variable:String;
		private static var variable:String;
			
		public function MyApp() {			
			this.variable = "foo";
			MyApp.variable = "bar";
			
			trace(this.variable); // "foo"
			trace(MyApp.variable); // "bar"
			trace(variable); // "foo"
		}
	}
}

__________________
senocular is offline   Reply With Quote
Old 07-14-2006, 12:05 AM   #79
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
EventDispatcher

ActionScript 3 uses the EventDispatcher (flash.events.EventDispatcher) class for all event handling. This class was available in ActionScript 2, but it existed as an external class in the mx framework. Now, it is built into the player (and in being so, improves performance).

Whenever you want to create an event handler to be called during a certain event, whether it be every frame (enterFrame event), or at the press of a button (mouseDown event), in AS 3, you will need to use EventDispatcher. This means there are no more onEnterFrame of onPress functions you can define that will automatically handle these events, nor are there any simple addListener methods for generalized event listening. EventDispatcher and addEventListener (and related methods) does it all.

Methods
  • addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void
  • dispatchEvent(event:Event):Boolean
  • hasEventListener(type:String):Boolean
  • removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void
  • willTrigger(type:String):Boolean

Note that addEventListener only takes functions as listeners, not objects. Also remember that class methods are bound to their instances so when used as listeners, 'this' in the event call still references the orginal class instance no matter what object dispatched the event.

Basic Example:
Code:
package {
	
	import flash.display.Sprite;
	import flash.events.Event;
	
	public class MyDispatcher extends Sprite {
		
		public function MyDispatcher() {
			addEventListener("customEvent", handleEvent);
			dispatchEvent(new Event("customEvent"));
		}
		
		private function handleEvent(event:Event):void {
			trace(event.type); // "customEvent"
		}
	}
}
By extending the EventDispatcher class or any class that inherits from it like Sprite (all DisplayObjects are inherently EventDispatchers), your class gains access to the EventDispatcher methods. Then, other instances (or the class instance itself) can add methods to instances of that class using addEventListener and in turn they can call those events through dispatchEvent.

If there is some reason your class cannot inherit from the EventDispatcher class (for example, if its already inheriting from another class which does not inherit from EventDispatcher), then you can use the EventDispatcher constructor to intialize your class instance with the methods of EventDispatcher via aggregation (composition). Just make sure you implement the IEventDispatcher interface (flash.events.IEventDispatcher). Ex:
Code:
package {
	
	import flash.display.Sprite;
	import flash.events.Event;
	
	public class MyDispatcher extends Sprite {
		
		public function MyDispatcher() {
			var dispatcher:CustomDispatcher = new CustomDispatcher();
			dispatcher.addEventListener("customEvent", handleEvent);
			dispatcher.dispatchEvent(new Event("customEvent"));
		}
		
		private function handleEvent(event:Event):void {
			trace(event.type); // "customEvent"
		}
	}
}

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.IEventDispatcher;

class CustomDispatcher implements IEventDispatcher {

	private var eventDispatcher:EventDispatcher;
		
	public function CustomDispatcher() {
		eventDispatcher = new EventDispatcher(this);
	}
	
	public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void {
		eventDispatcher.addEventListener(type, listener, useCapture, priority, useWeakReference);
	}
	public function dispatchEvent(event:Event):Boolean {
		return eventDispatcher.dispatchEvent(event);
	}
			
	public function hasEventListener(type:String):Boolean {
		return eventDispatcher.hasEventListener(type);
	}
			
	public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void {
		eventDispatcher.removeEventListener(type, listener, useCapture);
	}
			
	public function willTrigger(type:String):Boolean {
		return eventDispatcher.willTrigger(type);
	}
}
The CustomDispatcher helper class above doesn't inherit from EventDispatcher but uses aggregation to obtain EventDispatcher functionality through an instance of EventDispatcher initialized in the constructor.

__________________
senocular is offline   Reply With Quote
Old 07-14-2006, 02:00 AM   #80
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Events and Event Types

Event objects used with EventDispatcher in ActionScript 3 are a little less generic than those used with ActionScript 2. In AS 3, each event object has its own class. The most common event classes are Event (flash.events.Event) for general events and MouseEvent (flash.events.MouseEvent) for events associated with the mouse. Other event classes can be found in the flash.events package, all of which inherit from Event.

When using EventDispatcher.dispatchEvent(), you pass in an Event instance that is specific to the event being dispatched. The type of event dispatched is defined within the Event instance used. For example, dispatching an "enterFrame" event would mean using dispatchEvent with an Event instance instantiated with the type "enterFrame".
Code:
dispatchEvent(new Event("enterFrame"));
When an event handler is executed as a result of this event, that event object is passed into the function as a single argument. Properties from that event can then be extracted to learn more about the event that occured. For example, the type property from the Event class tells which event was dispatched.
Code:
addEventListener("enterFrame", eventHandler);
dispatchEvent(new Event("enterFrame"));
...
private function eventHandler(event:Event):void {
	trace(event.type); // "enterFrame"
}
Though event types are strings, all common Flash events are available in Flash through static constants of the Event classes. The "enterFrame" event type, for example, is accessible using Event.ENTER_FRAME. Mouse events are within the MouseEvent class. Click events, for example, are MouseEvent.CLICK. These constants are prefered over their string representations.
Code:
addEventListener(Event.ENTER_FRAME, eventHandler);
dispatchEvent(new Event(Event.ENTER_FRAME));
When making your custom Events, you can use the Event object with a custom type or alternatively, extend the Event class creating a new kind of Event instance to be used with your events.

__________________
senocular is offline   Reply With Quote
Old 07-14-2006, 04:28 PM   #81
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Writing Inline XML

In ActionScript 3, you can define XML variables using inline XML in your script. You don't even need to enclose it in Strings like you did in previous versions of ActionScript. The ActionScript 3 compiler will automatically parse the XML in the code and recognize when it stops and when normal AS code starts.

Code:
var myXml:XML = 
        <body>
            <!-- comment -->
            text1
            <a>
                <b>text2</b>
            </a>
        </body>;

__________________
senocular is offline   Reply With Quote
Old 07-14-2006, 07:45 PM   #82
gerardo
Registered User
Hey senocular, jus wondering if you can post something about the new URLLoader and URLRequest use with PHP. Thanks in advance.
gerardo is offline   Reply With Quote
Old 07-14-2006, 07:51 PM   #83
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Quote:
Originally Posted by gerardo
Hey senocular, jus wondering if you can post something about the new URLLoader and URLRequest use with PHP. Thanks in advance.
If you have a specific question, post a new thread about it in the forum

__________________
senocular is offline   Reply With Quote
Old 07-17-2006, 09:53 AM   #84
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
Determine Instance Class or Superclass

ActionScript 3 lets you easily obtain any instances class name using a new function called getQualifiedClassName (flash.utils.getQualifiedClassName).
Code:
var sprite:Sprite = new Sprite();
trace(getQualifiedClassName(sprite)); // "flash.display::Sprite"
You can also use the getQualifiedSuperclassName (flash.utils.getQualifiedSuperclassName) function to find its superclass
Code:
trace(getQualifiedSuperclassName(sprite)); // "flash.display::DisplayObjectContainer"
If you want to go backwards, and convert a string into an actual class reference, you can use getDefinitionByName (flash.utils.getDefinitionByName).
Code:
trace(getDefinitionByName("flash.display::Sprite")); // [class Sprite]
Also see describeType() (flash.utils.describeType) in the following post...

__________________
senocular is offline   Reply With Quote
Old 07-17-2006, 12:03 PM   #85
devonair
Registered User
that's beautiful.. so much better than typeof.. Though I might also add (if I may), if you want some extremely (almost stupid amount of) detailed info about your class type, you can also use describeType()..

so
[AS]var sprite:Sprite = new Sprite();
var spriteDescription:XML = describeType(sprite);
trace (spriteDescription);[/AS]

traces:
Code:
<type name="flash.display::Sprite" base="flash.display::DisplayObjectContainer" isDynamic="false" isFinal="false" isStatic="false">
  <extendsClass type="flash.display::DisplayObjectContainer"/>
  <extendsClass type="flash.display::InteractiveObject"/>
  <extendsClass type="flash.display::DisplayObject"/>
  <extendsClass type="flash.events::EventDispatcher"/>
  <extendsClass type="Object"/>
  <implementsInterface type="flash.events::IEventDispatcher"/>
  <implementsInterface type="flash.display::IBitmapDrawable"/>
  <accessor name="buttonMode" access="readwrite" type="Boolean" declaredBy="flash.display::Sprite"/>
  <accessor name="soundTransform" access="readwrite" type="flash.media::SoundTransform" declaredBy="flash.display::Sprite"/>
  <accessor name="useHandCursor" access="readwrite" type="Boolean" declaredBy="flash.display::Sprite"/>
  <method name="stopDrag" declaredBy="flash.display::Sprite" returnType="void"/>
  <accessor name="dropTarget" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::Sprite"/>
  <accessor name="graphics" access="readonly" type="flash.display::Graphics" declaredBy="flash.display::Sprite"/>
  <accessor name="hitArea" access="readwrite" type="flash.display::Sprite" declaredBy="flash.display::Sprite"/>
  <method name="startDrag" declaredBy="flash.display::Sprite" returnType="void">
    <parameter index="1" type="Boolean" optional="true"/>
    <parameter index="2" type="flash.geom::Rectangle" optional="true"/>
  </method>
  <method name="swapChildren" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    <parameter index="2" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <accessor name="tabChildren" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObjectContainer"/>
  <method name="getObjectsUnderPoint" declaredBy="flash.display::DisplayObjectContainer" returnType="Array">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <method name="getChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="int" optional="false"/>
  </method>
  <method name="removeChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="int" optional="false"/>
  </method>
  <method name="getChildIndex" declaredBy="flash.display::DisplayObjectContainer" returnType="int">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="areInaccessibleObjectsUnderPoint" declaredBy="flash.display::DisplayObjectContainer" returnType="Boolean">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <method name="contains" declaredBy="flash.display::DisplayObjectContainer" returnType="Boolean">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <accessor name="mouseChildren" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObjectContainer"/>
  <method name="removeChild" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="setChildIndex" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    <parameter index="2" type="int" optional="false"/>
  </method>
  <method name="addChildAt" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
    <parameter index="2" type="int" optional="false"/>
  </method>
  <accessor name="numChildren" access="readonly" type="int" declaredBy="flash.display::DisplayObjectContainer"/>
  <method name="addChild" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <method name="getChildByName" declaredBy="flash.display::DisplayObjectContainer" returnType="flash.display::DisplayObject">
    <parameter index="1" type="String" optional="false"/>
  </method>
  <accessor name="textSnapshot" access="readonly" type="flash.text::TextSnapshot" declaredBy="flash.display::DisplayObjectContainer"/>
  <method name="swapChildrenAt" declaredBy="flash.display::DisplayObjectContainer" returnType="void">
    <parameter index="1" type="int" optional="false"/>
    <parameter index="2" type="int" optional="false"/>
  </method>
  <accessor name="doubleClickEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="contextMenu" access="readwrite" type="flash.ui::ContextMenu" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="accessibilityImplementation" access="readwrite" type="flash.accessibility::AccessibilityImplementation" declaredBy="flash.display::InteractiveObject">
    <metadata name="Inspectable">
      <arg key="environment" value="none"/>
    </metadata>
  </accessor>
  <accessor name="mouseEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="focusRect" access="readwrite" type="Object" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="tabIndex" access="readwrite" type="int" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="tabEnabled" access="readwrite" type="Boolean" declaredBy="flash.display::InteractiveObject"/>
  <accessor name="alpha" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="scale9Grid" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
  <accessor name="name" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
  <accessor name="filters" access="readwrite" type="Array" declaredBy="flash.display::DisplayObject"/>
  <accessor name="y" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="rotation" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="scrollRect" access="readwrite" type="flash.geom::Rectangle" declaredBy="flash.display::DisplayObject"/>
  <accessor name="x" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="cacheAsBitmap" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
  <accessor name="accessibilityProperties" access="readwrite" type="flash.accessibility::AccessibilityProperties" declaredBy="flash.display::DisplayObject"/>
  <method name="globalToLocal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <method name="getBounds" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <accessor name="opaqueBackground" access="readwrite" type="Object" declaredBy="flash.display::DisplayObject"/>
  <method name="hitTestPoint" declaredBy="flash.display::DisplayObject" returnType="Boolean">
    <parameter index="1" type="Number" optional="false"/>
    <parameter index="2" type="Number" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
  </method>
  <accessor name="visible" access="readwrite" type="Boolean" declaredBy="flash.display::DisplayObject"/>
  <accessor name="mouseX" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="mask" access="readwrite" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
  <method name="getRect" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Rectangle">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <accessor name="scaleX" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="scaleY" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="root" access="readonly" type="flash.display::DisplayObject" declaredBy="flash.display::DisplayObject"/>
  <accessor name="loaderInfo" access="readonly" type="flash.display::LoaderInfo" declaredBy="flash.display::DisplayObject"/>
  <method name="hitTestObject" declaredBy="flash.display::DisplayObject" returnType="Boolean">
    <parameter index="1" type="flash.display::DisplayObject" optional="false"/>
  </method>
  <accessor name="transform" access="readwrite" type="flash.geom::Transform" declaredBy="flash.display::DisplayObject"/>
  <accessor name="width" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="stage" access="readonly" type="flash.display::Stage" declaredBy="flash.display::DisplayObject"/>
  <accessor name="parent" access="readonly" type="flash.display::DisplayObjectContainer" declaredBy="flash.display::DisplayObject"/>
  <accessor name="height" access="readwrite" type="Number" declaredBy="flash.display::DisplayObject"/>
  <method name="localToGlobal" declaredBy="flash.display::DisplayObject" returnType="flash.geom::Point">
    <parameter index="1" type="flash.geom::Point" optional="false"/>
  </method>
  <accessor name="mouseY" access="readonly" type="Number" declaredBy="flash.display::DisplayObject"/>
  <accessor name="blendMode" access="readwrite" type="String" declaredBy="flash.display::DisplayObject"/>
  <method name="removeEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
    <parameter index="1" type="String" optional="false"/>
    <parameter index="2" type="Function" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
  </method>
  <method name="addEventListener" declaredBy="flash.events::EventDispatcher" returnType="void">
    <parameter index="1" type="String" optional="false"/>
    <parameter index="2" type="Function" optional="false"/>
    <parameter index="3" type="Boolean" optional="true"/>
    <parameter index="4" type="int" optional="true"/>
    <parameter index="5" type="Boolean" optional="true"/>
  </method>
  <method name="toString" declaredBy="flash.events::EventDispatcher" returnType="String"/>
  <method name="dispatchEvent" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
    <parameter index="1" type="flash.events::Event" optional="false"/>
  </method>
  <method name="hasEventListener" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
    <parameter index="1" type="String" optional="false"/>
  </method>
  <method name="willTrigger" declaredBy="flash.events::EventDispatcher" returnType="Boolean">
    <parameter index="1" type="String" optional="false"/>
  </method>
</type>
I just love AS3... really, I do...

__________________
flash a-go-go | schwag
devonair is offline   Reply With Quote
Old 07-17-2006, 12:10 PM   #86
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
I was going to save that as a tip for another day but thanks

__________________
senocular is offline   Reply With Quote
Old 07-17-2006, 12:35 PM   #87
McGuffin
Registered User
 
McGuffin's Avatar
Sen, question about getDefinitionByName(). Does the class need to be hardcoded into the file before using the returned value for getDefinitionByName()? Example:

I have a pageType field in a MySQL database that tells the Flash site which page template to use for its pages. Homepage, Aboutpage, etc. I use:

Code:
var className:String = "pages."+_root.pageDatabase.getPageType(i);
var theStringClass:Function = mx.utils.ClassFinder.findClass(className);
_root["pageInstance"+i] = new theStringClass();
To create each page. The problem is, I need to hardcode an instance of each of these page classes into my site so that file will load and keep the class.

Code:
var homepagedisplay = new pages.Homepage();
delete homepagedisplay;
I'd like to skip that step, seeing as how I could have it completely dynamic if I didn't have to hardcode in anything.
McGuffin is offline   Reply With Quote
Old 07-17-2006, 01:04 PM   #88
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
You should need to at least import the needed classes into your file if not native player classes. If you dont, Flash will not have them in the SWF to use. With AS3, instantiation shouldnt be required (and really, with AS2, it wasnt either as long as you used the class reference somewhere).

__________________
senocular is offline   Reply With Quote
Old 07-17-2006, 01:08 PM   #89
devonair
Registered User
Quote:
Originally Posted by senocular
I was going to save that as a tip for another day but thanks
whoops.. sorry - seemed to fit the topic...

__________________
flash a-go-go | schwag
devonair is offline   Reply With Quote
Old 07-17-2006, 01:09 PM   #90
senocular
On Vacation
 
senocular's Avatar
Location San Francisco, CA (USA)

Posts 17,426
I almost added it as part of that one, but I was starting to get a little thin on topics, and since they were every day I'm going to try to stretch them out. Not a big deal

__________________
senocular is offline   Reply With Quote
Reply


Currently Active Users Viewing This Thread: 34 (1 members and 33 guests)
Uli
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 10:21 AM.

SHARE:

SUPPORTERS:

cdn
content delivery network (cdn)

Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd. Copyright 2010 - kirupa.com Copyright 2010 - kirupa.com