Procházet zdrojové kódy

Merge pull request #1150 from Azaezel/classPrototypingPresenter

Class prototyping presenter
Brian Roberts před 1 rokem
rodič
revize
2a577d19eb

+ 129 - 2
Engine/source/console/simObject.cpp

@@ -40,6 +40,7 @@
 #include "core/fileObject.h"
 #include "persistence/taml/tamlCustom.h"
 #include "gui/editor/guiInspector.h"
+#include "console/script.h"
 
 #include "sim/netObject.h"
 
@@ -90,7 +91,7 @@ SimObject::SimObject()
    mNameSpace    = NULL;
    mNotifyList   = NULL;
    mFlags.set( ModStaticFields | ModDynamicFields );
-
+   mPrototype = true;
    mProgenitorFile = StringTable->EmptyString();
 
    mFieldDictionary = NULL;
@@ -159,7 +160,8 @@ void SimObject::initPersistFields()
 
       addProtectedField("inheritFrom", TypeString, Offset(mInheritFrom, SimObject), &setInheritFrom, &defaultProtectedGetFn,
          "Optional Name of object to inherit from as a parent.");
-                  
+
+      addProtectedField("Prototype", TypeBool, Offset(mPrototype, SimObject), &_doPrototype, &defaultProtectedGetFn, "Prototype Methods", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
    endGroup( "Ungrouped" );
 
    addGroup( "Object" );
@@ -212,6 +214,15 @@ void SimObject::initPersistFields()
 }
 
 //-----------------------------------------------------------------------------
