In Rhino there are different ways to edit materials/environments, and handling these from the plugin is bit different (dependent on the actual mode), which causes problem here.
Normally in case the user edits the Custom Material from the Material panel. In this case every change happens instantly. But it is also possible to edit the material from a Modal Dialog (for example “Layer Material”) and in this case only after the user clicks on the OK button should the plugin accept the new values, but from the Eto Collapsible form it is not visible. I mean the plugin has no idea about the mode the material is edited and how to handle the change. (Also it knows nothing about what button the user clocks at the and - OK or Cancel).
What is the correct way to handle it? Maybe I could try to investigate what kind if dialog is on the top, and this could be a sign for the plugin how to handle changes, but it is a bit messy solution.
I don’t know the modal dialog very well, I use it about never. I don’t know if any of my materials in plug-ins (raytraced blend material, raytraced materials) work with it.
Those come with Rhino, but aren’t visible by default. You have to run the test command TestShowPrivateContent. After this the materials will be accessible through the UI.
And when Rhino opens my custom UI, the plugin reads the field values, and updates the custom UI according to the actual Field values.
It works fine with modeless dialogs, but the model dialog changes something.
The result is, when user clicks on cancel, the rendercontent keeps the latest values. And when user clicks OK, rendercontent reverses the changes. So as a result the behavior is the opposite of the expected.
I use only automatic user interface in these materials, correct.
For a modal dialog you’ll be working with a material that is not in the document, but in a sandbox. I’m not sure how you should handle that case, @maxsoder may know better.
Hi, @marton.parlagh If I understood it correctly the Modal dialog buttons (Ok, Cancel) work as if the buttons where switched. “Opposite as of expected”. It sounds like there is a bug in Rhino.
I have one question. I assume this is Windows as the button reads Ok instead of Apply. I would be interested to know if this happens also for your plugin on the Mac.
Unfortunately I was not able to test it under OSX. There is a bug with Eto forms (maybe you have already fixed it but my version still crashes), and when I try to change layer material to my Material type in Modal dialog mode, it crashes.
When you are updating your UI you have to ensure you’re not using the material from the document that this modal dialog is shown for. No references to a Rhino document should be made, including ActiveDoc.
Do you have a slightly more elaborate code sample based on that from the post that shows the problem with the modal material dialog that you’re experiencing?
As I was trying to put together a bit better sample code, but the result I wanted to show you is actually working normally. It means I have to recheck my own code, the Rhino dialog OK/Cancel buttons probably work fine… I will be back…
I also made a simple sample and tested on the Mac and Win. The Modal dialog case seems to work. I did my tests on 7.x, but the mechanism should be the same as in v6.
I will put my test code here so that others can have a look at it.
My test code
public class TestMaterialUiSection : Rhino.UI.Controls.EtoCollapsibleSection
{
private CheckBox m_cb;
public Rhino.Render.RenderContentCollection RenderContentCollectionSelectionReader
{
get
{
return ViewModel.GetData(Rhino.UI.Controls.DataSource.ProviderIds.ContentSelection, false, false) as Rhino.Render.RenderContentCollection;
}
}
public TestMaterialUiSection()
{
DataChanged += OnDataChanged;
m_cb = new CheckBox();
m_cb.Text = "My custom bool value";
m_cb.ThreeState = false;
m_cb.CheckedChanged += OnCheckedChanged;
Label label = new Label();
label.Text = "Hello there";
TableLayout table = new TableLayout()
{
Spacing = new Eto.Drawing.Size(5, 5),
Rows =
{
new TableRow(label),
new TableRow(m_cb),
null
}
};
Content = table;
}
public override Guid ViewModelId
{
get
{
return Guid.Empty;
}
}
public override Rhino.UI.LocalizeStringPair Caption
{
get
{
return new LocalizeStringPair("TestMaterial UI", "TestMaterial UI");
}
}
public override int SectionHeight
{
get
{
return 250;
}
}
private void OnDataChanged(object sender, Rhino.UI.Controls.DataSource.EventArgs args)
{
if (args.DataType == Rhino.UI.Controls.DataSource.ProviderIds.ContentParam ||
args.DataType == Rhino.UI.Controls.DataSource.ProviderIds.ContentSelection)
DisplayData();
}
private void DisplayData()
{
Rhino.Render.RenderContentCollection collection = RenderContentCollectionSelectionReader;
if (collection != null)
{
ContentCollectionIterator iterator = collection.Iterator();
Rhino.Render.RenderContent content = iterator.First();
if (content != null)
{
bool test_key = false;
content.Fields.TryGetValue("My custom bool value", out test_key);
m_cb.CheckedChanged -= OnCheckedChanged;
m_cb.Checked = test_key;
m_cb.CheckedChanged += OnCheckedChanged;
}
iterator.DeleteThis();
}
}
private void OnCheckedChanged(object sender, EventArgs e)
{
Rhino.Render.RenderContentCollection collection = RenderContentCollectionSelectionReader;
if (collection != null)
{
ContentCollectionIterator iterator = collection.Iterator();
Rhino.Render.RenderContent content = iterator.First();
if (content != null)
{
content.BeginChange(Rhino.Render.RenderContent.ChangeContexts.UI);
content.Fields.Set("My custom bool value", (bool)m_cb.Checked);
content.EndChange();
}
iterator.DeleteThis();
}
}
}
[Guid ("37D8ABBD-14BD-488C-B717-1FAA1F14EF62")]
public class TestMaterial : RenderMaterial
{
public override string TypeName { get { return "Test Material (DEV)"; } }
public override string TypeDescription { get { return "Test Material (DEV)"; } }
public float Gamma { get; set; }
public TestMaterial ()
{
Fields.Add ("My custom bool value", false);
Fields.Add ("diffuse_color", Rhino.Display.Color4f.White, "Diffuse Color");
}
protected override void OnAddUserInterfaceSections ()
{
AddAutomaticUserInterfaceSection ("Parameters", 0);
AddUserInterfaceSection (new TestMaterialUiSection ());
}
public override void SimulateMaterial (ref Rhino.DocObjects.Material simulatedMaterial, bool forDataOnly)
{
base.SimulateMaterial (ref simulatedMaterial, forDataOnly);
Rhino.Display.Color4f color;
if (Fields.TryGetValue ("diffuse_color", out color)) {
simulatedMaterial.DiffuseColor = color.AsSystemColor ();
}
}
}
´´´
In my code sample I get the content from the Selection datasource “RenderContentCollectionSelectionReader”. This datasource handles the Modal/Non Modal case. The UI Section does not need to know if it is displayed in a Modal or a non Modal dialog. In the Modal case the RenderContentCollectionSelectionReader datasource will return a content that is a copy from the actual content in the document. If the user click Ok, then the data will be copied to the content in the document. If the user clicks cancel, then the copied content is just discarded.
In the non modal case, the RenderContentCollectionSelectionReader will return the actual content in the document.