port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
<UserControl x:Class="Aiwaz.Editor.Controls.AiwazViewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms">
<Grid>
<WindowsFormsHost>
<wf:UserControl x:Name="RenderTarget" Resize="RenderTarget_Resize"/>
</WindowsFormsHost>
</Grid>
</UserControl>

View File

@@ -0,0 +1,407 @@
using System;
using System.Collections.Generic;
using System.Linq;
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 Aiwaz.Resources;
using System.Windows.Threading;
using Aiwaz.Core;
using Aiwaz.Contracts;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using SlimDX;
namespace Aiwaz.Editor.Controls
{
/// <summary>
/// Interaction logic for AiwazViewControl.xaml
/// </summary>
public partial class AiwazViewControl : System.Windows.Controls.UserControl
{
#region Win32
public static Point CorrectGetPosition(Visual relativeTo)
{
Win32Point w32Mouse = new Win32Point();
GetCursorPos(ref w32Mouse);
return relativeTo.PointFromScreen(new Point(w32Mouse.X, w32Mouse.Y));
}
[StructLayout(LayoutKind.Sequential)]
internal struct Win32Point
{
public Int32 X;
public Int32 Y;
};
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool GetCursorPos(ref Win32Point pt);
#endregion
private DateTime lastPerformCalledTime = DateTime.UtcNow;
private bool rightButtonPressed;
private bool leftButtonPressed;
private bool moveThresholdReached;
private Point lastMousePosition;
private int desiredFPS = 30;
private DispatcherTimer renderTimer;
private RenderCommandNode mainRootNode;
private RenderCommandNode rootNode;
private Shader selectionShader;
private RenderCommandNode selectionMarkerNode;
private PickableResourceInfo selectedResourceInfo;
public delegate void PerformCalledDelegate(object sender, TimeSpan elapsedTime);
public delegate void SelectedResourceChangedDelegate(object sender, PickableResourceInfo newSelectedResourceInfo);
public event PerformCalledDelegate PerformCalled;
public event SelectedResourceChangedDelegate SelectedResourceChanged;
public AiwazViewControl()
{
InitializeComponent();
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
return;
this.SwapChain = new SwapChain(RenderTarget.Handle);
this.SwapChain.HasDepthStencilBuffer = true;
MainRootNode.Children.Add(this.SwapChain);
MainRootNode.Children.Add(RootNode);
renderTimer = new DispatcherTimer();
renderTimer.Tick += new EventHandler(delegate(object s, EventArgs a)
{
this.Perform();
});
renderTimer.Interval = TimeSpan.FromMilliseconds(1000 / 60.0);
renderTimer.Start();
selectionMarkerNode = new RenderCommandNode();
selectionShader = new Shader(new ShaderParams() { FileName = "Resources/SelectionHighlight.fx" });
selectionShader.Priority = 128;
MainRootNode.Children.Add(selectionMarkerNode);
this.RenderTarget.MouseDown += new System.Windows.Forms.MouseEventHandler(RenderTarget_MouseButtonDown);
this.RenderTarget.MouseUp += new System.Windows.Forms.MouseEventHandler(RenderTarget_MouseButtonUp);
}
public ICamera MainCamera
{
get
{
return FindLastAvailableCamera(MainRootNode);
}
}
public PickableResourcesDataSource PickableResources { get; set; }
public RenderCommandNode MainRootNode
{
get
{
if (mainRootNode == null)
{
mainRootNode = new RenderCommandNode();
}
return mainRootNode;
}
set
{
mainRootNode = value;
}
}
public SwapChain SwapChain { get; protected set; }
public RenderCommandNode RootNode
{
get
{
if (rootNode == null)
{
rootNode = new RenderCommandNode();
}
return rootNode;
}
set
{
mainRootNode.Children.Remove(rootNode);
rootNode = value;
mainRootNode.Children.Add(value);
}
}
public TimeSpan RenderInterval
{
get { return renderTimer.Interval; }
set { renderTimer.Interval = value; }
}
public PickableResourceInfo SelectedResourceInfo
{
get
{
return selectedResourceInfo;
}
set
{
if (selectedResourceInfo != null)
{
selectionMarkerNode.Children.Clear();
selectionMarkerNode.MarkDirty();
}
selectedResourceInfo = value;
if (selectedResourceInfo != null)
{
selectionMarkerNode.Children.Add(selectionShader);
if (selectedResourceInfo.Transformation != null)
selectionMarkerNode.Children.Add(selectedResourceInfo.Transformation);
if (selectedResourceInfo.Resource != null)
selectionMarkerNode.Children.Add(selectedResourceInfo.Resource);
}
if (SelectedResourceChanged != null)
SelectedResourceChanged(this, selectedResourceInfo);
}
}
public int DesiredFPS
{
get
{
return desiredFPS;
}
set
{
desiredFPS = value;
if (desiredFPS <= 0)
renderTimer.Interval = TimeSpan.FromMilliseconds(0);
else
renderTimer.Interval = TimeSpan.FromMilliseconds(1000 / (double)desiredFPS);
}
}
private ICamera FindLastAvailableCamera(Resource rootNode)
{
ICamera lastFoundCamera = null;
if (rootNode.Children != null)
foreach (var child in rootNode.Children)
{
if (child is ICamera)
lastFoundCamera = child as ICamera;
if (child is Resource)
lastFoundCamera = this.FindLastAvailableCamera(child as Resource) ?? lastFoundCamera;
}
return lastFoundCamera;
}
protected void Perform()
{
mainRootNode.Update(false);
mainRootNode.ProcessCommands();
this.SwapChain.Present();
var deltaTime = DateTime.UtcNow - lastPerformCalledTime;
this.PerformCalledInternal(deltaTime);
if (PerformCalled != null)
PerformCalled(this, deltaTime);
lastPerformCalledTime = DateTime.UtcNow;
}
private void RenderTarget_Resize(object sender, EventArgs e)
{
if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
return;
this.SwapChain.Resize((int)this.Width, (int)this.Height);
}
private void RenderTarget_MouseButtonUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
rightButtonPressed = false;
else if (e.Button == MouseButtons.Left)
leftButtonPressed = false;
lastMousePosition = CorrectGetPosition(this);
if (!moveThresholdReached)
{
if (e.Button == MouseButtons.Right)
{
if (this.ContextMenu != null)
this.ContextMenu.IsOpen = true;
}
else if (e.Button == MouseButtons.Left)
{
if (PickableResources != null)
{
var mainCamera = this.MainCamera;
int width = this.SwapChain.ViewPort.Width;
int height = this.SwapChain.ViewPort.Height;
var viewProj = mainCamera.ViewMatrix * mainCamera.ProjectionMatrix;
Vector3 ZNearPlane = Vector3.Unproject(new Vector3((float)lastMousePosition.X, (float)lastMousePosition.Y, 0), 0, 0, width, height,
this.SwapChain.ViewPort.MinDepth, this.SwapChain.ViewPort.MaxDepth, viewProj);
Vector3 ZFarPlane = Vector3.Unproject(new Vector3((float)lastMousePosition.X, (float)lastMousePosition.Y, 1), 0, 0, width, height,
this.SwapChain.ViewPort.MinDepth, this.SwapChain.ViewPort.MaxDepth, viewProj);
Vector3 direction = ZFarPlane - ZNearPlane;
direction.Normalize();
Ray ray = new Ray(ZNearPlane, direction);
PickableResourceInfo winnerResourceInfo = this.SelectedResourceInfo;
float distance = float.MaxValue;
foreach (var pickable in PickableResources)
{
float newDistance;
if (pickable.PickHull.TryPick(ray, pickable.Transformation.WorldMatrix, out newDistance)
&& newDistance < distance)
{
winnerResourceInfo = pickable;
distance = newDistance;
}
}
if (this.SelectedResourceInfo != null && winnerResourceInfo != null && this.SelectedResourceInfo.Resource == winnerResourceInfo.Resource)
winnerResourceInfo = null;
this.SelectedResourceInfo = winnerResourceInfo;
}
}
}
if (!leftButtonPressed && !rightButtonPressed)
{
renderTimer.Interval = TimeSpan.FromMilliseconds(1000 / (double)desiredFPS);
moveThresholdReached = false;
}
}
private void RenderTarget_MouseButtonDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
rightButtonPressed = true;
else if (e.Button == MouseButtons.Left)
leftButtonPressed = true;
if (leftButtonPressed || rightButtonPressed)
renderTimer.Interval = TimeSpan.FromMilliseconds(0);
lastMousePosition = CorrectGetPosition(this);
}
private void PerformCalledInternal(TimeSpan elapsedTime)
{
var currentMousePosition = CorrectGetPosition(this);
var deltaTime = Math.Max(1.0, elapsedTime.TotalSeconds);
var deltaMouse = currentMousePosition - lastMousePosition;
lastMousePosition = currentMousePosition;
var power = 1.7;
if (rightButtonPressed && !leftButtonPressed)
power = 1.25;
deltaMouse.X = Math.Pow(Math.Abs(deltaMouse.X), power) * Math.Sign(deltaMouse.X) * deltaTime;
deltaMouse.Y = Math.Pow(Math.Abs(deltaMouse.Y), power) * Math.Sign(deltaMouse.Y) * deltaTime;
if (!leftButtonPressed && !rightButtonPressed)
return;
moveThresholdReached = moveThresholdReached || deltaMouse.Length >= 3.0;
if (!moveThresholdReached)
return;
var mainCamera = this.MainCamera as Transformation;
if (rightButtonPressed && leftButtonPressed)
{
mainCamera.LocalPosition += mainCamera.LocalUpDirection * -(float)deltaMouse.Y * 0.005f +
mainCamera.LocalRightDirection * (float)deltaMouse.X * 0.005f;
}
else if (leftButtonPressed)
{
mainCamera.LocalPosition += mainCamera.LocalDirection * -(float)deltaMouse.Y * 0.005f +
mainCamera.LocalRightDirection * (float)deltaMouse.X * 0.005f;
}
else if (rightButtonPressed)
{
var yawPitchRoll = mainCamera.LocalRotationYPR;
yawPitchRoll.X += (float)deltaMouse.X * 0.005f;
yawPitchRoll.Y += (float)deltaMouse.Y * 0.005f;
if (yawPitchRoll.Y > Math.PI / 2)
yawPitchRoll.Y = (float)Math.PI / 2;
else if (yawPitchRoll.Y < -Math.PI / 2)
yawPitchRoll.Y = -(float)Math.PI / 2;
mainCamera.LocalRotationYPR = yawPitchRoll;
}
}
}
public class PickableResourcesDataSource : List<PickableResourceInfo>
{
public static PickableResourcesDataSource CreateFromResource(Resource rootNode)
{
var pickablesDataResource = new PickableResourcesDataSource();
List<KeyValuePair<Transformation, IGeometryBuffer>> pickables = new List<KeyValuePair<Transformation, IGeometryBuffer>>();
FindAllPickables(rootNode, null, pickables);
foreach (var pickable in pickables)
{
pickablesDataResource.Add(new PickableResourceInfo()
{
PickHull = pickable.Value.PickHull,
Transformation = pickable.Key,
Resource = pickable.Value as IResource
});
}
return pickablesDataResource;
}
private static void FindAllPickables(Resource rootNode, Transformation lastTransformation, List<KeyValuePair<Transformation, IGeometryBuffer>> pickables)
{
if (rootNode.Children != null)
foreach (var child in rootNode.Children)
{
if (child is Transformation)
lastTransformation = child as Transformation;
if (child is IGeometryBuffer && lastTransformation != null)
{
var geoBuffer = child as IGeometryBuffer;
if (geoBuffer.IsPickable)
pickables.Add(new KeyValuePair<Transformation, IGeometryBuffer>(lastTransformation, geoBuffer));
}
if (child is Resource)
FindAllPickables(child as Resource, lastTransformation, pickables);
}
}
}
public class PickableResourceInfo
{
public IResource Resource;
public Transformation Transformation;
public IPickHull PickHull;
}
}

