Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Marquee tool
#1
I asked about marquee tool before, but I want to choose particles by only script not using UI. How can I choose particle by rect of coordinates? and create obi handle from there? I don't know how to select the target(obi cloth) and lead to edit by script
Reply
#2
Hi,

Quote:I asked about marquee tool before, but I want to choose particles by only script not using UI.

Well, a marquee tool is inherently a UI tool. I still don't get what you want to achieve.

Anyway, to create a marquee selection tool, project the particle positions to screen space, then compare their screen space positions to the rect coordinates to see which are inside of it. See:
https://docs.unity3d.com/ScriptReference...Point.html
Reply
#3
(10-06-2019, 08:32 AM)josemendez Wrote: Hi,


Well, a marquee tool is inherently a UI tool. I still don't get what you want to achieve.

Anyway, to create a marquee selection tool, project the particle positions to screen space, then compare their screen space positions to the rect coordinates to see which are inside of it. See:
https://docs.unity3d.com/ScriptReference...Point.html
Hello.

I just want to choose particles using coordinates and script ,without mouse.
How do you select the target(obi cloth) and lead to edit by script?
Reply
#4
(10-06-2019, 09:21 AM)Richard Wrote: Hello.

I just want to choose particles using coordinates and script ,without mouse.
How do you select the target(obi cloth) and lead to edit by script?

To choose particles using coordinates, you first need to decide which coordinate space to use. Marquee tools generally work in screen or UI space. So simply project particle positions using Camera.WorldToScreenPoint.

You cannot "lead to edit" by script. The particle editor is an editor tool, you cannot use it in a game. As I already told you in a previous thread, you need to determine whether you're making an editor tool to extend Unity, or a in-game tool.

Also, there's no concept of "selection" in Unity, except when running in editor. Again, these issues have nothing to do with Obi at all.
Reply
#5
(10-06-2019, 02:19 PM)josemendez Wrote: To choose particles using coordinates, you first need to decide which coordinate space to use. Marquee tools generally work in screen or UI space. So simply project particle positions using Camera.WorldToScreenPoint.

You cannot "lead to edit" by script. The particle editor is an editor tool, you cannot use it in a game. As I already told you in a previous thread, you need to determine whether you're making an editor tool to extend Unity, or a in-game tool.

Also, there's no concept of "selection" in Unity, except when running in editor. Again, these issues have nothing to do with Obi at all.

Would you tell me how to project particle positions using Camera.WorldToScreenPoint? It is not related to Obi? In the documentation, I have to assign particle to target.
Reply
#6
(10-06-2019, 02:37 PM)Richard Wrote: Would you tell me how to project particle positions using Camera.WorldToScreenPoint? It is not related to Obi? In the documentation, I have to assign particle to target.

Projecting a position is not related to Obi, since a position is a position regardless of where it came from. Obi gives you access to all per-particle properties (positions, velocities, masses, etc), and the documentation explains how to get/set them, but what you do with them is up to you, and largely not related to the engine itself.

Simply iterate over all particles projecting their current position, like this:

Code:
for (int i = 0; i < actor.positions.Length; ++i){
            int indexInSolver = actor.particleIndices[i];
            Vector3 projectedPos = camera.WorldToScreenPoint(solver.positions[indexInSolver]);
        }
Reply
#7
(10-06-2019, 03:44 PM)josemendez Wrote: Projecting a position is not related to Obi, since a position is a position regardless of where it came from. Obi gives you access to all per-particle properties (positions, velocities, masses, etc), and the documentation explains how to get/set them, but what you do with them is up to you, and largely not related to the engine itself.

Simply iterate over all particles projecting their current position, like this:

Code:
for (int i = 0; i < actor.positions.Length; ++i){
            int indexInSolver = actor.particleIndices[i];
            Vector3 projectedPos = camera.WorldToScreenPoint(solver.positions[indexInSolver]);
        }

After that I should write code below to make handle?


Code:
// Create the handle:
                GameObject c = new GameObject("Obi Handle");
                Undo.RegisterCreatedObjectUndo(c,"Create Obi Particle Handle");
                ObiParticleHandle handle = c.AddComponent<ObiParticleHandle>();
                handle.Actor = actor;

                // Calculate position of handle from average of particle positions:
                Vector3 average = Vector3.zero;
                for(int i = 0; i < selectionStatus.Length; i++){
                    if (selectionStatus[i]){
                        average += wsPositions[i];
                    }
                }

                c.transform.position = average / selectedCount;

                // Add the selected particles to the handle:
                for(int i = 0; i < selectionStatus.Length; i++){
                    if (selectionStatus[i]){
                        handle.AddParticle(i,wsPositions[i],actor.invMasses[i]);
                    }
                }
Reply
#8
(10-06-2019, 04:14 PM)Richard Wrote: After that I should write code below to make handle?


Code:
// Create the handle:
GameObject c = new GameObject("Obi Handle");
Undo.RegisterCreatedObjectUndo(c,"Create Obi Particle Handle");
ObiParticleHandle handle = c.AddComponent<ObiParticleHandle>();
handle.Actor = actor;

// Calculate position of handle from average of particle positions:
Vector3 average = Vector3.zero;
for(int i = 0; i < selectionStatus.Length; i++){
if (selectionStatus[i]){
average += wsPositions[i];
}
}

c.transform.position = average / selectedCount;

// Add the selected particles to the handle:
for(int i = 0; i < selectionStatus.Length; i++){
if (selectionStatus[i]){
handle.AddParticle(i,wsPositions[i],actor.invMasses[i]);
}
}

