Android : FirstPersonCameraController : Multitouch - libgdx

I am making a first-person 3D game in Libgdx and everything is going well. I have a small issue with the controls when running on mobile.
If a direction button (up, down, left or right) are pressed down first, then dragging around the screen (to look around) does not work. If I drag around the screen first, then both work together. The code is in Kotlin
class InputController : FirstPersonCameraController {
private var gameRenderScreen: GameRenderScreen = GameRenderScreen()
private val forwardButton = TextButton("Forward", Gui.skin)
private val backwardButton = TextButton("Backward", Gui.skin)
private val leftButton = TextButton("Left", Gui.skin)
private val rightButton = TextButton("Right", Gui.skin)
private val jumpButton = TextButton("Jump", Gui.skin)
private val modeButton = TextButton("Mode", Gui.skin)
#JvmField
var isAdding = true
constructor(camera: Camera) : super(camera) {}
constructor(camera: Camera, gameRenderScreen: GameRenderScreen, stage: Stage) : super(camera) {
this.gameRenderScreen = gameRenderScreen
// create control
if (Gdx.app.type == Application.ApplicationType.Android || Gdx.app.type == Application.ApplicationType.iOS) {
var width: Float = Gdx.graphics.width / 10f
var height: Float = Gdx.graphics.height / 10f
forwardButton.setBounds(50f + width, 100f + (height * 2), width, height)
stage.addActor(forwardButton)
leftButton.setBounds(50f, 50f + height, width, height)
stage.addActor(leftButton)
rightButton.setBounds(50f + (width * 2), 50f + height, width, height)
stage.addActor(rightButton)
backwardButton.setBounds(50f + width, 10f, width, height)
stage.addActor(backwardButton)
jumpButton.setBounds(Gdx.graphics.width - width - 50f, 50f + height, width, height)
stage.addActor(jumpButton)
modeButton.setBounds(Gdx.graphics.width - width - 50f, 100f + (height * 2), width, height)
stage.addActor(modeButton)
}
//Todo fix this as it stops touching working
val multiplexer = InputMultiplexer()
multiplexer.addProcessor(this)
multiplexer.addProcessor(stage)
Gdx.input.inputProcessor = multiplexer
}
override fun keyDown(keycode: Int): Boolean {
if ((keycode == Input.Keys.SPACE || jumpButton.isPressed) && gameRenderScreen.isJump == false && gameRenderScreen.jumping == 0.0f) {
gameRenderScreen.isJump = true
}
if (keycode == Input.Keys.ENTER || modeButton.isPressed) {
isAdding = !isAdding
}
return super.keyDown(keycode)
}
// Called from Render loop
fun updateControls() {
if (Gdx.app.type == Application.ApplicationType.Android || Gdx.app.type == Application.ApplicationType.iOS) {
if (forwardButton.isPressed) {
keyDown(Input.Keys.W)
} else {
keyUp(Input.Keys.W)
}
if (backwardButton.isPressed) {
keyDown(Input.Keys.S)
} else {
keyUp(Input.Keys.S)
}
if (leftButton.isPressed) {
keyDown(Input.Keys.A)
} else {
keyUp(Input.Keys.A)
}
if (rightButton.isPressed) {
keyDown(Input.Keys.D)
} else {
keyUp(Input.Keys.D)
}
if (modeButton.isPressed) {
isAdding = !isAdding
} else {
}
if (jumpButton.isPressed && gameRenderScreen.isJump == false && gameRenderScreen.jumping == 0.0f) {
gameRenderScreen.isJump = true
} else {
}
}
}
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
hasMoved = true
return super.touchDragged(screenX, screenY, pointer)
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
hasMoved = false
return super.touchDown(screenX, screenY, pointer, button)
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
if (hasMoved == false) {
gameRenderScreen.getObject(screenX, screenY)
}
return super.touchUp(screenX, screenY, pointer, button)
}
companion object {
fun width(): Int {
return Gdx.graphics.width
}
fun height(): Int {
return Gdx.graphics.height
}
var hasMoved: Boolean = false
}
}

