MoI discussion forum
MoI discussion forum

Full Version: How do you reference a specific object in Moi3D scripting?

Show messages: All  1-5  6-13

From: Elang
20 Jul   [#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
From: Michael Gibson
20 Jul   [#7] In reply to [#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
From: Elang
20 Jul   [#8] In reply to [#7]
Hi Michael,

Thank you very much for taking the time to write such a detailed explanation. It makes much more sense to me now.

I think I understand the distinction between using `update()/commit()` for interactive commands and using `calculate()` for programmatically generating geometry. I also understand why obtaining and keeping the object reference is the preferred approach.

I would like to spend some time studying these concepts and experimenting with both approaches before asking any further questions. I'm sure I'll learn much more by trying them myself first.

Earlier you asked what I was actually trying to accomplish. My long-term goal is to build procedural scripts that generate many objects and perform a sequence of operations on them. Rather than creating just one or two objects, a script may eventually generate dozens of intermediate and final objects before reaching the final result.

Once I have explored these concepts a bit more, I'll come back with a more concrete example of that workflow. I think it will make my questions much clearer.

Thank you again for your patience and for sharing your knowledge. I really appreciate your guidance, and I'll be back on the forum soon after I've had some time to experiment.

Best regards,

- Elang
From: Elang
23 Jul   [#9]
Hi Michael,

I've attached a script that I've been working on as part of an R&D project at the company where I work. We have three MoI3D V4 licenses, all of which are used by our design and engineering team.

The goal of this script is to automate the creation of production box designs for our souvenir products. The idea is simple: the user enters the overall bounding box dimensions of a souvenir, and the script automatically generates the corresponding box design.





If you have some time, I'd really appreciate it if you could take a look and share your comments. Also, if you notice that I'm still approaching things with the wrong paradigm (as you pointed out in one of my previous posts) please don't hesitate to correct me. I'd much rather learn the proper way than continue building on a flawed approach.

My hope is that this tool will reduce the engineering time required for each box design by around 10–20 minutes, making the workflow more efficient for our team.

Thank you very much for your continued support and for all the knowledge you've shared with the MoI community over the years. It is genuinely appreciated.

Best regards,

- Elang

Attachments:
-AutoBox02.htm
-AutoBox02.js

Image Attachments:
2026-07-23_155110.jpg  2026-07-23_155543.jpg 


From: Michael Gibson
23 Jul   [#10] In reply to [#9]
Hi Elang,

re:
> If you have some time, I'd really appreciate it if you could take a look and share your
> comments. Also, if you notice that I'm still approaching things with the wrong paradigm
> (as you pointed out in one of my previous posts) please don't hesitate to correct me.
> I'd much rather learn the proper way than continue building on a flawed approach.

It looks good to me! Some minor things in the .htm file:

The <link rel="stylesheet" href="moi://ui/moi.css" type="text/css"> can be removed, it isn't needed anymore starting with MoI version 3. Same with xmlns:moi in the <html>.

In the <head> you can put in a <style> with some style rules and then all the individual inline style="" and align="" attributes can be removed, see attached.

- Michael

Attachments:
-AutoBox02_styles.htm


From: Elang
23 Jul   [#11]
Hi Michael,

Thank you very much for pointing out the `.htm` documentation. I'll definitely take a look at it later.

For now, I think I may have found a bug related to the bounding box dimensions.

I wrote this simple script to retrieve the bounding box of the selected object(s). However, when I displayed the values using `moi.ui.alert()`, the reported dimensions did not match the X/Y/Z size shown in the Object Info panel.

Here is the script:
code:
function excercise_06()
{
	var rnd = moi.geometryDatabase.getSelectedObjects();
	var bbox = rnd.getBoundingBox();

	moi.ui.alert(
		'X Length : ' + bbox.xLength +
		'Y Length : ' + bbox.yLength +
		'Z Length : ' + bbox.zLength
		);
}

excercise_06();


In the screenshot below, you can see that the X dimension reported by `bbox.xLength` differs from the X Size shown in the Object Info panel.

Am I misunderstanding what `getBoundingBox()` returns, or could this be a bug? I've attached the 'problematic' 3dm file.



Thank you very much in advance for your attention.

- Elang

Attachments:
Plaque.3dm

Image Attachments:
2026-07-24_110041.jpg 


From: Michael Gibson
24 Jul   [#12] In reply to [#11]
Hi Elang, since getting a precise minimal bounding box can be a time consuming calculation there are various types of approximations.

The one in the object info panel is based off of the display mesh. If you click on it to open the "Edit size" menu it will do a more accurate solver based calculation in the menu.

The one used by ObjectList.getBoundingBox() is quick to calculate and uses the bounds of surface control points. It can be larger than the accurate bounding box.

Do this if you want a "tight" bounding box:

code:
function excercise_06()
{
	var rnd = moi.geometryDatabase.getSelectedObjects();
	var bbox = rnd.getHighAccuracyBoundingBox();

	moi.ui.alert(
		'X Length : ' + moi.ui.formatCoordinate(bbox.xLength) +
		' Y Length : ' + moi.ui.formatCoordinate(bbox.yLength) +
		' Z Length : ' + moi.ui.formatCoordinate(bbox.zLength)
		);
}

excercise_06();

From: Elang
24 Jul   [#13] In reply to [#12]
Understood... Thank you very much, Michael!

Show messages: All  1-5  6-13