Kotlin Composable detectDragGestures Output On Drop Position? - drag-and-drop

I have a Kotlin jetpack composable box item that I set to be able to click and drag. It outputs all the real time coordinates of the box, but is there a way to output only the last value the moment I lift my fingers and dropping the box?
#Composable
fun createDragImage(){
MaterialTheme{
val count = remember { mutableStateOf(0) }
val context = LocalContext.current
Row(
modifier = Modifier
.padding(20.dp)
.border(border = BorderStroke(width = 1.dp, color = Color.Red)),
verticalAlignment = Alignment.CenterVertically,
) {
Box() {
var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) }
Box(
Modifier
.offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
.background(Color.Transparent)
.size(150.dp)
.border(BorderStroke(4.dp, SolidColor(Color.Red)))
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
change.consumeAllChanges()
offsetX = box1.toFloat()
offsetY += dragAmount.y
}
}
)
}

You can use the onDragEnd parameter.
Something like:
var offsetX by remember { mutableStateOf(0f) }
var offsetY by remember { mutableStateOf(0f) }
var offsetDraggingX by remember { mutableStateOf(0f) }
var offsetDraggingY by remember { mutableStateOf(0f) }
Box(
Modifier
.offset { IntOffset(offsetX.roundToInt(), offsetY.roundToInt()) }
.pointerInput(Unit) {
detectDragGestures(
onDragEnd = {
offsetX = offsetDraggingX
offsetY = offsetDraggingY
}
) { change, dragAmount ->
//change.consumeAllChanges()
offsetDraggingX += dragAmount.x
offsetDraggingY += dragAmount.y
}
}
)

Related

Move player use Input.getKeyDown unity

Hello guys i want move player between two position use Input.getKeyDown
firstPosition = new vector2(0,0); secondPosition = new vector2(0,5);
if player in firstPosition will go to secondPosition if player press E key
if player in secondPosition will go to firstPosition if player press E key
(movement method is transform.Translate)
my code
if (stairsOn)
{
inHelecopter.inHelecopter = true;
rig2d.simulated = !enabled;
if (transform.localPosition.y > stairS.maxHigh)//down
{
dirUp = false;
}
else if (transform.localPosition.y <= stairS.minHigh)
{//up
dirUp = true;
}
if (transform.localPosition.y >= stairS.maxHigh || transform.localPosition.y <= stairS.minHigh)
{
rig2d.simulated = enabled;
stairsOn = false;
}
if (dirUp)
{
transform.Translate(Vector3.up * 2 * Time.fixedDeltaTime, Space.Self);
}
else
{
transform.Translate(Vector3.down * 2 * Time.fixedDeltaTime, Space.Self);
}
}
Try this:
bool b = true;
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
if (b)
{
transform.Translate(secondPosition - firstPosition);
b = false;
}
else
{
transform.Translate(firstPosition - secondPosition);
b = true;
}
}
}
In practice, I assign a variable that controls whether it is in the first or second position and moves the player towards the other.
In this script I use the transform.Translate method, but if you can I recommend that you simply assign the position like this:
bool b = true;
void Update()
{
if (Input.GetKeyDown(KeyCode.E))
{
if (b)
{
transform.position = secondPosition;
b = false;
}
else
{
transform.position = firstPosition;
b = true;
}
}
}
Good work!

Why Ag-grid cell renderer is getting re-initialized on horizontal scrolling (on moveable columns)?

While scrolling moveable columns cell renderer is getting re-initialized due to which the value in ag grid are getting reset. I need solution for this as I am not able to save row data as values gets reset on scrolling.
agInit(params): void {
this.params = params.data;
this.rowIndex = params.rowIndex;
this.selectedReason = params.data;
if (this.params.proposedCompletionDateInFormat) {
this.calender.selectedDateTime.startDate = new Date(params.data.proposedCompletionDateInFormat);
} else {
this.calender.selectedDateTime = null;
}
if(params.data.taskProgressState === "COMPLETED") {
this.disableField = true;
} else {
this.disableField = false;
}
}
refresh(params?: any): boolean {
this.formGroup = params.context.formGroup;
return true;
}
}
add
[suppressColumnVirtualisation]="true" flag

How do I get perform a single button press to call a method?