So,here is the fixed class, once you realise that finger 2 is a different input it makes sense :)
class InputController : FirstPersonCameraController {
private var gameRenderScreen: GameRenderScreen = GameRenderScreen()
private val forwardButton = TextButton("Forward", Gui.skin)
private val backwardButton = TextButton("Backward", Gui.skin)
private val leftButton = TextButton("Left", Gui.skin)
private val rightButton = TextButton("Right", Gui.skin)
private val jumpButton = TextButton("Jump", Gui.skin)
private val modeButton = TextButton("Mode", Gui.skin)
var myCamera: Camera
var tmp2 = Vector3();
private var degreesPerPixel2 = 0.5f
// stop to much dragging
private val touchPos = Vector2()
private val dragPos = Vector2()
private val radius = 20f
#JvmField
var isAdding = true
constructor(camera: Camera, gameRenderScreen: GameRenderScreen, stage: Stage) : super(camera) {
this.gameRenderScreen = gameRenderScreen
myCamera = camera
// create control
if (Gdx.app.type == Application.ApplicationType.Android || Gdx.app.type == Application.ApplicationType.iOS) {
var width: Float = width() / 10f
var height: Float = height() / 10f
forwardButton.setBounds(50f + width, 100f + (height * 2), width, height)
stage.addActor(forwardButton)
leftButton.setBounds(50f, 50f + height, width, height)
stage.addActor(leftButton)
rightButton.setBounds(50f + (width * 2), 50f + height, width, height)
stage.addActor(rightButton)
backwardButton.setBounds(50f + width, 10f, width, height)
stage.addActor(backwardButton)
jumpButton.setBounds(Gdx.graphics.width - width - 50f, 50f + height, width, height)
jumpButton.addListener(object : InputListener() {
override fun touchDown(event: InputEvent?, x: Float, y: Float, pointer: Int, button: Int): Boolean {
if (gameRenderScreen.isJump == false && gameRenderScreen.jumping == 0.0f) {
gameRenderScreen.isJump = true
}
return super.touchDown(event, x, y, pointer, button)
}
})
stage.addActor(jumpButton)
modeButton.setBounds(Gdx.graphics.width - width - 50f, 100f + (height * 2), width, height)
modeButton.addListener(object : InputListener() {
override fun touchDown(event: InputEvent?, x: Float, y: Float, pointer: Int, button: Int): Boolean {
isAdding = !isAdding
return super.touchDown(event, x, y, pointer, button)
}
})
stage.addActor(modeButton)
}
val multiplexer = InputMultiplexer()
multiplexer.addProcessor(stage)
multiplexer.addProcessor(this)
Gdx.input.inputProcessor = multiplexer
}
override fun keyDown(keycode: Int): Boolean {
if (keycode == Input.Keys.SPACE && gameRenderScreen.isJump == false && gameRenderScreen.jumping == 0.0f) {
gameRenderScreen.isJump = true
}
if (keycode == Input.Keys.ENTER || modeButton.isPressed) {
isAdding = !isAdding
}
Gdx.app.log("INPUT", "Keydown " + keycode)
return super.keyDown(keycode)
}
// Called from Render loop
fun updateControls() {
if (Gdx.app.type == Application.ApplicationType.Android || Gdx.app.type == Application.ApplicationType.iOS) {
if (forwardButton.isPressed) {
keyDown(Input.Keys.W)
} else {
keyUp(Input.Keys.W)
}
if (backwardButton.isPressed) {
keyDown(Input.Keys.S)
} else {
keyUp(Input.Keys.S)
}
if (leftButton.isPressed) {
keyDown(Input.Keys.A)
} else {
keyUp(Input.Keys.A)
}
if (rightButton.isPressed) {
keyDown(Input.Keys.D)
} else {
keyUp(Input.Keys.D)
}
}
}
override fun touchDragged(screenX: Int, screenY: Int, pointer: Int): Boolean {
dragPos.set(screenX.toFloat(), height() - screenY.toFloat())
val distance = touchPos.dst(dragPos)
if (distance <= radius) {
Gdx.app.log("BUILDING", "Not Dragging " + distance)
} else {
Gdx.app.log("BUILDING", "Dragging " + distance)
hasMoved = true
var cutoff = width() * 0.75
if (screenX > cutoff && pointer == 1 && Gdx.app.type == Application.ApplicationType.Android || Gdx.app.type == Application.ApplicationType.iOS) {
var deltaX = -Gdx.input.getDeltaX(1) * degreesPerPixel2
var deltaY = -Gdx.input.getDeltaY(1) * degreesPerPixel2
myCamera.direction.rotate(myCamera.up, deltaX)
tmp2.set(myCamera.direction).crs(myCamera.up).nor()
myCamera.direction.rotate(tmp2, deltaY)
return true
}
}
return super.touchDragged(screenX, screenY, pointer)
}
override fun touchDown(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
hasMoved = false
Gdx.app.log("INPUT", "touch Down " + pointer + " " + button)
touchPos.set(screenX.toFloat(), height() - screenY.toFloat());
return super.touchDown(screenX, screenY, pointer, button)
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
if (hasMoved == false) {
gameRenderScreen.getObject(screenX, screenY)
}
Gdx.app.log("INPUT", "touch up " + pointer + " " + button)
return super.touchUp(screenX, screenY, pointer, button)
}
companion object {
fun width(): Int {
return Gdx.graphics.width
}
fun height(): Int {
return Gdx.graphics.height
}
var hasMoved: Boolean = false
}
}

Related

How can I update seekBar by seconds on Media Player?(kotlin)

package com.example.ebookactivity
import android.media.MediaPlayer
import android.os.Bundle
import android.os.Handler
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.example.ebookactivity.databinding.FragmentDay1Binding
import android.widget.SeekBar
import android.os.SystemClock
import android.widget.TextView
import androidx.annotation.Dimension
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private const val ARG_PARAM1 = "param1"
private const val ARG_PARAM2 = "param2"
/**
* A simple [Fragment] subclass.
* Use the [day_1.newInstance] factory method to
* create an instance of this fragment.
*/
class day_1 : Fragment() {
// TODO: Rename and change types of parameters
private var param1: String? = null
private var param2: String? = null
private var _binding: FragmentDay1Binding? = null
private val binding get() = _binding!!
private var mediaPlayer: MediaPlayer? = null
private val textsize_plus: Float = 10.0f
private lateinit var runnable: Runnable
private lateinit var handler: Handler
private lateinit var duration: TextView
private val j:Int = 0
var size:Float = 70.0f
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
param1 = it.getString(ARG_PARAM1)
param2 = it.getString(ARG_PARAM2)
}
if(mediaPlayer?.isPlaying == true) {
//seekbar()
binding.textView2.text = "tankyou"
binding.seekBar.setProgress(mediaPlayer!!.currentPosition)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
// Inflate the layout for this fragment
_binding = FragmentDay1Binding.inflate(inflater,container,false)
if (mediaPlayer?.isPlaying == true) {
binding.seekBar.progress = mediaPlayer!!.currentPosition
}
binding.button1.setOnClickListener {
size -= textsize_plus
binding.gangu.setTextSize(Dimension.DP,size)}
binding.buttonplus.setOnClickListener {
size += textsize_plus
binding.gangu.setTextSize(Dimension.DP,size)}
//seekbar()
binding.startbutton.setOnClickListener {
if(mediaPlayer == null) {
mediaPlayer = MediaPlayer.create(activity, R.raw.days_1)
binding.seekBar.max = mediaPlayer!!.duration
binding.seekBar.setProgress(mediaPlayer!!.currentPosition)
// seekbar()
}
mediaPlayer?.start()
}
binding.pausebutton.setOnClickListener {
if (mediaPlayer?.isPlaying == true) {
mediaPlayer?.pause()
binding.seekBar.setProgress(mediaPlayer!!.currentPosition)
} else {
mediaPlayer?.start()
}
}
binding.stopbutton.setOnClickListener {
mediaPlayer?.stop()
mediaPlayer=null
}
fun onStop() {
super.onStop()
mediaPlayer?.release()
}
binding.seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
override fun onProgressChanged(seekBar: SeekBar, i: Int, b: Boolean) {
if (b) {
mediaPlayer?.seekTo(i/* * 1000*/)
// seekbar()
if (mediaPlayer?.isPlaying == true) {
binding.seekBar.setProgress(mediaPlayer!!.currentPosition)
}
}
binding.textView4.text = "ok"
if (mediaPlayer?.isPlaying == true) {
binding.seekBar.setProgress(mediaPlayer!!.currentPosition)
}
}
override fun onStartTrackingTouch(seekBar: SeekBar) {
}
override fun onStopTrackingTouch(seekBar: SeekBar) {
}
}
)
return binding.root
}
companion object {
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* #param param1 Parameter 1.
* #param param2 Parameter 2.
* #return A new instance of fragment day_1.
*/
// TODO: Rename and change types and number of parameters
#JvmStatic
fun newInstance(param1: String, param2: String) =
day_1().apply {
arguments = Bundle().apply {
putString(ARG_PARAM1, param1)
putString(ARG_PARAM2, param2)
}
}
}
override fun onPause() {
super.onPause()
mediaPlayer?.stop()
}
fun seekbar() {
binding.seekBar.setProgress(mediaPlayer!!.currentPosition)
val min2: Int = mediaPlayer!!.duration / 60000
val sec2: Int = (mediaPlayer!!.duration - min2 * 60000) / 1000
val min: Int = mediaPlayer!!.currentPosition / 60000
val sec: Int = (mediaPlayer!!.currentPosition - min * 60000) / 1000
binding.textView2.text = "" + min + " : " + sec + ""
binding.textView4.text = "" + min2 + " : " + sec2 + ""
runnable = Runnable { seekbar() }
handler.postDelayed(runnable, 1000)
}
}
I want to update seekBar by seconds. but No matter where I put setProgress code, it isn't working. SetProgress is just working on ButtonClick in this code. I want to make seekbar update by seconds. so I make seekbar function. but it isn't work. If I put seekbar function any places, application would be broken. So I cannot resolve this problem. Please help me...