View File

@@ -0,0 +1,36 @@
<HeaderedContentControl x:Class="Aiwaz.Editor.Controls.PropertyGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:pg="clr-namespace:Aiwaz.Editor.Controls">
<HeaderedContentControl.Header>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Search:" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBox x:Name="searchTextBox" Grid.Column="1"/>
</Grid>
</HeaderedContentControl.Header>
<Border BorderThickness="1" BorderBrush="#FF828790">
<Grid>
<Grid.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Color="LightGray" Offset="0.0" />
<GradientStop Color="White" Offset="1.0" />
</LinearGradientBrush>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<ScrollViewer x:Name="propertyGridScrollBar" Grid.Row="0" CanContentScroll="False" VerticalScrollBarVisibility="Visible">
<ScrollViewer.Content>
<StackPanel x:Name="PropertyPanel"/> <!--PropertyItems go in here-->
</ScrollViewer.Content>
</ScrollViewer>
<TextBlock x:Name="descriptionTextBlock" Grid.Row="1" TextWrapping="Wrap"/>
</Grid>
</Border>
</HeaderedContentControl>

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.ComponentModel;
namespace Aiwaz.Editor.Controls
{
public partial class PropertyGrid : HeaderedContentControl
{
private object selectedObject = null;
public PropertyGrid()
{
InitializeComponent();
searchTextBox.TextChanged += new TextChangedEventHandler(searchTextBox_TextChanged);
}
#region PropertyGrid related stuff
public object SelectedObject{
get { return selectedObject; }
set { selectedObject = value; SelectedObjectHelper(selectedObject,null); }
}
public void SelectedObjectHelper(object value,EventArgs e) {
if (!Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new EventHandler(SelectedObjectHelper), value, e);
}
else
{
this.PropertyPanel.Children.Clear(); //clear propertypanel
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value))
{
if (!property.IsBrowsable) continue; //could also check for browsableattribute, but this one's shorter
PropertyItem currentProperty = new PropertyItem();
currentProperty.PropertyName = property.Name;
Binding b = new Binding(property.Name);
b.Source = selectedObject;
b.Mode = property.IsReadOnly ? BindingMode.OneWay : BindingMode.TwoWay;
currentProperty.SetBinding(PropertyItem.PropertyValueProperty, b);
currentProperty.OnActive += new EventHandler<DescriptionEventArgs>(currentProperty_OnActive);
foreach (Attribute attribute in property.Attributes)
{
if (attribute.GetType() == typeof(DescriptionAttribute))
{
currentProperty.PropertyDescription = ((DescriptionAttribute)attribute).Description;
}
if (attribute.GetType() == typeof(CategoryAttribute)) {
currentProperty.PropertyCategory = ((CategoryAttribute)attribute).Category;
}
}
PropertyPanel.Children.Add(currentProperty); //add the propertyitem
}
}
}
#endregion
#region events
void searchTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
string filterText = searchTextBox.Text.ToLower(); //we don't want to be case sensitive
foreach (PropertyItem pi in PropertyPanel.Children)
{ //hide PropertyItem if it does not contain filter text
pi.Visibility = (pi.PropertyName.ToLower().Contains(filterText) || filterText.Equals(string.Empty)) ? Visibility.Visible : Visibility.Collapsed;
}
}
void currentProperty_OnActive(object sender, DescriptionEventArgs e)
{
if (!Application.Current.Dispatcher.CheckAccess()){
Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new EventHandler<DescriptionEventArgs>(currentProperty_OnActive),sender, e);
}else{
this.descriptionTextBlock.Text = e.Description;
}
}
#endregion
}
}

