How do you reference a specific object in Moi3D scripting?

Next
 From:  Elang
12042.1 
Dear forum members,

I'm just beginning to learn scripting for Moi3D. Before this, most of my scripting experience was writing VBA scripts for CorelDRAW (just below intermediate level).

Because of that, I hope you'll understand if I occasionally compare Moi3D's scripting model with how CorelDRAW works. I'm completely open to learning a different approach, so please don't hesitate to correct me whenever my assumptions are wrong.

I also understand that an object in Moi3D is much more sophisticated than an object in CorelDRAW. For example, when an object is selected in Moi3D, the whole object is highlighted, and then it's possible to further select individual faces, surfaces, or edges. This is a completely new concept for me, and at the moment I don't really have a mental model of how this is represented or handled in scripting.

For your information, I have already downloaded the unofficial Moi v5 API Documentation, and I've been reading through it. However, I'm having difficulty finding the answer because I suspect that Moi3D uses an object referencing model that is fundamentally different from the one I'm familiar with in CorelDRAW.

My very first question is about object references.

How does Moi3D identify or reference a specific object among many objects in the scene, and how can I select that object through a script?

In CorelDRAW, the most recently created object is placed at the top of the object stack, making it very easy to access. For example, I could reference `Object.Index(1)` and then assign it a unique name:

code:
Object.Index(1).Name = "ChooseMe"

Later in the script, I could simply find that object again by its name.

How is this typically done in Moi3D scripting?
* What are the common ways to reference a specific object?
* Is there an equivalent to assigning a unique identifier or name?
* What approaches do experienced Moi3D scripters usually recommend?

This is probably the most fundamental question for me, but I believe understanding this concept will help me move on to more advanced scripting topics.

Thank you very much for your time, your patience, and your support.

Best regards,

- Elang
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Frenchy Pilou (PILOU)
12042.2 
An another way can maybe use AI ... without any kowledge ! ;)

With the free Claude & or Gemini I made this! ;) https://moiscript.weebly.com/anime-svg.html French / English
An animation prog and a sort of illustrator for SGV format!
Of course i have no special knowledge of the all langages used! :)
You ask just that you want !
I suppose that will maybe the same for Moi script! :) (not yet tested)

Michael will can say to you the limit of this... :)
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Michael Gibson
12042.3 In reply to 12042.1 
Hi Elang, in MOI each object automatically gets a unique id value, you can get an object from its id by using the moi.geometryDatabase.findObject() function, like this:
var obj = moi.geometryDatabase.findObject( id );

But usually scripts don't do that, usually a script either generates an object using the GeometryFactory.calculate() function which returns an object list with the created objects in it, or works on selected objects which are returned by moi.geometryDatabase.getSelectedObjects() or by using an object picker.

It would be easier to show you in an actual script, what is it that you are trying to make your script do?

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Elang
12042.4 
Thank you very much for your quick responses. I truly appreciate them.

@Pilou
I want to understand Moi3D scripting as deeply as I can, so for now I'd like to set AI aside.

With all due respect to those who use it, I'm not a big fan of "vibe coding" because I think it has the potential to trap us in an illusion of competence.

That said, I'm sure I'll make good use of AI later, once I feel confident that I have a solid understanding of Moi3D scripting myself. So please don't take this as rejecting your suggestion... I completely agree that AI can be a great productivity tool.

@Michael
I'd like to start with the very basics.

So far, I've learned how to create a few solid objects using moi.command.createFactory() followed by commit(). However, I'm getting stuck once several objects have been created and I want to perform Boolean operations such as Union or Difference on just two of them.

For example, imagine there are ten objects in the scene. At that point, I've already "lost track" of the order in which they were created (again, this is me thinking in terms of CorelDRAW). Suppose I now want to perform a Union on two specific objects. I don't know how to identify those two objects as the operands for the Boolean operation. The main reason of Moi Scripting here is for automation process, like what Max Smirnov did with his _NutsAndBolts addon.

Could you please explain how ObjectList is intended to work, and what the recommended way is to obtain references to the specific objects I want?

Unlike working interactively in Moi3D, where I can visually recognize an object's shape, location, or other characteristics before selecting it, a script doesn't have that kind of intuition. From my current perspective, I don't yet understand how a script is expected to "know" which objects should become the operands of a Boolean operation.

Thank you again, Michael, for your time and for all the help you've generously given to the Moi3D community over the years. I really appreciate it.

- Elang

EDITED: 20 Jul 11:00 by ELANG

  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Frenchy Pilou (PILOU)
12042.5 In reply to 12042.4 
No problem!
Bon courage!
---
Pilou
Is beautiful that please without concept!
My Moi French Site
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
Next
 From:  Elang
12042.6 
Thanks, Pilou! ;)

---------------------------

Let's say I have this simple script that creates a line. By default, the object's name is empty and appears as "Unnamed" in the UI.

How can I assign a name to this line immediately after it is created, without manually selecting it first, so that I can easily refer to it later in the script?

code:
var linefactory = moi.command.createFactory( 'line' );
linefactory.setInput( 0, moi.vectorMath.createPoint( 0,0,0 ) );
linefactory.setInput( 1, moi.vectorMath.createPoint( 10,10,10 ) );
linefactory.commit();

My goal is to build fully automated scripts where the user only provides the initial parameters. Because of that, it would be very convenient if I could obtain a reference to the newly created object immediately after creation and assign it a unique name or identifier. Is there something equivalent to a "last created object" reference?

As another example, suppose I create a box and then separate all of its faces into individual objects. How would I programmatically select a specific face among them without relying on manual object picking?

I think this is the part of the object model that I'm currently struggling to understand.