KotlinX Serialization of Built-in Classes

Kotlinx docs don't seem to cover this, I am wondering if there is a way to write a custom Serializer for an existing class. In my case, I need to serialize PointF and Color. For PointF, I have done this:
object MyPointFAsStringSerializer : KSerializer<MyPointF>
{
override val descriptor: SerialDescriptor =
buildClassSerialDescriptor("Point") {
element<Float>("x")
element<Float>("y")
}
override fun serialize(encoder: Encoder, value: MyPointF) =
encoder.encodeStructure(descriptor) {
encodeFloatElement(descriptor, 0, (value.x))
encodeFloatElement(descriptor, 1, (value.y))
}
override fun deserialize(decoder: Decoder): MyPointF =
decoder.decodeStructure(descriptor) {
var x = -1f
var y = -1f
while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> x = decodeFloatElement(descriptor, 0)
1 -> y = decodeFloatElement(descriptor, 1)
CompositeDecoder.DECODE_DONE -> break
else -> error("Unexpected index: $index")
}
}
MyPointF(x, y)
}
}
#Serializable(with = MyPointFAsStringSerializer::class)
class MyPointF()
{
var x: Float = Float.MAX_VALUE
var y: Float = Float.MAX_VALUE
constructor(x: Float, y: Float) : this()
{
this.x = x
this.y = y
}
fun pointF () : PointF = PointF(this.x, this.y)
}
However, this approach is forcing me to go back and forth between PointF and MyPointF. I wondering how I could attach the same serializer to an existing class (i.e., PointF). In Swift, I simply do this by using encodeToString, which practically tells the compiler what to do with this kind of object when serializing. But I can't seem to find a way for Kotlin. Any suggestion would be appreciated.
It's definitely possible to serialize 3rd-party classes with kotlinx serialization. You can find the docs here
object PointFAsStringSerializer : KSerializer<PointF> {
override val descriptor: SerialDescriptor =
buildClassSerialDescriptor("Point") {
element<Float>("x")
element<Float>("y")
}
override fun serialize(encoder: Encoder, value: PointF) =
encoder.encodeStructure(descriptor) {
encodeFloatElement(descriptor, 0, (value.x))
encodeFloatElement(descriptor, 1, (value.y))
}
override fun deserialize(decoder: Decoder): PointF =
decoder.decodeStructure(descriptor) {
var x = -1f
var y = -1f
while (true) {
when (val index = decodeElementIndex(descriptor)) {
0 -> x = decodeFloatElement(descriptor, 0)
1 -> y = decodeFloatElement(descriptor, 1)
CompositeDecoder.DECODE_DONE -> break
else -> error("Unexpected index: $index")
}
}
PointF(x, y)
}
}
fun main() {
println(Json.encodeToString(PointFAsStringSerializer, PointF(1.1f, 2.2f)))
}

Java fraction calculator throws exception for division by zero when trying to simplify

