Create a basic project

This example describes how to create a basic SMTK project, add an attribute resource to it, and write the project to disk. A complete/working source file is included in the SMTK source repository, as file smtk/doc/tutorials/create_a_project/create_a_project.cxx. Snippets from that source file are described below.

Initialize SMTK Managers

To use SMTK projects, you first create SMTK resource manager, operation manager, and project manager instances, and then register the various SMTK features. In this example, we will be creating an attribute resource, so we also register the SMTK attribute feature to the resource and operation managers.

 1  // Initialize SMTK managers
 2  smtk::resource::ManagerPtr resManager = smtk::resource::Manager::create();
 3  smtk::project::Registrar::registerTo(resManager);
 5  smtk::operation::ManagerPtr opManager = smtk::operation::Manager::create();
 6  smtk::operation::Registrar::registerTo(opManager);
 7  opManager->registerResourceManager(resManager);
 9  smtk::project::ManagerPtr projManager = smtk::project::Manager::create(resManager, opManager);
10  smtk::project::Registrar::registerTo(projManager);
12  // Register SMTK attribute feature
13  smtk::attribute::Registrar::registerTo(resManager);
14  smtk::attribute::Registrar::registerTo(opManager);

Register and Create “basic” Project

SMTK projects are registered by a type (string) that is registered to the project manager. In the simplest case, you can register a project type with just a string, but you can also register the string plus a subclass of smtk::project::Project for more advanced applications. Although any project type can be used, for this example we deliberately chose to register “basic” because the CMB modelbuilder application also registers that type by default. As a result, the project saved in this example can be loaded into modelbuilder. Other project types require updating modelbuilder, typically via an SMTK plugin, to register the project type.

1  // Create project with type "basic", a generic type that can be loaded into modelbuilder by default.
2  projManager->registerProject("basic");
3  smtk::project::ProjectPtr project = projManager->create("basic");

Create Attribute Resource

Next we create a simple attribute resource for the project contents. Standard practice would use the SMTK ImportResource or ReadResource operations to load attribute and other resources, but in order to implement this example as a single source file, an inline string is used for the attribute template. Because the template is manually generated, we also check the error flag returned when the string is read.

In the last line of this snippet, we also create a single attribute instance to display in the instanced view. Refer to the attribute resource documentation for more information about create attribute templates and instances.

 1  // Create a small attribute resource
 2  smtk::attribute::ResourcePtr attResource = resManager->create<smtk::attribute::Resource>();
 3  const std::string attTemplate =
 4    "<SMTK_AttributeResource Version=\"4\">"
 5    "  <Definitions>"
 6    "    <AttDef Type=\"Example\">"
 7    "      <ItemDefinitions>"
 8    "        <String Name=\"String Item\">"
 9    "          <DefaultValue>Yellow denotes default value</DefaultValue>"
10    "        </String>"
11    "        <Int Name=\"Integer Item\">"
12    "          <DefaultValue>42</DefaultValue>"
13    "        </Int>"
14    "        <Double Name=\"Double Item\">"
15    "          <DefaultValue>3.14159</DefaultValue>"
16    "        </Double>"
17    "      </ItemDefinitions>"
18    "    </AttDef>"
19    "  </Definitions>"
20    "  <Views>"
21    "    <View Type=\"Instanced\" Title=\"Example\" TopLevel=\"true\""
22    "          FilterByAdvanceLevel=\"false\" FilterByCategory=\"false\">"
23    "      <InstancedAttributes>"
24    "        <Att Type=\"Example\" Name=\"example1\" />"
25    "      </InstancedAttributes>"
26    "    </View>"
27    "  </Views>"
28    "</SMTK_AttributeResource>";
30  smtk::io::AttributeReader attReader;
31  smtk::io::Logger logger;
32  bool err = attReader.readContents(attResource, attTemplate, logger);
33  if (err)
34  {
35    std::cerr << "ERROR: " << logger.convertToString() << std::endl;
36    return -1;
37  }
39  // Create the example attribute instance
40  attResource->createAttribute("example1", "Example");

Add Attribute Resource to Project

Adding a resource to a project is a single API call, passing in then resource (shared pointer) and a string identified called “role”. For example, a casting simulation project might have mulitple attribute resources with roles such as “heatup specification”, “pour”, “solidifcation”, and mesh resources with roles such as “heat transfer mesh”, “induction heating mesh”, and “fluid flow mesh”.

1  // Add the attribute resource to the project, stting its project role to "attributes".
2  const std::string role = "attributes";
3  project->resources().add(attResource, role);

Write Project Resource

Because the SMTK project class is a subclass of the SMTK resource class, The standard SMTK WriteResource operation can be used to serialize the project to the file system. To do this, specify a project filename with the standard “.smtk” extension. In this example, the operation writes 2 files to disk, the specified project file (the filename basic-project.smtk is used in the code snippet) and a separate file for the attribute resource that was added to the project. Project resource files are written to a resources subfolder. The filename used for the attribute resource file is its rolename plus the “.smtk” extension, in this case, attributes.smtk. So for this example, the outputs to the filesystem are:

working directory
|-- basic-project.smtk
|-- resources/
|---- attributes.smtk

The code to do this is the same as writing any SMTK resource.

 1  // Write the project to the filesystem using the default WriteResource operation.
 2  smtk::operation::WriteResource::Ptr writeOp = opManager->create<smtk::operation::WriteResource>();
 3  writeOp->parameters()->associate(project);
 4  writeOp->parameters()->findFile("filename")->setIsEnabled(true);
 5  writeOp->parameters()->findFile("filename")->setValue("basic-project.smtk");
 6  smtk::operation::Operation::Result writeResult = writeOp->operate();
 7  int writeOutcome = writeResult->findInt("outcome")->value();
 9  if (writeOutcome == static_cast<int>(smtk::operation::Operation::Outcome::SUCCEEDED))
10  {
11    std::cout << "Wrote project to the current directory.\n"
12              << " This consists of file \"basic-example.smtk\" in the current directory\n"
13              << " which is the project's resource file, and file \"resources/attributes.smtk\"\n"
14              << " which is the attribute resource." << std::endl;
15  }
16  else
17  {
18    std::cout << "Failed to write project file, with outcome " << writeOutcome << ".\n";
19    std::cout << logger.convertToString() << std::endl;
20    return -1;
21  }
23  return 0;

Open in modelbuilder Application

As noted above, the CMB modelbuilder application is configured by default to register SMTK projects of type “basic”. So you can use the modelbuilder File => Open menu to load the basic-project.smtk file which loads the entire project which, in this case, is just the single attribute resource. When you do this, enable the “Attribute Editor” and “Projects” views. An example the resulting display is show here. The “Projects” view, in the lower part, shows a tree view of the projects currently loaded, in this case, our basic project example. Above that is the “Attribute Editor” for the simple attribute resource we created and included in the project.


Going Further

For extra credit, you can obtain this source file at smtk/doc/tutorials/create_a_project/create_a_project.cxx and continue adding features, for example:

  • Replace the inline attribute with an external .sbt file.

  • Use the SMTK ReadResource operation to create the attribute resource from the .sbt file.

  • Load a model file and add that to the project.

  • Extend the attribute template to include model associations.