I would like a Unity progress slider to fill up when I press the spacebar. Currently, I have to mash the spacebar 100 times to fill up the progress bar.
It fills the progress slider automatically when moved to update().
It fills the progress slider when I hold the spacebar if I change Input.GetKeyDown to Input.GetKey.
But I don't want to hold the spacebar down. I want to press it once to start have the slider value gradually fill up the progress bar.
void Start()
{
sliderValue = 1.0f;
}
void Update()
{
pressSpacebar();
}
void pressSpacebar()
{
if (Input.GetKeyDown("space"))
{
filluptheslider();
}
}
void filluptheslider()
{
ProgressSlider.value += sliderValue * Time.deltaTime;
}
There are a few ways to handle this:
Method 1
Boolean value in the class to track the pressed state:
bool pressed = false;
void pressSpacebar()
{
if (Input.GetKeyDown("space"))
{
filluptheslider();
}
if(pressed)
{
filluptheslider();
}
}
Method 2
Coroutine that starts after space is pressed.
void pressSpacebar()
{
if (Input.GetKeyDown("space"))
{
StartCoroutine(FillUpTheSlider);
}
}
IEnumerator FillUpTheSlider()
{
while(ProgressSlider.value < ProgressSlider.maxValue)
{
ProgressSlider.value += sliderValue * Time.deltaTime;
yield return null;
}
}
If you press the space bar multiple times, multiple coroutines will spawn and it will fill faster. You can optionally add the following before you start the coroutine to prevent this behaviour:
StopCoroutine(FillUpTheSlider)
You could alternatively combine method 1 and 2 to remove this behaviour.
bool isFull = false;
bool isPressed = false;
void Update
{
If (Input.GetKeyDown(KeyCode.Space)
&&
!isFull)
{
isPressed = true;
}
if(isPressed)
{
//if you want fill to increase every 0.05 seconds.
StartCoroutine(FillGradually(0.05f));
isPressed = false;
}
}
Ienumerator FillGradually(float fillOffset)
{
//If 100 is your max value
while(ProgressSlider.value < 100)
{
ProgressSlider.value += 1 * Time.deltaTime;
yield return new WaitForSeconds(fillOffset);
}
isFull = true;
}
You can just use a bool condition and when space is pressed, you can just make it true once and when it is true, it will automatically start filling.
bool isSpacePressed; //bydefault, bool class variable is set to false //when initialized
update()
{
if(isSpacePressed==true) //no need to mention ==true just added to make it //readable
{
image.fillAmount=fillvalue+0.1f;
}
}
if(input.GetKey(keyCode.Space)==true)
{
isSpacePressed=true;
}

eption 'NSInvalidArgumentException', reason: 'Attemped to add a SKNode which already has a parent

i cant figure out this problem. Im deleting a certain SpriteNode, than re-adding it sometimes on a condition, however it crashes every time im calling addChild(). I know a SpriteNode can only have one parent so i dont understand this. Here is the relevant code:
override func touchesBegan(touches: NSSet, withEvent event:UIEvent) {
var touch: UITouch = touches.anyObject() as UITouch
var location = touch.locationInNode(self)
var node = self.nodeAtPoint(location)
for var i=0; i < tileNodeArray.count; i++
{
if (node == tileNodeArray[i]) {
flippedTilesCount++;
flippedTilesArray.append(tileNodeArray[i])
let removeAction = SKAction.removeFromParent()
tileNodeArray[i].runAction(removeAction)
if flippedTilesCount == 2
{
var helperNode1 = newMemoLabelNode("first",x: 0,y: 0,aka: "first")
var helperNode2 = newMemoLabelNode("second",x: 0,y: 0,aka: "second")
for var k = 0; k < labelNodeArray.count ;k++
{
if labelNodeArray[k].position == flippedTilesArray[0].position
{
helperNode1 = labelNodeArray[k]
}
if labelNodeArray[k].position == flippedTilesArray[1].position
{
helperNode2 = labelNodeArray[k]
}
}
if helperNode1.name == helperNode2.name
{
erasedTiles = erasedTiles + 2;
}
else
{
for var j = 0; j < flippedTilesArray.count ;j++
{
let waitAction = SKAction.waitForDuration(1.0)
flippedTilesArray[j].runAction(waitAction)
//self.addChild(flippedTilesArray[j]);
}
}
flippedTilesCount = 0;
flippedTilesArray = []
println("erased tiles:")
println(erasedTiles)
}
}
}
}
Appreciate your help!
I would recommend you not to use SKAction.removeFromParent but remove the node itself by calling:
tileNodeArray[i].removeFromParent()
instead of:
let removeAction = SKAction.removeFromParent()
tileNodeArray[i].runAction(removeAction)
The problem might be, that the SKActions don't wait for each other to finish. For example if you call the waitAction, the other actions will keep running.

Drag and drop in unity 2d