EDIT :
Just tried this:
code:
var factory = moi.command.createFactory( 'line' );
factory.setInput( 0, moi.vectorMath.createPoint(0,0,0) );
factory.setInput( 1, moi.vectorMath.createPoint(10,10,10) );
factory.commit();
moi.geometryDatabase.selectLastCreated();

still, the newly created line is not selected, so I can't specify its name (for future easy reference).


EDIT 2:
Just tried this:
code:
var factory = moi.command.createFactory( 'line' );
factory.setInput( 0, moi.vectorMath.createPoint(0,0,0) );
factory.setInput( 1, moi.vectorMath.createPoint(10,10,10) );
factory.commit();
moi.geometryDatabase.selectLastCreated();
moi.geometryDatabase.getSelectedObjects();

Not working, too... the line is not selected.

BUT : if I manually create an object, and do this :
code:
moi.geometryDatabase.selectLastCreated();
moi.geometryDatabase.getSelectedObjects();

My last created object IS SELECTED!.

Furthermore:
code:
moi.geometryDatabase.selectLastCreated();
moi.geometryDatabase.getSelectedObjects().setProperty('name', 'ME!');

Successfully name the last-created-selected object to 'ME!'.

So, there's seems to be significant difference between creating object manually and via createFactory.commit() ?


EDIT 3 :
I think I may not have described my actual intention clearly enough, so I would like to clarify my use case.

First of all, I fully understand and respect that MoI has its own object model. I am not trying to make MoI work like another software. My previous analogy with CorelDRAW was only to explain my initial way of thinking and the kind of workflow that feels natural to me as I start learning scripting in MoI.

What I am really trying to understand is how to manage a large number of objects created by a script.

In my planned workflow, the script will create many objects step by step: solids, construction objects, cutting objects, and intermediate results for further operations.

Because many objects will be generated automatically, I need a practical way to identify them from a human perspective.

For example:
- This object is the main box.
- This object is the cutting plane.
- This object is the reference geometry.
- This object is the final result.

When working manually in MoI, it is easy for a user to recognize objects visually. But when everything is generated by a script, I need to understand the proper way to organize and keep track of those objects.

My original question was basically: After creating an object through scripting, what is the recommended MoI approach to identify and manage that object so it can be referenced again later when the script continues with more operations?

I am still learning the MoI object model, so I would really appreciate your guidance on the proper scripting pattern rather than trying to apply assumptions from other software.

Thank you again for your patience and for sharing your knowledge. I am very interested in understanding MoI scripting properly and learning the way it is intended to work.

- Elang

EDITED: 20 Jul 15:55 by ELANG

  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged

Previous
 From:  Michael Gibson
12042.7 In reply to 12042.6 
Hi Elang,

re:
> How can I assign a name to this line immediately after it is created, without manually
> selecting it first, so that I can easily refer to it later in the script?

The preferred way to do that is to retrieve the object reference when it is created.

There are 2 ways that geometry factories can be used, one is by hooking up UI controls to factory inputs, triggering a factory.update() when the UI controls are changed, and then calling factory.commit() at the end. This is the way that most commands in MOI work since they have UI controls.

That way handles various things automatically like removing any previously generated objects from the geometry database and inserting the newly generated ones into the geometry database so they are displayed, clearing them out if the command is canceled, and other similar stuff.

Your example here is not like that:

code:
var linefactory = moi.command.createFactory( 'line' );
linefactory.setInput( 0, moi.vectorMath.createPoint( 0,0,0 ) );
linefactory.setInput( 1, moi.vectorMath.createPoint( 10,10,10 ) );
linefactory.commit();

The regular line command does a lot more than that, it sets up a point picker and spins an event loop waiting for the user to click a point with the mouse or type in the coordinates of the point, set a checkbox option, etc...

Your script here just wants to generate a line between 2 specific points, not collected from user input and no UI options to be set. Perhaps you don't even want the line to even be displayed and just use it as a building block to be sent in as an input to another factory.

For that case it is better to use the 2nd method of using a geometry factory, the factory.calculate() function. That will return an object list of what the factory generated and doesn't do anything else. The result will not even be displayed yet since it will be a "loose object" and not inserted into the Geometry Database yet, you can do that manually with moi.geometryDatabase.addObject().

Using factory.calculate() and getting the line object reference for use later on in the script is like this:

code:
var linefactory = moi.command.createFactory( 'line' );
linefactory.setInput( 0, moi.vectorMath.createPoint( 0,0,0 ) );
linefactory.setInput( 1, moi.vectorMath.createPoint( 10,10,10 ) );
var result_object_list = linefactory.calculate();
var line = result_object_list.item(0);

You could then assign a name using by doing
line.name = 'the line';
but you wouldn't normally do that as a lookup method later on, you would pass in the line variable that is an object reference.


It is possible to collect the output using the update()/commit()/cancel() method, to do that you would need to make sure factory.update() is called, then use factory.getCreatedObjects() before the .commit() :

code:
var linefactory = moi.command.createFactory( 'line' );
linefactory.setInput( 0, moi.vectorMath.createPoint( 0,0,0 ) );
linefactory.setInput( 1, moi.vectorMath.createPoint( 10,10,10 ) );
linefactory.update();
var result_object_list = linefactory.getCreatedObjects();
linefactory.commit();
var line = result_object_list.item(0);
line.name = 'the line';

But note that the line will be in the geometry database and so displayed in the viewports (the viewports draw the contents of the geometry database, they don't draw "loose objects" that are only referenced by script code and not listed in the geometry database).

If your script is generating the line as a building block with specific inputs instead of using a pointpicker the calculate() method is preferred.

Hope this makes sense, let me know if anything here isn't clear.

- Michael
  Reply Reply More Options
Post Options
Reply as PM Reply as PM
Print Print
Mark as unread Mark as unread
Relationship Relationship
IP Logged
 

Reply to All Reply to All