embedding a Movieclip with flashDevelop - apache-flex

I am trying to embed a movieClip with flashDevelop but apparently its not working because its not recognizing the movieclips that are within it. here is my code
package com.objects{
import flash.display.MovieClip
import flash.text.TextField;
import flash.events.*;
import flash.text.TextFormat;
[Embed(source='../../../lib/fighter.swf', symbol='InfoBox')]
public class InfoBox extends gameObject {
protected var textf:TextField;
protected var s:String;
public var type:Boolean = false;
private var letter:Number = 0;
private var string:Array;
private var line:Number = 0;
private var portNum:Array;
public function InfoBox():void
{
portNum = new Array();
portrait.stop();
x = 400;
y = 550;
string = new Array();
var format = new TextFormat();
format.size = 18;
textf = new TextField();
textf.width = 550;
textf.height = 85;
textf.x = -220;
textf.y = -60;
textf.wordWrap = true;
textf.defaultTextFormat = format;
addChild(textf);
contButton.addEventListener(MouseEvent.MOUSE_DOWN, StoryNext);
}
private function StoryNext(e:MouseEvent):void
{
if(string.length > 1)
{
portNum.splice(0,1);
string.splice(0,1);
trace(string.length);
letter = 0;
}
else
{
contButton.removeEventListener(MouseEvent.MOUSE_DOWN, StoryNext);
dispatchEvent(new Event("StoryContinue"));
}
}
public function textInfo(msg:String,num:Number = 1):void
{
string.push(msg);
portNum.push(num);
}
override public function updateObject():void
{
TypeWords();
}// End UpdateObject
public function TypeWords():void
{
if(type)
{
portrait.gotoAndStop(portNum[0]);
var s:String = string[0];
if(letter <= s.length)
{
textf.text = s.substring(0,letter);
}
letter++
}
}
}
}
and I am getting this error
C:\Users\numerical25\Documents\RealGames\FighterPilot\beta1FlashDev\src\com\objects\InfoBox.as(23): col: 4 Error: Access of undefined property portrait.
portrait is a movie clip that I have inside of the info box movie clip. it is already on the stage and i gave it a instance name of portrait. It worked in flash, but now its not in flashDevelop

Try accessing the childs by name. It should work.
(getChildByName("portrait") as MovieClip).gotoAndStop(portNum[0]);

You need to define the corresponding properties on your class. In this case you can add:
public var portrait:MovieClip;
If it's some other type, for instance a Sprite you can change the definition to that.
EDIT: If you're having trouble setting up Flash Develop, I wrote some tutorials on that

[Embed(source='../../../lib/fighter.swf',
symbol='InfoBox')]
I'd say use SWCs not SWFs, it will make it a ****load easier.
SWCs keep all the stuff in place, whereas the swf can remove assets that are not used to save room.
Also in your flash develop panel you will see the swc (like the swf) and see all the classes that are included. Just right-click on it and add it to library. You won't have to use the [embed] code.
give that a try first, unless you absolutely need an swf.
To create an swc, use the flash tab under publish settings.

you can add linkage name for your MovieClip and export it as SWC, suppose named "mymc"
then copy SWC file to you FD project.
in your code, just addChild(new mymc());

Related

Flex Widgets - Inheritance of styles