I have the following class which I am trying to use to perform calculations between fractions however every now and again i get a division by zero exception from on the simplify function and i cannot work out why it is doing it
public class Fraction {
private int top;
private int bottom;
Fraction(int t, int b) {
top = t;
bottom = b;
simplify();
}
public int getTop() {
return top;
}
public int getBottom() {
return bottom;
}
public void simplify() {
if (bottom % top == 0) {
bottom /= top;
top /= top;
} else {
int divisor = gcd(bottom, top);
top /= divisor;
bottom /= divisor;
}
}
public Fraction add(Fraction f) {
if (bottom == f.getBottom()) {
return new Fraction(top + f.getTop(), bottom);
} else {
return new Fraction(((top * f.getBottom()) + (f.getTop() * bottom)), bottom * f.getBottom());
}
}
public Fraction subtract(Fraction f) {
if (bottom == f.getBottom()) {
return new Fraction(top - f.getTop(), bottom);
} else {
return new Fraction(((top * f.getBottom()) - (f.getTop() * bottom)), bottom * f.getBottom());
}
}
public Fraction multiply(Fraction f) {
return new Fraction(top * f.getTop(), bottom * f.getBottom());
}
private static int gcd(int a, int b) {
if (a == 0 || b == 0) {
return a + b;
} else {
return gcd(b, a % b);
}
}
#Override
public String toString() {
return top + "/" + bottom;
}
}
The statement bottom % top yields a divide by zero error when top is zero.
You can fix it by changing the first line of your simplify() method to this:
if (top != 0 && bottom % top == 0) {

Facebook SDK Integration - LoadPicture Method ERROR

So hi to #ll this is my fist post/question on stackoverflow :D
I need help # following :
So i integrated the Facebook SDk sucessfully in my game but i´dont get the profile picture working ...
So i tryied it oldshool on Facebooks "Tutotial" Way and followed all steps to implement login functions and so on ...
I´ve downloaded the "friendsmash_start" Sample and implemented that Stuff ...
My Main Problem is i don´t get ahead with this problem and can´t figure out what i´m doing wrong so i´m hoping for help.
Here´s the complete Code from the MainMenu Script from the sample which is the only i´ve changed ... like in the tutorial ...
Unity shows me this Error -> "The name 'LoadPicture' does not exist in the current context ... so the errors are on these two parts of code :
"LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);" in the "OnLoggedIn" function
"LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);" in the "MyPictureCallback" function
I don´t understand it cause i searched myself in the script for this function "LoadPicture" and find nothing that was ... according to the "Tutorial" of facebook here :
https://developers.facebook.com/docs/games/unity/unity-tutorial?locale=de_DE
the function should be there cause they wrote there :
"Take a look at the LoadPicture method also in MainMenu.cs to see how we use the Unity WWW class to load the image returned by the graph API."
But i can´t find it :(
HOPE SOMEONE CAN HELP ME I DON´T GET IT ...
Have that problem unfortunately very long time ... thats enoying. :(
HERE`S THE FULL CODE OF MAINMENU.CS :
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Facebook.MiniJSON;
using System;
public class MainMenu : MonoBehaviour
{
// Inspector tunable members //
public Texture ButtonTexture;
public Texture PlayTexture; // Texture for main menu button icons
public Texture BragTexture;
public Texture ChallengeTexture;
public Texture StoreTexture;
public Texture FullScreenTexture;
public Texture FullScreenActiveTexture;
public Texture ResourcesTexture;
public Vector2 CanvasSize; // size of window on canvas
public Rect LoginButtonRect; // Position of login button
public Vector2 ResourcePos; // position of resource indicators (not used yet)
public Vector2 ButtonStartPos; // position of first button in main menu
public float ButtonScale; // size of main menu buttons
public float ButtonYGap; // gap between buttons in main menu
public float ChallengeDisplayTime; // Number of seconds the request sent message is displayed for
public Vector2 ButtonLogoOffset; // Offset determining positioning of logo on buttons
public float TournamentStep; // Spacing between tournament entries
public float MouseScrollStep = 40; // Amount score table moves with each step of the mouse wheel
public PaymentDialog paymentDialog;
public GUISkin MenuSkin;
public int CoinBalance;
public int NumLives;
public int NumBombs;
public Texture[] CelebTextures;
public string [] CelebNames;
// Private members //
private static MainMenu instance;
private static List<object> friends = null;
private static Dictionary<string, string> profile = null;
private static List<object> scores = null;
private static Dictionary<string, Texture> friendImages = new Dictionary<string, Texture>();
private Vector2 scrollPosition = Vector2.zero;
private bool haveUserPicture = false;
private float tournamentLength = 0;
private int tournamentWidth = 512;
private int mainMenuLevel = 0; // Level index of main menu
private string popupMessage;
private float popupTime;
private float popupDuration;
void Awake()
{
Util.Log("Awake");
paymentDialog = ((PaymentDialog)(GetComponent("PaymentDialog")));
// allow only one instance of the Main Menu
if (instance != null && instance != this)
{
Destroy(gameObject);
return;
}
#if UNITY_WEBPLAYER
// Execute javascript in iframe to keep the player centred
string javaScript = #"
window.onresize = function() {
var unity = UnityObject2.instances[0].getUnity();
var unityDiv = document.getElementById(""unityPlayerEmbed"");
var width = window.innerWidth;
var height = window.innerHeight;
var appWidth = " + CanvasSize.x + #";
var appHeight = " + CanvasSize.y + #";
unity.style.width = appWidth + ""px"";
unity.style.height = appHeight + ""px"";
unityDiv.style.marginLeft = (width - appWidth)/2 + ""px"";
unityDiv.style.marginTop = (height - appHeight)/2 + ""px"";
unityDiv.style.marginRight = (width - appWidth)/2 + ""px"";
unityDiv.style.marginBottom = (height - appHeight)/2 + ""px"";
}
window.onresize(); // force it to resize now";
Application.ExternalCall(javaScript);
#endif
DontDestroyOnLoad(gameObject);
instance = this;
// Initialize FB SDK
FB.Init(SetInit, OnHideUnity);
}
private void SetInit()
{
Util.Log("SetInit");
enabled = true; // "enabled" is a property inherited from MonoBehaviour
if (FB.IsLoggedIn)
{
Util.Log("Already logged in");
OnLoggedIn();
}
}
private void OnHideUnity(bool isGameShown)
{
Util.Log("OnHideUnity");
if (!isGameShown)
{
// pause the game - we will need to hide
Time.timeScale = 0;
}
else
{
// start the game back up - we're getting focus again
Time.timeScale = 1;
}
}
private void QueryScores()
{
FB.API("/app/scores?fields=score,user.limit(20)", Facebook.HttpMethod.GET, ScoresCallback);
}
private int getScoreFromEntry(object obj)
{
Dictionary<string,object> entry = (Dictionary<string,object>) obj;
return Convert.ToInt32(entry["score"]);
}
void ScoresCallback(FBResult result)
{
Util.Log("ScoresCallback");
if (result.Error != null)
{
Util.LogError(result.Error);
return;
}
scores = new List<object>();
List<object> scoresList = Util.DeserializeScores(result.Text);
foreach(object score in scoresList)
{
var entry = (Dictionary<string,object>) score;
var user = (Dictionary<string,object>) entry["user"];
string userId = (string)user["id"];
if (string.Equals(userId,FB.UserId))
{
// This entry is the current player
int playerHighScore = getScoreFromEntry(entry);
Util.Log("Local players score on server is " + playerHighScore);
if (playerHighScore < GameStateManager.Score)
{
Util.Log("Locally overriding with just acquired score: " + GameStateManager.Score);
playerHighScore = GameStateManager.Score;
}
entry["score"] = playerHighScore.ToString();
GameStateManager.HighScore = playerHighScore;
}
scores.Add(entry);
if (!friendImages.ContainsKey(userId))
{
// We don't have this players image yet, request it now
LoadPictureAPI(Util.GetPictureURL(userId, 128, 128),pictureTexture =>
{
if (pictureTexture != null)
{
friendImages.Add(userId, pictureTexture);
}
});
}
}
// Now sort the entries based on score
scores.Sort(delegate(object firstObj,
object secondObj)
{
return -getScoreFromEntry(firstObj).CompareTo(getScoreFromEntry(secondObj));
}
);
}
void OnApplicationFocus( bool hasFocus )
{
Util.Log ("hasFocus " + (hasFocus ? "Y" : "N"));
}
// Convenience function to check if mouse/touch is the tournament area
private bool IsInTournamentArea (Vector2 p)
{
return p.x > Screen.width-tournamentWidth;
}
// Scroll the tournament view by some delta
private void ScrollTournament(float delta)
{
scrollPosition.y += delta;
if (scrollPosition.y > tournamentLength - Screen.height)
scrollPosition.y = tournamentLength - Screen.height;
if (scrollPosition.y < 0)
scrollPosition.y = 0;
}
// variables for keeping track of scrolling
private Vector2 mouseLastPos;
private bool mouseDragging = false;
void Update()
{
if(Input.touches.Length > 0)
{
Touch touch = Input.touches[0];
if (IsInTournamentArea (touch.position) && touch.phase == TouchPhase.Moved)
{
// dragging
ScrollTournament (touch.deltaPosition.y*3);
}
}
if (Input.GetAxis("Mouse ScrollWheel") < 0)
{
ScrollTournament (MouseScrollStep);
}
else if (Input.GetAxis("Mouse ScrollWheel") > 0)
{
ScrollTournament (-MouseScrollStep);
}
if (Input.GetMouseButton(0) && IsInTournamentArea(Input.mousePosition))
{
if (mouseDragging)
{
ScrollTournament (Input.mousePosition.y - mouseLastPos.y);
}
mouseLastPos = Input.mousePosition;
mouseDragging = true;
}
else
mouseDragging = false;
}
// Button drawing logic //
private Vector2 buttonPos; // Keeps track of where we've got to on the screen as we draw buttons
private void BeginButtons()
{
// start drawing buttons at the chosen start position
buttonPos = ButtonStartPos;
}
private bool DrawButton(string text, Texture texture)
{
// draw a single button and update our position
bool result = GUI.Button(new Rect (buttonPos.x,buttonPos.y, ButtonTexture.width * ButtonScale, ButtonTexture.height * ButtonScale),text,MenuSkin.GetStyle("menu_button"));
Util.DrawActualSizeTexture(ButtonLogoOffset*ButtonScale+buttonPos,texture,ButtonScale);
buttonPos.y += ButtonTexture.height*ButtonScale + ButtonYGap;
if (paymentDialog.DialogEnabled)
result = false;
return result;
}
void OnGUI()
{
GUI.skin = MenuSkin;
if (Application.loadedLevel != mainMenuLevel) return; // don't display anything except when in main menu
GUILayout.Box("", MenuSkin.GetStyle("panel_welcome"));
if (!FB.IsLoggedIn)
{
GUI.Label((new Rect(179, 11, 287, 160)), "Login to Facebook", MenuSkin.GetStyle("text_only"));
if (GUI.Button(LoginButtonRect, "", MenuSkin.GetStyle("button_login")))
{
FB.Login("email,publish_actions", LoginCallback);
}
}
if (FB.IsLoggedIn)
{
string panelText = "Welcome ";
panelText += (!string.IsNullOrEmpty(GameStateManager.Username)) ? string.Format("{0}!", GameStateManager.Username) : "Smasher!";
if (GameStateManager.UserTexture != null)
GUI.DrawTexture( (new Rect(8,10, 150, 150)), GameStateManager.UserTexture);
GUI.Label( (new Rect(179 , 11, 287, 160)), panelText, MenuSkin.GetStyle("text_only"));
}
string subTitle = "Let's smash some friends!";
if (GameStateManager.Score > 0)
{
subTitle = "Score: " + GameStateManager.Score.ToString();
}
if (!string.IsNullOrEmpty(subTitle))
{
GUI.Label( (new Rect(132, 28, 400, 160)), subTitle, MenuSkin.GetStyle("sub_title"));
}
BeginButtons();
if (DrawButton("Play",PlayTexture))
{
onPlayClicked();
}
if (FB.IsLoggedIn)
{
// Draw resources bar
Util.DrawActualSizeTexture(ResourcePos,ResourcesTexture);
Util.DrawSimpleText(ResourcePos + new Vector2(47,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",CoinBalance));
Util.DrawSimpleText(ResourcePos + new Vector2(137,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",NumBombs));
Util.DrawSimpleText(ResourcePos + new Vector2(227,5) ,MenuSkin.GetStyle("resources_text"),string.Format("{0}",NumLives));
}
#if UNITY_WEBPLAYER
if (Screen.fullScreen)
{
if (DrawButton("Full Screen",FullScreenActiveTexture))
SetFullscreenMode(false);
}
else
{
if (DrawButton("Full Screen",FullScreenTexture))
SetFullscreenMode(true);
}
#endif
DrawPopupMessage();
}
public void AddPopupMessage(string message, float duration)
{
popupMessage = message;
popupTime = Time.realtimeSinceStartup;
popupDuration = duration;
}
public void DrawPopupMessage()
{
if (popupTime != 0 && popupTime + popupDuration > Time.realtimeSinceStartup)
{
// Show message that we sent a request
Rect PopupRect = new Rect();
PopupRect.width = 800;
PopupRect.height = 100;
PopupRect.x = Screen.width / 2 - PopupRect.width / 2;
PopupRect.y = Screen.height / 2 - PopupRect.height / 2;
GUI.Box(PopupRect,"",MenuSkin.GetStyle("box"));
GUI.Label(PopupRect, popupMessage, MenuSkin.GetStyle("centred_text"));
}
}
void TournamentGui()
{
GUILayout.BeginArea(new Rect((Screen.width - 450),0,450,Screen.height));
// Title box
GUI.Box (new Rect(0, - scrollPosition.y, 100,200), "", MenuSkin.GetStyle("tournament_bar"));
GUI.Label (new Rect(121 , - scrollPosition.y, 100,200), "Tournament", MenuSkin.GetStyle("heading"));
Rect boxRect = new Rect();
if(scores != null)
{
var x = 0;
foreach(object scoreEntry in scores)
{
Dictionary<string,object> entry = (Dictionary<string,object>) scoreEntry;
Dictionary<string,object> user = (Dictionary<string,object>) entry["user"];
string name = ((string) user["name"]).Split(new char[]{' '})[0] + "\n";
string score = "Smashed: " + entry["score"];
boxRect = new Rect(0, 121+(TournamentStep*x)-scrollPosition.y , 100,128);
// Background box
GUI.Box(boxRect,"",MenuSkin.GetStyle("tournament_entry"));
// Text
GUI.Label (new Rect(24, 136 + (TournamentStep * x) - scrollPosition.y, 100,128), (x+1)+".", MenuSkin.GetStyle("tournament_position")); // Rank e.g. "1.""
GUI.Label (new Rect(250,145 + (TournamentStep * x) - scrollPosition.y, 300,100), name, MenuSkin.GetStyle("tournament_name")); // name
GUI.Label (new Rect(250,193 + (TournamentStep * x) - scrollPosition.y, 300,50), score, MenuSkin.GetStyle("tournament_score")); // score
Texture picture;
if (friendImages.TryGetValue((string) user["id"], out picture))
{
GUI.DrawTexture(new Rect(118,128+(TournamentStep*x)-scrollPosition.y,115,115), picture); // Profile picture
}
x++;
}
}
else GUI.Label (new Rect(180,270,512,200), "Loading...", MenuSkin.GetStyle("text_only"));
// Record length so we know how far we can scroll to
tournamentLength = boxRect.y + boxRect.height + scrollPosition.y;
GUILayout.EndArea();
}
// React to menu buttons //
private void onPlayClicked()
{
Util.Log("onPlayClicked");
if (friends != null && friends.Count > 0)
{
// Select a random friend and get their picture
Dictionary<string, string> friend = Util.RandomFriend(friends);
GameStateManager.FriendName = friend["first_name"];
GameStateManager.FriendID = friend["id"];
GameStateManager.CelebFriend = -1;
LoadPictureURL(friend["image_url"],FriendPictureCallback);
}
else
{
//We can't access friends
GameStateManager.CelebFriend = UnityEngine.Random.Range(0,CelebTextures.Length - 1);
GameStateManager.FriendName = CelebNames[GameStateManager.CelebFriend];
}
// Start the main game
Application.LoadLevel("GameStage");
GameStateManager.Instance.StartGame();
}
public void SetFullscreenMode (bool on)
{
if (on)
{
Screen.SetResolution (Screen.currentResolution.width, Screen.currentResolution.height, true);
}
else
{
Screen.SetResolution ((int)CanvasSize.x, (int)CanvasSize.y, false);
}
}
public static void FriendPictureCallback(Texture texture)
{
GameStateManager.FriendTexture = texture;
}
delegate void LoadPictureCallback (Texture texture);
IEnumerator LoadPictureEnumerator(string url, LoadPictureCallback callback)
{
WWW www = new WWW(url);
yield return www;
callback(www.texture);
}
void LoadPictureAPI (string url, LoadPictureCallback callback)
{
FB.API(url,Facebook.HttpMethod.GET,result =>
{
if (result.Error != null)
{
Util.LogError(result.Error);
return;
}
var imageUrl = Util.DeserializePictureURLString(result.Text);
StartCoroutine(LoadPictureEnumerator(imageUrl,callback));
});
}
void LoadPictureURL (string url, LoadPictureCallback callback)
{
StartCoroutine(LoadPictureEnumerator(url,callback));
}
void LoginCallback(FBResult result)
{
Util.Log("LoginCallback");
if (FB.IsLoggedIn)
{
OnLoggedIn();
}
}
void OnLoggedIn()
{
Util.Log("Logged in. ID: " + FB.UserId);
// Reqest player info and profile picture
FB.API("/me?fields=id,first_name,friends.limit(100).fields(first_name,id)", Facebook.HttpMethod.GET, APICallback);
LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);
}
void APICallback(FBResult result)
{
Util.Log("APICallback");
if (result.Error != null)
{
Util.LogError(result.Error);
// Let's just try again
FB.API("/me?fields=id,first_name,friends.limit(100).fields(first_name,id)", Facebook.HttpMethod.GET, APICallback);
return;
}
profile = Util.DeserializeJSONProfile(result.Text);
GameStateManager.Username = profile["first_name"];
friends = Util.DeserializeJSONFriends(result.Text);
}
void MyPictureCallback(Texture texture)
{
Util.Log("MyPictureCallback");
if (texture == null)
{
// Let's just try again
LoadPicture(Util.GetPictureURL("me", 128, 128), MyPictureCallback);
return;`
}
GameStateManager.UserTexture = texture;
}
}
change the word "LoadPicture" for "LoadPictureAPI".
For reference see:
https://github.com/fbsamples/friendsmash-unity/blob/master/friendsmash_payments_start/Assets/Scripts/MainMenu.cs

