uid issue
This commit is contained in:
14
responserules/ResponseEditor/ResponseEditor/App.xaml
Normal file
14
responserules/ResponseEditor/ResponseEditor/App.xaml
Normal file
@ -0,0 +1,14 @@
|
||||
<Application x:Class="ResponseEditor.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:ResponseEditor"
|
||||
xmlns:as="clr-namespace:ManagedAppSystem;assembly=responserules_cli"
|
||||
StartupUri="Window1.xaml"
|
||||
Startup="Application_Startup"
|
||||
>
|
||||
<Application.Resources>
|
||||
<!-- Initialize global app system interface. -->
|
||||
<as:AppSystemWrapper x:Key="AppSystem" />
|
||||
<local:ResponseSystemWPF x:Key="ResponseSystem" />
|
||||
</Application.Resources>
|
||||
</Application>
|
34
responserules/ResponseEditor/ResponseEditor/App.xaml.cs
Normal file
34
responserules/ResponseEditor/ResponseEditor/App.xaml.cs
Normal file
@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
|
||||
using ResponseRulesCLI;
|
||||
using ManagedAppSystem;
|
||||
|
||||
namespace ResponseEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
public App()
|
||||
{
|
||||
// m_responseDatabase = new ResponseDatabase();
|
||||
// Resources["ResponseDatabase"] = m_responseDatabase;
|
||||
}
|
||||
|
||||
private void Application_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
// This forces initialization of the app system on start up.
|
||||
Resources["AppSystem"] = new AppSystemWrapper();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
124
responserules/ResponseEditor/ResponseEditor/Criterion.cs
Normal file
124
responserules/ResponseEditor/ResponseEditor/Criterion.cs
Normal file
@ -0,0 +1,124 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace ResponseEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single AI_Criterion inside a rule.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A response rule contains a list of criteria, each of which consists of a key,
|
||||
/// a matcher (comparator), and a value. A query into the response system contains a
|
||||
/// list of key:value pairs. Each of these is tested against all the criteria in a rule.
|
||||
/// Each matching criterion increases that rule's score. The best scoring rule is selected.
|
||||
/// If a criterion is marked as Required, then its failure rejects the rule.
|
||||
/// Otherwise it just doesn't contribute to the score.
|
||||
/// </remarks>
|
||||
public class DummyCriterion
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates the comparison of a value against this criterion.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Matcher performs the comparison between the value specified in
|
||||
/// the criterion and the value specified in a context. Eg, a criterion
|
||||
/// with key "foo", value 5 and matcher ">" means that only queries with
|
||||
/// context "foo" greater than 5 will match this criterion.
|
||||
///
|
||||
/// Right now this is a complete mockup since the actual matching code is all in the
|
||||
/// C++ side.
|
||||
/// </remarks>
|
||||
public class Matcher
|
||||
{
|
||||
public Matcher(string text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test to see if a given value from a query matches this criterion
|
||||
/// </summary>
|
||||
/// <param name="crit">The criterion to be matched (usually contains this matcher)</param>
|
||||
/// <param name="queryValue">The value to be tested, AKA the context.</param>
|
||||
bool Test( DummyCriterion crit, string queryValue)
|
||||
{
|
||||
throw new System.NotImplementedException("DummyCriterion::Matcher::Test() is not actually implemented.");
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The actual text of the matcher from the source file. May be null (implies ==)
|
||||
/// </summary>
|
||||
private string text;
|
||||
|
||||
public string Text
|
||||
{
|
||||
get { return text; }
|
||||
set { text = value; }
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Text;
|
||||
}
|
||||
};
|
||||
|
||||
public DummyCriterion(string key, string value, float weight, bool required, Matcher comparison)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.weight = weight;
|
||||
this.required = required;
|
||||
this.comparison = comparison;
|
||||
}
|
||||
|
||||
private string key;
|
||||
private string value;
|
||||
private float weight;
|
||||
private bool required;
|
||||
private Matcher comparison;
|
||||
|
||||
public string Key
|
||||
{
|
||||
get { return key; }
|
||||
// set { key = value; }
|
||||
}
|
||||
|
||||
public string Value
|
||||
{
|
||||
get { return this.value; }
|
||||
// set { this.value = value; }
|
||||
}
|
||||
|
||||
public bool Required
|
||||
{
|
||||
get { return required; }
|
||||
// set { required = value; }
|
||||
}
|
||||
|
||||
public Matcher Comparison
|
||||
{
|
||||
get { return comparison; }
|
||||
// set { comparison = value; }
|
||||
}
|
||||
|
||||
public float Weight
|
||||
{
|
||||
get { return weight; }
|
||||
// set { weight = value; }
|
||||
}
|
||||
|
||||
|
||||
/// dummy criteria data for testing
|
||||
public static DummyCriterion[] g_DummyCriteria =
|
||||
{
|
||||
new DummyCriterion( "foo", "1", 1, false, new Matcher(">") ),
|
||||
new DummyCriterion( "bar", "soup", 1, false, new Matcher("") ),
|
||||
new DummyCriterion( "Concept", "Talk", 1, true, new Matcher("") )
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("ResponseEditor")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("Valve")]
|
||||
[assembly: AssemblyProduct("ResponseEditor")]
|
||||
[assembly: AssemblyCopyright("Copyright © Valve 2009")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly: ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
71
responserules/ResponseEditor/ResponseEditor/Properties/Resources.Designer.cs
generated
Normal file
71
responserules/ResponseEditor/ResponseEditor/Properties/Resources.Designer.cs
generated
Normal file
@ -0,0 +1,71 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.3082
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ResponseEditor.Properties
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ResponseEditor.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,117 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
30
responserules/ResponseEditor/ResponseEditor/Properties/Settings.Designer.cs
generated
Normal file
30
responserules/ResponseEditor/ResponseEditor/Properties/Settings.Designer.cs
generated
Normal file
@ -0,0 +1,30 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:2.0.50727.3082
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace ResponseEditor.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
@ -0,0 +1,162 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="3.5" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProductVersion>9.0.30729</ProductVersion>
|
||||
<SchemaVersion>2.0</SchemaVersion>
|
||||
<ProjectGuid>{639289AE-64D7-4839-92EE-0A0C495477EC}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ResponseEditor</RootNamespace>
|
||||
<AssemblyName>ResponseEditor</AssemblyName>
|
||||
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||
<PublishUrl>../ResponseEditorFoo/</PublishUrl>
|
||||
<Install>true</Install>
|
||||
<InstallFrom>Disk</InstallFrom>
|
||||
<UpdateEnabled>false</UpdateEnabled>
|
||||
<UpdateMode>Foreground</UpdateMode>
|
||||
<UpdateInterval>7</UpdateInterval>
|
||||
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||
<UpdatePeriodically>false</UpdatePeriodically>
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>..\..\..\devtools\responseeditor\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>..\..\..\devtools\responseeditor\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="responserules_cli, Version=1.0.3440.21239, Culture=neutral, processorArchitecture=x86">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\bin\responserules_cli.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.DataSetExtensions">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="WPFToolkit, Version=3.5.40128.1, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ApplicationDefinition Include="App.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Page Include="Window1.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Window1.xaml.cs">
|
||||
<DependentUpon>Window1.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Criterion.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<Compile Include="ResponseSystemWPF.cs" />
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<AppDesigner Include="Properties\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework Client Profile</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 2.0 %28x86%29</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.0 %28x86%29</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5</ProductName>
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||
<Visible>False</Visible>
|
||||
<ProductName>Windows Installer 3.1</ProductName>
|
||||
<Install>true</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>
|
||||
</PostBuildEvent>
|
||||
</PropertyGroup>
|
||||
</Project>
|
106
responserules/ResponseEditor/ResponseEditor/ResponseSystemWPF.cs
Normal file
106
responserules/ResponseEditor/ResponseEditor/ResponseSystemWPF.cs
Normal file
@ -0,0 +1,106 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
using ResponseRulesCLI;
|
||||
using Tier1CLI.Containers;
|
||||
|
||||
namespace ResponseEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Wraps the ResponseSystemCLI with some additional glue that makes the WPF go.
|
||||
/// </summary>
|
||||
public class ResponseSystemWPF : ResponseRulesCLI.ResponseSystemCLI
|
||||
{
|
||||
#region Interface Wrappers
|
||||
public Tier1CLI.Containers.INotifiableList ResponseGroupBinding
|
||||
{
|
||||
get { return ResponseGroupsDict; }
|
||||
}
|
||||
|
||||
public Tier1CLI.Containers.INotifiableList CriteriaBinding
|
||||
{
|
||||
get { return CriteriaDict; }
|
||||
}
|
||||
|
||||
/*
|
||||
public Tier1CLI.Containers.INotifiableList EnumerationsBinding
|
||||
{
|
||||
get { return EnumerationsDict; }
|
||||
}
|
||||
*/
|
||||
|
||||
public RulesAsList RulesBinding
|
||||
{
|
||||
get { return Rules; }
|
||||
}
|
||||
|
||||
public override void LoadFromFile( String filename )
|
||||
{
|
||||
base.LoadFromFile(filename);
|
||||
|
||||
ResponseGroupBinding.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
CriteriaBinding.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
RulesBinding.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
|
||||
// EnumerationsBinding.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
|
||||
RefreshShadowLists();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public ResponseSystemWPF()
|
||||
{
|
||||
ResponseRulesCLI.SingletonResponseSystem_t.RS = this;
|
||||
CriteriaBinding.CollectionChanged += this.OnCriteriaChanged;
|
||||
m_concepts = new ObservableCollection<string>();
|
||||
}
|
||||
|
||||
#region Shadow Lists
|
||||
public ObservableCollection<String> ConceptsShadow
|
||||
{
|
||||
get { return m_concepts; }
|
||||
}
|
||||
|
||||
void OnCriteriaChanged( object sender, NotifyCollectionChangedEventArgs args )
|
||||
{
|
||||
RefreshShadowLists();
|
||||
}
|
||||
|
||||
void RefreshShadowLists()
|
||||
{
|
||||
// Do the concepts
|
||||
m_concepts.Clear();
|
||||
List<string> tempconcepts = new List<string>();
|
||||
// use reflection to fish out the Val prop.
|
||||
PropertyInfo valprop = CriteriaBinding[0].GetType().GetProperty("Val");
|
||||
|
||||
foreach ( Object tupletype in CriteriaBinding )
|
||||
{
|
||||
Criterion crit = (Criterion)valprop.GetValue(tupletype, null);
|
||||
if ( crit.Key.Equals("concept", StringComparison.OrdinalIgnoreCase ) )
|
||||
{
|
||||
tempconcepts.Add(crit.Value);
|
||||
}
|
||||
}
|
||||
tempconcepts.Sort();
|
||||
foreach ( string s in tempconcepts )
|
||||
{
|
||||
m_concepts.Add(s);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Local private data.
|
||||
// Here's some local conveniences for making the debugger pane.
|
||||
ObservableCollection<String> m_concepts;
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
239
responserules/ResponseEditor/ResponseEditor/Window1.xaml
Normal file
239
responserules/ResponseEditor/ResponseEditor/Window1.xaml
Normal file
@ -0,0 +1,239 @@
|
||||
<Window x:Class="ResponseEditor.Window1"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:tk="http://schemas.microsoft.com/wpf/2008/toolkit"
|
||||
xmlns:local="clr-namespace:ResponseEditor"
|
||||
xmlns:rr="clr-namespace:ResponseRulesCLI;assembly=responserules_cli"
|
||||
xmlns:as="clr-namespace:ManagedAppSystem;assembly=responserules_cli"
|
||||
|
||||
x:Name="MainAppWindow"
|
||||
DataContext="{Binding ElementName=MainAppWindow}"
|
||||
Title="Response Editor" Height="768" Width="1024">
|
||||
<Window.Resources>
|
||||
|
||||
<local:ObservableCollectionOfRules x:Key="RulesMatchingDebuggerCriterion"/>
|
||||
</Window.Resources>
|
||||
|
||||
<!-- ***************************** WINDOW! ********************************* -->
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="20" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TabControl>
|
||||
<TabItem Header="Criteria">
|
||||
<!--
|
||||
<ListBox Name="criteriaListBox" Grid.Column="0" Grid.Row="1" ItemsSource="{Binding Source={StaticResource ResponseSystem}, Path=CriteriaBinding}"
|
||||
ItemTemplate="{StaticResource CriteriaInListBoxTemplate}" />
|
||||
-->
|
||||
<tk:DataGrid x:Name="CriteriaGrid" ItemsSource="{Binding Source={StaticResource ResponseSystem}, Path=CriteriaBinding, Mode=OneWay}" AutoGenerateColumns="False">
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Name, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Key, Mode=OneWay}" Header="Key" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Value, Mode=OneWay}" Header="Value" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=Val.Required, Mode=OneWay}" Header="Required?" />
|
||||
<!--
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Comparison.Description, Mode=OneWay}" Header="Comparison" />
|
||||
-->
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Weight, Mode=OneWay}" Header="Weight" />
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
</TabItem>
|
||||
<TabItem Header="Responses" DataContext="{Binding Source={StaticResource ResponseSystem}, Path=ResponseGroupBinding, Mode=OneWay}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<tk:DataGrid x:Name="ResponseGroupsMaster" IsSynchronizedWithCurrentItem="True" Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Mode=OneWay}" AutoGenerateColumns="False">
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Name, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Count, Mode=OneWay}" Header="Count" />
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
<GridSplitter Grid.Row="1" ResizeDirection="Rows" Width="Auto" Height="4" HorizontalAlignment="Stretch" Margin="0" />
|
||||
<tk:DataGrid x:Name="ResponseGroupsDetail" Grid.Row="2" ItemsSource="{Binding Path=Val.ResponsesList }" AutoGenerateColumns="False">
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=type, Mode=OneWay}" Header="Type" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=value, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=weight, Mode=OneWay}" Header="Weight" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=DisplayFirst, Mode=OneWay}" Header="First" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=DisplayLast, Mode=OneWay}" Header="Last" />
|
||||
<!-- responseparams -->
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=params.IsSpeakOnce, Mode=OneWay}" Header="Last" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.delay, Mode=OneWay}" Header="Delay" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.respeakdelay, Mode=OneWay}" Header="RespkDelay" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.predelay, Mode=OneWay}" Header="PreDelay" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.odds, Mode=OneWay}" Header="Odds" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.soundlevel, Mode=OneWay}" Header="Sndlevel" />
|
||||
|
||||
<!-- <tk:DataGridTextColumn Binding="{Binding Path=Val.Count, Mode=OneWay}" Header="Count" /> -->
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Header="Rules" Loaded="OnRulesTabLoaded">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="16"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<!-- ROW 0 -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" FontSize="14">RULES</TextBlock>
|
||||
<!-- ROW 1 -->
|
||||
<tk:DataGrid x:Name="RulesGrid" Grid.Row="1"
|
||||
ItemsSource="{Binding Source={StaticResource ResponseSystem}, Path=RulesBinding, Mode=OneWay}" AutoGenerateColumns="False"
|
||||
SelectionChanged="RulesGrid_SelectionChanged" IsSynchronizedWithCurrentItem="True"
|
||||
>
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Name, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=MatchOnce, Mode=OneWay}" Header="MatchOnce" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=NumResponses, Mode=OneWay}" Header="NumResponses" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=NumCriteria, Mode=OneWay}" Header="NumCriteria" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Context, Mode=OneWay}" Header="Context" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=IsApplyContextToWorld, Mode=OneWay}" Header="Context Applies
To World" />
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
|
||||
<GridSplitter Grid.Row="2" ResizeDirection="Rows" Width="Auto" Height="4" HorizontalAlignment="Stretch" Margin="0" />
|
||||
|
||||
<Grid Grid.Row="3">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="16"/>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<!-- COLUMN 0 -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" HorizontalAlignment="Center" FontSize="14">CRITERIA</TextBlock>
|
||||
<tk:DataGrid x:Name="CriteriaGridInRulesPane" Grid.Row="1" Grid.Column="0"
|
||||
AutoGenerateColumns="False" HorizontalAlignment="Stretch" ColumnWidth="Auto" >
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Name, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Key, Mode=OneWay}" Header="Key" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Value, Mode=OneWay}" Header="Value" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=Val.Required, Mode=OneWay}" Header="Required?" />
|
||||
<!--
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Comparison.Description, Mode=OneWay}" Header="Comparison" />
|
||||
-->
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Weight, Mode=OneWay}" Header="Weight" />
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
<!-- COLUMN 1 -->
|
||||
<GridSplitter Grid.RowSpan="2" Width="4" />
|
||||
<!-- COLUMN 2 -->
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Center" FontSize="14">RESPONSES</TextBlock>
|
||||
<tk:DataGrid x:Name="ResponseGridInRulesPane" Grid.Row="1" Grid.Column="1"
|
||||
|
||||
AutoGenerateColumns="False">
|
||||
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Name, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Count, Mode=OneWay}" Header="Count" />
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</TabItem>
|
||||
<TabItem Header="Debugger" Loaded="OnDebuggerTabLoaded">
|
||||
<Grid FlowDirection="LeftToRight">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="52"/>
|
||||
<RowDefinition />
|
||||
<RowDefinition Height="4" />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<!-- ROW 0 -->
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<DockPanel Height="Auto" Width="Auto" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Top" >
|
||||
<TextBlock DockPanel.Dock="Top" Margin="5,5,0,0">
|
||||
CONCEPT
|
||||
</TextBlock>
|
||||
<ComboBox Height="25" Margin="0,0,0,0" Name="DebugTabConceptComboBox" SelectionChanged="DebugTabConceptComboBox_SelectionChanged"
|
||||
ItemsSource="{Binding Source={StaticResource ResponseSystem}, Path=ConceptsShadow, Mode=OneWay}"
|
||||
HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" DockPanel.Dock="Top" />
|
||||
|
||||
</DockPanel>
|
||||
|
||||
<DockPanel Height="Auto" Margin="15,0,0,0" Width="Auto" Grid.Row="0" HorizontalAlignment="Stretch" VerticalAlignment="Top" >
|
||||
<TextBlock DockPanel.Dock="Top" Margin="5,5,0,0" >
|
||||
FACTS (contexts) key1:val1,key2:val2,...
|
||||
</TextBlock>
|
||||
<TextBox DockPanel.Dock="Top" Height="25" Name="DebugTabFactsTextBox" Width="340" LostFocus="DebugTabFactsTextBox_LostFocus" KeyDown="DebugTabFactsTextBox_KeyDown" />
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
<!-- ROW 1 -->
|
||||
<tk:DataGrid x:Name="DebuggerRulesGrid" Grid.Row="1"
|
||||
ItemsSource="{Binding Source={StaticResource RulesMatchingDebuggerCriterion}, Mode=OneWay}" AutoGenerateColumns="False"
|
||||
SelectionChanged="DebuggerRuleGrid_SelectionChanged" >
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Key.Name, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Value, Mode=OneWay}" Header="Score" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=Key.MatchOnce, Mode=OneWay}" Header="MatchOnce" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Key.NumResponses, Mode=OneWay}" Header="NumResponses" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Key.NumCriteria, Mode=OneWay}" Header="NumCriteria" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Key.Context, Mode=OneWay}" Header="Context" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=Key.IsApplyContextToWorld, Mode=OneWay}" Header="Context Applies
To World" />
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
<!-- ROW 2 -->
|
||||
<GridSplitter Grid.Row="2" ResizeDirection="Rows" Width="Auto" Height="4" HorizontalAlignment="Stretch" Margin="0" />
|
||||
<!-- ROW 3 -->
|
||||
<Grid Grid.Row="3" >
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="2*" />
|
||||
<ColumnDefinition Width="3*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<tk:DataGrid x:Name="ResponseGridInDebuggerPane" Grid.Row="0" Grid.Column="0" AutoGenerateColumns="False"
|
||||
SelectionChanged="DebuggerResponseGroupGrid_SelectionChanged" >
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Name, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=Val.Count, Mode=OneWay}" Header="Count" />
|
||||
<!-- "<tk:DataGridTextColumn Binding="{Binding Path=Val.ResponsesList[0].value, Mode=OneWay}" Header="Example vcd" /> -->
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
<GridSplitter Grid.RowSpan="1" Width="4" />
|
||||
|
||||
<tk:DataGrid x:Name="DebuggerResponseGroupsDetail"
|
||||
Grid.Row="0" Grid.Column="1" AutoGenerateColumns="False">
|
||||
<tk:DataGrid.Columns>
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=type, Mode=OneWay}" Header="Type" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=value, Mode=OneWay}" Header="Name" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=weight, Mode=OneWay}" Header="Weight" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=DisplayFirst, Mode=OneWay}" Header="First" />
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=DisplayLast, Mode=OneWay}" Header="Last" />
|
||||
<!-- responseparams -->
|
||||
<tk:DataGridCheckBoxColumn Binding="{Binding Path=params.IsSpeakOnce, Mode=OneWay}" Header="Last" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.delay, Mode=OneWay}" Header="Delay" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.respeakdelay, Mode=OneWay}" Header="RespkDelay" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.predelay, Mode=OneWay}" Header="PreDelay" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.odds, Mode=OneWay}" Header="Odds" />
|
||||
<tk:DataGridTextColumn Binding="{Binding Path=params.soundlevel, Mode=OneWay}" Header="Sndlevel" />
|
||||
|
||||
<!-- <tk:DataGridTextColumn Binding="{Binding Path=Val.Count, Mode=OneWay}" Header="Count" /> -->
|
||||
</tk:DataGrid.Columns>
|
||||
</tk:DataGrid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
<Button Grid.Row="1" HorizontalAlignment="Right" Name="button1" Width="Auto" Click="button1_Click" Height="20" VerticalAlignment="Bottom">LOAD</Button>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
369
responserules/ResponseEditor/ResponseEditor/Window1.xaml.cs
Normal file
369
responserules/ResponseEditor/ResponseEditor/Window1.xaml.cs
Normal file
@ -0,0 +1,369 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using Microsoft.Win32;
|
||||
|
||||
using ResponseRulesCLI;
|
||||
using ManagedAppSystem;
|
||||
|
||||
namespace ResponseEditor
|
||||
{
|
||||
/// <summary>
|
||||
/// Interaction logic for Window1.xaml
|
||||
/// </summary>
|
||||
public partial class Window1 : Window
|
||||
{
|
||||
public Window1()
|
||||
{
|
||||
InitializeComponent();
|
||||
// m_RulesMatchingDebuggerCriterion = new ObservableCollection<Rule>();
|
||||
}
|
||||
|
||||
private void button1_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
// MessageBox.Show("CLICK!");
|
||||
// MessageBox.Show(Resources["AppSystem"].ToString());
|
||||
// AppSystemWrapper appSys = new AppSystemWrapper();
|
||||
// CritGrid.ItemsSource = RRSys.CriteriaBinding;
|
||||
// Resources["CritGrid"].ItemsSource = RRSys.CriteriaBinding;
|
||||
|
||||
// get a filename from the dialog box.
|
||||
string filename = null;
|
||||
|
||||
{
|
||||
// Configure open file dialog box
|
||||
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
|
||||
dlg.FileName = "response_rules.txt"; // Default file name
|
||||
dlg.DefaultExt = ".txt"; // Default file extension
|
||||
dlg.Filter = "Text (.txt)|*.txt"; // Filter files by extension
|
||||
string searchdir = System.IO.Path.Combine(Environment.GetEnvironmentVariable("VGAME"),
|
||||
Environment.GetEnvironmentVariable("VMOD"));
|
||||
if ( searchdir.Length > 4 )
|
||||
{
|
||||
dlg.InitialDirectory = System.IO.Path.Combine(searchdir, "scripts/talker");
|
||||
}
|
||||
else
|
||||
{
|
||||
dlg.InitialDirectory = Directory.GetCurrentDirectory();
|
||||
}
|
||||
|
||||
// Show open file dialog box
|
||||
Nullable<bool> result = dlg.ShowDialog();
|
||||
|
||||
// Process open file dialog box results
|
||||
if (result == true)
|
||||
{
|
||||
// Open document
|
||||
filename = dlg.FileName;
|
||||
}
|
||||
else
|
||||
{ // cancelled
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( System.IO.File.Exists( filename ) )
|
||||
{
|
||||
// get the local modpath directory from the given filename.
|
||||
string basedir = System.IO.Path.GetDirectoryName(filename);
|
||||
|
||||
// check to make sure that "scripts/talker" is in there somewhere,
|
||||
// and if not, bitch.
|
||||
bool bIsScriptsTalkerDir = (basedir.Contains("scripts/talker") || basedir.Contains("scripts\\talker"));
|
||||
if ( !bIsScriptsTalkerDir )
|
||||
{
|
||||
MessageBox.Show("File is not in a 'scripts/talker' directory; #includes may not work properly.",
|
||||
"Minor Annoyance");
|
||||
}
|
||||
else
|
||||
{
|
||||
// walk up two levels in the directory name.
|
||||
basedir = Directory.GetParent(basedir).Parent.FullName;
|
||||
}
|
||||
|
||||
AppSys.SetFileSystemSearchRoot(basedir);
|
||||
|
||||
// load just the bare file name.
|
||||
RRSys.LoadFromFile(filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
MessageBox.Show("That was a bad file name; no responses loaded.");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
foreach ( Object i in (System.Collections.IEnumerable)(RRSys.CriteriaBinding) )
|
||||
{
|
||||
Criterion c = (Criterion)i.GetType().GetProperty("Val").GetValue(i, null);
|
||||
// MessageBox.Show( c.GetType().GetProperty("Key").GetValue(c,null).ToString() );
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
#region Member data for all panes
|
||||
public ResponseSystemWPF RRSys
|
||||
{
|
||||
get { return (ResponseSystemWPF)this.FindResource("ResponseSystem"); }
|
||||
}
|
||||
public AppSystemWrapper AppSys
|
||||
{
|
||||
get { return (AppSystemWrapper)this.FindResource("AppSystem"); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Criterion Pane
|
||||
private void CritGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
#region Rules pane
|
||||
public void OnRulesTabLoaded(Object sender, RoutedEventArgs args)
|
||||
{
|
||||
ViewForCriteriaPanelInRulesPane = new ListCollectionView(RRSys.CriteriaBinding);
|
||||
ViewForResponsePanelInRulesPane = new ListCollectionView(RRSys.ResponseGroupBinding);
|
||||
}
|
||||
|
||||
public ListCollectionView ViewForCriteriaPanelInRulesPane;
|
||||
public ListCollectionView ViewForResponsePanelInRulesPane;
|
||||
|
||||
|
||||
private void RulesGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.AddedItems.Count > 1)
|
||||
{
|
||||
MessageBox.Show("How can you select more than one rule?");
|
||||
}
|
||||
|
||||
if (e.AddedItems.Count == 0)
|
||||
{
|
||||
ViewForCriteriaPanelInRulesPane.Filter = null;
|
||||
ViewForResponsePanelInRulesPane.Filter = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Rule r = e.AddedItems[0] as Rule;
|
||||
ViewForCriteriaPanelInRulesPane.Filter = MakeCriterionFilterForRule(r);
|
||||
ViewForResponsePanelInRulesPane.Filter = MakeResponseFilterForRule(r);
|
||||
}
|
||||
|
||||
Binding b = new Binding();
|
||||
b.Source = ViewForCriteriaPanelInRulesPane;
|
||||
b.Mode = BindingMode.OneWay;
|
||||
CriteriaGridInRulesPane.SetBinding(ItemsControl.ItemsSourceProperty, b);
|
||||
|
||||
b = new Binding();
|
||||
b.Source = ViewForResponsePanelInRulesPane;
|
||||
b.Mode = BindingMode.OneWay;
|
||||
ResponseGridInRulesPane.SetBinding(ItemsControl.ItemsSourceProperty, b);
|
||||
}
|
||||
|
||||
private Predicate<object> MakeCriterionFilterForRule( Rule r )
|
||||
{
|
||||
// make a closure scanning the response dict for just this rule's criteria.
|
||||
ResponseSystemWPF ResponseRuleSystem = RRSys;
|
||||
return x =>
|
||||
{
|
||||
int idx = ResponseRuleSystem.CriteriaBinding.IndexOf(x); ;
|
||||
for ( int i = 0 ; i < r.NumCriteria ; i++ )
|
||||
{
|
||||
if (r.get_CriteriaIndices(i) == idx)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
private Predicate<object> MakeResponseFilterForRule(Rule r)
|
||||
{
|
||||
// make a closure scanning the response dict for just this rule's responses.
|
||||
ResponseSystemWPF ResponseRuleSystem = RRSys;
|
||||
|
||||
// CLI seems to be having trouble with typedefs, so for now introspect the
|
||||
// necesasry properties
|
||||
System.Reflection.PropertyInfo valprop = RRSys.ResponseGroupsDict[0].GetType().GetProperty("Val");
|
||||
|
||||
return x =>
|
||||
{
|
||||
// clumsy hack to filter out NullResponse
|
||||
ResponseGroup g = valprop.GetValue(x, null) as ResponseGroup;
|
||||
if (g.Count < 1)
|
||||
return false;
|
||||
|
||||
int idx = ResponseRuleSystem.ResponseGroupBinding.IndexOf(x);
|
||||
for (int i = 0; i < r.NumCriteria; i++)
|
||||
{
|
||||
if (r.get_ResponseIndices(i) == idx)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Debugger Pane
|
||||
public void OnDebuggerTabLoaded(Object sender, RoutedEventArgs args)
|
||||
{
|
||||
ViewForResponsePanelInDebuggerPane = new ListCollectionView(RRSys.ResponseGroupBinding);
|
||||
}
|
||||
|
||||
|
||||
public ListCollectionView ViewForResponsePanelInDebuggerPane;
|
||||
// private Binding BindingForResponseDetailInDebuggerPane;
|
||||
|
||||
private void DebugTabConceptComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
// need to use event parameter rather than contents of combo box as
|
||||
// the combo box's text hasn't actually been set yet
|
||||
if ( e.AddedItems.Count > 0 )
|
||||
{
|
||||
DisplayBestRuleForConcept(e.AddedItems[0].ToString(), DebugTabFactsTextBox.Text);
|
||||
}
|
||||
else
|
||||
{
|
||||
ObservableCollectionOfRules collection = (ObservableCollectionOfRules)this.FindResource("RulesMatchingDebuggerCriterion");
|
||||
collection.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void DebuggerRuleGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.AddedItems.Count == 0)
|
||||
{
|
||||
ViewForResponsePanelInDebuggerPane.Filter = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
Rule r = ((KeyValuePair<Rule, float>) e.AddedItems[0]).Key as Rule;
|
||||
ViewForResponsePanelInDebuggerPane.Filter = MakeResponseFilterForRule(r);
|
||||
}
|
||||
|
||||
|
||||
Binding b = new Binding();
|
||||
b.Source = ViewForResponsePanelInDebuggerPane;
|
||||
b.Mode = BindingMode.OneWay;
|
||||
ResponseGridInDebuggerPane.SetBinding(ItemsControl.ItemsSourceProperty, b);
|
||||
}
|
||||
|
||||
private void DebuggerResponseGroupGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
/*
|
||||
if (BindingForResponseDetailInDebuggerPane == null)
|
||||
{
|
||||
BindingForResponseDetailInDebuggerPane = new Binding();
|
||||
BindingForResponseDetailInDebuggerPane.Mode = BindingMode.OneWay;
|
||||
DebuggerResponseGroupsDetail.SetBinding(ItemsControl.ItemsSourceProperty, BindingForResponseDetailInDebuggerPane);
|
||||
}
|
||||
*/
|
||||
|
||||
if (e.AddedItems.Count == 0)
|
||||
{
|
||||
DebuggerResponseGroupsDetail.SetBinding(ItemsControl.ItemsSourceProperty, (System.Windows.Data.BindingBase)null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// icky use of metadata
|
||||
ResponseGroup g = e.AddedItems[0].GetType().GetProperty("Val").GetValue(e.AddedItems[0], null) as ResponseGroup;
|
||||
|
||||
|
||||
Binding b = new Binding();
|
||||
b.Source = new ListCollectionView(g.ResponsesList);
|
||||
b.Mode = BindingMode.OneWay;
|
||||
DebuggerResponseGroupsDetail.SetBinding(ItemsControl.ItemsSourceProperty, b);
|
||||
}
|
||||
}
|
||||
|
||||
private void DebugTabFactsTextBox_LostFocus(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DisplayBestRuleForConcept(DebugTabConceptComboBox.Text, DebugTabFactsTextBox.Text);
|
||||
}
|
||||
|
||||
private void DebugTabFactsTextBox_KeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if ( e.Key == Key.Enter )
|
||||
{
|
||||
DisplayBestRuleForConcept(DebugTabConceptComboBox.Text, DebugTabFactsTextBox.Text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DisplayBestRuleForConcept( string concept, string factstring )
|
||||
{
|
||||
ObservableCollectionOfRules collection = (ObservableCollectionOfRules)this.FindResource("RulesMatchingDebuggerCriterion");
|
||||
collection.Clear();
|
||||
System.Collections.Generic.SortedList<string, string> facts = new System.Collections.Generic.SortedList<string, string>();
|
||||
facts.Add("concept", concept);
|
||||
AddColumnColonToDictionary(facts, factstring);
|
||||
|
||||
foreach ( KeyValuePair<Rule, float> pair in RRSys.FindAllRulesMatchingCriteria(facts) )
|
||||
{
|
||||
collection.Add(pair);
|
||||
}
|
||||
/*
|
||||
Rule bestMatchingRule = RRSys.FindBestMatchingRule( facts );
|
||||
if ( bestMatchingRule != null )
|
||||
{
|
||||
collection.Add(bestMatchingRule);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Temp: turn context1:value1,context2:value2,... into a dict
|
||||
/// </summary>
|
||||
static void AddColumnColonToDictionary( System.Collections.Generic.SortedList<string, string> facts,
|
||||
string input )
|
||||
{
|
||||
string[] pairs = input.Split(',');
|
||||
foreach( string p in pairs )
|
||||
{
|
||||
string[] kv = p.Split(':');
|
||||
if ( kv.Length >= 2 )
|
||||
facts.Add(kv[0], kv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public ObservableCollection<Rule> RulesMatchingDebuggerCriterion
|
||||
{
|
||||
get { return m_RulesMatchingDebuggerCriterion; }
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// TODO
|
||||
/// </summary>
|
||||
void QueryResponseSystemWithDebuggerData()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// ObservableCollection<Rule> m_RulesMatchingDebuggerCriterion;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
public class ObservableCollectionOfRules : ObservableCollection<KeyValuePair<Rule,float>> { };
|
||||
|
||||
}
|
40
responserules/responserules_cli/AssemblyInfo.cpp
Normal file
40
responserules/responserules_cli/AssemblyInfo.cpp
Normal file
@ -0,0 +1,40 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
using namespace System;
|
||||
using namespace System::Reflection;
|
||||
using namespace System::Runtime::CompilerServices;
|
||||
using namespace System::Runtime::InteropServices;
|
||||
using namespace System::Security::Permissions;
|
||||
|
||||
//
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
//
|
||||
[assembly:AssemblyTitleAttribute("responserules_cli")];
|
||||
[assembly:AssemblyDescriptionAttribute("")];
|
||||
[assembly:AssemblyConfigurationAttribute("")];
|
||||
[assembly:AssemblyCompanyAttribute("Valve")];
|
||||
[assembly:AssemblyProductAttribute("responserules_cli")];
|
||||
[assembly:AssemblyCopyrightAttribute("Copyright (c) Valve 2009")];
|
||||
[assembly:AssemblyTrademarkAttribute("")];
|
||||
[assembly:AssemblyCultureAttribute("")];
|
||||
|
||||
//
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the value or you can default the Revision and Build Numbers
|
||||
// by using the '*' as shown below:
|
||||
|
||||
[assembly:AssemblyVersionAttribute("1.0.*")];
|
||||
|
||||
[assembly:ComVisible(false)];
|
||||
|
||||
[assembly:CLSCompliantAttribute(true)];
|
||||
|
||||
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
|
31
responserules/responserules_cli/ReadMe.txt
Normal file
31
responserules/responserules_cli/ReadMe.txt
Normal file
@ -0,0 +1,31 @@
|
||||
========================================================================
|
||||
DYNAMIC LINK LIBRARY : responserules_cli Project Overview
|
||||
========================================================================
|
||||
|
||||
AppWizard has created this responserules_cli DLL for you.
|
||||
|
||||
This file contains a summary of what you will find in each of the files that
|
||||
make up your responserules_cli application.
|
||||
|
||||
responserules_cli.vcproj
|
||||
This is the main project file for VC++ projects generated using an Application Wizard.
|
||||
It contains information about the version of Visual C++ that generated the file, and
|
||||
information about the platforms, configurations, and project features selected with the
|
||||
Application Wizard.
|
||||
|
||||
responserules_cli.cpp
|
||||
This is the main DLL source file.
|
||||
|
||||
responserules_cli.h
|
||||
This file contains a class declaration.
|
||||
|
||||
AssemblyInfo.cpp
|
||||
Contains custom attributes for modifying assembly metadata.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
Other notes:
|
||||
|
||||
AppWizard uses "TODO:" to indicate parts of the source code you
|
||||
should add to or customize.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
5
responserules/responserules_cli/Stdafx.cpp
Normal file
5
responserules/responserules_cli/Stdafx.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
// stdafx.cpp : source file that includes just the standard includes
|
||||
// responserules_cli.pch will be the pre-compiled header
|
||||
// stdafx.obj will contain the pre-compiled type information
|
||||
|
||||
#include "stdafx.h"
|
56
responserules/responserules_cli/Stdafx.h
Normal file
56
responserules/responserules_cli/Stdafx.h
Normal file
@ -0,0 +1,56 @@
|
||||
// stdafx.h : include file for standard system include files,
|
||||
// or project specific include files that are used frequently,
|
||||
// but are changed infrequently
|
||||
|
||||
#pragma once
|
||||
|
||||
// temporarily make unicode go away as we deal with Valve types
|
||||
#ifdef _UNICODE
|
||||
#define PUT_UNICODE_BACK
|
||||
#undef _UNICODE
|
||||
#endif
|
||||
|
||||
#if _MANAGED
|
||||
#pragma unmanaged
|
||||
#undef FASTCALL
|
||||
#define FASTCALL
|
||||
#endif
|
||||
#include "platform.h"
|
||||
#include "wchartypes.h"
|
||||
#include <ctype.h>
|
||||
struct datamap_t;
|
||||
template <typename T> datamap_t *DataMapInit(T *);
|
||||
|
||||
#include "responserules/response_types.h"
|
||||
#include "../../responserules/runtime/response_types_internal.h"
|
||||
#include "response_system.h"
|
||||
|
||||
|
||||
#ifdef PUT_UNICODE_BACK
|
||||
#define _UNICODE
|
||||
#undef PUT_UNICODE_BACK
|
||||
#endif
|
||||
|
||||
#if _MANAGED
|
||||
/// implicitly converts a unicode CLR String^
|
||||
/// to a C string. The pointer returned should
|
||||
/// not be stored; it is valid only so long as
|
||||
/// this class exists.
|
||||
using namespace System;
|
||||
class StrToAnsi
|
||||
{
|
||||
|
||||
public:
|
||||
StrToAnsi( String ^unicodestr );
|
||||
~StrToAnsi( );
|
||||
operator TCHAR *() const;
|
||||
|
||||
private:
|
||||
TCHAR *m_pStr;
|
||||
};
|
||||
#pragma managed
|
||||
#undef FASTCALL
|
||||
#define FASTCALL __fastcall
|
||||
#include "cli_appsystem_thunk.h"
|
||||
#include "responserules_cli.h"
|
||||
#endif
|
BIN
responserules/responserules_cli/app.ico
Normal file
BIN
responserules/responserules_cli/app.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
63
responserules/responserules_cli/app.rc
Normal file
63
responserules/responserules_cli/app.rc
Normal file
@ -0,0 +1,63 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
#include "resource.h"
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon placed first or with lowest ID value becomes application icon
|
||||
|
||||
LANGUAGE 9, 1
|
||||
#pragma code_page(1252)
|
||||
1 ICON "app.ico"
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
"\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""afxres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\0"
|
||||
END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
65
responserules/responserules_cli/cli_appsystem_adapter.h
Normal file
65
responserules/responserules_cli/cli_appsystem_adapter.h
Normal file
@ -0,0 +1,65 @@
|
||||
/// The local implementation of an AppSystem for this project
|
||||
|
||||
#ifndef CLI_APPSYSTEM_ADAPTER_H
|
||||
#define CLI_APPSYSTEM_ADAPTER_H
|
||||
|
||||
#include "appframework/appframework.h"
|
||||
#include "filesystem.h"
|
||||
#include "vstdlib/random.h"
|
||||
#include "icommandline.h"
|
||||
|
||||
// if you don't use the proper AppSystem to make a filesystem connection:
|
||||
// #define TIER2_USE_INIT_DEFAULT_FILESYSTEM 1
|
||||
|
||||
/// A singleton class used to set up all the DLL interfaces.
|
||||
/// EXTREMELY IMPORTANT: This class must exist in unmanaged code.
|
||||
//#pragma unmanaged
|
||||
class IFileSystem;
|
||||
class IUniformRandomStream;
|
||||
class ICommandLine;
|
||||
class CCLIAppSystemAdapter : public CAppSystemGroup // , public ResponseRules_CLI::ICLI_AppSystem_Adapter
|
||||
{
|
||||
//// UNMANAGED:
|
||||
private:
|
||||
virtual bool Create();
|
||||
virtual bool PreInit();
|
||||
virtual int Main() { return 0; } ///< never used, cannot be used
|
||||
virtual void PostShutdown() {Wipe(true);} ///< does it leak?
|
||||
virtual void Destroy() {};
|
||||
|
||||
void Wipe( bool bPerformDelete );
|
||||
|
||||
IUniformRandomStream *m_pLocalRandomStream;
|
||||
#if TIER2_USE_INIT_DEFAULT_FILESYSTEM
|
||||
#else
|
||||
IFileSystem *m_pFilesystem;
|
||||
#endif
|
||||
|
||||
// IUniformRandomStream *m_pRandomstream;
|
||||
// ICommandLine *m_pCommandline;
|
||||
|
||||
public:
|
||||
CCLIAppSystemAdapter();
|
||||
virtual ~CCLIAppSystemAdapter();
|
||||
void SetupFileSystem( ) ;
|
||||
/// Make the "LOCAL" filesystem directory point at the given path.
|
||||
void AddFileSystemRoot( const char *pPath ) ;
|
||||
|
||||
IFileSystem * GetFilesytem();
|
||||
IUniformRandomStream * GetRandomStream();
|
||||
ICommandLine * GetCommandLine();
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline IUniformRandomStream * CCLIAppSystemAdapter::GetRandomStream()
|
||||
{
|
||||
return m_pLocalRandomStream;
|
||||
}
|
||||
inline ICommandLine * CCLIAppSystemAdapter::GetCommandLine()
|
||||
{
|
||||
return CommandLine();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
47
responserules/responserules_cli/cli_appsystem_thunk.cpp
Normal file
47
responserules/responserules_cli/cli_appsystem_thunk.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
/// These functions define the MANAGED interface. This file has /CLR.
|
||||
///
|
||||
/// Defines an interface which may be called from the MANAGED code's
|
||||
/// main function to start up (connect) and shut down (disconnect)
|
||||
/// the app system interface.
|
||||
|
||||
/// This class is a singleton. It gets manufactured explicitly
|
||||
/// from the Manufacture() call, which is a factory function that
|
||||
/// your app must implement in a non-/CLR file it will presumably
|
||||
/// return your custom type of CCLI_AppSystem_Adapter_Unmanaged).
|
||||
/// Calling Startup() will connect the app system and
|
||||
/// Shutdown() will disconnect it.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#pragma unmanaged
|
||||
#include "cli_appsystem_unmanaged_wrapper.h"
|
||||
#pragma managed
|
||||
|
||||
|
||||
// Allocate the native object on the C++ Heap via a constructor
|
||||
ManagedAppSystem::AppSystemWrapper::AppSystemWrapper()
|
||||
{
|
||||
m_Impl = new AppSystemWrapper_Unmanaged( StrToAnsi(Environment::CommandLine) );
|
||||
}
|
||||
|
||||
ManagedAppSystem::AppSystemWrapper::~AppSystemWrapper()
|
||||
{
|
||||
delete m_Impl;
|
||||
m_Impl = NULL;
|
||||
}
|
||||
|
||||
// Deallocate the native object on the finalizer just in case no destructor is called
|
||||
ManagedAppSystem::AppSystemWrapper::!AppSystemWrapper()
|
||||
{
|
||||
delete m_Impl;
|
||||
m_Impl = NULL;
|
||||
}
|
||||
|
||||
#pragma unmanaged
|
||||
#include "cli_appsystem_adapter.h"
|
||||
#pragma managed
|
||||
|
||||
void ManagedAppSystem::AppSystemWrapper::SetFileSystemSearchRoot( String ^path )
|
||||
{
|
||||
m_Impl->Get()->AddFileSystemRoot( StrToAnsi(path) );
|
||||
}
|
53
responserules/responserules_cli/cli_appsystem_thunk.h
Normal file
53
responserules/responserules_cli/cli_appsystem_thunk.h
Normal file
@ -0,0 +1,53 @@
|
||||
/// Defines an interface which may be called from the MANAGED code's
|
||||
/// main function to start up (connect) and shut down (disconnect)
|
||||
/// the app system interface.
|
||||
|
||||
/// This class is a singleton. It gets manufactured explicitly
|
||||
/// from the Manufacture() call, which is a factory function that
|
||||
/// your app must implement in a non-/CLR file it will presumably
|
||||
/// return your custom type of CCLI_AppSystem_Adapter_Unmanaged).
|
||||
/// Calling Startup() will connect the app system and
|
||||
/// Shutdown() will disconnect it.
|
||||
///
|
||||
/// This shim is necessary to hide the CAppSystemGroup header from the
|
||||
/// CLI compiler, because it'll freak out if it has to include it.
|
||||
///
|
||||
///
|
||||
/// Placed here so that can be instanced from the app's main loop
|
||||
/// after the dll loads; this workaround obviates having to write a
|
||||
/// DLLMain() which might cause a loader-lock.
|
||||
/// see: http://msdn.microsoft.com/en-us/library/ms173266(vs.80).aspx
|
||||
#ifndef CLI_APPSYSTEM_THUNK_H
|
||||
#define CLI_APPSYSTEM_THUNK_H
|
||||
#pragma once
|
||||
|
||||
class AppSystemWrapper_Unmanaged;
|
||||
|
||||
namespace ManagedAppSystem
|
||||
{
|
||||
public ref class AppSystemWrapper
|
||||
{
|
||||
public:
|
||||
// Allocate the native object on the C++ Heap via a constructor
|
||||
AppSystemWrapper() ; // : m_Impl( new UnmanagedClass ) {}
|
||||
|
||||
// Deallocate the native object on a destructor
|
||||
~AppSystemWrapper();
|
||||
|
||||
/// Set the "LOCAL" search path for the file system.
|
||||
void SetFileSystemSearchRoot( String ^path );
|
||||
|
||||
protected:
|
||||
// Deallocate the native object on the finalizer just in case no destructor is called
|
||||
!AppSystemWrapper();
|
||||
|
||||
private:
|
||||
AppSystemWrapper_Unmanaged * m_Impl;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,164 @@
|
||||
/// The unmanaged side of wrapping the app system for CLR
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "cli_appsystem_unmanaged_wrapper.h"
|
||||
#include "cli_appsystem_adapter.h"
|
||||
|
||||
|
||||
// temporarily make unicode go away as we deal with Valve types
|
||||
#ifdef _UNICODE
|
||||
#define PUT_UNICODE_BACK
|
||||
#undef _UNICODE
|
||||
#endif
|
||||
|
||||
#include "filesystem_helpers.h"
|
||||
#include "utils\common\filesystem_tools.h"
|
||||
|
||||
|
||||
#ifdef PUT_UNICODE_BACK
|
||||
#define _UNICODE
|
||||
#undef PUT_UNICODE_BACK
|
||||
#endif
|
||||
|
||||
inline void CCLIAppSystemAdapter::Wipe( bool bPerformDelete )
|
||||
{
|
||||
if ( bPerformDelete )
|
||||
{
|
||||
delete m_pLocalRandomStream;
|
||||
}
|
||||
m_pFilesystem = NULL;
|
||||
m_pLocalRandomStream = NULL;
|
||||
// m_pCommandline = NULL;
|
||||
}
|
||||
|
||||
CCLIAppSystemAdapter::CCLIAppSystemAdapter()
|
||||
{
|
||||
Wipe( false );
|
||||
}
|
||||
|
||||
|
||||
CCLIAppSystemAdapter::~CCLIAppSystemAdapter()
|
||||
{
|
||||
Wipe( true );
|
||||
g_pFullFileSystem = NULL;
|
||||
}
|
||||
|
||||
bool CCLIAppSystemAdapter::Create()
|
||||
{
|
||||
AppSystemInfo_t appSystems[] =
|
||||
{
|
||||
{ "filesystem_stdio.dll", FILESYSTEM_INTERFACE_VERSION },
|
||||
{ "", "" } // Required to terminate the list
|
||||
};
|
||||
return AddSystems( appSystems );
|
||||
}
|
||||
|
||||
bool CCLIAppSystemAdapter::PreInit( )
|
||||
{
|
||||
CreateInterfaceFn factory = GetFactory();
|
||||
#if TIER2_USE_INIT_DEFAULT_FILESYSTEM
|
||||
#else
|
||||
m_pFilesystem = (IFileSystem*)factory(FILESYSTEM_INTERFACE_VERSION,NULL );
|
||||
#endif
|
||||
|
||||
// m_pCommandline = CommandLine();
|
||||
m_pLocalRandomStream = new CUniformRandomStream();
|
||||
// GetCommandLine()->AppendParm("rreditor.exe","");
|
||||
// GetCommandLine()->AppendParm("-noasync","1");
|
||||
|
||||
#if TIER2_USE_INIT_DEFAULT_FILESYSTEM
|
||||
return true;
|
||||
#else
|
||||
return ( m_pFilesystem != NULL );
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CCLIAppSystemAdapter::SetupFileSystem( )
|
||||
{
|
||||
g_pFullFileSystem = m_pFilesystem;
|
||||
|
||||
g_pFullFileSystem->RemoveAllSearchPaths();
|
||||
g_pFullFileSystem->AddSearchPath( "", "LOCAL", PATH_ADD_TO_HEAD );
|
||||
g_pFullFileSystem->AddSearchPath( "", "DEFAULT_WRITE_PATH", PATH_ADD_TO_HEAD );
|
||||
|
||||
#if TIER2_USE_INIT_DEFAULT_FILESYSTEM
|
||||
InitDefaultFileSystem();
|
||||
#endif
|
||||
FileSystem_Init( "./", 0, FS_INIT_COMPATIBILITY_MODE, true );
|
||||
// m_pFilesystem->AddSearchPath( "./", "GAME", PATH_ADD_TO_HEAD );
|
||||
}
|
||||
|
||||
void CCLIAppSystemAdapter::AddFileSystemRoot( const char *pPath )
|
||||
{
|
||||
g_pFullFileSystem->AddSearchPath( pPath, "LOCAL", PATH_ADD_TO_HEAD );
|
||||
g_pFullFileSystem->AddSearchPath( pPath, "GAME", PATH_ADD_TO_HEAD );
|
||||
}
|
||||
|
||||
|
||||
IFileSystem * CCLIAppSystemAdapter::GetFilesytem()
|
||||
{
|
||||
#if TIER2_USE_INIT_DEFAULT_FILESYSTEM
|
||||
return g_pFullFileSystem;
|
||||
#else
|
||||
return m_pFilesystem;
|
||||
#endif
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// | unmanaged-code implementations for the AppSystemWrapper |
|
||||
// -----------------------------------------------------------
|
||||
|
||||
CCLIAppSystemAdapter * AppSystemWrapper_Unmanaged::sm_pAppSystemSingleton = NULL;
|
||||
int AppSystemWrapper_Unmanaged::sm_nSingletonReferences = 0;
|
||||
|
||||
|
||||
AppSystemWrapper_Unmanaged::AppSystemWrapper_Unmanaged( const char *pCommandLine )
|
||||
{
|
||||
if ( sm_pAppSystemSingleton != NULL )
|
||||
{
|
||||
Assert( sm_nSingletonReferences > 0 );
|
||||
sm_nSingletonReferences++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( sm_nSingletonReferences == 0 );
|
||||
sm_pAppSystemSingleton = new CCLIAppSystemAdapter();
|
||||
sm_nSingletonReferences = 1;
|
||||
InitializeAppSystem( sm_pAppSystemSingleton, pCommandLine );
|
||||
}
|
||||
}
|
||||
|
||||
AppSystemWrapper_Unmanaged::~AppSystemWrapper_Unmanaged()
|
||||
{
|
||||
if ( sm_nSingletonReferences > 1 )
|
||||
{
|
||||
sm_nSingletonReferences--;
|
||||
}
|
||||
else if ( sm_nSingletonReferences == 1 )
|
||||
{
|
||||
TerminateAppSystem( sm_pAppSystemSingleton );
|
||||
delete sm_pAppSystemSingleton;
|
||||
sm_pAppSystemSingleton = NULL;
|
||||
sm_nSingletonReferences = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert( sm_pAppSystemSingleton == NULL && sm_nSingletonReferences == 0 ) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AppSystemWrapper_Unmanaged::InitializeAppSystem( CCLIAppSystemAdapter * pAppSys, const char *pCommandLine )
|
||||
{
|
||||
pAppSys->GetCommandLine()->CreateCmdLine( pCommandLine );
|
||||
pAppSys->Startup();
|
||||
pAppSys->SetupFileSystem();
|
||||
}
|
||||
|
||||
void AppSystemWrapper_Unmanaged::TerminateAppSystem( CCLIAppSystemAdapter * pAppSys )
|
||||
{
|
||||
pAppSys->Shutdown();
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
/// The unmanaged side of wrapping the app system for CLR
|
||||
|
||||
#ifndef CLI_APPSYSTEM_UNMANAGED_WRAPPER_H
|
||||
#define CLI_APPSYSTEM_UNMANAGED_WRAPPER_H
|
||||
|
||||
|
||||
class CCLIAppSystemAdapter;
|
||||
|
||||
/// This is actually a manually implemented refcounter on
|
||||
/// a singleton instance, so that construction causes it to
|
||||
/// be initialized if necessary and destruction refcounts
|
||||
/// before NULLing the static global.
|
||||
class AppSystemWrapper_Unmanaged
|
||||
{
|
||||
public:
|
||||
AppSystemWrapper_Unmanaged( const char *pCommandLine );
|
||||
virtual ~AppSystemWrapper_Unmanaged();
|
||||
|
||||
|
||||
inline int CountRefs( void ) const { return sm_nSingletonReferences; };
|
||||
inline CCLIAppSystemAdapter *operator *() const { return sm_pAppSystemSingleton; }
|
||||
inline operator CCLIAppSystemAdapter *() const { return sm_pAppSystemSingleton; }
|
||||
inline static CCLIAppSystemAdapter *Get() { return sm_pAppSystemSingleton; }
|
||||
|
||||
protected:
|
||||
void InitializeAppSystem( CCLIAppSystemAdapter * pAppSys, const char *pCommandLine ) ;
|
||||
void TerminateAppSystem( CCLIAppSystemAdapter * pAppSys ) ;
|
||||
|
||||
private:
|
||||
static CCLIAppSystemAdapter *sm_pAppSystemSingleton;
|
||||
static int sm_nSingletonReferences;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
265
responserules/responserules_cli/engine_emulator.cpp
Normal file
265
responserules/responserules_cli/engine_emulator.cpp
Normal file
@ -0,0 +1,265 @@
|
||||
// This contains stubs that emulate the HL2 engine for places where
|
||||
// the response rules expect to find it.
|
||||
|
||||
// temporarily make unicode go away as we deal with Valve types
|
||||
#ifdef _UNICODE
|
||||
#define PUT_UNICODE_BACK
|
||||
#undef _UNICODE
|
||||
#endif
|
||||
|
||||
#include "platform.h"
|
||||
#include "wchartypes.h"
|
||||
#include <ctype.h>
|
||||
struct datamap_t;
|
||||
template <typename T> datamap_t *DataMapInit(T *);
|
||||
|
||||
#include "appframework/appframework.h"
|
||||
#include "filesystem.h"
|
||||
#include "vstdlib/random.h"
|
||||
#include "icommandline.h"
|
||||
|
||||
#include "responserules/response_types.h"
|
||||
#include "../../responserules/runtime/response_types_internal.h"
|
||||
#include "response_system.h"
|
||||
|
||||
#include "cli_appsystem_unmanaged_wrapper.h"
|
||||
#include "cli_appsystem_adapter.h"
|
||||
|
||||
#include "characterset.h"
|
||||
|
||||
#ifdef PUT_UNICODE_BACK
|
||||
#define _UNICODE
|
||||
#undef PUT_UNICODE_BACK
|
||||
#endif
|
||||
|
||||
|
||||
class CLI_SourceEngineEmulator;
|
||||
|
||||
const char *COM_Parse (const char *data);
|
||||
byte *UTIL_LoadFileForMe( const char *filename, int *pLength, IFileSystem *filesystem );
|
||||
|
||||
int TestRandomNumberGeneration( int bottom, int top )
|
||||
{
|
||||
return ResponseRules::IEngineEmulator::Get()->GetRandomStream()->RandomInt(bottom,top);
|
||||
}
|
||||
|
||||
const char *TestFileSystemHook( )
|
||||
{
|
||||
// return ResponseRules::IEngineEmulator::Get()->GetFilesystem() ? "present" : "absent" ;
|
||||
return ResponseRules::IEngineEmulator::Get()->GetFilesystem()->IsSteam() ? "steam" : "not steam";
|
||||
}
|
||||
|
||||
|
||||
class CLI_SourceEngineEmulator : public ResponseRules::IEngineEmulator
|
||||
{
|
||||
public:
|
||||
/// Given an input text buffer data pointer, parses a single token into the variable token and returns the new
|
||||
/// reading position
|
||||
virtual const char *ParseFile( const char *data, char *token, int maxlen );
|
||||
|
||||
/// Return a pointer to an IFileSystem we can use to read and process scripts.
|
||||
virtual IFileSystem *GetFilesystem();
|
||||
|
||||
/// Return a pointer to an instance of an IUniformRandomStream
|
||||
virtual IUniformRandomStream *GetRandomStream() ;
|
||||
|
||||
/// Return a pointer to a tier0 ICommandLine
|
||||
virtual ICommandLine *GetCommandLine();
|
||||
|
||||
/// Emulates the server's UTIL_LoadFileForMe
|
||||
virtual byte *LoadFileForMe( const char *filename, int *pLength );
|
||||
|
||||
/// Emulates the server's UTIL_FreeFile
|
||||
virtual void FreeFile( byte *buffer );
|
||||
|
||||
CLI_SourceEngineEmulator();
|
||||
virtual ~CLI_SourceEngineEmulator();
|
||||
|
||||
void LocalInit();
|
||||
// protected:
|
||||
};
|
||||
|
||||
CLI_SourceEngineEmulator g_EngineEmulator;
|
||||
|
||||
|
||||
CLI_SourceEngineEmulator::CLI_SourceEngineEmulator()
|
||||
{
|
||||
LocalInit();
|
||||
}
|
||||
|
||||
CLI_SourceEngineEmulator::~CLI_SourceEngineEmulator()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ResponseRules::IEngineEmulator *ResponseRules::IEngineEmulator::s_pSingleton = &g_EngineEmulator;
|
||||
|
||||
/// Return a pointer to an IFileSystem we can use to read and process scripts.
|
||||
IFileSystem *CLI_SourceEngineEmulator::GetFilesystem()
|
||||
{
|
||||
return AppSystemWrapper_Unmanaged::Get()->GetFilesytem();
|
||||
}
|
||||
|
||||
/// Return a pointer to an instance of an IUniformRandomStream
|
||||
IUniformRandomStream *CLI_SourceEngineEmulator::GetRandomStream()
|
||||
{
|
||||
return AppSystemWrapper_Unmanaged::Get()->GetRandomStream();
|
||||
}
|
||||
|
||||
/// Return a pointer to a tier0 ICommandLine
|
||||
ICommandLine *CLI_SourceEngineEmulator::GetCommandLine()
|
||||
{
|
||||
return AppSystemWrapper_Unmanaged::Get()->GetCommandLine();
|
||||
}
|
||||
|
||||
|
||||
/// Emulates the server's UTIL_LoadFileForMe
|
||||
byte *CLI_SourceEngineEmulator::LoadFileForMe( const char *filename, int *pLength )
|
||||
{
|
||||
return UTIL_LoadFileForMe( filename, pLength, GetFilesystem() );
|
||||
}
|
||||
|
||||
/// Emulates the server's UTIL_FreeFile
|
||||
void CLI_SourceEngineEmulator::FreeFile( byte *buffer )
|
||||
{
|
||||
GetFilesystem()->FreeOptimalReadBuffer( buffer );
|
||||
}
|
||||
|
||||
/*
|
||||
===================================
|
||||
STUFF COPIED FROM SOURCE ENGINE
|
||||
===================================
|
||||
*/
|
||||
|
||||
|
||||
// wordbreak parsing set
|
||||
static characterset_t g_BreakSet, g_BreakSetIncludingColons;
|
||||
bool com_ignorecolons = false;
|
||||
#define COM_TOKEN_MAX_LENGTH 1024
|
||||
char com_token[COM_TOKEN_MAX_LENGTH] = {0} ;
|
||||
|
||||
|
||||
|
||||
/// Given an input text buffer data pointer, parses a single token into the variable token and returns the new
|
||||
/// reading position
|
||||
const char *CLI_SourceEngineEmulator::ParseFile( const char *data, char *token, int maxlen )
|
||||
{
|
||||
Assert( data );
|
||||
|
||||
const char *return_data = COM_Parse(data);
|
||||
Q_strncpy(token, com_token, maxlen);
|
||||
return return_data;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
COM_Parse (from Quake engine)
|
||||
|
||||
Parse a token out of a string
|
||||
==============
|
||||
*/
|
||||
static
|
||||
const char *COM_Parse (const char *data)
|
||||
{
|
||||
unsigned char c;
|
||||
int len;
|
||||
characterset_t *breaks;
|
||||
|
||||
breaks = &g_BreakSetIncludingColons;
|
||||
if ( com_ignorecolons )
|
||||
breaks = &g_BreakSet;
|
||||
|
||||
len = 0;
|
||||
com_token[0] = 0;
|
||||
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
// skip whitespace
|
||||
skipwhite:
|
||||
while ( (c = *data) <= ' ')
|
||||
{
|
||||
if (c == 0)
|
||||
return NULL; // end of file;
|
||||
data++;
|
||||
}
|
||||
|
||||
// skip // comments
|
||||
if (c=='/' && data[1] == '/')
|
||||
{
|
||||
while (*data && *data != '\n')
|
||||
data++;
|
||||
goto skipwhite;
|
||||
}
|
||||
|
||||
|
||||
// handle quoted strings specially
|
||||
if (c == '\"')
|
||||
{
|
||||
data++;
|
||||
while (1)
|
||||
{
|
||||
c = *data++;
|
||||
if (c=='\"' || !c)
|
||||
{
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
}
|
||||
}
|
||||
|
||||
// parse single characters
|
||||
if ( IN_CHARACTERSET( *breaks, c ) )
|
||||
{
|
||||
com_token[len] = c;
|
||||
len++;
|
||||
com_token[len] = 0;
|
||||
return data+1;
|
||||
}
|
||||
|
||||
// parse a regular word
|
||||
do
|
||||
{
|
||||
com_token[len] = c;
|
||||
data++;
|
||||
len++;
|
||||
c = *data;
|
||||
if ( IN_CHARACTERSET( *breaks, c ) )
|
||||
break;
|
||||
} while (c>32);
|
||||
|
||||
com_token[len] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *filename -
|
||||
// *pLength -
|
||||
// Output : byte
|
||||
//-----------------------------------------------------------------------------
|
||||
static byte *UTIL_LoadFileForMe( const char *filename, int *pLength, IFileSystem *filesystem )
|
||||
{
|
||||
void *buffer = NULL;
|
||||
|
||||
int length = filesystem->ReadFileEx( filename, "GAME", &buffer, true, true );
|
||||
|
||||
if ( pLength )
|
||||
{
|
||||
*pLength = length;
|
||||
}
|
||||
|
||||
return (byte *)buffer;
|
||||
}
|
||||
|
||||
|
||||
void CLI_SourceEngineEmulator::LocalInit()
|
||||
{
|
||||
CharacterSetBuild( &g_BreakSet, "{}()'" );
|
||||
CharacterSetBuild( &g_BreakSetIncludingColons, "{}()':" );
|
||||
}
|
||||
|
3
responserules/responserules_cli/resource.h
Normal file
3
responserules/responserules_cli/resource.h
Normal file
@ -0,0 +1,3 @@
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by app.rc
|
52
responserules/responserules_cli/response_system.cpp
Normal file
52
responserules/responserules_cli/response_system.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
/// @file response_system.cpp
|
||||
/// This file contains the unmanaged code implementing the editor's version
|
||||
/// of a response-system.
|
||||
|
||||
#include "stdafx.h"
|
||||
using namespace ResponseRules;
|
||||
|
||||
const char *ResponseSystemImplementationCLI::GetScriptFile( void )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#pragma managed(push, off)
|
||||
|
||||
void ResponseSystemImplementationCLI::PrecacheResponses( bool bEnable )
|
||||
{
|
||||
// precaching is meaningless in the editor
|
||||
Assert(false);
|
||||
}
|
||||
|
||||
void ResponseSystemImplementationCLI::Release( )
|
||||
{
|
||||
// precaching is meaningless in the editor
|
||||
Assert(false);
|
||||
}
|
||||
|
||||
int ResponseSystemImplementationCLI::CountRules()
|
||||
{
|
||||
return m_RulePartitions.Count();
|
||||
}
|
||||
|
||||
/// Resets the output vector and overwrites it entirely.
|
||||
/// <remarks>
|
||||
/// Meant to be the same algorithm as CResponseSystem::FindBestMatchingRule().
|
||||
/// </remarks>
|
||||
void ResponseSystemImplementationCLI::FindAllRulesMatchingCriteria( CUtlSortVector<RuleAndScorePair_t, RuleAndScorePair_t::LessFunc> * RESTRICT outputList, const CriteriaSet& set, IResponseFilter *pFilter /*= NULL */ )
|
||||
{
|
||||
outputList->RemoveAll();
|
||||
outputList->EnsureCapacity(16);
|
||||
|
||||
ResponseRulePartition::tRuleDict &rules = m_RulePartitions.GetDictForCriteria( set );
|
||||
int c = rules.Count();
|
||||
int i;
|
||||
for ( i = 0; i < c; i++ )
|
||||
{
|
||||
float score = ScoreCriteriaAgainstRule( set, rules, i, false );
|
||||
outputList->Insert( RuleAndScorePair_t( m_RulePartitions.IndexFromDictElem( &rules, i ), score ));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#pragma managed(pop)
|
68
responserules/responserules_cli/response_system.h
Normal file
68
responserules/responserules_cli/response_system.h
Normal file
@ -0,0 +1,68 @@
|
||||
/// @file response_system.cpp
|
||||
/// This file defines the editor's version
|
||||
/// of a response-system.
|
||||
|
||||
#ifndef CS_RESPONSE_SYSTEM_H
|
||||
#define CS_RESPONSE_SYSTEM_H
|
||||
|
||||
#include "UtlSortVector.h"
|
||||
|
||||
class ResponseSystemImplementationCLI : public ResponseRules::CResponseSystem
|
||||
{
|
||||
public:
|
||||
|
||||
#pragma region Overrides on CResponseSystem
|
||||
/// From ResponseRules::CResponseSystem.
|
||||
/// There, it returns the filename to load; here
|
||||
/// it is NULL, since the file comes from the editor
|
||||
/// dialog.
|
||||
virtual const char *GetScriptFile( void ) ;
|
||||
|
||||
virtual void PrecacheResponses( bool bEnable );
|
||||
virtual void Release();
|
||||
|
||||
inline void LoadFromFile( const char *filename );
|
||||
#pragma endregion
|
||||
|
||||
int CountRules() ;
|
||||
|
||||
/// USed to return a sorted list of all rules matching the criteria in order of score (not just the best)
|
||||
struct RuleAndScorePair_t
|
||||
{
|
||||
ResponseRules::ResponseRulePartition::tIndex ruleidx;
|
||||
float score;
|
||||
|
||||
RuleAndScorePair_t( const ResponseRules::ResponseRulePartition::tIndex &_idx, float _score ) : ruleidx(_idx), score(_score) {};
|
||||
RuleAndScorePair_t( ) : ruleidx(ResponseRules::ResponseRulePartition::InvalidIdx()) {};
|
||||
|
||||
struct LessFunc
|
||||
{
|
||||
// actually "more" since sort from best to worst score
|
||||
bool Less( const RuleAndScorePair_t & lhs, const RuleAndScorePair_t & rhs, void *pContext )
|
||||
{
|
||||
if ( lhs.score == rhs.score )
|
||||
{
|
||||
return lhs.ruleidx < rhs.ruleidx;
|
||||
}
|
||||
else
|
||||
{
|
||||
return lhs.score > rhs.score;
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
typedef CUtlSortVector<RuleAndScorePair_t, RuleAndScorePair_t::LessFunc> FindAllRulesRetval_t;
|
||||
void FindAllRulesMatchingCriteria( FindAllRulesRetval_t* RESTRICT outputList,
|
||||
const ResponseRules::CriteriaSet& set, ResponseRules::IResponseFilter *pFilter = NULL );
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline void ResponseSystemImplementationCLI::LoadFromFile( const char *filename )
|
||||
{
|
||||
Clear();
|
||||
return LoadRuleSet( filename );
|
||||
}
|
||||
|
||||
|
||||
#endif
|
351
responserules/responserules_cli/response_types_marshal.cpp
Normal file
351
responserules/responserules_cli/response_types_marshal.cpp
Normal file
@ -0,0 +1,351 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Marhsalled types for native response-rules data.
|
||||
// Rather than have the CLR try to access the response rules natively,
|
||||
// we copy the data out from the native types to these garbage-collected
|
||||
// CLI types.
|
||||
// This is manually kept in sync with the native types in response_types.h
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "response_types_marshal.h"
|
||||
|
||||
#pragma unmanaged
|
||||
#include "../../responserules/runtime/response_types_internal.h"
|
||||
#pragma managed
|
||||
|
||||
using namespace ResponseRulesCLI;
|
||||
|
||||
|
||||
|
||||
// ============================================================= //
|
||||
// Matcher
|
||||
// ============================================================= //
|
||||
|
||||
|
||||
String^ Matcher::Token::get()
|
||||
{
|
||||
return gcnew String(m_pNative->GetToken());
|
||||
}
|
||||
|
||||
String^ Matcher::RawSource::get()
|
||||
{
|
||||
return gcnew String(m_pNative->GetRaw());
|
||||
}
|
||||
|
||||
// Duped from
|
||||
// ResponseRules::Matcher::Describe
|
||||
|
||||
String^ Matcher::Description::get()
|
||||
{
|
||||
if ( !m_pNative->valid )
|
||||
{
|
||||
return gcnew String("Invalid!");
|
||||
}
|
||||
System::Text::StringBuilder sb("", 128);
|
||||
|
||||
int minmaxcount = 0;
|
||||
if ( m_pNative->usemin )
|
||||
{
|
||||
sb.AppendFormat( ">{0}{1:f3}", m_pNative->minequals ? "=" : "", m_pNative->minval );
|
||||
minmaxcount++;
|
||||
}
|
||||
if ( m_pNative->usemax )
|
||||
{
|
||||
sb.AppendFormat( "{0}<{1}{2:f3}",
|
||||
minmaxcount > 0 ? " and " : "",
|
||||
m_pNative->maxequals ? "=" : "",
|
||||
m_pNative->maxval );
|
||||
|
||||
minmaxcount++;
|
||||
}
|
||||
|
||||
if ( minmaxcount >= 1 )
|
||||
{
|
||||
return sb.ToString();
|
||||
}
|
||||
else if ( m_pNative->notequal )
|
||||
{
|
||||
return (gcnew String("!="))->Concat(Token);
|
||||
}
|
||||
else
|
||||
{
|
||||
return (gcnew String("=="))->Concat(Token);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================= //
|
||||
// ResponseParams
|
||||
// ============================================================= //
|
||||
|
||||
|
||||
String ^ ResponseRulesCLI::responseparams_interval_t::ToString()
|
||||
{
|
||||
if ( range > 0 )
|
||||
{
|
||||
System::Text::StringBuilder sb("", 16);
|
||||
sb.AppendFormat("[{0:f1}+{1:f1}]", start, range );
|
||||
return sb.ToString();
|
||||
}
|
||||
else if ( start > 0 )
|
||||
{
|
||||
System::Text::StringBuilder sb("", 16);
|
||||
sb.AppendFormat("{0:f1}", start );
|
||||
return sb.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return gcnew String("0");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// unmanaged thunk for below
|
||||
#pragma unmanaged
|
||||
ResponseRules::ResponseParams *CopyResponseParams( ResponseRules::ResponseParams *pSourceNativeParams )
|
||||
{
|
||||
return new ResponseRules::ResponseParams( *pSourceNativeParams );
|
||||
}
|
||||
#pragma managed
|
||||
|
||||
|
||||
responseparams_interval_t::responseparams_interval_t( const ResponseRules::responseparams_interval_t &from )
|
||||
{
|
||||
start = from.start;
|
||||
range = from.range;
|
||||
}
|
||||
|
||||
responseparams_interval_t ResponseParams::delay::get()
|
||||
{
|
||||
return responseparams_interval_t( m_pNative->delay );
|
||||
}
|
||||
|
||||
responseparams_interval_t ResponseParams::respeakdelay::get()
|
||||
{
|
||||
return responseparams_interval_t( m_pNative->respeakdelay );
|
||||
}
|
||||
|
||||
responseparams_interval_t ResponseParams::weapondelay::get()
|
||||
{
|
||||
return responseparams_interval_t( m_pNative->weapondelay );
|
||||
}
|
||||
|
||||
responseparams_interval_t ResponseParams::predelay::get()
|
||||
{
|
||||
return responseparams_interval_t( m_pNative->predelay );
|
||||
}
|
||||
|
||||
|
||||
short ResponseParams::odds::get()
|
||||
{
|
||||
return m_pNative->odds;
|
||||
}
|
||||
|
||||
unsigned short ResponseParams::flags::get()
|
||||
{
|
||||
return m_pNative->flags;
|
||||
}
|
||||
|
||||
byte ResponseParams::soundlevel::get()
|
||||
{
|
||||
return m_pNative->soundlevel;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ============================================================= //
|
||||
// Response
|
||||
// ============================================================= //
|
||||
|
||||
/// A string containing the filename of a .vcd, the name of a sound script, etc.
|
||||
String^ Response::value::get()
|
||||
{
|
||||
return gcnew String( m_pNative->value );
|
||||
}
|
||||
|
||||
/// This response's relative weight in a rule.
|
||||
float Response::weight::get()
|
||||
{
|
||||
return m_pNative->weight.GetFloat();
|
||||
}
|
||||
|
||||
/// Used to track how many times a response can get said
|
||||
byte Response::depletioncount::get()
|
||||
{
|
||||
return m_pNative->depletioncount;
|
||||
}
|
||||
|
||||
/// What kind of response this is
|
||||
Response::ResponseType Response::type::get()
|
||||
{
|
||||
return ResponseType(m_pNative->type);
|
||||
}
|
||||
|
||||
/// Special flags that can be specified in the response
|
||||
bool Response::DisplayFirst::get()
|
||||
{
|
||||
return m_pNative->first;
|
||||
}
|
||||
|
||||
bool Response::DisplayLast::get()
|
||||
{
|
||||
return m_pNative->last;
|
||||
}
|
||||
|
||||
|
||||
// ============================================================= //
|
||||
// ResponseGroup
|
||||
// ============================================================= //
|
||||
|
||||
|
||||
// indexer goes into the cutlvector inside the group
|
||||
Response ^ ResponseGroup::default::get( int idx )
|
||||
{
|
||||
// Response ^frotz = gcnew Response(& m_pNative->group[idx] );
|
||||
// return gcnew Response(&m_pNative->group[idx]);
|
||||
return m_shadowResponseArray[idx];
|
||||
}
|
||||
|
||||
#pragma unmanaged
|
||||
static void AssignParserResponse( ResponseRules::ParserResponse *to, const ResponseRules::ParserResponse *from )
|
||||
{
|
||||
*to=*from;
|
||||
}
|
||||
#pragma managed
|
||||
|
||||
void ResponseGroup::default::set( int idx, Response^ from )
|
||||
{
|
||||
AssignParserResponse( &m_pNative->group[idx], from->GetNativePtr() );
|
||||
}
|
||||
|
||||
bool ResponseGroup::Sequential::get()
|
||||
{
|
||||
return m_pNative->IsSequential();
|
||||
}
|
||||
|
||||
bool ResponseGroup::NoRepeat::get()
|
||||
{
|
||||
return m_pNative->IsNoRepeat();
|
||||
}
|
||||
|
||||
bool ResponseGroup::Enabled::get()
|
||||
{
|
||||
return m_pNative->IsEnabled();
|
||||
}
|
||||
|
||||
int ResponseGroup::CurrentIndexInsideGroup::get()
|
||||
{
|
||||
return m_pNative->GetCurrentIndex();
|
||||
}
|
||||
|
||||
int ResponseGroup::Count::get()
|
||||
{
|
||||
return m_pNative->group.Count();
|
||||
}
|
||||
|
||||
|
||||
ResponseGroup::ResponseGroup( ResponseRules::ResponseGroup * RESTRICT ptr, int index )
|
||||
: BaseClass(ptr, false), m_index(index)
|
||||
{
|
||||
int numOfResponses = ptr->group.Count();
|
||||
m_shadowResponseArray = gcnew array<Response ^>(numOfResponses);
|
||||
|
||||
for ( int i = 0 ; i < numOfResponses ; ++i )
|
||||
{
|
||||
m_shadowResponseArray[i] = gcnew Response( &ptr->group[i], i );
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================= //
|
||||
// Criterion
|
||||
// ============================================================= //
|
||||
|
||||
|
||||
String^ Criterion::Key::get()
|
||||
{
|
||||
return gcnew String(m_pNative->name);
|
||||
}
|
||||
|
||||
String^ Criterion::Value::get()
|
||||
{
|
||||
return gcnew String(m_pNative->value);
|
||||
}
|
||||
|
||||
bool Criterion::Required::get()
|
||||
{
|
||||
return m_pNative->required;
|
||||
}
|
||||
|
||||
Matcher^ Criterion::Comparison::get()
|
||||
{
|
||||
return comparison;
|
||||
}
|
||||
|
||||
float Criterion::Weight::get()
|
||||
{
|
||||
return m_pNative->weight.GetFloat();
|
||||
}
|
||||
|
||||
|
||||
// ============================================================= //
|
||||
// Rule
|
||||
// ============================================================= //
|
||||
|
||||
|
||||
String^ Rule::Context::get()
|
||||
{
|
||||
return gcnew String(m_pNative->GetContext());
|
||||
}
|
||||
|
||||
void Rule::Context::set(String ^s)
|
||||
{
|
||||
m_pNative->SetContext( StrToAnsi(s) );
|
||||
}
|
||||
|
||||
bool Rule::Enabled::get()
|
||||
{
|
||||
return m_pNative->IsEnabled();
|
||||
}
|
||||
|
||||
bool Rule::MatchOnce::get()
|
||||
{
|
||||
return m_pNative->IsMatchOnce();
|
||||
}
|
||||
|
||||
bool Rule::IsApplyContextToWorld::get()
|
||||
{
|
||||
return m_pNative->IsApplyContextToWorld();
|
||||
}
|
||||
|
||||
// String^ GetValueForRuleCriterionByName( ResponseSystemCLI^ responsesystem, String^ criterionname );
|
||||
|
||||
unsigned short Rule::ResponseIndices::get( int idx )
|
||||
{
|
||||
return m_pNative->m_Responses[idx] ;
|
||||
}
|
||||
int Rule::NumResponses::get( )
|
||||
{
|
||||
return m_pNative->m_Responses.Count();
|
||||
}
|
||||
|
||||
ResponseGroup ^Rule::ResponseGroups::get( int idx )
|
||||
{
|
||||
return safe_cast<ResponseGroup ^>(SingletonResponseSystem_t::RS::get()->ResponseGroupsDict[idx]);
|
||||
}
|
||||
|
||||
unsigned short Rule::CriteriaIndices::get( int idx )
|
||||
{
|
||||
return m_pNative->m_Criteria[idx];
|
||||
}
|
||||
|
||||
int Rule::NumCriteria::get( )
|
||||
{
|
||||
return m_pNative->m_Criteria.Count();
|
||||
}
|
||||
|
||||
Criterion ^Rule::Criteria::get( int idx )
|
||||
{
|
||||
return safe_cast<Criterion ^>(SingletonResponseSystem_t::RS::get()->CriteriaDict[idx]);
|
||||
}
|
604
responserules/responserules_cli/response_types_marshal.h
Normal file
604
responserules/responserules_cli/response_types_marshal.h
Normal file
@ -0,0 +1,604 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Marhsalled types for native response-rules data.
|
||||
// Rather than have the CLR try to access the response rules natively,
|
||||
// we copy the data out from the native types to these garbage-collected
|
||||
// CLI types.
|
||||
// This is manually kept in sync with the native types in response_types.h
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef RESPONSE_TYPES_MARSHAL_H
|
||||
#define RESPONSE_TYPES_MARSHAL_H
|
||||
#pragma once
|
||||
|
||||
using namespace System;
|
||||
|
||||
|
||||
// forward-declare some classes we wrap
|
||||
namespace ResponseRules
|
||||
{
|
||||
struct ResponseParams;
|
||||
struct ParserResponse;
|
||||
class CRR_Response;
|
||||
|
||||
};
|
||||
|
||||
#include "response_types_marshal_wrappers.h"
|
||||
|
||||
namespace ResponseRulesCLI
|
||||
{
|
||||
ref class ResponseSystemCLI;
|
||||
// try to maintain a singleton pointer to the response system
|
||||
public value class SingletonResponseSystem_t
|
||||
{
|
||||
public:
|
||||
property ResponseSystemCLI ^RS
|
||||
{
|
||||
static ResponseSystemCLI ^get() { return g_RS; }
|
||||
static void set(ResponseSystemCLI ^ r ) { g_RS=r; }
|
||||
}
|
||||
|
||||
private:
|
||||
static ResponseSystemCLI ^g_RS;
|
||||
} SingletonResponseSystem;
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "internal" types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// Stub for now
|
||||
public ref class ResponseFollowup {};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Encapsulates the comparison of a value against a criterion.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The Matcher performs the comparison between the value specified in
|
||||
/// the criterion and the value specified in a context. Eg, a criterion
|
||||
/// with key "foo", value 5 and matcher ">" means that only queries with
|
||||
/// context "foo" greater than 5 will match this criterion.
|
||||
///
|
||||
/// This is a representation only since the actual matching code is all in the
|
||||
/// C++ side.
|
||||
/// </remarks>
|
||||
public ref class Matcher : public NativeTypeCopyWrapper<ResponseRules::Matcher>
|
||||
{
|
||||
typedef NativeTypeCopyWrapper<ResponseRules::Matcher> BaseClass;
|
||||
public:
|
||||
Matcher( ) {};
|
||||
Matcher( ResponseRules::Matcher *ptr ) : BaseClass(ptr, false) {};
|
||||
property String^ Token
|
||||
{
|
||||
String ^get();
|
||||
}
|
||||
|
||||
property String^ RawSource
|
||||
{
|
||||
String ^get();
|
||||
}
|
||||
|
||||
property String^ Description
|
||||
{
|
||||
String ^get();
|
||||
}
|
||||
|
||||
// flag accessors -- from the comparison mechanism
|
||||
// inherited from Yahn's original system of changelist
|
||||
// 59153.
|
||||
property bool FlagValid
|
||||
{
|
||||
inline bool get() { return m_pNative->valid; }
|
||||
}
|
||||
property bool FlagNumeric
|
||||
{
|
||||
inline bool get() { return m_pNative->isnumeric; }
|
||||
}
|
||||
property bool FlagNotEqual
|
||||
{
|
||||
inline bool get() { return m_pNative->notequal; }
|
||||
}
|
||||
property bool FlagUseMin
|
||||
{
|
||||
inline bool get() { return m_pNative->usemin; }
|
||||
}
|
||||
property bool FlagMinEquals
|
||||
{
|
||||
inline bool get() { return m_pNative->minequals; }
|
||||
}
|
||||
property bool FlagUseMax
|
||||
{
|
||||
inline bool get() { return m_pNative->usemax; }
|
||||
}
|
||||
property bool FlagMaxEquals
|
||||
{
|
||||
inline bool get() { return m_pNative->maxequals; }
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Represents a single AI_Criterion inside a rule.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A response rule contains a list of criteria, each of which consists of a key,
|
||||
/// a matcher (comparator), and a value. A query into the response system contains a
|
||||
/// list of key:value pairs. Each of these is tested against all the criteria in a rule.
|
||||
/// Each matching criterion increases that rule's score. The best scoring rule is selected.
|
||||
/// If a criterion is marked as Required, then its failure rejects the rule.
|
||||
/// Otherwise it just doesn't contribute to the score.
|
||||
/// </remarks>
|
||||
public ref class Criterion : public NativeTypeCopyWrapper<ResponseRules::Criteria>
|
||||
{
|
||||
typedef NativeTypeCopyWrapper<ResponseRules::Criteria> BaseClass;
|
||||
public:
|
||||
Criterion() {};
|
||||
Criterion( ResponseRules::Criteria *ptr, int _index ) : BaseClass( ptr, false ), index(_index)
|
||||
{
|
||||
comparison = gcnew Matcher( &ptr->matcher );
|
||||
};
|
||||
property String^ Key
|
||||
{
|
||||
String^ get();
|
||||
}
|
||||
|
||||
property String^ Value
|
||||
{
|
||||
String^ get();
|
||||
}
|
||||
|
||||
property bool Required
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
property Matcher^ Comparison
|
||||
{
|
||||
Matcher^ get();
|
||||
}
|
||||
|
||||
property float Weight
|
||||
{
|
||||
float get();
|
||||
}
|
||||
|
||||
property int Idx
|
||||
{
|
||||
int get() { return index; }
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
/// dummy criteria data for testing
|
||||
public static Criterion g_DummyCriteria[] =
|
||||
{
|
||||
new Criterion( "foo", "1", 1, false, new Matcher(">") ),
|
||||
new Criterion( "bar", "soup", 1, false, new Matcher("") ),
|
||||
new Criterion( "Concept", "Talk", 1, true, new Matcher("") )
|
||||
};
|
||||
*/
|
||||
|
||||
private:
|
||||
float weight;
|
||||
bool required;
|
||||
Matcher^ comparison;
|
||||
int index; ///< my ID in the large dictionary of all criteria.
|
||||
};
|
||||
|
||||
|
||||
public value struct responseparams_interval_t
|
||||
{
|
||||
float start;
|
||||
float range;
|
||||
|
||||
responseparams_interval_t( const ResponseRules::responseparams_interval_t &from );
|
||||
virtual String ^ToString() override;
|
||||
/*
|
||||
interval_t &ToInterval( interval_t &dest ) const { dest.start = start; dest.range = range; return dest; }
|
||||
void FromInterval( const interval_t &from ) { start = from.start; range = from.range; }
|
||||
float Random() const { interval_t temp = { start, range }; return RandomInterval( temp ); }
|
||||
*/
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Parameters for a ParserResponse.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
public ref struct ResponseParams : public NativeTypeCopyWrapper<ResponseRules::ResponseParams>
|
||||
{
|
||||
private:
|
||||
typedef NativeTypeCopyWrapper<ResponseRules::ResponseParams> BaseClass;
|
||||
public:
|
||||
// manually match the native version.
|
||||
// there is no way to automatically wrap
|
||||
// a native enum to a managed enum.
|
||||
[Flags]
|
||||
enum class ParamFlags_t
|
||||
{
|
||||
None = (0),
|
||||
RG_DELAYAFTERSPEAK = (1<<0),
|
||||
RG_SPEAKONCE = (1<<1),
|
||||
RG_ODDS = (1<<2),
|
||||
RG_RESPEAKDELAY = (1<<3),
|
||||
RG_SOUNDLEVEL = (1<<4),
|
||||
RG_DONT_USE_SCENE = (1<<5),
|
||||
RG_STOP_ON_NONIDLE = (1<<6),
|
||||
RG_WEAPONDELAY = (1<<7),
|
||||
RG_DELAYBEFORESPEAK = (1<<8),
|
||||
};
|
||||
|
||||
/*
|
||||
ResponseParams()
|
||||
{
|
||||
flags = 0;
|
||||
odds = 100;
|
||||
delay.start = 0;f
|
||||
delay.range = 0;
|
||||
respeakdelay.start = 0;
|
||||
respeakdelay.range = 0;
|
||||
weapondelay.start = 0;
|
||||
weapondelay.range = 0;
|
||||
soundlevel = 0;
|
||||
predelay.start = 0;
|
||||
predelay.range = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
ResponseParams(){};
|
||||
|
||||
ResponseParams( ResponseRules::ResponseParams *pSourceNativeParams ) :
|
||||
BaseClass( pSourceNativeParams, false ) {};
|
||||
|
||||
|
||||
property responseparams_interval_t delay
|
||||
{
|
||||
responseparams_interval_t get();
|
||||
}
|
||||
property responseparams_interval_t respeakdelay
|
||||
{
|
||||
responseparams_interval_t get();
|
||||
}
|
||||
property responseparams_interval_t weapondelay
|
||||
{
|
||||
responseparams_interval_t get();
|
||||
}
|
||||
property responseparams_interval_t predelay
|
||||
{
|
||||
responseparams_interval_t get();
|
||||
}
|
||||
|
||||
property short odds
|
||||
{
|
||||
short get();
|
||||
}
|
||||
property unsigned short flags
|
||||
{
|
||||
unsigned short get();
|
||||
}
|
||||
property bool IsSpeakOnce
|
||||
{
|
||||
bool get() { return ( ((ParamFlags_t)(flags)) & ParamFlags_t::RG_RESPEAKDELAY ) != ParamFlags_t::None ; }
|
||||
}
|
||||
property byte soundlevel
|
||||
{
|
||||
byte get();
|
||||
}
|
||||
|
||||
ResponseFollowup^ m_pFollowup;
|
||||
|
||||
protected:
|
||||
// ResponseRules::ResponseParams *m_pNative;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Response as read from the script file.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The action that ensues as a result of a query into the RR system
|
||||
/// is a Response. It may be a .vcd, a sound, or many other things.
|
||||
/// This Response class represents the entry in the source data file,
|
||||
/// not the result of a query into the system. Its analogue in C++
|
||||
/// is the ParserResponse.
|
||||
/// </remarks>
|
||||
public ref class Response : public NativeTypeCopyWrapper<ResponseRules::ParserResponse>
|
||||
{
|
||||
typedef NativeTypeCopyWrapper<ResponseRules::ParserResponse> BaseClass ;
|
||||
public:
|
||||
Response(){};
|
||||
Response( ResponseRules::ParserResponse *x , int index) : BaseClass(x, false),
|
||||
m_index(index)
|
||||
{
|
||||
m_params = gcnew ResponseParams(&x->params);
|
||||
};
|
||||
|
||||
/// The various types of response available.
|
||||
enum class ResponseType
|
||||
{
|
||||
RESPONSE_NONE = 0,
|
||||
RESPONSE_SPEAK,
|
||||
RESPONSE_SENTENCE,
|
||||
RESPONSE_SCENE,
|
||||
RESPONSE_RESPONSE, // A reference to another response by name
|
||||
RESPONSE_PRINT,
|
||||
|
||||
NUM_RESPONSES,
|
||||
};
|
||||
|
||||
property ResponseParams ^params
|
||||
{
|
||||
ResponseParams ^get() { return m_params; }
|
||||
}
|
||||
|
||||
/// A string containing the filename of a .vcd, the name of a sound script, etc.
|
||||
property String^ value
|
||||
{
|
||||
String^ get();
|
||||
}
|
||||
|
||||
/// This response's relative weight in a rule.
|
||||
property float weight
|
||||
{
|
||||
float get();
|
||||
}
|
||||
|
||||
/// Used to track how many times a response can get said
|
||||
property byte depletioncount
|
||||
{
|
||||
byte get();
|
||||
}
|
||||
|
||||
/// What kind of response this is
|
||||
property ResponseType type
|
||||
{
|
||||
ResponseType get();
|
||||
}
|
||||
|
||||
/// Special flags that can be specified in the response
|
||||
property bool DisplayFirst
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
property bool DisplayLast
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
// property ResponseFollowup^ followup;
|
||||
|
||||
|
||||
protected:
|
||||
/// in my owning responsegroup
|
||||
int m_index;
|
||||
ResponseParams ^m_params;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a group of Responses, eg all the ones available
|
||||
/// when a rule is matched.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The ordering of responses in this group isn't innately important.
|
||||
/// However some responses may be marked "first" or "last" in which
|
||||
/// case they are played either at beginning or end for the rule.
|
||||
/// Implements IList, representing a list of the responses it contains.
|
||||
/// </remarks>
|
||||
public ref class ResponseGroup : public NativeTypeCopyWrapper<ResponseRules::ResponseGroup>
|
||||
{
|
||||
typedef public NativeTypeCopyWrapper<ResponseRules::ResponseGroup> BaseClass;
|
||||
public:
|
||||
ResponseGroup() {};
|
||||
ResponseGroup( ResponseRules::ResponseGroup *ptr, int index );
|
||||
property bool Sequential
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
property bool NoRepeat
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
property bool Enabled
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
property int CurrentIndexInsideGroup
|
||||
{
|
||||
int get();
|
||||
}
|
||||
|
||||
property int Count
|
||||
{
|
||||
int get();
|
||||
}
|
||||
|
||||
/// The index of this response group inside the global system's dict
|
||||
property int Index
|
||||
{
|
||||
int get() { return m_index; }
|
||||
}
|
||||
|
||||
/// For WPF views, get the responses as a list.
|
||||
property System::Collections::IList^ ResponsesList
|
||||
{
|
||||
System::Collections::IList^ get() { return m_shadowResponseArray; }
|
||||
}
|
||||
|
||||
|
||||
/// indexer goes into the cutlvector inside the group
|
||||
property Response ^ default[int]
|
||||
{
|
||||
Response ^get( int idx );
|
||||
void set( int idx, Response^ from );
|
||||
}
|
||||
|
||||
protected:
|
||||
/// in the global system dictionary
|
||||
int m_index;
|
||||
|
||||
private:
|
||||
/// we'll preallocate the Response wrapper objects inside here
|
||||
/// to speed up the access in wpf views.
|
||||
array<Response ^>^ m_shadowResponseArray;
|
||||
};
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Response Rule
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// A rule contains a bunch of criteria and a group of responses.
|
||||
/// A query into the RR system means iterating through the database of
|
||||
/// Rules with a set of contexts; the contexts are matched against the
|
||||
/// criteria and the best match is returned.
|
||||
/// </remarks>
|
||||
public ref class Rule : public NativeTypeCopyWrapper<ResponseRules::Rule>
|
||||
{
|
||||
typedef NativeTypeCopyWrapper<ResponseRules::Rule> BaseClass ;
|
||||
public:
|
||||
typedef IndexPropertyToIListReadOnly<ResponseGroup ^> ResGroupAsIList_t;
|
||||
typedef IndexPropertyToIListReadOnly<Criterion ^> CriteriaAsIList_t;
|
||||
|
||||
public:
|
||||
Rule(){};
|
||||
Rule( ResponseRules::Rule *x, ResponseRules::ResponseRulePartition::tIndex idx, const char *name ) :
|
||||
BaseClass(x, false), m_index(idx), m_name(gcnew String(name)),
|
||||
m_ResponseGroupsAsList( nullptr ), m_CriteriaAsList( nullptr )
|
||||
{
|
||||
m_ResponseGroupsAsList = gcnew ResGroupAsIList_t(
|
||||
gcnew ResGroupAsIList_t::lGetter(this, &ResponseGroups::get),
|
||||
gcnew ResGroupAsIList_t::lCounter(this, &NumResponses::get) ) ;
|
||||
|
||||
m_CriteriaAsList = gcnew CriteriaAsIList_t(
|
||||
gcnew CriteriaAsIList_t::lGetter(this, &Criteria::get),
|
||||
gcnew CriteriaAsIList_t::lCounter(this, &NumCriteria::get) ) ;
|
||||
};
|
||||
|
||||
property String^ Context
|
||||
{
|
||||
String^ get();
|
||||
void set(String ^s);
|
||||
}
|
||||
|
||||
property bool Enabled
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
property bool MatchOnce
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
property bool IsApplyContextToWorld
|
||||
{
|
||||
bool get();
|
||||
}
|
||||
|
||||
// String^ GetValueForRuleCriterionByName( ResponseSystemCLI^ responsesystem, String^ criterionname );
|
||||
|
||||
/// indexes into the response system
|
||||
property unsigned short ResponseIndices[int]
|
||||
{
|
||||
unsigned short get( int idx );
|
||||
}
|
||||
property int NumResponses
|
||||
{
|
||||
int get( );
|
||||
}
|
||||
property ResponseGroup ^ResponseGroups[int]
|
||||
{
|
||||
ResponseGroup ^get( int idx );
|
||||
}
|
||||
property ResGroupAsIList_t ^ResponseGroupsAsIList
|
||||
{
|
||||
ResGroupAsIList_t ^get() { return m_ResponseGroupsAsList; }
|
||||
}
|
||||
|
||||
|
||||
property unsigned short CriteriaIndices[int]
|
||||
{
|
||||
unsigned short get( int idx );
|
||||
}
|
||||
property int NumCriteria
|
||||
{
|
||||
int get( );
|
||||
}
|
||||
property Criterion ^Criteria[int]
|
||||
{
|
||||
Criterion ^get( int idx );
|
||||
}
|
||||
property CriteriaAsIList_t ^CriteriaAsIList
|
||||
{
|
||||
CriteriaAsIList_t ^get() { return m_CriteriaAsList; }
|
||||
}
|
||||
|
||||
property ResponseRules::ResponseRulePartition::tIndex IndexInResponseSystem
|
||||
{
|
||||
ResponseRules::ResponseRulePartition::tIndex get() { return m_index; }
|
||||
}
|
||||
|
||||
property String^ Name
|
||||
{
|
||||
String ^get() { return m_name; }
|
||||
}
|
||||
|
||||
private:
|
||||
/// index inside responsesystem
|
||||
ResponseRules::ResponseRulePartition::tIndex m_index;
|
||||
String ^m_name;
|
||||
ResGroupAsIList_t ^m_ResponseGroupsAsList;
|
||||
CriteriaAsIList_t ^m_CriteriaAsList;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// "public" types
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#if 0
|
||||
/// Takes ownership of the response object and DELETES IT when finalized.
|
||||
public ref class ResponseQueryResult
|
||||
{
|
||||
public:
|
||||
ResponseQueryResult( ) : m_pNative(NULL) {};
|
||||
ResponseQueryResult( ResponseRules::CRR_Response * source ) : m_pNative(source) {};
|
||||
~ResponseQueryResult() { this->!ResponseQueryResult(); }
|
||||
!ResponseQueryResult()
|
||||
{
|
||||
delete m_pNative;
|
||||
m_pNative = NULL;
|
||||
}
|
||||
|
||||
property String^ RuleName
|
||||
{
|
||||
String^ get();
|
||||
}
|
||||
|
||||
property String^ ResponseName
|
||||
{
|
||||
String^ get();
|
||||
}
|
||||
|
||||
protected:
|
||||
ResponseRules::CRR_Response *m_pNative;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
// henceforth contexts shall be called "facts".
|
||||
};
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,27 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Templates for use in response_types_marhsal.h
|
||||
// Placed here just to keep code a little bit cleaner.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef RESPONSE_TYPES_MARSHAL_WRAPPERS_H
|
||||
#define RESPONSE_TYPES_MARSHAL_WRAPPERS_H
|
||||
#pragma once
|
||||
|
||||
#include "utlcontainer_cli.h"
|
||||
|
||||
/// Some (unpublished) template specializations for the above.
|
||||
extern ResponseRules::ResponseParams *CopyResponseParams( ResponseRules::ResponseParams *pSourceNativeParams );
|
||||
template < >
|
||||
NativeTypeCopyWrapper< ResponseRules::ResponseParams >::NativeTypeCopyWrapper( ResponseRules::ResponseParams *pSourceNativeParams, bool bCopy )
|
||||
{
|
||||
m_bIsCopy = bCopy;
|
||||
if ( bCopy )
|
||||
m_pNative = CopyResponseParams( pSourceNativeParams );
|
||||
else
|
||||
m_pNative = pSourceNativeParams;
|
||||
}
|
||||
|
||||
#endif
|
247
responserules/responserules_cli/responserules_cli.cpp
Normal file
247
responserules/responserules_cli/responserules_cli.cpp
Normal file
@ -0,0 +1,247 @@
|
||||
// This is the main DLL file.
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
extern int TestRandomNumberGeneration( int bottom, int top ) ;
|
||||
extern const char *TestFileSystemHook( ) ;
|
||||
|
||||
using namespace ResponseRulesCLI;
|
||||
|
||||
namespace MikeCTest
|
||||
{
|
||||
public ref class Person
|
||||
{
|
||||
private:
|
||||
String^ _name;
|
||||
public:
|
||||
Person( String^ name )
|
||||
{
|
||||
_name = name;
|
||||
}
|
||||
String^ Description()
|
||||
{
|
||||
// this is the big test!
|
||||
int rndNum = TestRandomNumberGeneration( 0, 10 );
|
||||
String^ foo = gcnew String(TestFileSystemHook());
|
||||
|
||||
return ( "My name is " + _name +
|
||||
" filesystem is " + foo
|
||||
// " my ID is " + rndNum.ToString()
|
||||
);
|
||||
}
|
||||
|
||||
static bool HopefullyDontCrash()
|
||||
{
|
||||
TestFileSystemHook( );
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#include "response_system.h"
|
||||
|
||||
|
||||
|
||||
StrToAnsi::StrToAnsi( String ^unicodestr )
|
||||
{
|
||||
m_pStr = (char*)(void*)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(unicodestr);
|
||||
}
|
||||
|
||||
StrToAnsi::~StrToAnsi( )
|
||||
{
|
||||
System::Runtime::InteropServices::Marshal::FreeHGlobal((System::IntPtr)(void*)m_pStr);
|
||||
}
|
||||
|
||||
StrToAnsi::operator TCHAR *() const
|
||||
{
|
||||
return m_pStr;
|
||||
}
|
||||
|
||||
/*
|
||||
using namespace System::Runtime::InteropServices; // for class Marshal
|
||||
|
||||
void PrintMessage(System::String^ str)
|
||||
{
|
||||
const char* str2 = (char*)(void*)Marshal::StringToHGlobalAnsi(str);
|
||||
printf(str2);
|
||||
Marshal::FreeHGlobal((System::IntPtr)(void*)str2);
|
||||
}
|
||||
|
||||
PrintMessage("Method 2");
|
||||
*/
|
||||
|
||||
|
||||
using namespace ResponseRulesCLI;
|
||||
|
||||
// Allocate the native object on the C++ Heap via a constructor
|
||||
ResponseSystemCLI::ResponseSystemCLI()
|
||||
{
|
||||
m_pImpl = new ResponseSystemImplementationCLI();
|
||||
m_CriteriaDict = gcnew CriterionDictWrapper_t(&m_pImpl->m_Criteria);
|
||||
m_ResponseGroupsDict = gcnew ResponseGroupDictWrapper_t(&m_pImpl->m_Responses);
|
||||
m_RulesContainer = gcnew RulesAsList(this);
|
||||
}
|
||||
|
||||
// Deallocate the native object on a destructor
|
||||
ResponseSystemCLI::~ResponseSystemCLI()
|
||||
{
|
||||
this->!ResponseSystemCLI();
|
||||
}
|
||||
|
||||
// Deallocate the native object on the finalizer just in case no destructor is called
|
||||
ResponseSystemCLI::!ResponseSystemCLI()
|
||||
{
|
||||
delete m_pImpl;
|
||||
}
|
||||
|
||||
|
||||
void ResponseSystemCLI::LoadFromFile( String^ filename )
|
||||
{
|
||||
return m_pImpl->LoadFromFile( StrToAnsi(filename) );
|
||||
}
|
||||
|
||||
|
||||
int ResponseSystemCLI::CountRules()
|
||||
{
|
||||
return m_pImpl->CountRules();
|
||||
}
|
||||
|
||||
ResponseSystemImplementationCLI *ResponseSystemCLI::GetNativePtr()
|
||||
{
|
||||
return m_pImpl;
|
||||
}
|
||||
|
||||
void ResponseSystemCLI::RulesAsList::RulesIterator::Reset()
|
||||
{
|
||||
m_bIsBefore = true;
|
||||
m_idx = m_System->GetNativePtr()->m_RulePartitions.First();
|
||||
}
|
||||
|
||||
bool ResponseSystemCLI::RulesAsList::RulesIterator::MoveNext()
|
||||
{
|
||||
if (m_bIsBefore)
|
||||
{
|
||||
m_bIsBefore = false;
|
||||
m_idx = m_System->GetNativePtr()->m_RulePartitions.First();
|
||||
return IsValid();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !IsValid() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// stick the index on the stack temporarily so we can pass a reference to it
|
||||
ResponseRules::ResponseRulePartition::tIndex tmp = m_idx;
|
||||
m_idx = m_System->GetNativePtr()->m_RulePartitions.Next(tmp);
|
||||
return IsValid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ResponseSystemCLI::RulesAsList::RulesIterator::IsValid()
|
||||
{
|
||||
// stick the index on the stack temporarily so we can pass a reference to it
|
||||
ResponseRules::ResponseRulePartition::tIndex tmp = m_idx;
|
||||
return m_System->GetNativePtr()->m_RulePartitions.IsValid( tmp );
|
||||
}
|
||||
|
||||
Object^ ResponseSystemCLI::RulesAsList::RulesIterator::Current::get()
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
ResponseRules::ResponseRulePartition::tIndex i = m_idx;
|
||||
return gcnew Rule(&m_System->GetNativePtr()->m_RulePartitions[i],
|
||||
i,
|
||||
m_System->GetNativePtr()->m_RulePartitions.GetElementName(i) );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw gcnew System::InvalidOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
/// access to the dictionary of index->criteria
|
||||
Criterion ^ ResponseSystemCLI::Criteria::get( short key )
|
||||
{
|
||||
return gcnew Criterion(&m_pImpl->m_Criteria[key], key);
|
||||
}
|
||||
unsigned int ResponseSystemCLI::CriteriaCount::get()
|
||||
{
|
||||
return m_pImpl->m_Criteria.Count();
|
||||
}
|
||||
*/
|
||||
|
||||
Rule ^ ResponseSystemCLI::FindBestMatchingRule( System::Collections::IDictionary ^facts )
|
||||
{
|
||||
ResponseRules::CriteriaSet criteria;
|
||||
TurnIDictIntoCriteriaSet( facts, &criteria );
|
||||
float bestscore; // of matching rule
|
||||
ResponseRules::ResponseRulePartition::tIndex bestRuleIndex = m_pImpl->FindBestMatchingRule( criteria, false, bestscore );
|
||||
|
||||
if ( m_pImpl->m_RulePartitions.IsValid( bestRuleIndex ) )
|
||||
{
|
||||
return RuleFromIdx(bestRuleIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Rule ^ResponseSystemCLI::RuleFromIdx( ResponseRules::ResponseRulePartition::tIndex idx )
|
||||
{
|
||||
return gcnew Rule( &m_pImpl->m_RulePartitions[idx],
|
||||
idx,
|
||||
m_pImpl->m_RulePartitions.GetElementName(idx) );
|
||||
}
|
||||
|
||||
void ResponseSystemCLI::TurnIDictIntoCriteriaSet( System::Collections::IDictionary ^facts, ResponseRules::CriteriaSet *critset )
|
||||
{
|
||||
// for each key and value in the dictionary, add to set.
|
||||
for each ( System::Collections::DictionaryEntry pair in facts )
|
||||
{
|
||||
critset->AppendCriteria( StrToAnsi(pair.Key->ToString()), StrToAnsi(pair.Value->ToString()) );
|
||||
}
|
||||
}
|
||||
|
||||
array< System::Collections::Generic::KeyValuePair<Rule ^,float> >^ ResponseSystemCLI::FindAllRulesMatchingCriteria( System::Collections::IDictionary ^facts )
|
||||
{
|
||||
ResponseRules::CriteriaSet crits;
|
||||
TurnIDictIntoCriteriaSet( facts, &crits );
|
||||
ResponseSystemImplementationCLI::FindAllRulesRetval_t ruleresults;
|
||||
m_pImpl->FindAllRulesMatchingCriteria( &ruleresults, crits );
|
||||
if ( ruleresults.Count() < 1 )
|
||||
{
|
||||
// return empty array.
|
||||
return gcnew array< System::Collections::Generic::KeyValuePair<Rule ^,float> >(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int count = ruleresults.Count();
|
||||
array< System::Collections::Generic::KeyValuePair<Rule ^,float> >^ retval = gcnew array< System::Collections::Generic::KeyValuePair<Rule ^,float> >(count);
|
||||
for (int i = 0 ; i < count ; ++i )
|
||||
{
|
||||
const ResponseSystemImplementationCLI::RuleAndScorePair_t &pair = ruleresults[i];
|
||||
retval[i] = System::Collections::Generic::KeyValuePair<Rule ^,float>(RuleFromIdx(pair.ruleidx),pair.score);
|
||||
|
||||
/*
|
||||
retval[i].Key = RuleFromIdx(pair.ruleidx);
|
||||
retval[i].Value = pair.score;
|
||||
*/
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
#pragma unmanaged
|
||||
#include "../../responserules/runtime/response_types_internal.h"
|
||||
#pragma managed
|
||||
*/
|
155
responserules/responserules_cli/responserules_cli.h
Normal file
155
responserules/responserules_cli/responserules_cli.h
Normal file
@ -0,0 +1,155 @@
|
||||
// responserules_cli.h
|
||||
|
||||
#pragma once
|
||||
|
||||
using namespace System;
|
||||
|
||||
|
||||
#pragma unmanaged
|
||||
namespace ResponseRules
|
||||
{
|
||||
/// forward declare unmanaged implementation
|
||||
class CriteriaSet;
|
||||
}
|
||||
#pragma managed
|
||||
|
||||
|
||||
#include "response_types_marshal.h"
|
||||
|
||||
namespace ResponseRulesCLI {
|
||||
|
||||
typedef CCLIUtlDictEnumerable< ResponseRules::Criteria, short, ResponseRulesCLI::Criterion > CriterionDictWrapper_t;
|
||||
typedef CCLIUtlDictEnumerable< ResponseRules::ResponseGroup, short, ResponseRulesCLI::ResponseGroup > ResponseGroupDictWrapper_t;
|
||||
// enumerations aren't used right now it seems.
|
||||
// typedef CCLIUtlDictEnumerable< ResponseRules::CResponseSystem::Enumeration, short, System::Single > EnumerationDictWrapper_t;
|
||||
|
||||
|
||||
|
||||
/// Encapsulates an entire response system based on a file,
|
||||
/// containing responses, rules, criteria, and other data.
|
||||
public ref class ResponseSystemCLI
|
||||
{
|
||||
public:
|
||||
// Allocate the native object on the C++ Heap via a constructor
|
||||
ResponseSystemCLI();
|
||||
|
||||
// Deallocate the native object on a destructor
|
||||
~ResponseSystemCLI() ;
|
||||
|
||||
/// Load this system from a talker file.
|
||||
virtual void LoadFromFile( String^ filename );
|
||||
int CountRules();
|
||||
|
||||
property ResponseGroupDictWrapper_t ^ResponseGroupsDict
|
||||
{
|
||||
ResponseGroupDictWrapper_t ^get() { return m_ResponseGroupsDict; }
|
||||
}
|
||||
|
||||
property CriterionDictWrapper_t ^CriteriaDict
|
||||
{
|
||||
CriterionDictWrapper_t ^get() { return m_CriteriaDict; }
|
||||
}
|
||||
|
||||
/*
|
||||
property EnumerationDictWrapper_t ^EnumerationsDict
|
||||
{
|
||||
EnumerationDictWrapper_t ^get() { return m_EnumerationsDict; }
|
||||
}
|
||||
*/
|
||||
|
||||
/// interface to enumerate rules.
|
||||
ref class RulesAsList : public System::Collections::IEnumerable, System::Collections::Specialized::INotifyCollectionChanged
|
||||
{
|
||||
public:
|
||||
|
||||
ref struct RulesIterator : System::Collections::IEnumerator
|
||||
{
|
||||
public:
|
||||
RulesIterator( ResponseSystemCLI^ enumerable ) :
|
||||
m_System(enumerable), m_bIsBefore(false), m_idx(ResponseRules::ResponseRulePartition::InvalidIdx()) {Reset();};
|
||||
virtual void Reset();
|
||||
virtual bool MoveNext(); // return false when falling off the end
|
||||
|
||||
property Object^ Current
|
||||
{
|
||||
virtual Object^ get();
|
||||
};
|
||||
|
||||
protected:
|
||||
bool m_bIsBefore; // is "one before" everything in the array, required by iterator interface
|
||||
bool IsValid() ;
|
||||
ResponseSystemCLI ^m_System; ///< the system I iterate
|
||||
ResponseRules::ResponseRulePartition::tIndex m_idx;
|
||||
};
|
||||
|
||||
RulesAsList( ResponseSystemCLI^ owner ) : m_owner(owner) {};
|
||||
|
||||
property int Count
|
||||
{
|
||||
int get() { return m_owner->GetNativePtr()->CountRules(); }
|
||||
}
|
||||
|
||||
virtual System::Collections::IEnumerator^ GetEnumerator()
|
||||
{
|
||||
return gcnew RulesIterator(m_owner);
|
||||
}
|
||||
|
||||
#pragma region INotifyCollectionChanged interface
|
||||
|
||||
System::Collections::Specialized::NotifyCollectionChangedEventHandler ^m_CollectionChanged;
|
||||
virtual event System::Collections::Specialized::NotifyCollectionChangedEventHandler ^CollectionChanged
|
||||
{
|
||||
void add(System::Collections::Specialized::NotifyCollectionChangedEventHandler ^ d) {
|
||||
m_CollectionChanged += d;
|
||||
}
|
||||
void remove(System::Collections::Specialized::NotifyCollectionChangedEventHandler ^ d) {
|
||||
m_CollectionChanged -= d;
|
||||
}
|
||||
}
|
||||
virtual void OnCollectionChanged(System::Collections::Specialized::NotifyCollectionChangedEventArgs ^e)
|
||||
{
|
||||
if (m_CollectionChanged != nullptr)
|
||||
{
|
||||
m_CollectionChanged(this, e);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
private:
|
||||
ResponseSystemCLI^ m_owner;
|
||||
};
|
||||
|
||||
property RulesAsList^ Rules
|
||||
{
|
||||
RulesAsList^ get() { return m_RulesContainer; };
|
||||
}
|
||||
|
||||
#pragma region "Queries Into Response System"
|
||||
|
||||
/// Given a dictionary of key:value pairs (the contexts and their values),
|
||||
/// find the best matching rule.
|
||||
Rule ^FindBestMatchingRule( System::Collections::IDictionary ^facts );
|
||||
|
||||
/// Find *all* rules that match the given criteria, in sorted order of best to worst.
|
||||
array< System::Collections::Generic::KeyValuePair<Rule ^,float> >^ FindAllRulesMatchingCriteria( System::Collections::IDictionary ^facts );
|
||||
|
||||
#pragma endregion
|
||||
|
||||
/// please be careful
|
||||
ResponseSystemImplementationCLI *GetNativePtr();
|
||||
|
||||
protected:
|
||||
// Deallocate the native object on the finalizer just in case no destructor is called
|
||||
!ResponseSystemCLI() ;
|
||||
ResponseSystemImplementationCLI *m_pImpl;
|
||||
|
||||
void TurnIDictIntoCriteriaSet( System::Collections::IDictionary ^facts, ResponseRules::CriteriaSet *critset );
|
||||
Rule ^RuleFromIdx( ResponseRules::ResponseRulePartition::tIndex idx );
|
||||
|
||||
private:
|
||||
CriterionDictWrapper_t ^m_CriteriaDict;
|
||||
ResponseGroupDictWrapper_t ^m_ResponseGroupsDict;
|
||||
// EnumerationDictWrapper_t ^m_EnumerationsDict;
|
||||
RulesAsList ^m_RulesContainer;
|
||||
};
|
||||
}
|
445
responserules/responserules_cli/responserules_cli.vcproj
Normal file
445
responserules/responserules_cli/responserules_cli.vcproj
Normal file
@ -0,0 +1,445 @@
|
||||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="9.00"
|
||||
Name="responserules_cli"
|
||||
ProjectGUID="{0BA4E446-7651-4CC5-917F-6AC6B8A5C097}"
|
||||
RootNamespace="responserules_cli"
|
||||
Keyword="ManagedCProj"
|
||||
TargetFrameworkVersion="196613"
|
||||
>
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"
|
||||
/>
|
||||
</Platforms>
|
||||
<ToolFiles>
|
||||
</ToolFiles>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="$(SolutionDir)..\bin"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
ManagedExtensions="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories="..\..\common;..\..\public;..\..\public\tier0;..\..\public\tier1;..\..\"
|
||||
PreprocessorDefinitions="WIN32;DEBUG;COMPILER_MSVC;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_DLL_EXT=.dll;COMPILER_MSVC32"
|
||||
RuntimeLibrary="3"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="tier0.lib tier1.lib tier2.lib vstdlib.lib interfaces.lib appframework.lib responserules_runtime.lib"
|
||||
LinkIncremental="2"
|
||||
AdditionalLibraryDirectories="..\..\lib\public"
|
||||
IgnoreDefaultLibraryNames="LIBCMT.lib;LIBCMTD.lib"
|
||||
GenerateDebugInformation="true"
|
||||
AssemblyDebug="1"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="copy to devtools\bin"
|
||||
CommandLine="if exist ..\..\devtools\responseeditor\. goto ValveStart
mkdir ..\..\devtools\responseeditor
:ValveStart
call ..\..\vpc_scripts\valve_p4_edit.cmd ..\..\devtools\responseeditor\.\$(TargetFileName) ..\..
copy "$(TargetDir)"$(TargetFileName) ..\..\devtools\responseeditor\.\$(TargetFileName)
if ERRORLEVEL 1 goto BuildEventFailed
if exist "$(TargetDir)\bin"$(TargetName).map copy "$(TargetDir)"$(TargetName).map ..\..\devtools\responseeditor\.\$(TargetName).map
call ..\..\vpc_scripts\valve_p4_edit.cmd ..\..\devtools\responseeditor\.\$(TargetName).pdb ..\..
copy "$(TargetDir)"$(TargetName).pdb ..\..\devtools\responseeditor\.\$(TargetName).pdb 
if ERRORLEVEL 1 goto BuildEventFailed
goto BuildEventOK
:BuildEventFailed
echo *** ERROR! PostBuildStep FAILED for $(ProjectName)! EXE or DLL is probably running. ***
del /q "$(TargetDir)"$(TargetFileName)
exit 1
:BuildEventOK
"
|
||||
/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="$(SolutionDir)..\bin"
|
||||
IntermediateDirectory="$(ConfigurationName)"
|
||||
ConfigurationType="2"
|
||||
CharacterSet="1"
|
||||
ManagedExtensions="1"
|
||||
WholeProgramOptimization="1"
|
||||
>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="3"
|
||||
WholeProgramOptimization="false"
|
||||
AdditionalIncludeDirectories="..\..\common;..\..\public;..\..\public\tier0;..\..\public\tier1;..\..\"
|
||||
PreprocessorDefinitions="WIN32;RELEASE;COMPILER_MSVC;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;_DLL_EXT=.dll;COMPILER_MSVC32"
|
||||
RuntimeLibrary="2"
|
||||
UsePrecompiledHeader="2"
|
||||
WarningLevel="3"
|
||||
DebugInformationFormat="3"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManagedResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCLinkerTool"
|
||||
AdditionalDependencies="tier0.lib tier1.lib tier2.lib vstdlib.lib interfaces.lib appframework.lib responserules_runtime.lib"
|
||||
LinkIncremental="1"
|
||||
AdditionalLibraryDirectories="..\..\lib\public"
|
||||
IgnoreDefaultLibraryNames="LIBCMT.lib"
|
||||
GenerateDebugInformation="true"
|
||||
LinkTimeCodeGeneration="0"
|
||||
TargetMachine="1"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCALinkTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCManifestTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCXDCMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCBscMakeTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCFxCopTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCAppVerifierTool"
|
||||
/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"
|
||||
Description="copy to devtools\bin"
|
||||
CommandLine="if exist ..\..\devtools\responseeditor\. goto ValveStart
mkdir ..\..\devtools\responseeditor
:ValveStart
call ..\..\vpc_scripts\valve_p4_edit.cmd ..\..\devtools\responseeditor\.\$(TargetFileName) ..\..
copy "$(TargetDir)"$(TargetFileName) ..\..\devtools\responseeditor\.\$(TargetFileName)
if ERRORLEVEL 1 goto BuildEventFailed
if exist "$(TargetDir)\bin"$(TargetName).map copy "$(TargetDir)"$(TargetName).map ..\..\devtools\responseeditor\.\$(TargetName).map
call ..\..\vpc_scripts\valve_p4_edit.cmd ..\..\devtools\responseeditor\.\$(TargetName).pdb ..\..
copy "$(TargetDir)"$(TargetName).pdb ..\..\devtools\responseeditor\.\$(TargetName).pdb 
if ERRORLEVEL 1 goto BuildEventFailed
goto BuildEventOK
:BuildEventFailed
echo *** ERROR! PostBuildStep FAILED for $(ProjectName)! EXE or DLL is probably running. ***
del /q "$(TargetDir)"$(TargetFileName)
exit 1
:BuildEventOK
"
|
||||
/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
<AssemblyReference
|
||||
RelativePath="System.dll"
|
||||
AssemblyName="System, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
|
||||
MinFrameworkVersion="131072"
|
||||
/>
|
||||
<AssemblyReference
|
||||
RelativePath="System.Data.dll"
|
||||
AssemblyName="System.Data, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=x86"
|
||||
MinFrameworkVersion="131072"
|
||||
/>
|
||||
<AssemblyReference
|
||||
RelativePath="System.XML.dll"
|
||||
AssemblyName="System.Xml, Version=2.0.0.0, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL"
|
||||
MinFrameworkVersion="131072"
|
||||
/>
|
||||
<AssemblyReference
|
||||
RelativePath="WindowsBase.dll"
|
||||
AssemblyName="WindowsBase, Version=3.0.0.0, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"
|
||||
MinFrameworkVersion="196608"
|
||||
/>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\AssemblyInfo.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cli_appsystem_thunk.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cli_appsystem_unmanaged_wrapper.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\engine_emulator.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\response_system.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\response_types_marshal.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\responserules_cli.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="2"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Stdafx.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
UsePrecompiledHeader="1"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\utlcontainer_cli.cpp"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="public"
|
||||
>
|
||||
<File
|
||||
RelativePath="..\..\public\filesystem_helpers.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/U "_UNICODE" /U "UNICODE""
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/U "_UNICODE" /U "UNICODE""
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\public\filesystem_init.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/U "_UNICODE" /U "UNICODE""
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/U "_UNICODE" /U "UNICODE""
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\utils\common\filesystem_tools.cpp"
|
||||
>
|
||||
<FileConfiguration
|
||||
Name="Debug|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/U "_UNICODE" /U "UNICODE""
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
<FileConfiguration
|
||||
Name="Release|Win32"
|
||||
>
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalOptions="/U "_UNICODE" /U "UNICODE""
|
||||
UsePrecompiledHeader="0"
|
||||
CompileAsManaged="0"
|
||||
/>
|
||||
</FileConfiguration>
|
||||
</File>
|
||||
</Filter>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\cli_appsystem_adapter.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cli_appsystem_thunk.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\cli_appsystem_unmanaged_wrapper.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\resource.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\public\responserules\response_host_interface.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\response_system.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\public\responserules\response_types.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\response_types_marshal.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\response_types_marshal_wrappers.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\responserules_cli.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\public\responserules\rr_speechconcept.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Stdafx.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\utlcontainer_cli.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\app.ico"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\app.rc"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<File
|
||||
RelativePath=".\ReadMe.txt"
|
||||
>
|
||||
</File>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
5
responserules/responserules_cli/utlcontainer_cli.cpp
Normal file
5
responserules/responserules_cli/utlcontainer_cli.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
#include "stdafx.h"
|
||||
#include "utlcontainer_cli.h"
|
||||
|
||||
|
||||
// CCLIUtlDictEnumerable< int, int > foo();
|
833
responserules/responserules_cli/utlcontainer_cli.h
Normal file
833
responserules/responserules_cli/utlcontainer_cli.h
Normal file
@ -0,0 +1,833 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Wrappers to turn various Source Utl* containers into CLR
|
||||
// enumerables.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef UTLCONTAINER_CLI_H
|
||||
#define UTLCONTAINER_CLI_H
|
||||
|
||||
#if defined( _WIN32 )
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/// Handy wrapper to turn any indexing property into
|
||||
/// an IList (assuming it is numbered 0..count). You
|
||||
/// need only initialize it with a delegate that yields
|
||||
/// int->type and another that gets the count.
|
||||
generic< typename T >
|
||||
public ref class IndexPropertyToIListReadOnly : public System::Collections::Generic::IList<T>
|
||||
{
|
||||
public:
|
||||
delegate T lGetter( int idx ); // will wrap the indexer
|
||||
delegate int lCounter( ); // will wrap the counter
|
||||
|
||||
IndexPropertyToIListReadOnly( lGetter ^getter, lCounter ^counter )
|
||||
{
|
||||
m_getterFunc = getter;
|
||||
m_counterFunc = counter;
|
||||
}
|
||||
|
||||
/*
|
||||
virtual ~IndexPropertyToIListReadOnly( ) { !IndexPropertyToIListReadOnly( ); }
|
||||
virtual !IndexPropertyToIListReadOnly( ) {}
|
||||
*/
|
||||
|
||||
property int Count
|
||||
{
|
||||
virtual int get() { return m_counterFunc(); }
|
||||
}
|
||||
|
||||
#pragma region IList<T> Members
|
||||
|
||||
virtual int IndexOf(T item)
|
||||
{
|
||||
int count = Count::get();
|
||||
for ( int i = 0 ; i < count ; ++i )
|
||||
{
|
||||
if ( item->Equals( m_getterFunc(i) ) )
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
virtual void Insert(int index, T item)
|
||||
{
|
||||
throw gcnew NotSupportedException( "Read-only." );
|
||||
}
|
||||
|
||||
virtual void RemoveAt(int index)
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
property T default[int]
|
||||
{
|
||||
virtual T get(int index)
|
||||
{
|
||||
if ( index < 0 || index > Count::get() )
|
||||
{
|
||||
throw gcnew ArgumentOutOfRangeException();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_getterFunc(index);
|
||||
}
|
||||
|
||||
}
|
||||
virtual void set(int index, T to)
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#pragma region ICollection<T> Members
|
||||
|
||||
virtual void Add(T item)
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
virtual void Clear()
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
virtual bool Contains(T item)
|
||||
{
|
||||
return IndexOf(item) != -1;
|
||||
}
|
||||
|
||||
virtual void CopyTo( cli::array<T,1> ^arr, int start)
|
||||
{
|
||||
int stop = Count::get();
|
||||
for (int i = 0 ; i < stop ; ++i )
|
||||
{
|
||||
arr->SetValue((*this)[i],start+i);
|
||||
}
|
||||
// throw gcnew NotImplementedException();
|
||||
}
|
||||
|
||||
property bool IsReadOnly
|
||||
{
|
||||
virtual bool get() { return true; }
|
||||
}
|
||||
|
||||
virtual bool Remove(T item)
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
#pragma region Enumerator
|
||||
ref class LinearEnumerator : System::Collections::Generic::IEnumerator<T>
|
||||
{
|
||||
// Enumerators are positioned before the first element
|
||||
// until the first MoveNext() call.
|
||||
int position;
|
||||
public:
|
||||
LinearEnumerator(IndexPropertyToIListReadOnly<T> ^owner)
|
||||
{
|
||||
m_owner = owner;
|
||||
position = -1;
|
||||
}
|
||||
~LinearEnumerator(){};
|
||||
!LinearEnumerator(){};
|
||||
|
||||
virtual bool MoveNext()
|
||||
{
|
||||
position++;
|
||||
return ( position < m_owner->Count );
|
||||
}
|
||||
|
||||
virtual void Reset()
|
||||
{
|
||||
position = -1;
|
||||
}
|
||||
|
||||
virtual property T Current
|
||||
{
|
||||
virtual T get() = System::Collections::Generic::IEnumerator<T>::Current::get
|
||||
{
|
||||
if ( position >= 0 && position < m_owner->Count )
|
||||
{
|
||||
return m_owner[position];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw gcnew InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual property System::Object^ CurrentAgainBecauseCPP_CLISucks
|
||||
{
|
||||
virtual System::Object^ get() = System::Collections::IEnumerator::Current::get
|
||||
{
|
||||
if ( position >= 0 && position < m_owner->Count )
|
||||
{
|
||||
return m_owner[position];
|
||||
}
|
||||
else
|
||||
{
|
||||
throw gcnew InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IndexPropertyToIListReadOnly<T> ^m_owner;
|
||||
};
|
||||
#pragma endregion
|
||||
|
||||
#pragma region IEnumerable<T> Members
|
||||
|
||||
virtual System::Collections::Generic::IEnumerator<T> ^ GetEnumerator()
|
||||
{
|
||||
return gcnew LinearEnumerator(this);
|
||||
}
|
||||
|
||||
virtual System::Collections::IEnumerator^ GetEnumerator2() = System::Collections::IEnumerable::GetEnumerator
|
||||
{
|
||||
return gcnew LinearEnumerator(this);
|
||||
}
|
||||
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
protected:
|
||||
lGetter ^m_getterFunc;
|
||||
lCounter ^m_counterFunc;
|
||||
};
|
||||
|
||||
#if 0
|
||||
/// <summary>
|
||||
/// Tiny class that wraps an indexing property in a class with an IList interface
|
||||
/// so that the WPF databinding can access it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Assumes that all indexes are from 0..count.
|
||||
/// </remarks>
|
||||
/// <typeparam name="U"> The type of the class whose property we wrap </typeparam>
|
||||
/// <typeparam name="T"> The type of the value returned from the class property </typeparam>
|
||||
public class BindingWrapper<T> : IList<T>, INotifyCollectionChanged
|
||||
{
|
||||
// lambda types. You'll pass in one of each of these with the constructor.
|
||||
/// <summary>
|
||||
/// Given an int, return the i-th element of wrapper property in owning class.
|
||||
/// </summary>
|
||||
public delegate T lGetter( int idx );
|
||||
|
||||
/// <summary>
|
||||
/// Given an int, return the i-th element of wrapper property in owning class.
|
||||
/// </summary>
|
||||
public delegate int lCounter( );
|
||||
|
||||
public BindingWrapper( /*U owner,*/ lGetter getter, lCounter counter )
|
||||
{
|
||||
// m_owner = owner;
|
||||
m_getterFunc = getter;
|
||||
m_counterFunc = counter;
|
||||
}
|
||||
|
||||
#region IList<T> Members
|
||||
|
||||
public int IndexOf(T item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
/*
|
||||
// hang onto this number
|
||||
int count = Count;
|
||||
for (int i = 0 ; i < count ; ++i )
|
||||
{
|
||||
if (this[i] == item)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
*/
|
||||
}
|
||||
|
||||
public void Insert(int index, T item)
|
||||
{
|
||||
throw new NotSupportedException( "Read-only." );
|
||||
}
|
||||
|
||||
public void RemoveAt(int index)
|
||||
{
|
||||
throw new NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_getterFunc(index);
|
||||
}
|
||||
|
||||
}
|
||||
set
|
||||
{
|
||||
throw new NotSupportedException("Read-only.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ICollection<T> Members
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
throw new NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
throw new NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
public bool Contains(T item)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void CopyTo(T[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotSupportedException("Noncopyable.");
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return m_counterFunc(); }
|
||||
}
|
||||
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public bool Remove(T item)
|
||||
{
|
||||
throw new NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region Enumerator
|
||||
public class LinearEnumerator : System.Collections.IEnumerator
|
||||
{
|
||||
// Enumerators are positioned before the first element
|
||||
// until the first MoveNext() call.
|
||||
int position = -1;
|
||||
|
||||
public LinearEnumerator(BindingWrapper<T> owner)
|
||||
{
|
||||
m_owner = owner;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
position++;
|
||||
return ( position < m_owner.Count );
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
position = -1;
|
||||
}
|
||||
|
||||
public Object Current
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
return m_owner[position];
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BindingWrapper<T> m_owner;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region IEnumerable<T> Members
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
throw new NotImplementedException(); // return new LinearEnumerator(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
#region IEnumerable Members
|
||||
|
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
||||
{
|
||||
return new LinearEnumerator(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region INotifyCollectionChanged
|
||||
public event NotifyCollectionChangedEventHandler CollectionChanged;
|
||||
public virtual void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
if (CollectionChanged != null)
|
||||
{
|
||||
CollectionChanged(this, e);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private data
|
||||
// U m_owner;
|
||||
lGetter m_getterFunc;
|
||||
lCounter m_counterFunc;
|
||||
#endregion
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/// Common code for classes that wrap native RR
|
||||
/// types. You have the option to make a COPY
|
||||
/// rather than a pointer to the native class:
|
||||
/// in that case, the constructor here new's a copy
|
||||
/// of the given type on the heap, and the finalizer
|
||||
/// deletes it.
|
||||
/// It may be necessary to specialize the constructor
|
||||
/// in certain cases where a managed function is not
|
||||
/// allowed to new the given type.
|
||||
/// Subclass this with a CLI version of the wrapped
|
||||
/// class and create whatever accessor properties you
|
||||
/// would like to expose to the managed side.
|
||||
template< typename T >
|
||||
public ref class NativeTypeCopyWrapper
|
||||
{
|
||||
public:
|
||||
NativeTypeCopyWrapper( ) : m_pNative(NULL), m_bIsCopy(true) {};
|
||||
NativeTypeCopyWrapper( T* from ) // this overload assumes no copy
|
||||
{
|
||||
m_bIsCopy = false;
|
||||
if ( false )
|
||||
{
|
||||
m_pNative = new T( *from );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pNative = from;
|
||||
}
|
||||
}
|
||||
NativeTypeCopyWrapper( T* from, bool bCopy )
|
||||
{
|
||||
m_bIsCopy = bCopy;
|
||||
if ( bCopy )
|
||||
{
|
||||
m_pNative = new T( *from );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pNative = from;
|
||||
}
|
||||
}
|
||||
~NativeTypeCopyWrapper() { this->!NativeTypeCopyWrapper(); }
|
||||
!NativeTypeCopyWrapper()
|
||||
{
|
||||
if ( m_bIsCopy )
|
||||
delete m_pNative;
|
||||
|
||||
m_pNative = NULL;
|
||||
}
|
||||
// copy constructor
|
||||
NativeTypeCopyWrapper(NativeTypeCopyWrapper% r)
|
||||
{
|
||||
m_bIsCopy = r->m_bIsCopy;
|
||||
if (m_bIsCopy)
|
||||
m_pNative = new T( *r->GetNativePtr() );
|
||||
else
|
||||
m_pNative = r->GetNativePtr();
|
||||
}
|
||||
|
||||
inline bool IsValid( ) { return m_pNative != NULL; }
|
||||
|
||||
/// use the assignment operator on the internal native type, copying
|
||||
/// over the one in the given FROM class, and make me point to it.
|
||||
/// So named to be explicit about what's happening, and because I'm
|
||||
/// not sure what happens when you = on a ref.
|
||||
void Assign( NativeTypeCopyWrapper^ from )
|
||||
{
|
||||
*m_pNative = *from.m_pNative;
|
||||
}
|
||||
|
||||
/// please be careful
|
||||
T* GetNativePtr() { return m_pNative; }
|
||||
|
||||
protected:
|
||||
T* m_pNative;
|
||||
bool m_bIsCopy;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// CUtlDict as enumerable.
|
||||
#include "utldict.h"
|
||||
|
||||
/*
|
||||
template <class T, class I>
|
||||
class CUtlDict
|
||||
*/
|
||||
|
||||
namespace Tier1CLI
|
||||
{
|
||||
namespace Containers
|
||||
{
|
||||
public interface class INotifiableList
|
||||
: public System::Collections::IList ,
|
||||
public System::Collections::Specialized::INotifyCollectionChanged
|
||||
{
|
||||
virtual void OnCollectionChanged(System::Collections::Specialized::NotifyCollectionChangedEventArgs ^e) = 0;
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A class that wraps a tier1 CUtlDict in a way that can be iterated over from C#.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The CONVERTOR template parameter below shall be the class
|
||||
/// that wraps the native C++ * type into a CLR reference type.
|
||||
/// It should have a constructor that takes a parameter of type
|
||||
/// T* , which will be called like:
|
||||
/// return gcnew CONVERTOR(T *foo);
|
||||
/// </remarks>
|
||||
template <class T, typename I, class CONVERTOR = NativeTypeCopyWrapper<T> >
|
||||
public ref class CCLIUtlDictEnumerable : // public System::Collections::IEnumerable,
|
||||
public Tier1CLI::Containers::INotifiableList
|
||||
{
|
||||
public:
|
||||
typedef CUtlDict< T,I > dict_t;
|
||||
typedef CONVERTOR value_t;
|
||||
typedef const char * key_t;
|
||||
|
||||
#pragma region Enumeration interface
|
||||
ref struct tuple_t
|
||||
{
|
||||
key_t key;
|
||||
value_t ^val;
|
||||
I index;
|
||||
|
||||
inline tuple_t( const key_t &k, T &v, I i ) : key(k), index(i)
|
||||
{
|
||||
val = gcnew CONVERTOR( &v, i );
|
||||
};
|
||||
|
||||
// conversions to CLR types
|
||||
property System::String^ Name
|
||||
{
|
||||
System::String^ get()
|
||||
{
|
||||
return gcnew String(key);
|
||||
}
|
||||
}
|
||||
property CONVERTOR^ Val
|
||||
{
|
||||
CONVERTOR^ get()
|
||||
{
|
||||
return val;
|
||||
}
|
||||
}
|
||||
property I Index
|
||||
{
|
||||
I get()
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
// convenience functions for WPF databindings, which may hand back a
|
||||
// tuple_t object to C#, which can't get at the typedefs above.
|
||||
// this can cause trouble with getting at the properties; rather than
|
||||
// use reflection, you can just use these.
|
||||
System::String^ NameFor( tuple_t ^ tup )
|
||||
{
|
||||
return tup->Name;
|
||||
}
|
||||
value_t^ ValFor( tuple_t ^ tup )
|
||||
{
|
||||
return tup->Val;
|
||||
}
|
||||
*/
|
||||
|
||||
CONVERTOR ^GetValue( I idx )
|
||||
{
|
||||
return gcnew CONVERTOR(m_pInnerDict->Element(idx));
|
||||
}
|
||||
|
||||
CONVERTOR ^GetKey( I idx )
|
||||
{
|
||||
return gcnew String(m_pInnerDict->GetElementName(idx));
|
||||
}
|
||||
|
||||
property int Count
|
||||
{
|
||||
virtual int get() { return m_pInnerDict->Count(); }
|
||||
}
|
||||
|
||||
/// Iterator type. Walks over the UtlDict in the same order as its
|
||||
/// internal iterator. Returns a tuple of <key,value>, where key is
|
||||
/// always a string type (as in the utldict).
|
||||
/// TODO: can I make this a value struct so it doesn't need to be
|
||||
/// boxed/unboxed?
|
||||
ref struct Enumerator : public System::Collections::IEnumerator
|
||||
{
|
||||
typedef CCLIUtlDictEnumerable<T,I> owner_t;
|
||||
|
||||
Enumerator( dict_t *pDict ) : m_pEnumeratedDict(pDict), m_bIsBefore(true)
|
||||
{
|
||||
m_index = dict_t::InvalidIndex();
|
||||
}
|
||||
|
||||
inline bool IsValid()
|
||||
{
|
||||
return m_pEnumeratedDict->IsValidIndex(m_index);
|
||||
}
|
||||
|
||||
// IEnumerator interface
|
||||
virtual void Reset()
|
||||
{
|
||||
m_bIsBefore = true;
|
||||
m_index = m_pEnumeratedDict->First();
|
||||
}
|
||||
|
||||
// return false when falling off the end
|
||||
virtual bool MoveNext()
|
||||
{
|
||||
if (m_bIsBefore)
|
||||
{
|
||||
m_bIsBefore = false;
|
||||
m_index = m_pEnumeratedDict->First();
|
||||
return IsValid();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !IsValid() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_index = m_pEnumeratedDict->Next( m_index );
|
||||
return IsValid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
property System::Object^ Current
|
||||
{
|
||||
virtual System::Object^ get()
|
||||
{
|
||||
if ( IsValid() )
|
||||
{
|
||||
return gcnew tuple_t( m_pEnumeratedDict->GetElementName(m_index),
|
||||
m_pEnumeratedDict->Element(m_index),
|
||||
m_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw gcnew System::InvalidOperationException();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// data:
|
||||
protected:
|
||||
I m_index;
|
||||
dict_t *m_pEnumeratedDict;
|
||||
bool m_bIsBefore;
|
||||
};
|
||||
|
||||
virtual System::Collections::IEnumerator^ GetEnumerator()
|
||||
{
|
||||
return gcnew Enumerator(m_pInnerDict);
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
bool IsValidIndex( I idx ) { return m_pInnerDict->IsValidIndex(idx); }
|
||||
tuple_t ^GetElement( I i )
|
||||
{
|
||||
return gcnew tuple_t( m_pInnerDict->GetElementName(i),
|
||||
m_pInnerDict->Element(i),
|
||||
i);
|
||||
}
|
||||
|
||||
#pragma region ILIST interface
|
||||
|
||||
virtual int IndexOf( System::Object ^obj )
|
||||
{
|
||||
tuple_t ^t = dynamic_cast< tuple_t ^>(obj);
|
||||
if (t)
|
||||
{
|
||||
return t->index;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw gcnew System::ArrayTypeMismatchException();
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool Contains( System::Object ^obj )
|
||||
{
|
||||
tuple_t ^t = dynamic_cast< tuple_t ^>(obj);
|
||||
if (t)
|
||||
{
|
||||
return IsValidIndex(t->index);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw gcnew System::ArrayTypeMismatchException();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Insert(int index, System::Object ^ item)
|
||||
{
|
||||
throw gcnew NotSupportedException( "Read-only." );
|
||||
}
|
||||
|
||||
virtual void Remove(System::Object ^)
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
virtual void RemoveAt(int index)
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
virtual int Add(System::Object ^o)
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
virtual void Clear()
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
|
||||
virtual property Object ^ SyncRoot
|
||||
{
|
||||
Object ^ get() { return this; }
|
||||
}
|
||||
|
||||
virtual void CopyTo(Array ^arr, int start)
|
||||
{
|
||||
int stop = Count::get();
|
||||
for (int i = 0 ; i < stop ; ++i )
|
||||
{
|
||||
arr->SetValue((*this)[i],start+i);
|
||||
}
|
||||
// throw gcnew NotImplementedException();
|
||||
}
|
||||
|
||||
property System::Object ^ default[int]
|
||||
{
|
||||
virtual System::Object ^get( int index )
|
||||
{
|
||||
if (index < 0 || index > Count)
|
||||
{
|
||||
throw gcnew ArgumentOutOfRangeException();
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetElement(index);
|
||||
}
|
||||
|
||||
}
|
||||
virtual void set(int idx, System::Object ^s)
|
||||
{
|
||||
throw gcnew NotSupportedException("Read-only.");
|
||||
}
|
||||
}
|
||||
|
||||
property bool IsReadOnly
|
||||
{
|
||||
virtual bool get() { return true; }
|
||||
}
|
||||
|
||||
property bool IsFixedSize
|
||||
{
|
||||
virtual bool get() { return true; }
|
||||
}
|
||||
|
||||
property bool IsSynchronized
|
||||
{
|
||||
virtual bool get() { return true; }
|
||||
}
|
||||
|
||||
#pragma endregion
|
||||
|
||||
|
||||
#pragma region INotifyCollectionChanged interface
|
||||
|
||||
System::Collections::Specialized::NotifyCollectionChangedEventHandler ^m_CollectionChanged;
|
||||
virtual event System::Collections::Specialized::NotifyCollectionChangedEventHandler ^CollectionChanged
|
||||
{
|
||||
void add(System::Collections::Specialized::NotifyCollectionChangedEventHandler ^ d) {
|
||||
m_CollectionChanged += d;
|
||||
}
|
||||
void remove(System::Collections::Specialized::NotifyCollectionChangedEventHandler ^ d) {
|
||||
m_CollectionChanged -= d;
|
||||
}
|
||||
}
|
||||
virtual void OnCollectionChanged(System::Collections::Specialized::NotifyCollectionChangedEventArgs ^e)
|
||||
{
|
||||
if (m_CollectionChanged != nullptr)
|
||||
{
|
||||
m_CollectionChanged(this, e);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
|
||||
/// construct with a pointer at a UtlDict. Does not
|
||||
/// own the pointer; simply stores it internally.
|
||||
CCLIUtlDictEnumerable( dict_t *pInnerDict )
|
||||
//: m_CollectionChanged(gcnew System::Collections::Specialized::NotifyCollectionChangedEventHandler )
|
||||
{
|
||||
Init(pInnerDict);
|
||||
};
|
||||
CCLIUtlDictEnumerable( ) :m_pInnerDict(NULL)//
|
||||
//,m_CollectionChanged(gcnew System::Collections::Specialized::NotifyCollectionChangedEventHandler )
|
||||
{ };
|
||||
|
||||
void Init( dict_t *pInnerDict )
|
||||
{
|
||||
m_pInnerDict = pInnerDict;
|
||||
}
|
||||
|
||||
protected:
|
||||
dict_t *m_pInnerDict;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -0,0 +1,52 @@
|
||||
// ----------------------------------------- //
|
||||
// File generated by VPC //
|
||||
// ----------------------------------------- //
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\criteriaset.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\criteriaset.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\criteriaset.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\common\debug_lib_check.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\common\debug_lib_check.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\common\debug_lib_check.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_system.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_system.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_system.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_types.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_types.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_types.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_types_internal.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_types_internal.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\response_types_internal.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rr_response.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rr_response.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rr_response.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rr_speechconcept.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rr_speechconcept.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rr_speechconcept.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
||||
Source file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rrrlib.cpp
|
||||
Debug output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rrrlib.cpp
|
||||
Release output file: D:\Users\berta\Downloads\csgosourcecode\cstrike15_src\responserules\runtime\rrrlib.cpp
|
||||
Containing unity file:
|
||||
PCH file:
|
||||
|
470
responserules/runtime/criteriaset.cpp
Normal file
470
responserules/runtime/criteriaset.cpp
Normal file
@ -0,0 +1,470 @@
|
||||
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//===========================================================================//
|
||||
#include "rrbase.h"
|
||||
|
||||
#include "utlmap.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
using namespace ResponseRules;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Case-insensitive criteria symbol table
|
||||
//-----------------------------------------------------------------------------
|
||||
CUtlSymbolTable CriteriaSet::sm_CriteriaSymbols( 1024, 1024, true );
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *raw -
|
||||
// *key -
|
||||
// keylen -
|
||||
// *value -
|
||||
// valuelen -
|
||||
// *duration -
|
||||
// Output : static bool
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *SplitContext( const char *raw, char *key, int keylen, char *value, int valuelen, float *duration, const char *entireContext )
|
||||
{
|
||||
char *colon1 = Q_strstr( raw, ":" );
|
||||
if ( !colon1 )
|
||||
{
|
||||
DevMsg( "SplitContext: warning, ignoring context '%s', missing colon separator!\n", raw );
|
||||
*key = *value = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int len = colon1 - raw;
|
||||
Q_strncpy( key, raw, MIN( len + 1, keylen ) );
|
||||
key[ MIN( len, keylen - 1 ) ] = 0;
|
||||
|
||||
bool last = false;
|
||||
char *end = Q_strstr( colon1 + 1, "," );
|
||||
if ( !end )
|
||||
{
|
||||
int remaining = Q_strlen( colon1 + 1 );
|
||||
end = colon1 + 1 + remaining;
|
||||
last = true;
|
||||
}
|
||||
|
||||
char *colon2 = Q_strstr( colon1 + 1, ":" );
|
||||
if ( colon2 && ( colon2 < end ) )
|
||||
{
|
||||
if ( duration )
|
||||
*duration = atof( colon2 + 1 );
|
||||
|
||||
char durationStartChar = *(colon2 + 1);
|
||||
if ( durationStartChar < '0' || durationStartChar > '9' )
|
||||
{
|
||||
DevMsg( "SplitContext: warning, ignoring context '%s', missing comma separator! Entire context was '%s'.\n", raw, entireContext );
|
||||
*key = *value = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = MIN( colon2 - ( colon1 + 1 ), valuelen - 1 );
|
||||
Q_strncpy( value, colon1 + 1, len + 1 );
|
||||
value[ len ] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( duration )
|
||||
*duration = 0.0;
|
||||
|
||||
len = MIN( end - ( colon1 + 1 ), valuelen - 1 );
|
||||
Q_strncpy( value, colon1 + 1, len + 1 );
|
||||
value[ len ] = 0;
|
||||
}
|
||||
|
||||
return last ? NULL : end + 1;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CriteriaSet::CriteriaSet() : m_Lookup( 0, 0, CritEntry_t::LessFunc ), m_bOverrideOnAppend(true),
|
||||
m_nNumPrefixedContexts(0)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CriteriaSet::CriteriaSet( const CriteriaSet& src ) : m_Lookup( 0, 0, CritEntry_t::LessFunc ), m_nNumPrefixedContexts(src.m_nNumPrefixedContexts)
|
||||
{
|
||||
m_Lookup.EnsureCapacity( src.m_Lookup.Count() );
|
||||
for ( short i = src.m_Lookup.FirstInorder();
|
||||
i != src.m_Lookup.InvalidIndex();
|
||||
i = src.m_Lookup.NextInorder( i ) )
|
||||
{
|
||||
m_Lookup.Insert( src.m_Lookup[ i ] );
|
||||
}
|
||||
}
|
||||
|
||||
CriteriaSet::CriteriaSet( const char *criteria, const char *value ) : m_Lookup( 0, 0, CritEntry_t::LessFunc ), m_bOverrideOnAppend(true)
|
||||
{
|
||||
AppendCriteria(criteria,value);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Computes a symbol for the criteria
|
||||
//-----------------------------------------------------------------------------
|
||||
CriteriaSet::CritSymbol_t CriteriaSet::ComputeCriteriaSymbol( const char *criteria )
|
||||
{
|
||||
return sm_CriteriaSymbols.AddString( criteria );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Computes a symbol for the criteria
|
||||
//-----------------------------------------------------------------------------
|
||||
void CriteriaSet::AppendCriteria( CriteriaSet::CritSymbol_t criteria, const char *value, float weight )
|
||||
{
|
||||
int idx = FindCriterionIndex( criteria );
|
||||
if ( idx == -1 )
|
||||
{
|
||||
CritEntry_t entry;
|
||||
entry.criterianame = criteria;
|
||||
MEM_ALLOC_CREDIT();
|
||||
idx = m_Lookup.Insert( entry );
|
||||
if ( sm_CriteriaSymbols.String(criteria)[0] == kAPPLYTOWORLDPREFIX )
|
||||
{
|
||||
m_nNumPrefixedContexts += 1;
|
||||
}
|
||||
}
|
||||
else // criteria already existed
|
||||
{
|
||||
// bail out if override existing criteria is not allowed
|
||||
if ( !m_bOverrideOnAppend )
|
||||
return;
|
||||
}
|
||||
|
||||
CritEntry_t *entry = &m_Lookup[ idx ];
|
||||
entry->SetValue( value );
|
||||
entry->weight = weight;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *criteria -
|
||||
// "" -
|
||||
// 1.0f -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CriteriaSet::AppendCriteria( const char *pCriteriaName, const char *value /*= ""*/, float weight /*= 1.0f*/ )
|
||||
{
|
||||
CUtlSymbol criteria = ComputeCriteriaSymbol( pCriteriaName );
|
||||
AppendCriteria( criteria, value, weight );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *criteria -
|
||||
// "" -
|
||||
// 1.0f -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CriteriaSet::AppendCriteria( const char *criteria, float value, float weight /*= 1.0f*/ )
|
||||
{
|
||||
char buf[32];
|
||||
V_snprintf( buf, 32, "%f", value );
|
||||
AppendCriteria( criteria, buf, weight );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Removes criteria in a set
|
||||
//-----------------------------------------------------------------------------
|
||||
void CriteriaSet::RemoveCriteria( const char *criteria )
|
||||
{
|
||||
const int idx = FindCriterionIndex( criteria );
|
||||
if ( idx == -1 )
|
||||
return;
|
||||
|
||||
if ( criteria[0] == kAPPLYTOWORLDPREFIX )
|
||||
{
|
||||
Assert( m_nNumPrefixedContexts > 0 );
|
||||
m_nNumPrefixedContexts = isel( m_nNumPrefixedContexts - 1, m_nNumPrefixedContexts - 1, 0 );
|
||||
}
|
||||
RemoveCriteria( idx, false );
|
||||
}
|
||||
|
||||
// bTestForIndex tells us whether the calling function has already checked for a
|
||||
// $ prefix and decremented m_nNumPrefixedContexts appropriately (false),
|
||||
// or if this function should do that (true).
|
||||
void CriteriaSet::RemoveCriteria( int idx, bool bTestForPrefix )
|
||||
{
|
||||
Assert( m_Lookup.IsValidIndex(idx) );
|
||||
if ( bTestForPrefix )
|
||||
{
|
||||
if ( sm_CriteriaSymbols.String( m_Lookup[idx].criterianame )[0] == kAPPLYTOWORLDPREFIX )
|
||||
{
|
||||
Assert( m_nNumPrefixedContexts > 0 );
|
||||
m_nNumPrefixedContexts = isel( m_nNumPrefixedContexts - 1, m_nNumPrefixedContexts - 1, 0 );
|
||||
}
|
||||
}
|
||||
m_Lookup.RemoveAt( idx );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int CriteriaSet::GetCount() const
|
||||
{
|
||||
return m_Lookup.Count();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *name -
|
||||
// Output : int
|
||||
//-----------------------------------------------------------------------------
|
||||
int CriteriaSet::FindCriterionIndex( CritSymbol_t criteria ) const
|
||||
{
|
||||
CritEntry_t search;
|
||||
search.criterianame = criteria;
|
||||
int idx = m_Lookup.Find( search );
|
||||
return ( idx == m_Lookup.InvalidIndex() ) ? -1 : idx;
|
||||
}
|
||||
|
||||
int CriteriaSet::FindCriterionIndex( const char *name ) const
|
||||
{
|
||||
CUtlSymbol criteria = ComputeCriteriaSymbol( name );
|
||||
return FindCriterionIndex( criteria );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Returns the name symbol
|
||||
//-----------------------------------------------------------------------------
|
||||
CriteriaSet::CritSymbol_t CriteriaSet::GetNameSymbol( int nIndex ) const
|
||||
{
|
||||
if ( nIndex < 0 || nIndex >= (int)m_Lookup.Count() )
|
||||
return UTL_INVAL_SYMBOL;
|
||||
|
||||
const CritEntry_t *entry = &m_Lookup[ nIndex ];
|
||||
return entry->criterianame;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : index -
|
||||
// Output : char const
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CriteriaSet::GetName( int index ) const
|
||||
{
|
||||
if ( index < 0 || index >= (int)m_Lookup.Count() )
|
||||
return "";
|
||||
else
|
||||
{
|
||||
const char *pCriteriaName = sm_CriteriaSymbols.String( m_Lookup[ index ].criterianame );
|
||||
return pCriteriaName ? pCriteriaName : "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : index -
|
||||
// Output : char const
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CriteriaSet::GetValue( int index ) const
|
||||
{
|
||||
if ( index < 0 || index >= (int)m_Lookup.Count() )
|
||||
return "";
|
||||
|
||||
const CritEntry_t *entry = &m_Lookup[ index ];
|
||||
return entry->value ? entry->value : "";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : index -
|
||||
// Output : float
|
||||
//-----------------------------------------------------------------------------
|
||||
float CriteriaSet::GetWeight( int index ) const
|
||||
{
|
||||
if ( index < 0 || index >= (int)m_Lookup.Count() )
|
||||
return 1.0f;
|
||||
|
||||
const CritEntry_t *entry = &m_Lookup[ index ];
|
||||
return entry->weight;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Merge another criteria set into this one.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CriteriaSet::Merge( const CriteriaSet * RESTRICT otherCriteria )
|
||||
{
|
||||
Assert(otherCriteria);
|
||||
if (!otherCriteria)
|
||||
return;
|
||||
|
||||
// for now, just duplicate everything.
|
||||
int count = otherCriteria->GetCount();
|
||||
EnsureCapacity( count + GetCount() );
|
||||
for ( int i = 0 ; i < count ; ++i )
|
||||
{
|
||||
AppendCriteria( otherCriteria->GetNameSymbol(i), otherCriteria->GetValue(i), otherCriteria->GetWeight(i) );
|
||||
}
|
||||
}
|
||||
|
||||
void CriteriaSet::Merge( const char *modifiers ) // add criteria parsed from a text string
|
||||
{
|
||||
// Always include any optional modifiers
|
||||
if ( modifiers == NULL )
|
||||
return;
|
||||
|
||||
char copy_modifiers[ 255 ];
|
||||
const char *pCopy;
|
||||
char key[ 128 ] = { 0 };
|
||||
char value[ 128 ] = { 0 };
|
||||
|
||||
Q_strncpy( copy_modifiers, modifiers, sizeof( copy_modifiers ) );
|
||||
pCopy = copy_modifiers;
|
||||
|
||||
while( pCopy )
|
||||
{
|
||||
pCopy = SplitContext( pCopy, key, sizeof( key ), value, sizeof( value ), NULL, modifiers );
|
||||
|
||||
if( *key && *value )
|
||||
{
|
||||
AppendCriteria( key, value, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CriteriaSet::Describe() const
|
||||
{
|
||||
// build an alphabetized representation of the set for printing
|
||||
typedef CUtlMap<const char *, const CritEntry_t *> tMap;
|
||||
tMap m_TempMap( 0, m_Lookup.Count(), CaselessStringLessThan );
|
||||
|
||||
for ( short i = m_Lookup.FirstInorder(); i != m_Lookup.InvalidIndex(); i = m_Lookup.NextInorder( i ) )
|
||||
{
|
||||
const CritEntry_t *entry = &m_Lookup[ i ];
|
||||
|
||||
m_TempMap.Insert( sm_CriteriaSymbols.String( entry->criterianame ), entry );
|
||||
}
|
||||
|
||||
for ( tMap::IndexType_t i = m_TempMap.FirstInorder(); i != m_TempMap.InvalidIndex(); i = m_TempMap.NextInorder( i ) )
|
||||
{
|
||||
// const CritEntry_t *entry = &m_TempMap[ i ];
|
||||
// const char *pCriteriaName = sm_CriteriaSymbols.String( entry->criterianame );
|
||||
|
||||
const char *name;
|
||||
name = m_TempMap.Key( i );
|
||||
const CritEntry_t *entry = m_TempMap.Element( i );
|
||||
if ( entry->weight != 1.0f )
|
||||
{
|
||||
DevMsg( " %20s = '%s' (weight %f)\n", name, entry->value ? entry->value : "", entry->weight );
|
||||
}
|
||||
else
|
||||
{
|
||||
DevMsg( " %20s = '%s'\n", name, entry->value ? entry->value : "" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for ( short i = m_Lookup.FirstInorder(); i != m_Lookup.InvalidIndex(); i = m_Lookup.NextInorder( i ) )
|
||||
{
|
||||
const CritEntry_t *entry = &m_Lookup[ i ];
|
||||
|
||||
const char *pCriteriaName = sm_CriteriaSymbols.String( entry->criterianame );
|
||||
if ( entry->weight != 1.0f )
|
||||
{
|
||||
DevMsg( " %20s = '%s' (weight %f)\n", pCriteriaName, entry->value ? entry->value : "", entry->weight );
|
||||
}
|
||||
else
|
||||
{
|
||||
DevMsg( " %20s = '%s'\n", pCriteriaName, entry->value ? entry->value : "" );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void CriteriaSet::Reset()
|
||||
{
|
||||
m_Lookup.Purge();
|
||||
}
|
||||
|
||||
void CriteriaSet::WriteToEntity( CBaseEntity *pEntity )
|
||||
{
|
||||
#if 0
|
||||
if ( GetCount() < 1 )
|
||||
return;
|
||||
|
||||
for ( int i = Head() ; IsValidIndex(i); i = Next(i) )
|
||||
{
|
||||
pEntity->AddContext( GetName(i), GetValue(i), 0 );
|
||||
}
|
||||
#else
|
||||
AssertMsg( false, "CriteriaSet::WriteToEntity has not been ported from l4d2.\n" );
|
||||
#endif
|
||||
}
|
||||
|
||||
int CriteriaSet::InterceptWorldSetContexts( CriteriaSet * RESTRICT pFrom, CriteriaSet * RESTRICT pSetOnWorld )
|
||||
{
|
||||
// Assert( pFrom ); Assert( pTo ); Assert( pSetOnWorld );
|
||||
Assert( pSetOnWorld != pFrom );
|
||||
Assert( pSetOnWorld->GetCount() == 0 );
|
||||
|
||||
if ( pFrom->m_nNumPrefixedContexts == 0 )
|
||||
{
|
||||
// nothing needs to be done to it.
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
// save this off for later error checking.
|
||||
const int nPrefixedContexts = pFrom->m_nNumPrefixedContexts;
|
||||
#endif
|
||||
|
||||
// make enough space for the expected output quantity.
|
||||
pSetOnWorld->EnsureCapacity( pFrom->m_nNumPrefixedContexts );
|
||||
|
||||
// initialize a buffer with the "world" prefix (so we can use strncpy instead of snprintf and be much faster)
|
||||
char buf[80] = { 'w', 'o', 'r', 'l', 'd', '\0' };
|
||||
const unsigned int PREFIXLEN = 5; // strlen("world")
|
||||
|
||||
// create a second tree that has the appropriately renamed criteria,
|
||||
// then swap it into pFrom
|
||||
CriteriaSet rewrite;
|
||||
rewrite.EnsureCapacity( pFrom->GetCount() + 1 );
|
||||
|
||||
for ( int i = pFrom->Head(); pFrom->IsValidIndex(i); i = pFrom->Next(i) )
|
||||
{
|
||||
const char *pszName = pFrom->GetName( i );
|
||||
if ( pszName[0] == CriteriaSet::kAPPLYTOWORLDPREFIX )
|
||||
{ // redirect to the world contexts
|
||||
V_strncpy( buf+PREFIXLEN, pszName+1, sizeof(buf) - PREFIXLEN );
|
||||
rewrite.AppendCriteria( buf, pFrom->GetValue(i), pFrom->GetWeight(i) );
|
||||
pSetOnWorld->AppendCriteria( pszName+1, pFrom->GetValue(i), pFrom->GetWeight(i) );
|
||||
buf[PREFIXLEN] = 0;
|
||||
}
|
||||
else
|
||||
{ // does not need to be fiddled; do not write back to world
|
||||
rewrite.AppendCriteria( pFrom->GetNameSymbol(i), pFrom->GetValue(i), pFrom->GetWeight(i) );
|
||||
}
|
||||
}
|
||||
AssertMsg2( pSetOnWorld->GetCount() == nPrefixedContexts, "Count of $ persistent RR contexts is inconsistent (%d vs %d)! Call Elan.",
|
||||
pSetOnWorld->GetCount(), nPrefixedContexts );
|
||||
|
||||
pFrom->m_nNumPrefixedContexts = 0;
|
||||
pFrom->m_Lookup.Swap(rewrite.m_Lookup);
|
||||
return pSetOnWorld->GetCount();
|
||||
}
|
2708
responserules/runtime/response_system.cpp
Normal file
2708
responserules/runtime/response_system.cpp
Normal file
File diff suppressed because it is too large
Load Diff
260
responserules/runtime/response_types.cpp
Normal file
260
responserules/runtime/response_types.cpp
Normal file
@ -0,0 +1,260 @@
|
||||
//========= Copyright <20> 1996-2010, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Core types for the response rules -- criteria, responses, rules, and matchers.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "rrbase.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace ResponseRules;
|
||||
|
||||
|
||||
// bizarre function handed down from the misty days of yore
|
||||
// and the original response system. a lot of stuff uses it
|
||||
// and I can't be arsed to replace everything with the c stdlib
|
||||
// stuff
|
||||
namespace ResponseRules
|
||||
{
|
||||
extern const char *ResponseCopyString( const char *in );
|
||||
};
|
||||
|
||||
|
||||
//-------------------- MATCHER ----------------------------------------------
|
||||
|
||||
Matcher::Matcher()
|
||||
{
|
||||
valid = false;
|
||||
isnumeric = false;
|
||||
notequal = false;
|
||||
usemin = false;
|
||||
minequals = false;
|
||||
usemax = false;
|
||||
maxequals = false;
|
||||
maxval = 0.0f;
|
||||
minval = 0.0f;
|
||||
|
||||
token = UTL_INVAL_SYMBOL;
|
||||
rawtoken = UTL_INVAL_SYMBOL;
|
||||
}
|
||||
|
||||
void Matcher::Describe( void )
|
||||
{
|
||||
if ( !valid )
|
||||
{
|
||||
DevMsg( " invalid!\n" );
|
||||
return;
|
||||
}
|
||||
char sz[ 128 ];
|
||||
|
||||
sz[ 0] = 0;
|
||||
int minmaxcount = 0;
|
||||
if ( usemin )
|
||||
{
|
||||
Q_snprintf( sz, sizeof( sz ), ">%s%.3f", minequals ? "=" : "", minval );
|
||||
minmaxcount++;
|
||||
}
|
||||
if ( usemax )
|
||||
{
|
||||
char sz2[ 128 ];
|
||||
Q_snprintf( sz2, sizeof( sz2 ), "<%s%.3f", maxequals ? "=" : "", maxval );
|
||||
|
||||
if ( minmaxcount > 0 )
|
||||
{
|
||||
Q_strncat( sz, " and ", sizeof( sz ), COPY_ALL_CHARACTERS );
|
||||
}
|
||||
Q_strncat( sz, sz2, sizeof( sz ), COPY_ALL_CHARACTERS );
|
||||
minmaxcount++;
|
||||
}
|
||||
|
||||
if ( minmaxcount >= 1 )
|
||||
{
|
||||
DevMsg( " matcher: %s\n", sz );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( notequal )
|
||||
{
|
||||
DevMsg( " matcher: !=%s\n", GetToken() );
|
||||
return;
|
||||
}
|
||||
|
||||
DevMsg( " matcher: ==%s\n", GetToken() );
|
||||
}
|
||||
|
||||
void Matcher::SetToken( char const *s )
|
||||
{
|
||||
token = g_RS.AddString( s );
|
||||
}
|
||||
|
||||
void Matcher::SetRaw( char const *raw )
|
||||
{
|
||||
rawtoken = g_RS.AddString( raw );
|
||||
}
|
||||
|
||||
char const *Matcher::GetToken()
|
||||
{
|
||||
if ( token.IsValid() )
|
||||
{
|
||||
return g_RS.String( token );
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
char const *Matcher::GetRaw()
|
||||
{
|
||||
if ( rawtoken.IsValid() )
|
||||
{
|
||||
return g_RS.String( rawtoken );
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//-------------------- CRITERIA ----------------------------------------------
|
||||
|
||||
Criteria::Criteria()
|
||||
{
|
||||
value = NULL;
|
||||
weight.SetFloat( 1.0f );
|
||||
required = false;
|
||||
}
|
||||
Criteria::Criteria(const Criteria& src )
|
||||
{
|
||||
operator=( src );
|
||||
}
|
||||
|
||||
Criteria::~Criteria()
|
||||
{
|
||||
// do nothing because we don't own name and value anymore
|
||||
}
|
||||
|
||||
Criteria& Criteria::operator =(const Criteria& src )
|
||||
{
|
||||
if ( this == &src )
|
||||
return *this;
|
||||
|
||||
nameSym = src.nameSym;
|
||||
value = ResponseCopyString( src.value );
|
||||
weight = src.weight;
|
||||
required = src.required;
|
||||
|
||||
matcher = src.matcher;
|
||||
|
||||
int c = src.subcriteria.Count();
|
||||
subcriteria.EnsureCapacity( c );
|
||||
for ( int i = 0; i < c; i++ )
|
||||
{
|
||||
subcriteria.AddToTail( src.subcriteria[ i ] );
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//-------------------- RESPONSE ----------------------------------------------
|
||||
|
||||
|
||||
|
||||
ParserResponse::ParserResponse() : m_followup()
|
||||
{
|
||||
type = RESPONSE_NONE;
|
||||
value = NULL;
|
||||
weight.SetFloat( 1.0f );
|
||||
depletioncount = 0;
|
||||
first = false;
|
||||
last = false;
|
||||
}
|
||||
|
||||
ParserResponse& ParserResponse::operator =( const ParserResponse& src )
|
||||
{
|
||||
if ( this == &src )
|
||||
return *this;
|
||||
weight = src.weight;
|
||||
type = src.type;
|
||||
value = ResponseCopyString( src.value );
|
||||
depletioncount = src.depletioncount;
|
||||
first = src.first;
|
||||
last = src.last;
|
||||
params = src.params;
|
||||
|
||||
m_followup.followup_concept = ResponseCopyString(src.m_followup.followup_concept);
|
||||
m_followup.followup_contexts = ResponseCopyString(src.m_followup.followup_contexts);
|
||||
m_followup.followup_target = ResponseCopyString(src.m_followup.followup_target);
|
||||
m_followup.followup_entityioinput = ResponseCopyString(src.m_followup.followup_entityioinput);
|
||||
m_followup.followup_entityiotarget = ResponseCopyString(src.m_followup.followup_entityiotarget);
|
||||
m_followup.followup_delay = src.m_followup.followup_delay;
|
||||
m_followup.followup_entityiodelay = src.m_followup.followup_entityiodelay;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ParserResponse::ParserResponse( const ParserResponse& src )
|
||||
{
|
||||
operator=( src );
|
||||
}
|
||||
|
||||
ParserResponse::~ParserResponse()
|
||||
{
|
||||
// nothing to do, since we don't own
|
||||
// the strings anymore
|
||||
}
|
||||
|
||||
// ------------ RULE ---------------
|
||||
|
||||
Rule::Rule() : m_nForceWeight(0)
|
||||
{
|
||||
m_bMatchOnce = false;
|
||||
m_bEnabled = true;
|
||||
m_szContext = NULL;
|
||||
m_bApplyContextToWorld = false;
|
||||
}
|
||||
|
||||
Rule& Rule::operator =( const Rule& src )
|
||||
{
|
||||
if ( this == &src )
|
||||
return *this;
|
||||
|
||||
int i;
|
||||
int c;
|
||||
|
||||
c = src.m_Criteria.Count();
|
||||
m_Criteria.EnsureCapacity( c );
|
||||
for ( i = 0; i < c; i++ )
|
||||
{
|
||||
m_Criteria.AddToTail( src.m_Criteria[ i ] );
|
||||
}
|
||||
|
||||
c = src.m_Responses.Count();
|
||||
m_Responses.EnsureCapacity( c );
|
||||
for ( i = 0; i < c; i++ )
|
||||
{
|
||||
m_Responses.AddToTail( src.m_Responses[ i ] );
|
||||
}
|
||||
|
||||
SetContext( src.m_szContext );
|
||||
m_bMatchOnce = src.m_bMatchOnce;
|
||||
m_bEnabled = src.m_bEnabled;
|
||||
m_bApplyContextToWorld = src.m_bApplyContextToWorld;
|
||||
m_nForceWeight = src.m_nForceWeight;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rule::Rule( const Rule& src )
|
||||
{
|
||||
operator=(src);
|
||||
}
|
||||
|
||||
Rule::~Rule()
|
||||
{
|
||||
}
|
||||
|
||||
void Rule::SetContext( const char *context )
|
||||
{
|
||||
// we don't own the data we point to, so just update pointer
|
||||
m_szContext = ResponseCopyString( context );
|
||||
}
|
||||
|
||||
|
120
responserules/runtime/response_types_internal.cpp
Normal file
120
responserules/runtime/response_types_internal.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
//========= Copyright <20> 1996-2010, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Core types for the response rules -- criteria, responses, rules, and matchers.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "rrbase.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
using namespace ResponseRules;
|
||||
|
||||
|
||||
|
||||
|
||||
ResponseRulePartition::ResponseRulePartition()
|
||||
{
|
||||
Assert(true);
|
||||
COMPILE_TIME_ASSERT( kIDX_ELEM_MASK < (1 << 16) );
|
||||
COMPILE_TIME_ASSERT( (kIDX_ELEM_MASK & (kIDX_ELEM_MASK + 1)) == 0 ); /// assert is power of two minus one
|
||||
}
|
||||
|
||||
ResponseRulePartition::~ResponseRulePartition()
|
||||
{
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
ResponseRulePartition::tIndex ResponseRulePartition::IndexFromDictElem( tRuleDict* pDict, int elem )
|
||||
{
|
||||
Assert( pDict );
|
||||
// If this fails, you've tried to build an index for a rule that's not stored
|
||||
// in this partition
|
||||
Assert( pDict >= m_RuleParts && pDict < m_RuleParts + N_RESPONSE_PARTITIONS );
|
||||
AssertMsg1( elem <= kIDX_ELEM_MASK, "A rule dictionary has %d elements; this exceeds the 255 that can be packed into an index.\n", elem );
|
||||
|
||||
int bucket = pDict - m_RuleParts;
|
||||
return ( bucket << 16 ) | ( elem & kIDX_ELEM_MASK ); // this is a native op on PPC
|
||||
}
|
||||
|
||||
|
||||
char const *ResponseRulePartition::GetElementName( const tIndex &i ) const
|
||||
{
|
||||
Assert( IsValid(i) );
|
||||
return m_RuleParts[ BucketFromIdx(i) ].GetElementName( PartFromIdx(i) );
|
||||
}
|
||||
|
||||
|
||||
int ResponseRulePartition::Count( void )
|
||||
{
|
||||
int count = 0 ;
|
||||
for ( int bukkit = 0 ; bukkit < N_RESPONSE_PARTITIONS ; ++bukkit )
|
||||
{
|
||||
count += m_RuleParts[bukkit].Count();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void ResponseRulePartition::RemoveAll( void )
|
||||
{
|
||||
for ( int bukkit = 0 ; bukkit < N_RESPONSE_PARTITIONS ; ++bukkit )
|
||||
{
|
||||
for ( int i = m_RuleParts[bukkit].FirstInorder(); i != m_RuleParts[bukkit].InvalidIndex(); i = m_RuleParts[bukkit].NextInorder( i ) )
|
||||
{
|
||||
delete m_RuleParts[bukkit][ i ];
|
||||
}
|
||||
m_RuleParts[bukkit].RemoveAll();
|
||||
}
|
||||
}
|
||||
|
||||
// don't bucket "subject" criteria that prefix with operators, since stripping all that out again would
|
||||
// be a big pain, and the most important rules that need subjects are tlk_remarks anyway.
|
||||
static inline bool CanBucketBySubject( const char * RESTRICT pszSubject )
|
||||
{
|
||||
return pszSubject &&
|
||||
( ( pszSubject[0] >= 'A' && pszSubject[0] <= 'Z' ) ||
|
||||
( pszSubject[0] >= 'a' && pszSubject[0] <= 'z' ) );
|
||||
}
|
||||
|
||||
ResponseRulePartition::tRuleDict &ResponseRulePartition::GetDictForRule( CResponseSystem *pSystem, Rule *pRule )
|
||||
{
|
||||
const static CUtlSymbol kWHO = CriteriaSet::ComputeCriteriaSymbol("Who");
|
||||
const static CUtlSymbol kCONCEPT = CriteriaSet::ComputeCriteriaSymbol("Concept");
|
||||
const static CUtlSymbol kSUBJECT = CriteriaSet::ComputeCriteriaSymbol("Subject");
|
||||
|
||||
const char *pszSpeaker = pRule->GetValueForRuleCriterionByName( pSystem, kWHO );
|
||||
const char *pszConcept = pRule->GetValueForRuleCriterionByName( pSystem, kCONCEPT );
|
||||
const Criteria *pSubjCrit = pRule->GetPointerForRuleCriterionByName( pSystem, kSUBJECT );
|
||||
|
||||
return m_RuleParts[
|
||||
GetBucketForSpeakerAndConcept( pszSpeaker, pszConcept,
|
||||
( pSubjCrit && pSubjCrit->required && CanBucketBySubject(pSubjCrit->value) ) ?
|
||||
pSubjCrit->value :
|
||||
NULL )
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
void ResponseRulePartition::GetDictsForCriteria( CUtlVectorFixed< ResponseRulePartition::tRuleDict *, 2 > *pResult, const CriteriaSet &criteria )
|
||||
{
|
||||
pResult->RemoveAll();
|
||||
pResult->EnsureCapacity( 2 );
|
||||
|
||||
// get the values for Who and Concept, which are what we bucket on
|
||||
int speakerIdx = criteria.FindCriterionIndex( "Who" );
|
||||
const char *pszSpeaker = speakerIdx != -1 ? criteria.GetValue( speakerIdx ) : NULL ;
|
||||
|
||||
int conceptIdx = criteria.FindCriterionIndex( "Concept" );
|
||||
const char *pszConcept = conceptIdx != -1 ? criteria.GetValue( conceptIdx ) : NULL ;
|
||||
|
||||
int subjectIdx = criteria.FindCriterionIndex( "Subject" );
|
||||
const char *pszSubject = subjectIdx != -1 ? criteria.GetValue( subjectIdx ) : NULL ;
|
||||
|
||||
pResult->AddToTail( &m_RuleParts[ GetBucketForSpeakerAndConcept(pszSpeaker, pszConcept, pszSubject) ] );
|
||||
// also try the rules not specifying subject
|
||||
pResult->AddToTail( &m_RuleParts[ GetBucketForSpeakerAndConcept(pszSpeaker, pszConcept, NULL) ] );
|
||||
|
||||
}
|
48
responserules/runtime/responserules_runtime.vpc
Normal file
48
responserules/runtime/responserules_runtime.vpc
Normal file
@ -0,0 +1,48 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// RESPONSERULES_RUNTIME.VPC
|
||||
//
|
||||
// Project Script
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
$Macro SRCDIR "..\.."
|
||||
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
|
||||
|
||||
$Configuration
|
||||
{
|
||||
$Compiler
|
||||
{
|
||||
$AdditionalIncludeDirectories "$BASE;$SRCDIR\public"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$Project "responserules_runtime"
|
||||
{
|
||||
$Folder "Header Files"
|
||||
{
|
||||
$file "$SRCDIR\public\responserules\response_types.h"
|
||||
$file "$SRCDIR\public\responserules\response_host_interface.h"
|
||||
$file "$SRCDIR\public\responserules\rr_speechconcept.h"
|
||||
$file "$SRCDIR\common\responserules\response_types_internal.h"
|
||||
$file "$SRCDIR\responserules\responserules_cli\response_system.h"
|
||||
$file "rrbase.h"
|
||||
}
|
||||
|
||||
|
||||
$Folder "Source Files"
|
||||
{
|
||||
$file "rrrlib.cpp"
|
||||
$file "response_types.cpp"
|
||||
$file "response_types_internal.cpp"
|
||||
$file "response_system.cpp"
|
||||
$file "rr_speechconcept.cpp"
|
||||
$file "rr_response.cpp"
|
||||
$file "criteriaset.cpp"
|
||||
}
|
||||
|
||||
$Folder "Public Header Files"
|
||||
{
|
||||
$File "$SRCDIR\public\tier2\interval.h"
|
||||
|
||||
}
|
||||
}
|
13
responserules/runtime/responserules_runtime.vpc.vpc_cache
Normal file
13
responserules/runtime/responserules_runtime.vpc.vpc_cache
Normal file
@ -0,0 +1,13 @@
|
||||
"vpc_cache"
|
||||
{
|
||||
"CacheVersion" "1"
|
||||
"win32"
|
||||
{
|
||||
"CRCFile" "responserules_runtime.vcxproj.vpc_crc"
|
||||
"OutputFiles"
|
||||
{
|
||||
"0" "responserules_runtime.vcxproj"
|
||||
"1" "responserules_runtime.vcxproj.filters"
|
||||
}
|
||||
}
|
||||
}
|
14
responserules/runtime/rr_convars.cpp
Normal file
14
responserules/runtime/rr_convars.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
//========= Copyright <20> 1996-2010, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Convars used by the response rule system.
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "rrbase.h"
|
||||
#include <convar.h>
|
||||
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
311
responserules/runtime/rr_response.cpp
Normal file
311
responserules/runtime/rr_response.cpp
Normal file
@ -0,0 +1,311 @@
|
||||
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//
|
||||
//===========================================================================//
|
||||
#include "rrbase.h"
|
||||
|
||||
#include <tier2/interval.h>
|
||||
|
||||
/*
|
||||
#include "AI_Criteria.h"
|
||||
#include "ai_speech.h"
|
||||
#include <keyvalues.h>
|
||||
#include "engine/IEngineSound.h"
|
||||
*/
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
using namespace ResponseRules;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CRR_Response::CRR_Response() : m_fMatchScore(0)
|
||||
{
|
||||
m_Type = ResponseRules::RESPONSE_NONE;
|
||||
m_szResponseName[0] = 0;
|
||||
m_szMatchingRule[0]=0;
|
||||
m_szContext = NULL;
|
||||
m_bApplyContextToWorld = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
CRR_Response::CRR_Response( const CRR_Response &from ) : m_fMatchScore(0)
|
||||
{
|
||||
// Assert( (void*)(&m_Type) == (void*)this );
|
||||
Invalidate();
|
||||
memcpy( this, &from, sizeof(*this) );
|
||||
m_szContext = NULL;
|
||||
SetContext( from.m_szContext );
|
||||
m_bApplyContextToWorld = from.m_bApplyContextToWorld;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
CRR_Response &CRR_Response::operator=( const CRR_Response &from )
|
||||
{
|
||||
// Assert( (void*)(&m_Type) == (void*)this );
|
||||
Invalidate();
|
||||
memcpy( this, &from, sizeof(*this) );
|
||||
m_szContext = NULL;
|
||||
SetContext( from.m_szContext );
|
||||
m_bApplyContextToWorld = from.m_bApplyContextToWorld;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
CRR_Response::~CRR_Response()
|
||||
{
|
||||
if (m_szContext)
|
||||
delete[] m_szContext;
|
||||
}
|
||||
|
||||
void CRR_Response::Invalidate()
|
||||
{
|
||||
if (m_szContext)
|
||||
{
|
||||
delete[] m_szContext;
|
||||
m_szContext = NULL;
|
||||
}
|
||||
m_Type = ResponseRules::RESPONSE_NONE;
|
||||
m_szResponseName[0] = 0;
|
||||
// not really necessary:
|
||||
/*
|
||||
m_szMatchingRule[0]=0;
|
||||
m_szContext = NULL;
|
||||
m_bApplyContextToWorld = false;
|
||||
*/
|
||||
}
|
||||
|
||||
// please do not new or delete CRR_Responses.
|
||||
void CRR_Response::operator delete(void* p)
|
||||
{
|
||||
AssertMsg(false, "DO NOT new or delete CRR_Response s.");
|
||||
free(p);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : *response -
|
||||
// *criteria -
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRR_Response::Init( ResponseType_t type, const char *responseName, const ResponseParams& responseparams, const char *ruleName, const char *applyContext, bool bApplyContextToWorld )
|
||||
{
|
||||
m_Type = type;
|
||||
Q_strncpy( m_szResponseName, responseName, sizeof( m_szResponseName ) );
|
||||
// Copy underlying criteria
|
||||
Q_strncpy( m_szMatchingRule, ruleName ? ruleName : "NULL", sizeof( m_szMatchingRule ) );
|
||||
m_Params = responseparams;
|
||||
SetContext( applyContext );
|
||||
m_bApplyContextToWorld = bApplyContextToWorld;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Debug-print the response. You can optionally pass in the criteria
|
||||
// used to come up with this response (usually present in the calling function)
|
||||
// if you want to print that as well. DO NOT store the entire criteria set in
|
||||
// CRR_Response just to make this debug print cleaner.
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRR_Response::Describe( const CriteriaSet *pDebugCriteria )
|
||||
{
|
||||
if ( pDebugCriteria )
|
||||
{
|
||||
DevMsg( "Search criteria:\n" );
|
||||
pDebugCriteria->Describe();
|
||||
}
|
||||
|
||||
if ( m_szMatchingRule[ 0 ] )
|
||||
{
|
||||
DevMsg( "Matched rule '%s', ", m_szMatchingRule );
|
||||
}
|
||||
if ( m_szContext )
|
||||
{
|
||||
DevMsg( "Contexts to set '%s' on %s, ", m_szContext, m_bApplyContextToWorld ? "world" : "speaker" );
|
||||
}
|
||||
|
||||
DevMsg( "response %s = '%s'\n", DescribeResponse( (ResponseType_t)m_Type ), m_szResponseName );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : char const
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRR_Response::GetName( char *buf, size_t buflen ) const
|
||||
{
|
||||
Q_strncpy( buf, m_szResponseName, buflen );
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : char const
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRR_Response::GetResponse( char *buf, size_t buflen ) const
|
||||
{
|
||||
GetName( buf, buflen );
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Input : type -
|
||||
// Output : char const
|
||||
//-----------------------------------------------------------------------------
|
||||
const char *CRR_Response::DescribeResponse( ResponseType_t type )
|
||||
{
|
||||
if ( (int)type < 0 || (int)type >= ResponseRules::NUM_RESPONSES )
|
||||
{
|
||||
Assert( 0 );
|
||||
return "???CRR_Response bogus index";
|
||||
}
|
||||
|
||||
switch( type )
|
||||
{
|
||||
default:
|
||||
{
|
||||
Assert( 0 );
|
||||
}
|
||||
// Fall through
|
||||
case ResponseRules::RESPONSE_NONE:
|
||||
return "RESPONSE_NONE";
|
||||
case ResponseRules::RESPONSE_SPEAK:
|
||||
return "RESPONSE_SPEAK";
|
||||
case ResponseRules::RESPONSE_SENTENCE:
|
||||
return "RESPONSE_SENTENCE";
|
||||
case ResponseRules::RESPONSE_SCENE:
|
||||
return "RESPONSE_SCENE";
|
||||
case ResponseRules::RESPONSE_RESPONSE:
|
||||
return "RESPONSE_RESPONSE";
|
||||
case ResponseRules::RESPONSE_PRINT:
|
||||
return "RESPONSE_PRINT";
|
||||
case ResponseRules::RESPONSE_ENTITYIO:
|
||||
return "RESPONSE_ENTITYIO";
|
||||
}
|
||||
|
||||
return "RESPONSE_NONE";
|
||||
}
|
||||
|
||||
/*
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRR_Response::Release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
// Output : soundlevel_t
|
||||
//-----------------------------------------------------------------------------
|
||||
soundlevel_t CRR_Response::GetSoundLevel() const
|
||||
{
|
||||
if ( m_Params.flags & ResponseParams::RG_SOUNDLEVEL )
|
||||
{
|
||||
return (soundlevel_t)m_Params.soundlevel;
|
||||
}
|
||||
|
||||
return SNDLVL_TALKING;
|
||||
}
|
||||
|
||||
float CRR_Response::GetRespeakDelay( void ) const
|
||||
{
|
||||
if ( m_Params.flags & ResponseParams::RG_RESPEAKDELAY )
|
||||
{
|
||||
interval_t temp;
|
||||
m_Params.respeakdelay.ToInterval( temp );
|
||||
return RandomInterval( temp );
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float CRR_Response::GetWeaponDelay( void ) const
|
||||
{
|
||||
if ( m_Params.flags & ResponseParams::RG_WEAPONDELAY )
|
||||
{
|
||||
interval_t temp;
|
||||
m_Params.weapondelay.ToInterval( temp );
|
||||
return RandomInterval( temp );
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
bool CRR_Response::GetSpeakOnce( void ) const
|
||||
{
|
||||
if ( m_Params.flags & ResponseParams::RG_SPEAKONCE )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CRR_Response::ShouldntUseScene( void ) const
|
||||
{
|
||||
return ( m_Params.flags & ResponseParams::RG_DONT_USE_SCENE ) != 0;
|
||||
}
|
||||
|
||||
bool CRR_Response::ShouldBreakOnNonIdle( void ) const
|
||||
{
|
||||
return ( m_Params.flags & ResponseParams::RG_STOP_ON_NONIDLE ) != 0;
|
||||
}
|
||||
|
||||
int CRR_Response::GetOdds( void ) const
|
||||
{
|
||||
if ( m_Params.flags & ResponseParams::RG_ODDS )
|
||||
{
|
||||
return m_Params.odds;
|
||||
}
|
||||
return 100;
|
||||
}
|
||||
|
||||
float CRR_Response::GetDelay() const
|
||||
{
|
||||
if ( m_Params.flags & ResponseParams::RG_DELAYAFTERSPEAK )
|
||||
{
|
||||
interval_t temp;
|
||||
m_Params.delay.ToInterval( temp );
|
||||
return RandomInterval( temp );
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
float CRR_Response::GetPreDelay() const
|
||||
{
|
||||
if ( m_Params.flags & ResponseParams::RG_DELAYBEFORESPEAK )
|
||||
{
|
||||
interval_t temp;
|
||||
m_Params.predelay.ToInterval( temp );
|
||||
return RandomInterval( temp );
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Sets context string
|
||||
// Output : void
|
||||
//-----------------------------------------------------------------------------
|
||||
void CRR_Response::SetContext( const char *context )
|
||||
{
|
||||
if (m_szContext)
|
||||
{
|
||||
delete[] m_szContext;
|
||||
m_szContext = NULL;
|
||||
}
|
||||
|
||||
if ( context )
|
||||
{
|
||||
int len = Q_strlen( context );
|
||||
m_szContext = new char[ len + 1 ];
|
||||
Q_memcpy( m_szContext, context, len );
|
||||
m_szContext[ len ] = 0;
|
||||
}
|
||||
}
|
73
responserules/runtime/rr_speechconcept.cpp
Normal file
73
responserules/runtime/rr_speechconcept.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#include "rrbase.h"
|
||||
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include <tier0/memdbgon.h>
|
||||
|
||||
#if RR_CONCEPTS_ARE_STRINGS
|
||||
#pragma error("RR_CONCEPTS_ARE_STRINGS no longer supported")
|
||||
#else
|
||||
|
||||
using namespace ResponseRules;
|
||||
|
||||
// Used to turn ad-hoc concept from strings into numbers.
|
||||
CRR_ConceptSymbolTable *g_pRRConceptTable = NULL;
|
||||
|
||||
// Q&D hack to defer initialization of concept table until I can figure out where it
|
||||
// really needs to come from.
|
||||
static void InitializeRRConceptTable()
|
||||
{
|
||||
if (g_pRRConceptTable == NULL)
|
||||
{
|
||||
g_pRRConceptTable = new CRR_ConceptSymbolTable( 64, 64, true );
|
||||
}
|
||||
}
|
||||
|
||||
// construct from string
|
||||
CRR_Concept::CRR_Concept(const char *fromString)
|
||||
{
|
||||
InitializeRRConceptTable();
|
||||
m_iConcept = g_pRRConceptTable->AddString(fromString);
|
||||
}
|
||||
|
||||
CRR_Concept &CRR_Concept::operator=(const char *fromString)
|
||||
{
|
||||
InitializeRRConceptTable();
|
||||
m_iConcept = g_pRRConceptTable->AddString(fromString);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CRR_Concept::operator==(const char *pszConcept)
|
||||
{
|
||||
int otherConcept = g_pRRConceptTable->Find(pszConcept);
|
||||
return ( otherConcept != UTL_INVAL_SYMBOL && otherConcept == m_iConcept );
|
||||
}
|
||||
|
||||
const char *CRR_Concept::GetStringConcept() const
|
||||
{
|
||||
InitializeRRConceptTable();
|
||||
AssertMsg( m_iConcept.IsValid(), "AI Concept has invalid string symbol.\n" );
|
||||
const char * retval = g_pRRConceptTable->String(m_iConcept);
|
||||
AssertMsg( retval, "An RR_Concept couldn't find its string in the symbol table!\n" );
|
||||
if (retval == NULL)
|
||||
{
|
||||
Warning( "An RR_Concept couldn't find its string in the symbol table!\n" );
|
||||
retval = "";
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char *CRR_Concept::GetStringForGenericId(tGenericId genericId)
|
||||
{
|
||||
InitializeRRConceptTable();
|
||||
return g_pRRConceptTable->String(genericId);
|
||||
}
|
||||
|
||||
#endif
|
59
responserules/runtime/rrbase.h
Normal file
59
responserules/runtime/rrbase.h
Normal file
@ -0,0 +1,59 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef RRBASE_H
|
||||
#define RRBASE_H
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
// Silence certain warnings
|
||||
// #pragma warning(disable : 4244) // int or float down-conversion
|
||||
// #pragma warning(disable : 4305) // int or float data truncation
|
||||
// #pragma warning(disable : 4201) // nameless struct/union
|
||||
// #pragma warning(disable : 4511) // copy constructor could not be generated
|
||||
// #pragma warning(disable : 4675) // resolved overload was found by argument dependent lookup
|
||||
#endif
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define DEBUG 1
|
||||
#endif
|
||||
|
||||
// Misc C-runtime library headers
|
||||
#include <math.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// tier 0
|
||||
#include "tier0/dbg.h"
|
||||
#include "tier0/platform.h"
|
||||
#include "basetypes.h"
|
||||
|
||||
// tier 1
|
||||
#include "tier1/strtools.h"
|
||||
#include "utlvector.h"
|
||||
#include "utlsymbol.h"
|
||||
|
||||
// tier 2
|
||||
#include "string_t.h"
|
||||
|
||||
// Shared engine/DLL constants
|
||||
#include "const.h"
|
||||
#include "edict.h"
|
||||
|
||||
// app
|
||||
#if defined(_GAMECONSOLE)
|
||||
#define DISABLE_DEBUG_HISTORY 1
|
||||
#endif
|
||||
|
||||
#include "responserules/response_types.h"
|
||||
#include "responserules/response_types_internal.h"
|
||||
#include "responserules/response_host_interface.h"
|
||||
|
||||
|
||||
#endif // CBASE_H
|
13
responserules/runtime/rrrlib.cpp
Normal file
13
responserules/runtime/rrrlib.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
/// PLACEHOLDER FILE FOR RESPONSE RULES RUNTIME LIBRARY
|
||||
|
||||
#include "rrbase.h"
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
namespace ResponseRules
|
||||
{
|
||||
/// Custom symbol table for the response rules.
|
||||
CUtlSymbolTable g_RS;
|
||||
};
|
11
responserules/runtime/stdafx.cpp
Normal file
11
responserules/runtime/stdafx.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Builds the precompiled header for the game DLL
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
|
||||
#include "rrbase.h"
|
||||
|
||||
// NOTE: DO NOT ADD ANY CODE OR HEADERS TO THIS FILE!!!
|
2
responserules/runtime/vsi.nul
Normal file
2
responserules/runtime/vsi.nul
Normal file
@ -0,0 +1,2 @@
|
||||
SN Visual Studio Integration
|
||||
IMPORTANT: Do not remove the custom build step for this file
|
Reference in New Issue
Block a user