I am trying to implement drag and drop functionality for my game in unity 2d. I have multiple copies of same object in my screen and they differ only by collider name. I attached the same script to them. Here is a piece of my code
function Start () {
playerTouches = [-1, -1];
}
function resetPlayer(touchNumber: int) {
for(var i = 0; i < playerTouches.length; ++i) {
if(touchNumber == playerTouches[i]) {
playerTouches[i] = -1;
}
}
}
function getCollider(vec: Vector2) {
var ray : Ray = Camera.main.ScreenPointToRay(vec);
var hit : RaycastHit2D = Physics2D.Raycast(ray.origin, ray.direction);
if (hit) {
if (hit.collider != null) {
Debug.Log(hit.collider.name);
return hit.collider.name;
} else {
Debug.Log("is null");
return "null";
}
} else {
Debug.Log("empty");
return "";
}
return "";
}
function processTouch(touch: Touch, touchNumber: int) {
if(touch.phase == TouchPhase.Began) {
var colliderName: String = getCollider(touch.position);
if(colliderName == "Object01" && playerTouches[0] == -1) {
playerTouches[0] = touchNumber;
} else if(colliderName == "Object02" && playerTouches[1] == -1) {
playerTouches[1] = touchNumber;
}
} else if(touch.phase == TouchPhase.Moved) {
// get object and change coords
} else if(touch.phase == TouchPhase.Ended || touch.phase == TouchPhase.Canceled) {
resetPlayer(touchNumber);
}
}
function Update() {
if(Input.touchCount > 0) {
//Debug.Log("count = " + Input.touchCount);
for(var i = 0; i < Input.touchCount; i++)
{
processTouch(Input.GetTouch(i), i);
//Debug.Log("touch : " + i + " " + Input.GetTouch(i).position);
}
}
}
For now I'm detecting on which object user touch. I need to be able to get that object and change it's position.
I also found this code snippet which allows to move rigidbody
var touchDeltaPosition: Vector2 = touch.deltaPosition;
var touchPosition: Vector2;
touchPosition.Set(touchDeltaPosition.x, touchDeltaPosition.y);
rigidbody2D.transform.position = Vector2.Lerp(transform.position, touchPosition, Time.deltaTime * spd);
but it moves all objects regardless of what object I select.
Well, you can do like this. If you have 12 copies of same object and want to move the object which selected by user. So when user Touches the object Change that GameObject tag or Name to another tag. Afterward you can use the some Conditional Statement to work with your code.
Example :
if(Input.GetMouseButtonDown(0)) {
Debug.Log("Mouse is down");
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitInfo = new RaycastHit();
//bool hit = Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hitInfo);
if(Physics.Raycast(ray, out hitInfo, 30)) {
Debug.Log("Hit " + hitInfo.transform.gameObject.name);
if(hitInfo.transform.gameObject.tag == "Deselected") {
//Debug.Log ("It's working! Attaching MoveCube Script to game :" + hitInfo.transform.gameObject.tag);
findObject = GameObject.FindGameObjectsWithTag("Deselected");
foreach(GameObject go in findObject) {
//go.gameObject.renderer.material.color = Color.white;
go.GetComponent<MoveCube>().enabled = false;
if(hitInfo.transform.gameObject.name.Equals(go.gameObject.name)) {
//hitInfo.transform.renderer.material.color = Color.white;
hitInfo.transform.gameObject.GetComponent<MoveCube>().enabled = true;
changeTAG = true;
} else {
hitInfo.transform.gameObject.tag = "Deselected"
}
}
playerObject = GameObject.FindGameObjectsWithTag("Player");
foreach(GameObject game in playerObject) {
count++;
if(count == 1) {
hitInfo.transform.gameObject.tag = "Player";
}
if(count >= 1) {
game.gameObject.tag = "Deselected";
game.gameObject.GetComponent<MoveCube>().enabled = false;
//game.gameObject.renderer.material.color = Color.white;
}
}
if(changeTAG) {
hitInfo.transform.gameObject.tag = "Player";
/*if (hitInfo.transform.gameObject.GetComponent<Rigidbody> ()) {
Debug.Log ("RigidBody is already added Can't add another RigidBody");
hitInfo.transform.rigidbody.WakeUp ();
} else {
hitInfo.transform.gameObject.AddComponent<Rigidbody> ().useGravity = false;
// hitInfo.transform.gameObject.GetComponent<Rigidbody> ().WakeUp ();
}*/
changeTAG = false;
} else if(!changeTAG) {
hitInfo.transform.gameObject.tag = "Deselected";
}
} else {
Debug.Log("Not Working");
}
} else {
Debug.Log("No hit");
}
Debug.Log("Mouse is down");
}
The above code is for Change the tag for selected and deselected cube. After that you can easily identify the Selected gameObject and can move it where ever you want.
You can use this code in the Update function.