Save/ load QuickAccessToolBar

I 'm using Microsoft.Windows.Controls.Ribbon, and i would like save and load QuickAccessToolBar.
How I Can find QuickAccessToolBar items, in ribbon control?
This is my idea to save ribbon QuickAccessToolBar
OnClosing application : Get QuickAccessToolBar items, and locaize on Ribbon items. And then serialize
OnLoad : Read serilize object, and add insert items QuickAccessToolBar
Finally i did it!
I'm based on WPF Ribbon Sample to save/load. It used datacontext to localize control on RibbonControl, and i didn't like, so i isued QuickAccessToolBarId to localize the control.
This is the solution:
- OnClosing Application:
I save QuickAccessToolBar, search items on ribbon control by QuickAccessToolBar, and save path. Note: When item is in application menufirst path is -1.A
- OnLoadApplication:
Load items , and seerch on ribbon control by path.
And this is the code:
RibbonHelper:
class RibbonHelper
{
Ribbon ribbon;
public RibbonHelper(Ribbon ribbon)
{
this.ribbon = ribbon;
}
string _qatFileName = "qat.xml";
internal void Save()
{
try
{
SaveQatItems();
}
catch { }
}
internal void Load()
{
try
{
LoadQatItems();
}
catch
{
}
}
#region Save Qat
private void SaveQatItems()
{
QatItemCollection qatItems = GetQatItemsToSave(ribbon.QuickAccessToolBar);
if (qatItems != null)
{
QatItemCollection remainingItems = new QatItemCollection();
remainingItems.AddRange(qatItems);
SaveQatItemsOfApplicationMenu(remainingItems);
SaveQatItemsOfTabs(remainingItems);
SaveQatItems(qatItems);
}
}
private void SaveQatItems(QatItemCollection qatItems)
{
XmlWriter xmlWriter = XmlWriter.Create(_qatFileName);
XamlWriter.Save(qatItems, xmlWriter);
xmlWriter.Close();
}
private void SaveQatItemsOfApplicationMenu(QatItemCollection remainingItems)
{
if (ribbon.ApplicationMenu != null)
{
if (remainingItems != null)
{
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Add(-1);
});
for (int index = 0; index < ribbon.ApplicationMenu.Items.Count && remainingItems.Count > 0; index++)
{
SaveQatItemsAmongChildren(remainingItems, ribbon.ApplicationMenu.Items[index],index);
}
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Clear();
});
}
}
}
private void SaveQatItemsOfTabs(QatItemCollection remainingItems)
{
if (ribbon.Items != null)
{
if (remainingItems != null)
{
for (int tabIndex = 0; tabIndex < ribbon.Items.Count && remainingItems.Count > 0; tabIndex++)
{
RibbonTab tab = ribbon.Items[tabIndex] as RibbonTab;
SaveQatItemsAmongChildren(remainingItems, tab, tabIndex);
}
}
}
}
private void SaveQatItemsAmongChildren(QatItemCollection remainingItems, object control, int controlIndex)
{
if (control == null)
{
return;
}
//Añaidmos el control index a los pendientes
remainingItems.ForEach(qat =>
{
qat.ControlIndices.Add(controlIndex);
});
SaveQatItemsAmongChildrenInner(remainingItems, control);
//Eliminamos el control index de los pendientes ya que no estan dentro de ese control
remainingItems.ForEach(qat =>
{
int last = qat.ControlIndices.Count - 1;
qat.ControlIndices.RemoveAt(last);
});
}
private void SaveQatItemsAmongChildrenInner(QatItemCollection remainingItems, object parent)
{
SaveQatItemsIfMatchesControl(remainingItems, parent);
if (remainingItems.Count == 0 || IsLeaf(parent))
{
return;
}
int childIndex = 0;
DependencyObject dependencyObject = parent as DependencyObject;
if (dependencyObject != null)
{
IEnumerable children = LogicalTreeHelper.GetChildren(dependencyObject);
foreach (object child in children)
{
SaveQatItemsAmongChildren(remainingItems, child, childIndex);
childIndex++;
}
}
if (childIndex != 0)
{
return;
}
// if we failed to get any logical children, enumerate the visual ones
Visual visual = parent as Visual;
if (visual == null)
{
return;
}
for (childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(visual); childIndex++)
{
Visual child = VisualTreeHelper.GetChild(visual, childIndex) as Visual;
SaveQatItemsAmongChildren(remainingItems, child, childIndex);
}
}
private bool IsLeaf(object element)
{
if ((element is RibbonButton) ||
(element is RibbonToggleButton) ||
(element is RibbonRadioButton) ||
(element is RibbonCheckBox) ||
(element is RibbonTextBox) ||
(element is RibbonSeparator))
{
return true;
}
RibbonMenuItem menuItem = element as RibbonMenuItem;
if (menuItem != null &&
menuItem.Items.Count == 0)
{
return true;
}
return false;
}
private bool SaveQatItemsIfMatchesControl(QatItemCollection remainingItems, object control)
{
bool matched = false;
FrameworkElement element = control as FrameworkElement;
if (element != null)
{
object getQuickAccessToolBarId = RibbonControlService.GetQuickAccessToolBarId(element);
if (getQuickAccessToolBarId != null)
{
int remove = remainingItems.RemoveAll(qat => qat.QuickAccessToolBarIdHashCode == getQuickAccessToolBarId.GetHashCode());
matched = remove > 0;
}
}
return matched;
}
private QatItemCollection GetQatItemsToSave(RibbonQuickAccessToolBar qat)
{
QatItemCollection qatItems = new QatItemCollection();
if (qat != null && qat.Items != null && qat.Items.Count > 0)
{
foreach (var item in qat.Items)
{
FrameworkElement element = item as FrameworkElement;
if (element != null)
{
object getQuickAccessToolBarId = RibbonControlService.GetQuickAccessToolBarId(element);
if (getQuickAccessToolBarId != null)
{
QatItem qatItem = new QatItem(getQuickAccessToolBarId.GetHashCode());
qatItems.Add(qatItem);
}
}
}
}
return qatItems;
}
#endregion
#region load qat
private void LoadQatItems()
{
if (ribbon.QuickAccessToolBar == null)
{
ribbon.QuickAccessToolBar = new RibbonQuickAccessToolBar();
}
QatItemCollection qatItems = GetQatItemsToLoad();
if ((qatItems != null) && (qatItems.Count > 0))
{
SearchInApplicationMenu(qatItems);
SearchInTabs(qatItems);
qatItems.Where(qat => qat.Owner != null).ToList().ForEach(qat =>
{
if (RibbonCommands.AddToQuickAccessToolBarCommand.CanExecute(null, qat.Owner))
{
RibbonCommands.AddToQuickAccessToolBarCommand.Execute(null, qat.Owner);
}
});
}
}
private void SearchInApplicationMenu(QatItemCollection qatItems)
{
if (qatItems != null)
{
int remainingItemsCount = qatItems.Count(qat=>qat.Owner==null);
QatItemCollection matchedItems = new QatItemCollection();
for (int index = 0; index < ribbon.ApplicationMenu.Items.Count && remainingItemsCount > 0; index++)
{
matchedItems.Clear();
matchedItems.AddRange(qatItems.Where(qat => qat.ControlIndices[0] == -1)); //-1 is applicationMenu
//remove -1
matchedItems.ForEach(qat =>
{
qat.ControlIndices.RemoveAt(0);
}
);
object item = ribbon.ApplicationMenu.Items[index];
if (item != null)
{
if (!IsLeaf(item))
{
LoadQatItemsAmongChildren(matchedItems, 0, index, item, ref remainingItemsCount);
}
else
{
LoadQatItemIfMatchesControl(matchedItems, new QatItemCollection(), 0, index, item, ref remainingItemsCount);
}
}
//Add -1
matchedItems.ForEach(qat =>
{
qat.ControlIndices.Insert(0, -1);
});
}
}
}
private void SearchInTabs(QatItemCollection qatItems)
{
int remainingItemsCount = qatItems.Count(qat => qat.Owner == null);
QatItemCollection matchedItems = new QatItemCollection();
for (int tabIndex = 0; tabIndex < ribbon.Items.Count && remainingItemsCount > 0; tabIndex++)
{
matchedItems.Clear();
matchedItems.AddRange(qatItems.Where(qat => qat.ControlIndices[0] == tabIndex));
RibbonTab tab = ribbon.Items[tabIndex] as RibbonTab;
if (tab != null)
{
LoadQatItemsAmongChildren(matchedItems, 0, tabIndex, tab, ref remainingItemsCount);
}
}
}
private void LoadQatItemsAmongChildren(
QatItemCollection previouslyMatchedItems,
int matchLevel,
int controlIndex,
object parent,
ref int remainingItemsCount)
{
if (previouslyMatchedItems.Count == 0)
{
return;
}
if (IsLeaf(parent))
{
return;
}
int childIndex = 0;
DependencyObject dependencyObject = parent as DependencyObject;
if (dependencyObject != null)
{
IEnumerable children = LogicalTreeHelper.GetChildren(dependencyObject);
foreach (object child in children)
{
if (remainingItemsCount == 0)
{
break;
}
QatItemCollection matchedItems = new QatItemCollection();
LoadQatItemIfMatchesControl(previouslyMatchedItems, matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
LoadQatItemsAmongChildren(matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
childIndex++;
}
}
if (childIndex != 0)
{
return;
}
// if we failed to get any logical children, enumerate the visual ones
Visual visual = parent as Visual;
if (visual == null)
{
return;
}
for (childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(visual); childIndex++)
{
if (remainingItemsCount == 0)
{
break;
}
Visual child = VisualTreeHelper.GetChild(visual, childIndex) as Visual;
QatItemCollection matchedItems = new QatItemCollection();
LoadQatItemIfMatchesControl(previouslyMatchedItems, matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
LoadQatItemsAmongChildren(matchedItems, matchLevel + 1, childIndex, child, ref remainingItemsCount);
}
}
private void LoadQatItemIfMatchesControl(
QatItemCollection previouslyMatchedItems,
QatItemCollection matchedItems,
int matchLevel,
int controlIndex,
object control,
ref int remainingItemsCount)
{
for (int qatIndex = 0; qatIndex < previouslyMatchedItems.Count; qatIndex++)
{
QatItem qatItem = previouslyMatchedItems[qatIndex];
if (qatItem.ControlIndices[matchLevel] == controlIndex)
{
if (qatItem.ControlIndices.Count == matchLevel + 1)
{
qatItem.Owner = control as Control; ;
remainingItemsCount--;
}
else
{
matchedItems.Add(qatItem);
}
}
}
}
private QatItemCollection GetQatItemsToLoad()
{
try
{
if (File.Exists(_qatFileName))
{
using (XmlReader xmlReader = XmlReader.Create(_qatFileName))
{
QatItemCollection qatItems = (QatItemCollection)XamlReader.Load(xmlReader);
xmlReader.Close();
return qatItems;
}
}
}
catch
{
//Do nothing, return null;
}
return null;
}
#endregion
}
Classes to serialize:
public class QatItem {
public QatItem()
{
}
public QatItem(int qatbIdHashCode)
{
QuickAccessToolBarIdHashCode = qatbIdHashCode;
}
public Int32Collection ControlIndices
{
get
{
if (_controlIndices == null)
{
_controlIndices = new Int32Collection();
}
return _controlIndices;
}
set
{
_controlIndices = value;
}
}
Int32Collection _controlIndices;
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int QuickAccessToolBarIdHashCode { get; set; }
//Is only for load
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Control Owner { get; set; }
}
public class QatItemCollection : List<QatItem>
{
}
And this is the code to save/load from window
RibbonHelper helper;
protected override void OnClosing(CancelEventArgs e)
{
helper.Save();
base.OnClosing(e);
}
private void RibbonWindow_Loaded(object sender, RoutedEventArgs e)
{
helper = new RibbonHelper(ribbon);
helper.Load();
}