I have a main application (Flex 4.6), in which I intend to use any number of widgets. The widgets are .swf files (s:Module OR s:Application, Flex 4.6).
My problem is that the loaded widget does NOT inherit the styles of the application which is using it.
To put it briefly, I load the widget as an .swf file from the sever (using URLLoader class). After downloading it, I create the instances of the widgets (whereas a single widget can be cointained in the main application on several various places - multiply).
In the main application, the following CSS file is used:
<fx:Style source="css/common.css" />
common.css content is:
s|TextInput {
contentBackgroundColor: #9FD1F2;
focusColor: #8FD7F9;
skinClass: ClassReference("skins.textInputTestSkin");
}
s|Label {
color: #2211FF;
}
And this is how I create and load the widgets:
private var bytesLoader:Loader = null;
public var loadedApp:SystemManager = null;
public var loadedModule:Module = null;
...
bytesLoader.addEventListener(Event.COMPLETE, onBytesLoaderComplete);
var context:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain);
bytesLoader.loadBytes(urlLoader.data, context);
...
private function onBytesLoaderComplete(e:Event):void {
var dataContent:DisplayObject = bytesLoader.content;
//(Application)
if(dataContent && (dataContent is SystemManager)) {
loadedApp = dataContent as SystemManager;
loadedApp.addEventListener(FlexEvent.APPLICATION_COMPLETE,appWidgetCreationComplete);
appHolder.addChild(dataContent);
} else if(dataContent is IFlexModuleFactory) {
//(Module)
var moduleLoader:LoaderInfo = LoaderInfo(e.target);
moduleLoader.content.addEventListener("ready", moduleWidgetReadyHandler);
}
}
private function moduleWidgetReadyHandler(e:Event):void {
var factory:IFlexModuleFactory = IFlexModuleFactory(e.target);
if(factory) {
loadedModule = factory.create() as Module;
if(loadedModule) {
this.addElement(loadedModule);
}
}
}
My question is first, in what way can I apply the styles of the parents on the widget and secondly(s:Module), in what way is it possible for me to apply the styles of the parents on the widget (s:Application).
UPDATE 1
If I change getter moduleFactory (as seen below) in every single of the widgets, the styles are set just right. Meaning the textInput in the widget (Module and Application) has the same skin as in the main application.
override public function get moduleFactory():IFlexModuleFactory {
return FlexGlobals.topLevelApplication.moduleFactory;
}
It's workaround? It's good solution?
Ok, here is a solution:
Add before bytesLoader.loadBytes(urlLoader.data, context);
//init - moduleFactory
bytesLoader.contentLoaderInfo.addEventListener(Event.INIT, onContentLoaderInfoInit);
private function onContentLoaderInfoInit(e:Event):void {
if(bytesLoader && bytesLoader.contentLoaderInfo) {
bytesLoader.contentLoaderInfo.removeEventListener(Event.INIT, onContentLoaderInfoInit);
}
var loaderInfo:LoaderInfo = LoaderInfo(e.target);
loaderInfo.content.addEventListener(Request.GET_PARENT_FLEX_MODULE_FACTORY_REQUEST, onGetParentModuleFactoryRequest);
}
private function onGetParentModuleFactoryRequest(r:Request):void {
if(isGlobalStyleAllowed) {
if ("value" in r) {
r["value"] = FlexGlobals.topLevelApplication.moduleFactory;
}
}
//remove eventListener
if(bytesLoader && bytesLoader.contentLoaderInfo) {
var loaderInfo:LoaderInfo = LoaderInfo(bytesLoader.contentLoaderInfo);
loaderInfo.content.removeEventListener(Request.GET_PARENT_FLEX_MODULE_FACTORY_REQUEST, onGetParentModuleFactoryRequest);
}
}
It's works.

Flex: how to change the volume of an EMBEDDED sound?

Searching for how to change the volume of sounds, I always get this irritating snd=new Sound(URLRequest), followed by snd.setVolume(val). Oh, fine, but my sound is not an URLRequest, it's an embed.
I've made a lot of random attempts (1) to no avail. How am I supposed to do that instead?
(1) including casting my class to Sound, creating a Sound with the embed class as argument, creating a SoundTransform and setting it to the channel, etc.
Instantiate your embedded class like this:
[Embed(source="MySound.mp3")]
public var soundClass:Class;
protected function application1_creationCompleteHandler(event:FlexEvent):void
{
var smallSound:Sound = new soundClass() as Sound;
var trans:SoundTransform = new SoundTransform(.01);
smallSound.play(0,0,trans);
}
Update:
In case what you really wanted to know was how to change the volume if the sound was already playing:
[Embed(source="MySound.mp3")]
public var soundClass:Class;
public var smallSound : Sound;
public var vol : Number = 0.01;
public var trans : SoundTransform;
public var chan : SoundChannel = new SoundChannel();
protected function application1_creationCompleteHandler(event:FlexEvent):void {
smallSound = new soundClass() as Sound;
trans = new SoundTransform(vol);
chan = smallSound.play(0,0,trans);
}
protected function volUp_clickHandler(event:MouseEvent):void {
vol += .1;
trans = new SoundTransform(vol);
chan.soundTransform = trans;
}

