149 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			149 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Copyright (c) 2023 Dominic Masters
 | 
						|
// 
 | 
						|
// This software is released under the MIT License.
 | 
						|
// https://opensource.org/licenses/MIT
 | 
						|
 | 
						|
#include "PrefabGen.hpp"
 | 
						|
 | 
						|
using namespace Dawn;
 | 
						|
 | 
						|
void PrefabGen::generate(
 | 
						|
  std::vector<std::string> *out,
 | 
						|
  struct Prefab *info,
 | 
						|
  std::string tabs
 | 
						|
) {
 | 
						|
  struct ClassGenInfo classInfo;
 | 
						|
  classInfo.clazz = info->name;
 | 
						|
  classInfo.extend = "SceneItemPrefab<" + info->name + ">";
 | 
						|
  classInfo.constructorArgs = "Scene *scene, sceneitemid_t id";
 | 
						|
  classInfo.extendArgs = "scene, id";
 | 
						|
 | 
						|
  struct MethodGenInfo methodAssets;
 | 
						|
  methodAssets.name = "prefabAssets";
 | 
						|
  methodAssets.isStatic = true;
 | 
						|
  methodAssets.type = "std::vector<Asset*>";
 | 
						|
  methodAssets.args = "AssetManager *man";
 | 
						|
  line(&methodAssets.body, "std::vector<Asset*> assets;", "");
 | 
						|
 | 
						|
  struct MethodGenInfo methodInit;
 | 
						|
  methodInit.name = "prefabInit";
 | 
						|
  methodInit.isOverride = true;
 | 
						|
  methodInit.args = "AssetManager *man";
 | 
						|
 | 
						|
  classInfo.includes.push_back("prefab/SceneItemPrefab.hpp");
 | 
						|
 | 
						|
  // Process assets
 | 
						|
  int32_t assetNumber = 0;
 | 
						|
  auto processAsset = [&](struct PrefabAsset a) {
 | 
						|
    std::string assetType = "";
 | 
						|
    switch(a.type) {
 | 
						|
      case PREFAB_ASSET_TYPE_TEXTURE:
 | 
						|
        assetType = "TextureAsset";
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        assertUnreachable();
 | 
						|
    }
 | 
						|
    a.usageName = "asset" + std::to_string(assetNumber++);
 | 
						|
    line(&methodInit.body, "auto " + a.usageName + " = man->get<" + assetType + ">(" + a.fileName + ");", "");
 | 
						|
  };
 | 
						|
 | 
						|
  // Load self assets
 | 
						|
  auto itAssets = info->root.assets.begin();
 | 
						|
  while(itAssets != info->root.assets.end()) {
 | 
						|
    processAsset(*itAssets);
 | 
						|
    ++itAssets;
 | 
						|
  }
 | 
						|
  // TODO: Load child assets?
 | 
						|
 | 
						|
  // Process root and all of its children
 | 
						|
  int32_t childNumber = 0;
 | 
						|
  int32_t componentNumber = 0;
 | 
						|
 | 
						|
  auto processComponent = [&](struct PrefabComponent c, std::string item) {
 | 
						|
    auto componentName = "cmp" + std::to_string(componentNumber++);
 | 
						|
    bool_t componentInit = true;
 | 
						|
    if(c.ref.size() > 0) {
 | 
						|
      componentInit = false;
 | 
						|
      componentName = c.ref;
 | 
						|
      line(&classInfo.publicProperties, c.type + " *" + c.ref + " = nullptr;", "");
 | 
						|
    }
 | 
						|
 | 
						|
    // Initialize
 | 
						|
    line(&methodInit.body, (componentInit ? "auto " : "") + componentName + " = " + item + "->addComponent<" + c.type + ">();", "");
 | 
						|
 | 
						|
    // Now set each property
 | 
						|
    auto itValues = c.values.begin();
 | 
						|
    while(itValues != c.values.end()) {
 | 
						|
      line(&methodInit.body, componentName + "->" + itValues->first + " = " + itValues->second + ";", "");
 | 
						|
      ++itValues;
 | 
						|
    }
 | 
						|
 | 
						|
    classInfo.includes.push_back(c.include);
 | 
						|
  };
 | 
						|
 | 
						|
  std::function<void(struct PrefabChild &, std::string)> processChild;
 | 
						|
  processChild = [&](struct PrefabChild &child, std::string parent) {
 | 
						|
    auto name = "itm" + std::to_string(childNumber++);
 | 
						|
    bool_t init = true;
 | 
						|
    if(child.ref.size() > 0) {
 | 
						|
      init = false;
 | 
						|
      name = child.ref;
 | 
						|
      line(&classInfo.publicProperties, "SceneItemComponent *" + name + " = nullptr;", "");
 | 
						|
    }
 | 
						|
    line(&methodInit.body, (init ? "auto " : "") + name + " = scene->createSceneItem();", "");
 | 
						|
 | 
						|
    // Process extra properties
 | 
						|
    if(child.position.size() > 0) {
 | 
						|
      line(&methodInit.body, name + "->transform.setLocalPosition(" + child.position + ");", "");
 | 
						|
    }
 | 
						|
 | 
						|
    if(child.scale.size() > 0) {
 | 
						|
      line(&methodInit.body, name + "->transform.setLocalScale(" + child.scale + ");", "");
 | 
						|
    }
 | 
						|
 | 
						|
    // Add components for children
 | 
						|
    auto itComponents = child.components.begin();
 | 
						|
    while(itComponents != child.components.end()) {
 | 
						|
      auto c = *itComponents;
 | 
						|
      processComponent(c, name);
 | 
						|
      ++itComponents;
 | 
						|
    }
 | 
						|
 | 
						|
    // Process sub children
 | 
						|
    auto itChildren = child.children.begin();
 | 
						|
    while(itChildren != child.children.end()) {
 | 
						|
      processChild(*itChildren, name);
 | 
						|
      ++itChildren;
 | 
						|
    }
 | 
						|
 | 
						|
    // Set parent
 | 
						|
    line(&methodInit.body, name + "->transform.setParent(&"+parent+"->transform);", "");
 | 
						|
  };
 | 
						|
  
 | 
						|
  // Process each child
 | 
						|
  auto itChildren = info->root.children.begin();
 | 
						|
  while(itChildren != info->root.children.end()) {
 | 
						|
    processChild(*itChildren, "this");
 | 
						|
    line(&methodInit.body, "", "");
 | 
						|
    ++itChildren;
 | 
						|
  }
 | 
						|
 | 
						|
  // Process self components
 | 
						|
  auto itComponents = info->root.components.begin();
 | 
						|
  while(itComponents != info->root.components.end()) {
 | 
						|
    auto c = *itComponents;
 | 
						|
    processComponent(c, "this");
 | 
						|
    ++itComponents;
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Seal methods
 | 
						|
  line(&methodAssets.body, "return assets;", "");
 | 
						|
 | 
						|
  // Add in methods
 | 
						|
  CodeGen::methodGen(&classInfo.publicCode, methodAssets);
 | 
						|
  line(&classInfo.publicCode, "", "");
 | 
						|
  CodeGen::methodGen(&classInfo.publicCode, methodInit);
 | 
						|
 | 
						|
  CodeGen::classGen(out, classInfo);
 | 
						|
} |