View File

@@ -0,0 +1,13 @@
<UserControl x:Class="Aiwaz.Editor.Controls.PropertyItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid x:Name="PropertyItemGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=PropertyName}" Grid.Column="0"/>
<TextBox Text="{Binding Path=PropertyValue,Mode=TwoWay}" Grid.Column="1" MouseEnter="TextBox_MouseEnter" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Input;
using System.ComponentModel;
namespace Aiwaz.Editor.Controls
{
/// <summary>
/// Interaction logic for PropertyItem.xaml
/// </summary>
public partial class PropertyItem : UserControl
{
public static readonly DependencyProperty PropertyNameProperty = DependencyProperty.Register("PropertyName", typeof(string), typeof(PropertyItem));
public static readonly DependencyProperty PropertyValueProperty = DependencyProperty.Register("PropertyValue", typeof(object), typeof(PropertyItem));
public static readonly DependencyProperty PropertyDescriptionProperty = DependencyProperty.Register("PropertyDescription", typeof(string), typeof(PropertyItem));
public static readonly DependencyProperty PropertyCategoryProperty = DependencyProperty.Register("PropertyCategory", typeof(string), typeof(PropertyItem));
public EventHandler<DescriptionEventArgs> DescriptionEventHandler;
public event EventHandler<DescriptionEventArgs> OnActive;
public PropertyItem()
{
InitializeComponent();
PropertyItemGrid.DataContext = this;
}
public string PropertyName {
get { return (string)GetValue(PropertyItem.PropertyNameProperty); }
set { SetValue(PropertyItem.PropertyNameProperty, value); }
}
public object PropertyValue
{
get{ return (string)GetValue(PropertyItem.PropertyValueProperty);}
set{ SetValue(PropertyItem.PropertyValueProperty, value); }
}
public string PropertyDescription
{
get { return (string)GetValue(PropertyItem.PropertyDescriptionProperty); }
set { SetValue(PropertyItem.PropertyDescriptionProperty, value);}
}
public string PropertyCategory
{
get { return (string)GetValue(PropertyItem.PropertyCategoryProperty); }
set { SetValue(PropertyItem.PropertyCategoryProperty, value); }
}
#region events
private void TextBox_MouseEnter(object sender, MouseEventArgs e)
{
if (OnActive != null) {
OnActive(this, new DescriptionEventArgs(PropertyDescription));
}
}
#endregion
}
public class DescriptionEventArgs : EventArgs{
public string Description { get; set;}
public DescriptionEventArgs(string descr){
this.Description = descr;
}
}
}