+bool SimObject::_doPrototype(void* object, const char* index, const char* data)
+{
+   if (!Con::isFunction("PrototypeClass")) return false;
+   if (dAtoi(data) != 1) return false;
+   SimObject* obj = reinterpret_cast<SimObject*>(object);
+   String command = String("PrototypeClass(") + (obj->getName()? String(obj->getName()) : String::ToString(obj->getId())) + ");";
+   Con::evaluate(command.c_str());
+   return false;
+}
 
 String SimObject::describeSelf() const
 {
@@ -2707,6 +2718,59 @@ DefineEngineMethod(SimObject, getMethodSigs, ArrayObject*, (bool commands), (fal
 
    return dictionary;
 }
+
+DefineEngineFunction(getMethodSigsNS, ArrayObject*, (StringTableEntry className, bool commands), (false),
+   "List the methods defined on this object.\n\n"
+   "Each description is a newline-separated vector with the following elements:\n"
+   "- method prototype string.\n"
+   "- Documentation string (not including prototype).  This takes up the remainder of the vector.\n"
+   "@return An ArrayObject populated with (name,description) pairs of all methods defined on the object.")
+{
+   
+   Namespace* ns = Con::lookupNamespace(className);
+   if (!ns)
+      return 0;
+
+   ArrayObject* dictionary = new ArrayObject();
+   dictionary->registerObject();
+
+   VectorPtr<Namespace::Entry*> vec(__FILE__, __LINE__);
+   ns->getEntryList(&vec);
+   for (Vector< Namespace::Entry* >::iterator j = vec.begin(); j != vec.end(); j++)
+   {
+      Namespace::Entry* e = *j;
+
+      if (commands)
+      {
+         if ((e->mType < Namespace::Entry::ConsoleFunctionType))
+            continue;
+      }
+      else
+      {
+         if ((e->mType > Namespace::Entry::ScriptCallbackType))
+            continue;
+      }
+      StringBuilder str;
+      str.append("function ");
+      str.append(ns->getName());
+      str.append("::");
+      str.append(e->getPrototypeSig());
+      str.append('\n');
+      str.append("{");
+      String docs = e->getDocString();
+      if (!docs.isEmpty())
+      {
+         str.append("\n/*");
+         str.append(docs);
+         str.append("\n*/");
+      }
+      str.append('\n');
+      str.append("}");
+      dictionary->push_back(e->mFunctionName, str.end());
+   }
+
+   return dictionary;
+}
 //-----------------------------------------------------------------------------
 
 namespace {
@@ -3262,6 +3326,33 @@ DefineEngineMethod( SimObject, getFieldCount, S32, (),,
    return list.size() - numDummyEntries;
 }
 
+DefineEngineFunction(getFieldCountNS, S32, (StringTableEntry className), ,
+   "Get the number of static fields on the name space.\n"
+   "@return The number of static fields defined on the object.")
+{
+   Namespace* ns = Con::lookupNamespace(className);
+   if (!ns)
+      return 0;
+   AbstractClassRep* rep = ns->mClassRep;
+   if (!rep)
+      return 0;
+
+   const AbstractClassRep::FieldList& list = rep->mFieldList;
+   const AbstractClassRep::Field* f;
+   U32 numDummyEntries = 0;
+
+   for (S32 i = 0; i < list.size(); i++)
+   {
+      f = &list[i];
+
+      // The special field types do not need to be counted.
+      if (f->type >= AbstractClassRep::ARCFirstCustomField || f->flag.test(AbstractClassRep::FieldFlags::FIELD_ComponentInspectors))
+         numDummyEntries++;
+   }
+
+   return list.size() - numDummyEntries;
+}
+
 //-----------------------------------------------------------------------------
 
 DefineEngineMethod( SimObject, getField, const char*, ( S32 index ),,
@@ -3293,6 +3384,42 @@ DefineEngineMethod( SimObject, getField, const char*, ( S32 index ),,
    return "";
 }
 
+DefineEngineFunction(getFieldNS, const char*, (StringTableEntry className,S32 index), ,
+   "Retrieve the value of a static field by index.\n"
+   "@param index The index of the static field.\n"
+   "@return The value of the static field with the given index or \"\".")
+{
+   Namespace* ns = Con::lookupNamespace(className);
+   if (!ns)
+      return 0;
+   AbstractClassRep* rep = ns->mClassRep;
+   if (!rep)
+      return 0;
+
+   const AbstractClassRep::FieldList& list = rep->mFieldList;
+   if ((index < 0) || (index >= list.size()))
+      return "";
+
+   const AbstractClassRep::Field* f;
+   S32 currentField = 0;
+   for (U32 i = 0; i < list.size() && currentField <= index; i++)
+   {
+      f = &list[i];
+
+      // The special field types can be skipped.
+      if (f->type >= AbstractClassRep::ARCFirstCustomField || f->flag.test(AbstractClassRep::FieldFlags::FIELD_ComponentInspectors))
+         continue;
+
+      if (currentField == index)
+         return f->pFieldname;
+
+      currentField++;
+   }
+
+   // if we found nada, return nada.
+   return "";
+}
+
 DefineEngineFunction(getClassHierarchy, const char*, (const char* name), ,
    "Returns the inheritance hierarchy for a given class.")
 {

+ 2 - 2
Engine/source/console/simObject.h

@@ -300,7 +300,7 @@ class SimObject: public ConsoleObject, public TamlCallbacks
       SimObject*       nextIdObject;
 
       StringTableEntry mInheritFrom;
-
+      bool    mPrototype;
       /// SimGroup we're contained in, if any.
       SimGroup*   mGroup;
       
@@ -388,7 +388,7 @@ class SimObject: public ConsoleObject, public TamlCallbacks
    public:
       inline void setProgenitorFile(const char* pFile) { mProgenitorFile = StringTable->insert(pFile); }
       inline StringTableEntry getProgenitorFile(void) const { return mProgenitorFile; }
-
+      static bool _doPrototype(void* object, const char* index, const char* data);
    protected:
       /// Taml callbacks.
       virtual void onTamlPreWrite(void) {}

+ 3 - 0
Templates/BaseGame/game/data/Prototyping/Prototyping.tscript

@@ -37,6 +37,9 @@ function Prototyping::onDestroyGameServer(%this)
 //This is called when the client is initially set up by the game application
 function Prototyping::initClient(%this)
 {
+   //class method prototyping
+   %this.queueExec("./UI/classPrototyping");
+   %this.queueExec("./UI/classPrototyping.gui");
 }
 
 //This is called when a client connects to a server

+ 5 - 0
Templates/BaseGame/game/data/Prototyping/UI/classPrototyping.asset.taml

@@ -0,0 +1,5 @@
+<GUIAsset
+    AssetName="classPrototyping"
+    ScriptFile="@assetFile=classPrototyping.tscript"
+    GUIFile="@assetFile=classPrototyping.gui"
+    VersionId="1"/>

+ 115 - 0
Templates/BaseGame/game/data/Prototyping/UI/classPrototyping.gui

@@ -0,0 +1,115 @@
+//--- OBJECT WRITE BEGIN ---
+$guiContent = new GuiControl(classPrototyping) {
+   extent = "1024 768";
+   profile = "GuiDefaultProfile";
+   tooltipProfile = "GuiToolTipProfile";
+   isContainer = "1";
+   canSaveDynamicFields = "1";
+      originalAssetName = "classPrototyping";
+
+   new GuiWindowCtrl() {
+      text = "Class Prototyping";
+      position = "216 124";
+      extent = "592 519";
+      horizSizing = "center";
+      vertSizing = "center";
+      profile = "ToolsGuiWindowProfile";
+      tooltipProfile = "GuiToolTipProfile";
+      closeCommand = "Canvas.popDialog(classPrototyping);";
+      new GuiScrollCtrl() {
+         lockVertScroll = "1";
+         position = "14 30";
+         extent = "564 33";
+         profile = "ToolsGuiScrollProfile";
+         tooltipProfile = "GuiToolTipProfile";
+
+         new GuiDynamicCtrlArrayControl(ClassInheritanceListCtrl) {
+            colCount = "1";
+            colSize = "80";
+            rowCount = "1";
+            rowSize = "18";
+            autoCellSize = "1";
+            fillRowFirst = "0";
+            dynamicSize = "1";
+            position = "1 1";
+            extent = "400 18";
+            profile = "GuiDefaultProfile";
+            tooltipProfile = "GuiToolTipProfile";
+         };
+      };
+      new GuiTextCtrl() {
+         text = "Callbacks";
+         position = "24 66";
+         extent = "54 14";
+         profile = "ToolsGuiTextProfile";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+      new GuiScrollCtrl() {
+         position = "19 80";
+         extent = "552 326";
+         profile = "ToolsGuiScrollProfile";
+         tooltipProfile = "GuiToolTipProfile";
+
+         new GuiDynamicCtrlArrayControl(ClassMethodListCtrl) {
+            colCount = "1";
+            colSize = "8000";
+            rowCount = "1";
+            rowSize = "18";
+            dynamicSize = "1";
+            extent = "552 326";
+            profile = "GuiDefaultProfile";
+            tooltipProfile = "GuiToolTipProfile";
+         };
+      };
+      new GuiBitmapButtonCtrl() {
+         BitmapAsset = "ToolsModule:iconOpen_image";
+         bitmapMode = "Centered";
+         position = "348 467";
+         extent = "22 22";
+         horizSizing = "left";
+         profile = "ToolsGuiButtonProfile";
+         command = "SelectAssetPath.showDialog(AssetBrowser.dirHandler.currentAddress, \"setProtoTypeFilePath\");\nSelectAssetPathWindow.selectWindow();";
+         tooltipProfile = "GuiToolTipProfile";
+         tooltip = "New Module";
+      };
+      new GuiTextEditCtrl() {
+         text = "data/ExampleModule";
+         position = "143 470";
+         extent = "201 20";
+         horizSizing = "width";
+         profile = "ToolsGuiTextEditProfile";
+         active = "0";
+         tooltipProfile = "GuiToolTipProfile";
+         internalName = "targetPath";
+      };
+      new GuiTextCtrl() {
+         text = "Target Path:";
+         position = "20 470";
+         extent = "116 17";
+         profile = "ToolsGuiTextProfile";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+      new GuiButtonCtrl() {
+         text = "Save";
+         position = "431 465";
+         profile = "ToolsGuiButtonProfile";
+         command = "classPrototyping.writeResults();";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+      new GuiCheckBoxCtrl(ReportCommands) {
+         text = "Report Commands";
+         position = "16 420";
+         extent = "125 30";
+         profile = "ToolsGuiCheckBoxProfile";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+      new GuiCheckBoxCtrl(ReportVariables) {
+         text = "Report Stock Variables";
+         position = "152 420";
+         extent = "125 30";
+         profile = "ToolsGuiCheckBoxProfile";
+         tooltipProfile = "GuiToolTipProfile";
+      };
+   };
+};
+//--- OBJECT WRITE END ---

+ 204 - 0
Templates/BaseGame/game/data/Prototyping/UI/classPrototyping.tscript

@@ -0,0 +1,204 @@
+function classPrototyping::onWake(%this)
+{
+    
+}
+
+function classPrototyping::onSleep(%this)
+{
+    
+}
+//PrototypeClass(MainMenuGui)
+//PrototypeClass(GuiChunkedBitmapCtrl)
+function PrototypeClass(%classInstance)
+{
+    if (!isObject(%classInstance)) return;
+    Canvas.pushDialog(classPrototyping);
+    classPrototyping.fillClasslist(%classInstance);
+    classPrototyping.SetNamespaceUsed(%classInstance);
+}
+
+function classPrototyping::fillClasslist(%this, %classInstance)
+{
+    ClassInheritanceListCtrl.deleteAllObjects();
+    %this.instanceName = %classInstance.getName();
+    
+    //get potentially scripted namespaces
+    %class = %classInstance.getClassName();    
+    %prepend = "";
+    if (%classInstance.getName() !$= "")
+        %prepend = %classInstance.getName();
+    if (%classInstance.class !$= "")
+        %prepend = %prepend SPC %classInstance.class;        
+    if (%classInstance.superclass !$= "")
+        %prepend = %prepend SPC %classInstance.superclass;
+        
+    //append to hardcoded potential namespaces
+    %this.classlist = %prepend SPC getClassHierarchy(%class);
+    %this.classCount = getWordCount(%this.classlist);
+    for (%i=0; %i<%this.classCount; %i++)
+    {
+        %inheritanceOrder = %this.classCount-(%i+1);
+        %className = getWord(%this.classlist,%inheritanceOrder);
+        if (%i<%this.classCount-1)
+            %className = %className @"->";
+        %elemClass = new GuiRadioCtrl("ProtoClassSelect"@ %i) {
+               text = %className;
+               entry = strreplace(%className,"->","");
+               groupNum = "1";
+               extent = "80 18";
+               profile = "ToolsGuiRadioProfile";
+               tooltipProfile = "GuiToolTipProfile";
+               };
+        eval("function ProtoClassSelect"@ %i @"::onClick(%this){classPrototyping.SetNamespaceUsed(%this.entry);}");
+        ClassInheritanceListCtrl.addGuiControl(%elemClass);
+    }
+    %lastElem = "ProtoClassSelect"@ %this.classCount-1;
+    %lastElem.setStateOn(true);
+}
+
+function classPrototyping::SetNamespaceUsed(%this, %nameSpaceUsed)
+{
+    ClassMethodListCtrl.deleteAllObjects();
+    %this.fillMethodlist(%nameSpaceUsed);
+}
+
+function classPrototyping::fillMethodlist(%this, %nameSpaceUsed)
+{
+    ClassMethodListCtrl.deleteAllObjects();
+    %this.nameSpaceUsed = %nameSpaceUsed;
+    %this.methodArray = getMethodSigsNS(%nameSpaceUsed);
+    %this.methodCount = %this.methodArray.count();
+    
+    for (%i=0; %i<%this.methodCount; %i++)
+    {
+         %methodDef = getRecord(%this.methodArray.getValue(%i),0);
+         %methodName = strreplace(%methodDef,"::"," ");
+         %methodName = getWord(strreplace(%methodName,"("," "),2);
+         
+        %elemMethod = new GuiCheckBoxCtrl("ProtoMethodSelect"@ %i) {
+            text = %methodName;
+            position = "1 1";
+            profile = "ToolsGuiCheckBoxProfile";
+            tooltipProfile = "GuiToolTipProfile";
+         };
+        ClassMethodListCtrl.addGuiControl(%elemMethod);
+    }
+}
+
+function setProtoTypeFilePath(%targetPath)
+{
+   classPrototyping-->targetPath.text = %targetPath;
+}
+
+function classPrototyping::readExistingLayout(%this)
+{
+    for (%i=0; %i<%this.classCount; %i++)
+    {
+        %inheritanceOrder = %this.classCount-(%i+1);
+        %obj = "ProtoClassSelect"@ %i;
+        if (%obj.isStateOn())
+            %namespaceUsed = getWord(%this.classlist,%inheritanceOrder);
+    }
+    
+	%file = new FileObject();
+    %filename = classPrototyping-->targetPath.text @"/"@ %namespaceUsed @"."@ $TorqueScriptFileExtension;
+    
+    if (!isObject(%this.callbacksDefined))
+        %this.callbacksDefined = new arrayobject();
+    %this.callbacksDefined.empty();
+    %this.reportedCommands = false;
+    %this.reportedVariables = false;
+    %this.callbackBlockDefined = false;
+    
+    %key=0;
+	if(%file.openForRead(%filename))
+    {
+        while (!%file.isEof())
+        {
+            %line = %file.readLine();
+            
+            //have we already reported commands?
+            if (startsWith(%line,"/* Available Commands:") )
+                %this.reportedCommands = true;
+                
+            //have we already reported variables?
+            if (startsWith(%line,"/* HardCoded Variables") )
+                %this.reportedVariables = true;
+                
+            if (startsWith(%line,"/*--- Callbacks ---*/") )
+                %this.callbackBlockDefined = true;
+            
+            //get list of methods already existing
+            if (startswith(%line,"function "@ %namespaceUsed) )
+            {
+                %methodName = strreplace(%line,"::"," ");
+                %methodName = getWord(strreplace(%methodName,"("," "),2);
+                %this.callbacksDefined.add(%key++,%methodName);
+            }
+        }
+    }
+	%file.delete();
+}
+
+function classPrototyping::writeResults(%this)
+{
+    %namespaceUsed = "";
+    for (%i=0; %i<%this.classCount; %i++)
+    {
+        %inheritanceOrder = %this.classCount-(%i+1);
+        %obj = "ProtoClassSelect"@ %i;
+        if (%obj.isStateOn())
+            %namespaceUsed = getWord(%this.classlist,%inheritanceOrder);
+    }
+    %this.readExistingLayout();
+	%file = new FileObject();
+    %filename = classPrototyping-->targetPath.text @"/"@ %namespaceUsed @"."@ $TorqueScriptFileExtension;
+	if(%file.openForAppend(%filename))
+    {
+        if (ReportCommands.isStateOn() && %this.reportedCommands == false)
+        {
+            %this.commandArray = getMethodSigsNS(%this.nameSpaceUsed,true);
+            %this.commandCount = %this.commandArray.count();
+            %file.writeLine("/* Available Commands:");
+            for (%i=0; %i< %this.commandCount; %i++)
+            {
+                %file.writeLine(getRecord(%this.commandArray.getValue(%i),0));
+            }
+            %file.writeLine("*/");
+        }
+    
+        if (ReportVariables.isStateOn() && %this.reportedVariables == false)
+        {
+            %file.writeLine("/* HardCoded Variables");
+            for (%i=0; %i< getFieldCountNS(%this.nameSpaceUsed); %i++)
+            {
+                %file.writeLine(getFieldNS(%this.nameSpaceUsed,%i));
+            }
+            %file.writeLine("*/");
+        }
+        
+        if (%this.callbackBlockDefined == false)
+            %file.writeLine("\n/*--- Callbacks ---*/\n");
+            
+        for (%i=0; %i<%this.methodCount; %i++)
+        {
+            %obj = "ProtoMethodSelect"@ %i;
+            if (%obj.isStateOn())
+            {
+                %methodDef = getRecord(%this.methodArray.getValue(%i),0);
+                %methodName = strreplace(%methodDef,"::"," ");
+                %methodName = getWord(strreplace(%methodName,"("," "),2);
+                if (%this.callbacksDefined.countValue(%methodName)==0)
+                {
+                    echo(%methodName @ "not found. defining...");
+                    %file.writeLine("\n" @ strreplace(%this.methodArray.getValue(%i),%this.instanceName,%namespaceUsed));
+                }
+            }
+        }
+    }
+	else
+	{
+		error( "Failed to open " @ %filename @ " for writing" );
+	}
+	%file.delete();
+}