Announcement

Collapse
No announcement yet.

Displaying Steam Avatars with friends list in Scaleform

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

    Displaying Steam Avatars with friends list in Scaleform

    Hey everyone!

    I'm working on an updating friends list component that displays the player's steam friends with each friends steam avatar portrait. I've run into an issue passing the texture read in from ReadOnlineAvatar to scaleform or even test HUD elements with DrawTile.

    I want to be able to display multiple portraits at once, although each time I read one from Steamworks, it overwrites the previous texture results.

    How can I store or copy the texture, so I can save the older results while still reading in new results?

    Here is an image of the friends list displaying the duplicate avatars:

    #2
    Forgive me if this sounds incredibly understated, but can't you just initialize a Texture2D from ReadOnlineAvatar and store it in an array of textures?

    At the same time you can be storing their steam name in another array so that you can use it as a key value like a hash table.

    Obviously psuedo-code
    Code:
    var array<Texture2D> avatars;
    var array<string> names;
    
    
    for( i = 0; i < Steam.FriendsCount; i++)
    {
          names[i] = Steam.Friends[i];
          avatars[i] = Steam.ReadAvatar
    }
    
    function int IndexOfFriend(string name)
    {
          for(int i  = 0; i < 0; i++)
                  if(names[i] == name) return i;
    
         return -1;
    }
    
    Texture2D avatar = avatars[IndexOfFriend("friend name")];
    GFxMoviePlayerVar.SetFriendPic(IndexOfFriend("friend name"), avatar);
    
    SetFriendPic could be an ActionScriptVoid

    Comment


      #3
      That is essentially what I'm doing, I create a copy of the passed in Texture2D (parameter name Avatar) with the following:
      Code:
      AllAvatarInfos[index].avatarTexture = new class'Texture2D' (Avatar);
      This creates a new texture, but unfortunately doesn't allocate new texture space. It shares memory and simply has a pointer to the original texture data. Copying a Texture2D just copies the reference to the original data. I pass Scaleform the source address so I can load the texture from a custom AS3 UILoader.

      Code:
      AllAvatarInfos[index].avatarSource = "img://" $ AllAvatarInfos[index].avatarTexture.GetPackageName() $ "." $ AllAvatarInfos[index].avatarTexture.Name;
      Here are the textures it creates, although they all are linked to the original when rendered.



      I know this a uScript issue, since I've been testing using DrawTiles (pure Canvas, no Scaleform) and it has the same results. I've even tried storing bitmap copies in AS3, but with no luck. I'm really just looking for a way to deep copy and duplicate textures so that I can display multiple avatars!

      Comment


        #4
        Are you using this?

        Code:
        delegate OnReadOnlineAvatarComplete(const UniqueNetId PlayerNetId, Texture2D Avatar);
        There's no need to create a "new" Texture2D for this. It's going to create a duplicate by assignment it to an array, you're not passing a pointer.

        do it like this
        Code:
        AllAvatarInfos[index].avatarTexture = Avatar;
        If that changes nothing, could you please post all relevant code from the time steam subsys is created and you've assigned that delegate to a function to when you render the image in your HUD?

        Comment


          #5
          Code:
          AllAvatarInfos[index].avatarTexture = Avatar;
          This results in no new 'textures' being created (at least according to the listtextures console command). All the AvatarInfos have a texture reference to the exact same texture (Transient.Avatar_2147483647). Using the new keyword passing in a reference to the original texture, new textures are created but they simply link back to the original. I haven't been able to find a method for deep copying the texture data so I can read and display multiple avatars at the same time.


          Here's the code block that creates the AvatarInfo for a player:

          Code:
          // if we haven't read the avatar for this player
          if( FindAvatarInfo( AllOnlineFriends[currentAvatarUpdateIndex].UniqueId ) == None)
          {
          	NewAvatarInfo = new class'GrAvatarInfo';
          	NewAvatarInfo.netID = AllOnlineFriends[currentAvatarUpdateIndex].UniqueId;
          	NewAvatarInfo.hasAvatar = false;
          	NewAvatarInfo.FriendOwner = AllOnlineFriends[currentAvatarUpdateIndex];
          	NewAvatarInfo.avatarID = GetAvatarID();
          	AllAvatarInfos[NewAvatarInfo.avatarID] = NewAvatarInfo;
          	OnlineSubSteam.ReadOnlineAvatar( AllOnlineFriends[currentAvatarUpdateIndex].UniqueId, 64, OnReadOnlineAvatarComplete );
          }

          Non-scaleform test HUD code that displays the textures:
          Code:
          foreach AllAvatarInfos(AvatarInfo)
          {
          	Canvas.SetPos(XPos, YPos);
          	YPos += 64.0f;
          	Canvas.SetDrawColor(255,255,255,255);
          	Canvas.DrawTile(AvatarInfo.avatarTexture, 64, 64, 0, 0, 64, 64);
          }
          Heres the delegate that receives the avatar texture from the Steamworks OnlineSubsystem:
          Code:
          simulated function OnReadOnlineAvatarComplete(const UniqueNetId PlayerNetId, Texture2D Avatar)
          {
          	local int index;
          
          	for(index = 0; index < AllAvatarInfos.Length; index++)
          	{
          		if(AllAvatarInfos[index].netID.Uid.A == PlayerNetId.Uid.A && AllAvatarInfos[index].netID.Uid.B == PlayerNetId.Uid.B)
          		{	
          			AllAvatarInfos[index].avatarTexture = new class'Texture2D' (Avatar);
          			AllAvatarInfos[index].avatarSource = "img://" $ AllAvatarInfos[index].avatarTexture.GetPackageName() $ "." $ AllAvatarInfos[index].avatarTexture.Name;
          			AllAvatarInfos[index].hasAvatar = true;
          			break;
          		}
          	}
          
          	currentAvatarUpdateIndex++;
          	bReadyForNextFriendUpdate = true;
          }

          Comment


            #6
            For debug purposes, you could create a HUD function that renders the argument Avatar from your delegate function rather than in a foreach statement.

            I would create a function that renders Avatar & one that renders avatarTexture in a column to the right.

            Nothing jumps out at me in your code.

            Comment


              #7
              Through timed testing I know can read all of the avatars and render them independently, the issue appears whenever I call ReadOnlineAvatar it overwrites the previous texture with the latest. Since the texture copy I created is still referencing the original texture, when it is overwritten the copy is overwritten as well. I just need to find a way to copy the contents of the result texture from ReadOnlineAvatar into a separate texture buffer, so that when I read the next player avatar the copy remains unchanged. Looking through the Epic and other Unreal 3 documentation, I've been unable to find a method to accomplish this. Also it seems that SetExternalTexture seems to be getting an update in the next version of UDK, it may hold a potential solution.

              Comment


                #8
                This seems to be down to an odd bug in the engine; the textures are named 'Avatar_x' with x being a number (the players UID), but internally, the engine splits the 'Avatar' and '_x' parts because of how it handles names (so that means 'Avatar_0' is the same as 'Avatar_1', hence it only ever uses one texture).

                I have this fixed locally, but it requires C++ changes, so you'll need to wait for a future UDK to get the fixed code. I don't know if there is a way to copy textures in the meantime.

                Comment


                  #9
                  Originally posted by Shambler View Post
                  This seems to be down to an odd bug in the engine; the textures are named 'Avatar_x' with x being a number (the players UID), but internally, the engine splits the 'Avatar' and '_x' parts because of how it handles names (so that means 'Avatar_0' is the same as 'Avatar_1', hence it only ever uses one texture).

                  I have this fixed locally, but it requires C++ changes, so you'll need to wait for a future UDK to get the fixed code. I don't know if there is a way to copy textures in the meantime.
                  Alright, thanks for the info. It's nice to know why this was happening and that there is a chance that a fix will be implemented in a future UDK. I'll just work on other features until it's fixed!

                  Comment

                  Working...
                  X