What event is fired when all SkinSparts are available in a SkinnableComponent?

I'm (slowly) learning Flex 4 and working on skinning a custom component that extends SkinnableComponent. The component is all in ActionScript and essentially looks like this:
package components
{
import spark.components.supportClasses.SkinnableComponent
[SkinState("normal")]
[SkinState("over")]
[SkinState("selected")]
public class AccountSummary extends SkinnableComponent
{
[Bindable]
public var itemIndex:int = 0;
[Bindable]
public var accountName:String = "";
[Bindable]
public var accountNumber:String = "";
[Bindable]
public var currentBalance:String = "";
[SkinPart(required="true")]
public var lblAccountName:Label;
[SkinPart(required="true")]
public var lblCurrentBalance:Label;
[SkinPart(required="true")]
public var lblAccountNumber:Label;
[SkinPart(required="true")]
public var lblLastUpdated:Label;
public function AccountSummary()
{
super();
lblAccountName.text = accountName;
lblCurrentBalance.text = currentBalance;
lblAccountNumber.text = "Acc: " + accountNumber;
lblLastUpdated.text = "Last Updated: ";
}
override protected function getCurrentSkinState():String
{
return "normal";
}
}
}
The issue I'm having is on NULL REFERENCES in the Constructor for the various SkinParts, because they're not created yet. I'm trying to find out when is the best time to access them to assign their .text values. I know I can override partAdded() and add the .text value as each part is added, but I'd rather just listen for some magic event that is dispatched when they're all available.
I'm not sure whether or not it matters, but the accountName, accountNumber variables are assigned by using a repeater with a dataProvider on the host component. I'm not sure if that too has something to do with when the data is available to the AccountSummary component - which may also needed to be waited on. I was able to successfully use FlexEvent.CREATION_COMPLETE to assign all my .text values to the SkinParts, but is that the right event/best practice? Any help would be greatly appreciated!
You need to read up on the Flex 4 Component LifeCycle, specifically the piece about component instantiation. Nothing will be created at the time the constructor executes. The values you are referencing (accountName, lblCurrentBalance. etc...) will not have moved beyond the default states either.
You want to set your default values in the partAdded() method. Rewrite your constructor code to something like this:
public function AccountSummary()
{
super();
}
override protected function partAdded(partName : String, instance: Object):void{
super.partAdded(partName, instance);
if(instance == lblAccountName){
lblAccountName.text = accountName;
else if(instance == lblCurrentBalance){
} else if (instance == lblCurrentBalance){
lblCurrentBalance.text = currentBalance;
} else if (instance == lblAccountNumber){
lblAccountNumber.text = "Acc: " + accountNumber;
} else if (instance == lblLastUpdated){
lblLastUpdated.text = "Last Updated: ";
}
}
If you're a new programmer, you may want to devote some time to learning some basic programming concepts. This ActionScript 3 Guide may help you get started. If you have experience in other languages, but are new to Flex, I strongly suggest spending a couple of days reading through the full flex documentation to help get your head around it.

How to trigger a function only once in case of a mouseEvent

I am trying to make a simple mp3 player using flash. The songs are loaded using an XML file which contains the song list. I have "play" button with the instance name "PlayBtn". I have an actionscript file named "playctrl", the content of which are listed below:
package classes
{
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.events.*;
import flash.events.MouseEvent;
import flash.net.URLRequest;
public class playctrl
{
private var MusicLoading:URLRequest;
private var music:Sound;
private var sc:SoundChannel;
private var currentSound:Sound;
private static var CurrentPos:Number;
private var xml:XML;
private var songlist:XMLList;
private static var currentIndex:Number;
public function playctrl()
{
music = new Sound();
currentSound= music;
CurrentPos = 0;
currentIndex = 0;
}
public function success(e:Event):void
{
xml = new XML(e.target.data);
songlist = xml.song;
MusicLoading = new URLRequest(songlist[0].file);
music.load(MusicLoading);
}
public function playSong(e:Event):void
{
if(sc != null)
sc.stop();
sc = currentSound.play(CurrentPos);
trace("HELLO !!!");
}
}
}
I have a second file named "play.as", the content of which is listed below:
import classes.playctrl;
var obj:playctrl = new playctrl();
var XMLLoader:URLLoader = new URLLoader(); //XML Loader
XMLLoader.addEventListener(Event.COMPLETE, obj.success);
XMLLoader.load(new URLRequest("playlist.xml"));
PlayBtn.addEventListener(MouseEvent.CLICK, obj.playSong);
However on clicking the play button, I notice that the function playSong() is called 7-8 times(check by printing an error msg. inside the function) resulting in overlapped audio output and the player crashing as a result. The function should be called only once when the MouseEvent.CLICK is triggered. Please help ...
interestingly, sound object doesn't have a built-in "isPlaying" boolean property (strange), so you could just create your own.
var isPlaying:Boolean
function playSong():void
{
if(!isPlaying)
sound.play();
}
function stopSong():void
{
if(isPlaying)
{
channel.stop();
isPlaying = false;
}
just a note: by convention, class names are capitalized camel case while instance names are uncapitalized camel case. so your playctrl.as class file should (or could) be PlayCtrl.as, and your PlayBtn instance should (or could) be playBtn.
Edit:
The title of your question is a bit misleading, the answer I gave you is a solution to the question expressed in the title.
Looking at your code, I would look at separating the concerns, on one hand you want to load the song data, on the other hand you want to control the sounds. I would implement separate classes for each concern. If you create a separate class for your player control, you'll be able to dispatch event within that class without the event bubbling all over your app and calling your functions several times.
//Previous answer
You could do this by implementing a Boolean that would be set when the sound is stopped or played.
In any case here's another way to filter unwanted clicks
private function playSong(event:MouseEvent ):void
{
// set up a conditional to identify your button ,
// here's an example...
if( event.currentTarget.name is "PlayBtn" )
{
//do whatever
//then...
event.stopImmediatePropagation();
}
}
This being said, in your case , it sounds like a bit of a quick fix since a MouseEvent shouldn't trigger the play function several times...
It would make sense to debug your code in order to understand why several events are dispatched after a Mouse click
private var _isPlaying:Boolean;
public function playSong(e:Event):void
{
if(sc != null)
{
sc.stop();
_isPlaying = false;
}
if( !_isPlaying )
{
sc = currentSound.play(CurrentPos);
_isPlaying = true;
trace("HELLO !!!");
}
}

How does one define a default style for a custom Flex component?

I'm creating a new Flex component (Flex 3). I'd like it to have a default style. Is there a naming convention or something for my .cs file to make it the default style? Am I missing something?
Christian's right about applying the CSS, but if you're planning on using the component in a library across projects, you're gonna want to write a default css file for that library. Here's how you do it:
Create a css file called "defaults.css" (Only this file name will work!) and put it at the top level under the "src" folder of your library. If the css file references any assets, they have to be under "src" as well.
(IMPORTANT!) Go to library project's Properties > Flex Library Build Path > Assets and include the css file and all assets.
That's how the Adobe team sets up all their default styles, now you can do it too. Just figured this out- huge
Two ways, generally. One's just by referencing the class name directly -- so for example, if you'd created a new component class MyComponent in ActionScript, or indirectly by making an MXML component extending another UIComponent called MyComponent, in both cases, the component would pick up the styles declared in your external stylesheet, provided that stylesheet's been imported into your application (e.g., via Style source):
MyComponent
{
backgroundColor: #FFFFFF;
}
Another way is by setting the UIComponent's styleName property (as a string):
public class MyComponent
{
// ...
this.styleName = "myStyle";
// ...
}
... and defining the style in the CSS file like so (note the dot notation):
.myStyle
{
backgroundColor: #FFFFFF;
}
Make sense?
In addition to what Christian Nunciato suggested, another option is to define a static initializer for your Flex component's styles. This allows you to set the default styles without requiring the developer to include a CSS file.
private static function initializeStyles():void
{
var styles:CSSStyleDeclaration = StyleManager.getStyleDeclaration("ExampleComponent");
if(!styles)
{
styles = new CSSStyleDeclaration();
}
styles.defaultFactory = function():void
{
this.exampleNumericStyle = 4;
this.exampleStringStyle = "word to your mother";
this.exampleClassStyle = DefaultItemRenderer //make sure to import it!
}
StyleManager.setStyleDeclaration("ExampleComponent", styles, false);
}
//call the static function immediately after the declaration
initializeStyles();
A refinement of what joshtynjala suggested:
public class CustomComponent extends UIComponent {
private static var classConstructed:Boolean = classConstruct();
private static function classConstruct():Boolean {
if (!StyleManager.getStyleDeclaration("CustomComponent")) {
var cssStyle:CSSStyleDeclaration = new CSSStyleDeclaration();
cssStyle.defaultFactory = function():void {
this.fontFamily = "Tahoma";
this.backgroundColor = 0xFF0000;
this.backgroundAlpha = 0.2;
}
StyleManager.setStyleDeclaration("CustomComponent", cssStyle, true);
}
return true;
}
}
I've read this in the docs somewhere; the classContruct method gets called automatically.
You may want to override default styles using the <fx:Style> tag or similar. If that's the case, a CSSStyleDeclaration may already exist by the time classConstructed is checked. Here's a solution:
private static var classConstructed:Boolean = getClassConstructed ();
private static function getClassConstructed ():Boolean {
var defaultCSSStyles:Object = {
backgroundColorGood: 0x87E224,
backgroundColorBad: 0xFF4B4B,
backgroundColorInactive: 0xCCCCCC,
borderColorGood: 0x333333,
borderColorBad: 0x333333,
borderColorInactive: 0x666666,
borderWeightGood: 2,
borderWeightBad: 2,
borderWeightInactive: 2
};
var cssStyleDeclaration:CSSStyleDeclaration = FlexGlobals.topLevelApplication.styleManager.getStyleDeclaration ("StatusIndicator");
if (!cssStyleDeclaration) {
cssStyleDeclaration = new CSSStyleDeclaration ("StatusIndicator", FlexGlobals.topLevelApplication.styleManager, true);
}
for (var i:String in defaultCSSStyles) {
if (cssStyleDeclaration.getStyle (i) == undefined) {
cssStyleDeclaration.setStyle (i, defaultCSSStyles [i]);
}
}
return (true);
}
To create a default style you can also have a property in your class and override the styleChanged() function in UIComponent, eg to only draw a background color across half the width of the component:
// this metadata helps flex builder to give you auto complete when writing
// css for your CustomComponent
[Style(name="customBackgroundColor", type="uint", format="color", inherit="no")]
public class CustomComponent extends UIComponent {
private static const DEFAULT_CUSTOM_COLOR:uint = 0x00FF00;
private var customBackgroundColor:uint = DEFAULT_CUSTOM_COLOR;
override public function styleChanged(styleProp:String):void
{
super.styleChanged(styleProp);
var allStyles:Boolean = (!styleProp || styleProp == "styleName");
if(allStyles || styleProp == "customBackgroundColor")
{
if(getStyle("customBackgroundColor") is uint);
{
customBackgroundColor = getStyle("customBackgroundColor");
}
else
{
customBackgroundColor = DEFAULT_CUSTOM_COLOR;
}
invalidateDisplayList();
}
// carry on setting any other properties you might like
// check out UIComponent.styleChanged() for more examples
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
graphics.clear();
graphics.beginFill(customBackgroundColor);
graphics.drawRect(0,0,unscaledWidth/2,unscaledHeight);
}
}
You could also create a setter for the customBackgroundColor that called invalidateDisplayList(), so you could also set the customBackgroundColor property programatically as well as through css.

Resources