Announcement

Collapse
No announcement yet.

[SOLVED] CLIKWidget not initialized: What's wrong?!

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    [SOLVED] CLIKWidget not initialized: What's wrong?!

    Hi there! Since I don't have much time for my project, I wanted to utilize the GFxUDKFrontEnd for my menu. I'm just learning UnrealScript and don't know the first thing about ActionScript, and up until now, I didn't need to.
    My project requires the user to input a name and the dialog that would fit best for this is the GFxUDKFrontEnd_PasswordDialog.uc found in UTGame. The problem is: the input CLIKWidget isn't recognized by the WidgetInitialized event.
    This is all in the UDK, I'll show you what I mean and hope somebody can help:

    First the relevant stuff from the GFxUDKFrontEnd_PasswordDialog.uc

    Code:
    class GFxUDKFrontEnd_PasswordDialog extends GFxUDKFrontEnd_Dialog;    
    
    
    /** Reference to the password renderer. */
    var GFxClikWidget PasswordRendererMC;
    
    
    /** Reference to the input textField within the password renderer. */
    var GFxObject PasswordTextField;
    
    /////////////////////
    // all the functions
    /////////////////////
    
    event bool WidgetInitialized( name WidgetName, name WidgetPath, GFxObject Widget )
    {
        local bool bWasHandled;
        bWasHandled = false;
    
    
        // `log("GFxUDKFrontEnd_PasswordDialog: " @ WidgetName @ " : " @ WidgetPath @ " : " @ Widget);
        switch(WidgetName)
        {
            case ( 'item1' ):             //NOTE: 'item1' isn't recognized
                if ( PasswordRendererMC == none )
                {
                    PasswordRendererMC = GFxClikWidget(Widget);
                    PasswordRendererMC.SetString("label", "PASSWORD:");
                    PasswordTextField = GFxClikWidget(PasswordRendererMC.GetObject("textinput", class'GFxClikWidget'));
                    bWasHandled = true;
                }
                break;
    
               /////////////////////
               // some more cases
               /////////////////////
    
            default:
                break;
        }
           
        if (!bWasHandled)          //NOTE: in the UDK there is actually a bug here (MISSING EXCLAMATION MARK ! )
        {
            bWasHandled = Super.WidgetInitialized(WidgetName, WidgetPath, Widget);
        }
    
    
        return bWasHandled;
    }
    
    
    defaultproperties
    {
        // Password Dialog
        SubWidgetBindings.Add((WidgetName="item1",WidgetClass=class'GFxClikWidget'))
    }
    When you open up this class, the first thing you need to do is to fix a bug, that someone left there. At the end of WidgetInitialized() it should be if (!bWasHandled). The exclamation mark is missing and thus all the widgets that haven't been handled yet, will apparently stay that way. So a minor bug, no problem, but annoying. That's what betas are for, right?
    But the real problem is that the 'item1' case isn't handled! And so PasswordRendererMC and PasswordTextField stay NONE.

    If you fixed the small bug I mentioned, uncomment the `log statement and bring up the dialog somehow, you get something like this in the log:
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: Dialog : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog : GFxObject_525
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: Back : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.back : GFxClikWidget_55
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: btn : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.back.btn : GFxObject_527
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: join : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.join : GFxObject_528
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: btn : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.join.btn : GFxObject_529
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: textinput : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.item1.textinput : GFxObject_530
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: popup_title : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.popup_title : GFxObject_531
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: Back : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.back : GFxClikWidget_62
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: btn : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.back.btn : GFxObject_600
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: join : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.join : GFxObject_601
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: btn : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.join.btn : GFxObject_602
    ScriptLog: GFxUDKFrontEnd_PasswordDialog: textinput : _level0.manager.PasswordDialogContainer.PasswordDi alog.container.dialog.item1.textinput : GFxObject_614

    ScriptWarning: Accessed None 'PasswordTextField'
    GFxUDKFrontEnd_PasswordDialog UDKFrontEndMap.TheWorld:PersistentLevel.Main_Seque nce.GFxUDKFrontEnd_0.GFxUDKFrontEnd_PasswordDialog _0
    Function UTGame.GFxUDKFrontEnd_PasswordDialog:GetPassword:0 027

    ScriptWarning: Accessed None 'PasswordRendererMC'
    GFxUDKFrontEnd_PasswordDialog UDKFrontEndMap.TheWorld:PersistentLevel.Main_Seque nce.GFxUDKFrontEnd_0.GFxUDKFrontEnd_PasswordDialog _0
    Function UTGame.GFxUDKFrontEnd_PasswordDialog: DisableSubComponents:0018


    I included the warnings as an example to show you, that PasswordTextField & PasswordRendererMC are NONE. You can see that 'textinput' is recognized inside of item1, but item1 itself doesn't show up as a widget. I just can't figure out why that is. Some more intel:

    udk_assets.swf
    item1 is the instance name of the movieclip/component menu_item_password that has this class assigned: com.scaleform.udk.controls.MultiControlItemRendere r.
    This component resides inside a movieclip menu_list_password (class gfx.core.UIComponent) and that all is imported by the udk_dialog_password.swf.

    Sooooo, anyone can find the culprit? PLEASE

    #2
    That's because this widget does not fire off the WidgetInitialized() callback. If you want that widget to do so, you'll have to modify the code. Take note of the following:

    in gfx.controls.TextInput.as, which extends UIComponent:
    Code:
    [InspectableList("disabled", "visible", "textID", "password", "maxChars", /*"restrict",*/ "editable", "actAsButton", "defaultText", "enableInitCallback", "soundMap")]
    This line adds enableInitCallback to the list of component properties. This must be toggled true to fire off the WidgetInitialized() callback.

    UIComponent.as is where enableInitCallback is handled:

    Code:
    
    public var enableInitCallback:Boolean = true;
    
    private function onLoadImpl():Void {        
    		if (initialized) return;
            
    		// Only set these values if they have not been set previously (attachMovie, etc.)
    		if (isNaN(__width))  { __width = _width;    } 
            if (isNaN(__height)) { __height = _height;  }
    		initialized = true;		
    		configUI();
    		validateNow();
            
    		if (enableInitCallback && _global.CLIK_loadCallback) { _global.CLIK_loadCallback(this._name, targetPath(this), this); }
            
    		// InputDelegate will not instantiate unless a component is clicked. This forces it to.
    		// Additionally, there is no focusBoundary if selected is set before initialization is complete.
    		if (_focused != 0 && Selection.getFocusBitmask(this) == 0) {
    			for (var i:Number = 0; i < Selection.numFocusGroups; i++) {
    				var focused:Boolean = ((_focused >> i) & 0x1) != 0;
    				if (focused) {
    					var controllerMask:Number = Selection.getControllerMaskByFocusGroup(i);
    					for (var j:Number = 0; j < capabilities["numControllers"]; j++) {
    						if ((controllerMask >> j) & 0x1 != 0) { FocusHandler.instance.onSetFocus(null, this, j); }
    					}
    				}
    			}
    		}
    	}
    	
    	private function onUnload():Void {
    		if (enableInitCallback && _global.CLIK_unloadCallback) { _global.CLIK_unloadCallback(this._name, targetPath(this), this); }
    	}

    Comment


      #3
      There have been a hand-full of issues since UDK-2011-11. While there are some work arounds, if you are going to build a larger UI its probably wiser to use UDK-2011-10 until the issues are addressed.

      Comment


        #4
        Whoohoo! Thanks a lot, Matt! I didn't need to delve into ActionScript, just add the keyword in the appropiate class, create a new component bool parameter "enableInitCallback" for that component and set it to true. Why was it disabled in the first place?!

        Comment


          #5
          Oh no... I rejoiced too soon. My dialog is just working fine now, but my settings screen is broken. Since the items there are also of class 'com.scaleform.udk.controls.MultiControlItemRender er' I think this is related. Does this mean... more ActionScript?!

          Comment


            #6
            Ok, because my settings menu wouldn't work if I added enableInitCallback to InspectableList in MultiControlItemRenderer, I ended up making my own ActionScript class for the desired widget and set it to that class in flash. I just stripped the MultiControlItemRenderer.as to this:

            Code:
            import gfx.utils.Delegate;
            import gfx.ui.InputDetails;
            import gfx.ui.NavigationCode;
            import gfx.utils.Constraints;
            import com.scaleform.udk.controls.FocusItemRenderer;
            
            
            [InspectableList("disabled", "visible", "labelID", "enableInitCallback", "disableConstraints"]
            class com.scaleform.udk.controls.InputItemRenderer extends FocusItemRenderer {
            
            
            	// Constants:
            
            
            // Public Properties:
            	public var textinput:gfx.controls.TextInput;
            	public var control:MovieClip;
            	
            // Private Properties
            	private var _bDataUpdate:Boolean = false;
            	private var hit:MovieClip;
            	
            // Initialization:
            	public function InputItemRenderer() { super(); }
            
            
            // Public Methods:
            	public function get selected():Boolean { return _selected; }
            	public function set selected(value:Boolean):Void {		
            		super.selected = value;		
            	}    
            	
            	private function changeFocus():Void {
            		super.changeFocus();		
            		var state:String = (_selected) ? "focused" : "default";		
            		/* Set the TextInput to the focused state. */
            		if (!control.disabled && control != null)
            		{						
            			control.gotoAndPlay(state);
            		}
            	}
            		
                
            	public function setData(data:Object):Void {
            		super.setData(data);             
                    
            		if (data.disabled)
            			this.disabled = data.disabled;
            	}	
            	
            	public function draw()
            	{
            		super.draw();   
                    
            		// If the control passed in was an text input
            		if (data.control == "input")
            		{
            			control = textinput;               
            			textinput._visible = true;
            			textinput.disabled = false;
            			textinput.text = data.text;	
            			textinput.maxChars = data.editBoxMaxLength;
            		}
            		
            		super.draw();
            	}
            	
            	public function handleInput(details:InputDetails, pathToFocus:Array):Boolean {		        
            		var nextItem:MovieClip = MovieClip(pathToFocus.shift());
            		var handled:Boolean;
            		if (nextItem != null) {
            			handled = nextItem.handleInput(details, pathToFocus);
            			if (handled) { return true; }
            		}
            
            
            		// If the user presses enter, shift focus to the textinput and vice versa.
            		// details.code != 32 prevents spacebar from triggering this behavior.
            		if (details.navEquivalent == NavigationCode.GAMEPAD_A && details.value == "keyUp" && details.code != 32)
            		{       
            			if (textinput)
            			{
            				if (!textinput.disabled && !textinput.focused) {                    
            					Selection.setFocus(textinput);
            					return true;
            				}
            				else if (textinput.focused) {                
            					 Selection.setFocus(this);
            					 return true;
            				}
            			}
            		}     
            		return false; // or true if handled
            	}
                
            	public function onTextChange(event:Object) {        
            		data.text = textinput.text;
            		var event:Object = {type:"change"};
            		dispatchEvent(event);
            	}
                
            	/** @exclude */
            	public function toString():String {
            		return "[Scaleform OptionItemRenderer " + _name + "]";
            	}          
            	
            // Private Methods:
            	private function configUI():Void {                
            		constraints = new Constraints(this, true);
            		if (!_disableConstraints) {
            			constraints.addElement(textField, Constraints.ALL);
            		}		
            		
            		// Force dimension check if autoSize is set to true
            		if (_autoSize != "none") {
            			sizeIsInvalid = true;
            		}
                    
            		hit.onRollOver = Delegate.create(this, handleMouseRollOver);
            		hit.onRollOut = Delegate.create(this, handleMouseRollOut);
            		hit.onPress = Delegate.create(this, handleMousePress);
            		hit.onRelease = Delegate.create(this, handleMouseRelease);		
            		hit.onDragOver = Delegate.create(this, handleDragOver);
            		hit.onDragOut = Delegate.create(this, handleDragOut);
            		hit.onReleaseOutside = Delegate.create(this, handleReleaseOutside);		
            		hit.tabEnabled = false;
                    
            		focusTarget = owner;
                    
            		if (textinput != null) {			
            			textinput.addEventListener("textChange", this, "onTextChange");
            			textinput.tabEnabled = false;			
            			textinput.tabChildren = false;                      
            			textinput.focusEnabled = false;
            		}
            		
            		updateAfterStateChange();
            	}     
            }
            It works for me. I guess many of the if statements have become unnecessary, because there is only the textinput left and no optionstepper, but I thought better safe than sorry. But I would nevertheless appreciate a real solution if there is any.

            Comment


              #7
              Your solution is perfectly valid. Extending the classes that are already there is the preferred method of adding functionality.

              Comment

              Working...
              X