after you've determined which particles end up projected inside your marquee coordinates, then yes, you can make a handle out of them using the above code.
Reply
#9
(10-06-2019, 07:21 PM)josemendez Wrote: after you've determined which particles end up projected inside your marquee coordinates, then yes, you can make a handle out of them using the above code.
Currently, my code is below;

Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Obi
{
   public class CreateHandle : MonoBehaviour
   {
       ObiActor actor;
       public ObiSolver solver;
       public Transform anchor;
       static protected Vector3[] wsPositions = new Vector3[0];
       static public bool[] selectionStatus = new bool[0];
       static int lastSelectedParticle = 0;
       //Selection related:
       static protected int selectedCount = 0;
       public static int SelectedParticleCount
       {
           get { return selectedCount; }
       }
       // Start is called before the first frame update
       void Start()
       {
           ObiSolver solver = actor.Solver;
           actor = GetComponent<ObiActor>();

           for (int i = 0; i < actor.positions.Length; ++i)
           {
               int indexInSolver = actor.particleIndices[i];
               Vector3 projectedPos = GetComponent<Camera>().WorldToScreenPoint(solver.positions[indexInSolver]);
               selectionStatus[i] = true;
           }

           // Create the handle:
           GameObject c = new GameObject("Obi Handle");
           Undo.RegisterCreatedObjectUndo(c, "Create Obi Particle Handle");
           ObiParticleHandle handle = c.AddComponent<ObiParticleHandle>();
           handle.Actor = actor;

           selectedCount = 0;
           for (int i = 0; i < selectionStatus.Length; i++)
           {
               if (actor.active[i] && selectionStatus[i])
               {
                   selectedCount++;
                   lastSelectedParticle = i;
               }
           }

           // Calculate position of handle from average of particle positions:
           Vector3 average = Vector3.zero;
           for (int i = 0; i < selectionStatus.Length; i++)
           {
               if (selectionStatus[i])
               {
                   average += wsPositions[i];
               }
           }

           c.transform.position = average / selectedCount;

           // Add the selected particles to the handle:
           for (int i = 0; i < selectionStatus.Length; i++)
           {
               if (selectionStatus[i])
               {
                   handle.AddParticle(i, wsPositions[i], actor.invMasses[i]);
               }
           }
       }


       // Update is called once per frame
       void Update()
       {

       }
   }
}

There are two errors.
・Obi Solver does not contain definition of "position"
(error CS1061: 'ObiSolver' does not contain a definition for 'positions' and no accessible extension method 'positions' accepting a first argument of type 'ObiSolver' could be found (are you missing a using directive or an assembly reference?))

・I cannot find out "Undo"
(error CS0103: The name 'Undo' does not exist in the current context)


Do you know how to fix this? Or are there other much problems here, or I should change code at a fundamental level?
Reply
#10
(11-06-2019, 08:38 AM)Richard Wrote: Currently, my code is below;

Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Obi
{
   public class CreateHandle : MonoBehaviour
   {
       ObiActor actor;
       public ObiSolver solver;
       public Transform anchor;
       static protected Vector3[] wsPositions = new Vector3[0];
       static public bool[] selectionStatus = new bool[0];
       static int lastSelectedParticle = 0;
       //Selection related:
       static protected int selectedCount = 0;
       public static int SelectedParticleCount
       {
           get { return selectedCount; }
       }
       // Start is called before the first frame update
       void Start()
       {
           ObiSolver solver = actor.Solver;
           actor = GetComponent<ObiActor>();

           for (int i = 0; i < actor.positions.Length; ++i)
           {
               int indexInSolver = actor.particleIndices[i];
               Vector3 projectedPos = GetComponent<Camera>().WorldToScreenPoint(solver.positions[indexInSolver]);
               selectionStatus[i] = true;
           }

           // Create the handle:
           GameObject c = new GameObject("Obi Handle");
           Undo.RegisterCreatedObjectUndo(c, "Create Obi Particle Handle");
           ObiParticleHandle handle = c.AddComponent<ObiParticleHandle>();
           handle.Actor = actor;

           selectedCount = 0;
           for (int i = 0; i < selectionStatus.Length; i++)
           {
               if (actor.active[i] && selectionStatus[i])
               {
                   selectedCount++;
                   lastSelectedParticle = i;
               }
           }

           // Calculate position of handle from average of particle positions:
           Vector3 average = Vector3.zero;
           for (int i = 0; i < selectionStatus.Length; i++)
           {
               if (selectionStatus[i])
               {
                   average += wsPositions[i];
               }
           }

           c.transform.position = average / selectedCount;

           // Add the selected particles to the handle:
           for (int i = 0; i < selectionStatus.Length; i++)
           {
               if (selectionStatus[i])
               {
                   handle.AddParticle(i, wsPositions[i], actor.invMasses[i]);
               }
           }
       }


       // Update is called once per frame
       void Update()
       {

       }
   }
}

There are two errors.
・Obi Solver does not contain definition of "position"
(error CS1061: 'ObiSolver' does not contain a definition for 'positions' and no accessible extension method 'positions' accepting a first argument of type 'ObiSolver' could be found (are you missing a using directive or an assembly reference?))

・I cannot find out "Undo"
(error CS0103: The name 'Undo' does not exist in the current context)


Do you know how to fix this? Or are there other much problems here, or I should change code at a fundamental level?

Hi Richard,

You just copy-pasted code straight out the particle editor (which is editor code, that cannot run in-game), without modifying it. You just cannot use this code as-is in your game, it won't work.

Blindly copy-pasting code won't get you far. You need to understand what you're writing and why. For instance, the selectionStatus array is a per-particle array that holds whether each particle is selected or not. This only makes sense in the context of in-editor selection. The "Undo" class only exists in the UnityEditor namespace, so you cannot use it here.

As I've pointed out multiple times before, you must determine whether you're writing an editor tool, or code for a game. You're constantly mixing up both.
Reply