diff --git a/sp/src/public/vgui_controls/ExpandButton.h b/sp/src/public/vgui_controls/ExpandButton.h new file mode 100644 index 00000000..2dbf8493 --- /dev/null +++ b/sp/src/public/vgui_controls/ExpandButton.h @@ -0,0 +1,61 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A button with no borders that shows a left-pointing or down-pointing triangle +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef EXPANDBUTTON_H +#define EXPANDBUTTON_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: A button with no borders that shows a left-pointing or down-pointing arrow +//----------------------------------------------------------------------------- +class ExpandButton : public ToggleButton +{ + DECLARE_CLASS_SIMPLE( ExpandButton, ToggleButton ); + +public: + ExpandButton( Panel *parent, const char *panelName ); + ~ExpandButton(); + + // Expand the button (selected == expanded) + virtual void SetSelected( bool bExpand ); + + // sets whether or not the state of the check can be changed + // if this is set to false, then no input in the code or by the user can change it's state + void SetExpandable(bool state); + + virtual void Paint(); + +protected: + virtual void ApplySchemeSettings(IScheme *pScheme); + MESSAGE_FUNC_PTR( OnExpanded, "Expanded", panel ); + + virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); + + /* MESSAGES SENT + "Expanded" - sent when the expand button state is changed + "state" - button state: 1 is expanded, 0 is unexpanded + */ + +private: + bool m_bExpandable; + HFont m_hFont; + Color m_Color; +}; + +} // namespace vgui + +#endif // EXPANDBUTTON_H diff --git a/sp/src/public/vgui_controls/FileOpenDialog.h b/sp/src/public/vgui_controls/FileOpenDialog.h new file mode 100644 index 00000000..bcaccf0f --- /dev/null +++ b/sp/src/public/vgui_controls/FileOpenDialog.h @@ -0,0 +1,160 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Declaration of FileOpenDialog class, a generic open/save as file dialog +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef FILEOPENDIALOG_H +#define FILEOPENDIALOG_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/Frame.h" + +namespace vgui +{ + +class FileCompletionEdit; // local +class InputDialog; + +//----------------------------------------------------------------------------- +// Purpose: generic open/save as file dialog +//----------------------------------------------------------------------------- +enum FileOpenDialogType_t +{ + FOD_SAVE = 0, + FOD_OPEN, + FOD_SELECT_DIRECTORY, +}; + + +class FileOpenDialog : public vgui::Frame +{ + DECLARE_CLASS_SIMPLE( FileOpenDialog, Frame ); + +public: + // NOTE: Backward compat constructor + FileOpenDialog( Panel *parent, const char *title, bool bOpenFile, KeyValues *pContextKeyValues = 0 ); + + // The context keyvalues are added to all messages sent by this dialog if they are specified + FileOpenDialog( Panel *parent, const char *title, FileOpenDialogType_t type, KeyValues *pContextKeyValues = 0 ); + ~FileOpenDialog(); + + // Set the directory the file search starts in + void SetStartDirectory(const char *dir); + + // Sets the start directory context (and resets the start directory in the process) + // NOTE: If you specify a startdir context, then if you've already opened + // a file with that same start dir context before, it will start in the + // same directory it ended up in. + void SetStartDirectoryContext( const char *pContext, const char *pDefaultDir ); + + // Add filters for the drop down combo box + // The filter info, if specified, gets sent back to the app in the FileSelected message + void AddFilter( const char *filter, const char *filterName, bool bActive, const char *pFilterInfo = NULL ); + + // Activate the dialog + // NOTE: The argument is there for backward compat + void DoModal( bool bUnused = false ); + + // Get the directory this is currently in + void GetCurrentDirectory( char *buf, int bufSize ); + + // Get the last selected file name + void GetSelectedFileName( char *buf, int bufSize ); + + /* + messages sent: + "FileSelected" + "fullpath" // specifies the fullpath of the file + "filterinfo" // Returns the filter info associated with the active filter + "FileSelectionCancelled" + */ + +protected: + virtual void OnCommand( const char *command ); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void OnClose(); + virtual void OnKeyCodeTyped(KeyCode code); + + // handles the open button being pressed + // checks on what has changed and acts accordingly + MESSAGE_FUNC( OnOpen, "OnOpen" ); + MESSAGE_FUNC( OnSelectFolder, "SelectFolder" ); + MESSAGE_FUNC( OnFolderUp, "OnFolderUp" ); + MESSAGE_FUNC( OnNewFolder, "OnNewFolder" ); + MESSAGE_FUNC( OnOpenInExplorer, "OpenInExplorer" ); + + MESSAGE_FUNC( PopulateFileList, "PopulateFileList" ); + MESSAGE_FUNC( PopulateDriveList, "PopulateDriveList" ); + MESSAGE_FUNC( PopulateFileNameCompletion, "PopulateFileNameCompletion" ); + + // moves the directory structure up + virtual void MoveUpFolder(); + + // validates that the current path is valid + virtual void ValidatePath(); + + // handles an item in the list being selected + MESSAGE_FUNC( OnItemSelected, "ItemSelected" ); + MESSAGE_FUNC( OnListItemSelected, "ListItemSelected" ) + { + OnItemSelected(); + } + + // changes directories in response to selecting drives from the combo box + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", kv ); + + MESSAGE_FUNC( OnInputCanceled, "InputCanceled" ); + MESSAGE_FUNC_PARAMS( OnInputCompleted, "InputCompleted", data ); + +private: + // Necessary because we have 2 constructors + void Init( const char *title, KeyValues *pContextKeyValues ); + + // Does the specified extension match something in the filter list? + bool ExtensionMatchesFilter( const char *pExt ); + + // Choose the first non *.* filter in the filter list + void ChooseExtension( char *pExt, int nBufLen ); + + // Saves the file to the start dir context + void SaveFileToStartDirContext( const char *pFullPath ); + + // Posts a file selected message + void PostFileSelectedMessage( const char *pFileName ); + + // Creates a new folder + void NewFolder( char const *folderName ); + + vgui::ComboBox *m_pFullPathEdit; + vgui::ListPanel *m_pFileList; + + FileCompletionEdit *m_pFileNameEdit; + + vgui::ComboBox *m_pFileTypeCombo; + vgui::Button *m_pOpenButton; + vgui::Button *m_pCancelButton; + vgui::Button *m_pFolderUpButton; + vgui::Button *m_pNewFolderButton; + vgui::Button *m_pOpenInExplorerButton; + vgui::ImagePanel *m_pFolderIcon; + vgui::Label *m_pFileTypeLabel; + + KeyValues *m_pContextKeyValues; + + char m_szLastPath[1024]; + unsigned short m_nStartDirContext; + FileOpenDialogType_t m_DialogType; + bool m_bFileSelected : 1; + + VPANEL m_SaveModal; + vgui::DHANDLE< vgui::InputDialog > m_hInputDialog; +}; + +} // namespace vgui + +#endif // FILEOPENDIALOG_H diff --git a/sp/src/public/vgui_controls/FileOpenStateMachine.h b/sp/src/public/vgui_controls/FileOpenStateMachine.h new file mode 100644 index 00000000..4fb327cb --- /dev/null +++ b/sp/src/public/vgui_controls/FileOpenStateMachine.h @@ -0,0 +1,172 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// This is a helper class designed to help with the chains of modal dialogs +// encountered when trying to open or save a particular file +// +//============================================================================= + +#ifndef FILEOPENSTATEMACHINE_H +#define FILEOPENSTATEMACHINE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/Panel.h" +#include "tier1/utlstring.h" + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- + + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Interface for things using the file open state machine +//----------------------------------------------------------------------------- +abstract_class IFileOpenStateMachineClient +{ +public: + // Called by to allow clients to set up the save dialog + virtual void SetupFileOpenDialog( vgui::FileOpenDialog *pDialog, bool bOpenFile, const char *pFileFormat, KeyValues *pContextKeyValues ) = 0; + + // Called by to allow clients to actually read the file in + virtual bool OnReadFileFromDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ) = 0; + + // Called by to allow clients to actually write the file out + virtual bool OnWriteFileToDisk( const char *pFileName, const char *pFileFormat, KeyValues *pContextKeyValues ) = 0; +}; + + +//----------------------------------------------------------------------------- +// This is a helper class designed to help with chains of modal dialogs +//----------------------------------------------------------------------------- +enum FileOpenStateMachineFlags_t +{ + FOSM_SHOW_PERFORCE_DIALOGS = 0x1, + FOSM_SHOW_SAVE_QUERY = 0x2, +}; + +class FileOpenStateMachine : public Panel +{ + DECLARE_CLASS_SIMPLE( FileOpenStateMachine, Panel ); + +public: + enum CompletionState_t + { + IN_PROGRESS = 0, // Still not finished, not successful or error + SUCCESSFUL, // Operation finished successfully + FILE_SAVE_CANCELLED, // The user chose 'cancel' in the dialog asking if he wanted to save + FILE_SAVE_NAME_NOT_SPECIFIED, // User hit cancel in the SaveAs dialog + FILE_NOT_OVERWRITTEN, // Operation aborted; existed file and user chose to not write over it + FILE_NOT_CHECKED_OUT, // Operation aborted; file wasn't checked out so couldn't be written over + ERROR_WRITING_FILE, // Error occurred writing the file out + ERROR_MAKING_FILE_WRITEABLE, // Error occurred when making the file writeable + FILE_NOT_MADE_WRITEABLE, // User chose to not make the file be writeable + FILE_OPEN_NAME_NOT_SPECIFIED, // User hit cancel in the Open dialog + ERROR_READING_FILE, // Error occurred reading the file in + }; + + FileOpenStateMachine( vgui::Panel *pParent, IFileOpenStateMachineClient *pClient ); + virtual ~FileOpenStateMachine(); + + // Opens a file, saves an existing one if necessary + void OpenFile( const char *pOpenFileType, KeyValues *pContextKeyValues, const char *pSaveFileName = NULL, const char *pSaveFileType = NULL, int nFlags = 0 ); + + // Version of OpenFile that skips browsing for a particular file to open + void OpenFile( const char *pOpenFileName, const char *pOpenFileType, KeyValues *pContextKeyValues, const char *pSaveFileName = NULL, const char *pSaveFileType = NULL, int nFlags = 0 ); + + // Used to save a specified file, and deal with all the lovely dialogs + // Pass in NULL to get a dialog to choose a filename to save + void SaveFile( KeyValues *pContextKeyValues, const char *pFileName, const char *pFileType, int nFlags = FOSM_SHOW_PERFORCE_DIALOGS ); + + // Returns the state machine completion state + CompletionState_t GetCompletionState(); + + /* MESSAGES SENT + "FileStateMachineFinished" - Called when we exit the state machine for any reason + "completionState" - See the CompletionState_t enum above + "wroteFile" - Indicates whether a file was written or not + "fullPath" - Indicates the full path of the file read for OpenFile or written for SaveFile + "fileType" - Indicates the file type of the file read for OpenFile or written for SaveFile + Use GetFirstTrueSubKey() to get the context passed into the OpenFile/SaveFile methods + */ + +private: + enum FOSMState_t + { + STATE_NONE = -1, + STATE_SHOWING_SAVE_DIRTY_FILE_DIALOG = 0, + STATE_SHOWING_SAVE_DIALOG, + STATE_SHOWING_OVERWRITE_DIALOG, + STATE_SHOWING_CHECK_OUT_DIALOG, + STATE_SHOWING_MAKE_FILE_WRITEABLE_DIALOG, + STATE_WRITING_FILE, + STATE_SHOWING_PERFORCE_ADD_DIALOG, + STATE_SHOWING_OPEN_DIALOG, + STATE_READING_FILE, + }; + + MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", pKeyValues ); + MESSAGE_FUNC( OnFileSelectionCancelled, "FileSelectionCancelled" ); + MESSAGE_FUNC_PARAMS( OnPerforceQueryCompleted, "PerforceQueryCompleted", pKeyValues ); + MESSAGE_FUNC( OnMakeFileWriteable, "MakeFileWriteable" ); + MESSAGE_FUNC( OnCancelMakeFileWriteable, "CancelMakeFileWriteable" ); + + // These messages are related to the dialog in OverwriteFileDialog + MESSAGE_FUNC( OnOverwriteFile, "OverwriteFile" ); + MESSAGE_FUNC( OnCancelOverwriteFile, "CancelOverwriteFile" ); + + // These messages come from the savedocumentquery dialog + MESSAGE_FUNC( OnSaveFile, "OnSaveFile" ); + MESSAGE_FUNC( OnMarkNotDirty, "OnMarkNotDirty" ); + MESSAGE_FUNC( OnCancelSaveDocument, "OnCancelSaveDocument" ); + + // Cleans up keyvalues + void CleanUpContextKeyValues(); + + // Utility to set the completion state + void SetCompletionState( CompletionState_t state ); + + // Show the save document query dialog + void ShowSaveQuery( ); + + // Shows the overwrite existing file dialog + void OverwriteFileDialog( ); + + // Shows the open file for edit dialog + void CheckOutDialog( ); + + // Shows the make file writeable dialog + void MakeFileWriteableDialog( ); + + // Writes the file out + void WriteFile(); + + // Shows the open file dialog + void OpenFileDialog( ); + + // Reads the file in + void ReadFile(); + + IFileOpenStateMachineClient *m_pClient; + KeyValues *m_pContextKeyValues; + FOSMState_t m_CurrentState; + CompletionState_t m_CompletionState; + CUtlString m_FileName; + CUtlString m_SaveFileType; + CUtlString m_OpenFileType; + CUtlString m_OpenFileName; + bool m_bShowPerforceDialogs : 1; + bool m_bShowSaveQuery : 1; + bool m_bIsOpeningFile : 1; + bool m_bWroteFile : 1; +}; + +} // end namespace vgui + + + +#endif // FILEOPENSTATEMACHINE_H diff --git a/sp/src/public/vgui_controls/FocusNavGroup.h b/sp/src/public/vgui_controls/FocusNavGroup.h new file mode 100644 index 00000000..2d743512 --- /dev/null +++ b/sp/src/public/vgui_controls/FocusNavGroup.h @@ -0,0 +1,61 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef FOCUSNAVGROUP_H +#define FOCUSNAVGROUP_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class Panel; + +//----------------------------------------------------------------------------- +// Purpose: Handles navigation through a set of panels, with tab order & hotkeys +//----------------------------------------------------------------------------- +class FocusNavGroup +{ +public: + FocusNavGroup(Panel *panel); + ~FocusNavGroup(); + virtual Panel *GetDefaultPanel(); // returns a pointer to the panel with the default focus + + virtual void SetDefaultButton(Panel *panel); // sets which panel should receive input when ENTER is hit + virtual VPANEL GetDefaultButton(); // panel which receives default input when ENTER is hit, if current focused item cannot accept ENTER + virtual VPANEL GetCurrentDefaultButton(); // panel which receives input when ENTER is hit + virtual Panel *FindPanelByHotkey(wchar_t key); // finds the panel which is activated by the specified key + virtual bool RequestFocusPrev(VPANEL panel = NULL); // if panel is NULL, then the tab increment is based last known panel that had key focus + virtual bool RequestFocusNext(VPANEL panel = NULL); + + virtual Panel *GetCurrentFocus(); + virtual VPANEL SetCurrentFocus(VPANEL panel, VPANEL defaultPanel); // returns the Default panel + + // sets the panel that owns this FocusNavGroup to be the root in the focus traversal heirarchy + // focus change via KEY_TAB will only travel to children of this main panel + virtual void SetFocusTopLevel(bool state); + + virtual void SetCurrentDefaultButton(VPANEL panel, bool sendCurrentDefaultButtonMessage = true); +private: + bool CanButtonBeDefault(VPANEL panel); + + VPanelHandle _defaultButton; + VPanelHandle _currentDefaultButton; + VPanelHandle _currentFocus; + + Panel *_mainPanel; + bool _topLevelFocus; +}; + +} // namespace vgui + +#endif // FOCUSNAVGROUP_H diff --git a/sp/src/public/vgui_controls/Frame.h b/sp/src/public/vgui_controls/Frame.h new file mode 100644 index 00000000..0485a374 --- /dev/null +++ b/sp/src/public/vgui_controls/Frame.h @@ -0,0 +1,260 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef VGUI_FRAME_H +#define VGUI_FRAME_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include +#include + +namespace vgui +{ + +class FrameButton; +class FrameSystemButton; + +//----------------------------------------------------------------------------- +// Purpose: Windowed frame +//----------------------------------------------------------------------------- +class Frame : public EditablePanel +{ + DECLARE_CLASS_SIMPLE( Frame, EditablePanel ); + +public: + Frame(Panel *parent, const char *panelName, bool showTaskbarIcon = true, bool bPopup = true ); + virtual ~Frame(); + + // Set the text in the title bar. Set surfaceTitle=true if you want this to be the taskbar text as well. + virtual void SetTitle(const char *title, bool surfaceTitle); + virtual void SetTitle(const wchar_t *title, bool surfaceTitle); + + // Bring the frame to the front and requests focus, ensures it's not minimized + virtual void Activate(); + + // activates the dialog; if dialog is not currently visible it starts it minimized and flashing in the taskbar + virtual void ActivateMinimized(); + + // closes the dialog + MESSAGE_FUNC( Close, "Close" ); + MESSAGE_FUNC( CloseModal, "CloseModal" ); + + // sets the dialog to delete self on close + virtual void SetDeleteSelfOnClose( bool state ); + + // Move the dialog to the center of the screen + virtual void MoveToCenterOfScreen(); + + // Set the movability of the panel + virtual void SetMoveable(bool state); + // Check the movability of the panel + virtual bool IsMoveable(); + + // Set the resizability of the panel + virtual void SetSizeable(bool state); + // Check the resizability of the panel + virtual bool IsSizeable(); + // Toggle visibility of the system menu button + virtual void SetMenuButtonVisible(bool state); + void SetMenuButtonResponsive(bool state); + + // Toggle visibility of the minimize button + virtual void SetMinimizeButtonVisible(bool state); + // Toggle visibility of the maximize button + virtual void SetMaximizeButtonVisible(bool state); + // Toggles visibility of the minimize-to-systray icon (defaults to false) + virtual void SetMinimizeToSysTrayButtonVisible(bool state); + + // Toggle visibility of the close button + virtual void SetCloseButtonVisible(bool state); + + // returns true if the dialog is currently minimized + virtual bool IsMinimized(); + // Flash the window system tray button until the frame gets focus + virtual void FlashWindow(); + // Stops any window flashing + virtual void FlashWindowStop(); + // command handling + virtual void OnCommand(const char *command); + + // Get the system menu + virtual Menu *GetSysMenu(); + // Set the system menu + virtual void SetSysMenu(Menu *menu); + + // Set the system menu images + void SetImages( const char *pEnabledImage, const char *pDisabledImage = NULL ); + + // set whether the title bar should be rendered + virtual void SetTitleBarVisible( bool state ); + + // When moving via caption, don't let any part of window go outside parent's bounds + virtual void SetClipToParent( bool state ); + virtual bool GetClipToParent() const; + + // Set to true to make the caption height small + virtual void SetSmallCaption( bool state ); + virtual bool IsSmallCaption() const; + + virtual int GetDraggerSize(); + virtual int GetCornerSize(); + virtual int GetBottomRightSize(); + virtual int GetCaptionHeight(); + + /* CUSTOM MESSAGE HANDLING + "SetTitle" + input: "text" - string to set the title to be + */ + + // Load the control settings + virtual void LoadControlSettings( const char *dialogResourceName, const char *pathID = NULL, KeyValues *pPreloadedKeyValues = NULL, KeyValues *pConditions = NULL ); + + void SetChainKeysToParent( bool state ); + bool CanChainKeysToParent() const; + + // Shows the dialog in a modal fashion + virtual void DoModal(); + + void PlaceUnderCursor( ); + + // Disables the fade-in/out-effect even if configured in the scheme settings + void DisableFadeEffect( void ); + + // Temporarily enables or disables the fade effect rather than zeroing the fade times as done in DisableFadeEffect + void SetFadeEffectDisableOverride( bool disabled ); + +protected: + // Respond to mouse presses + virtual void OnMousePressed(MouseCode code); + // Respond to Key typing + virtual void OnKeyCodeTyped(KeyCode code); + virtual void OnKeyTyped(wchar_t unichar); + // Respond to Key releases + virtual void OnKeyCodeReleased(KeyCode code); + // Respond to Key focus ticks + virtual void OnKeyFocusTicked(); + virtual void ApplySchemeSettings(IScheme *pScheme); + // Recalculate the position of all items + virtual void PerformLayout(); + // Respond when a close message is recieved. Can be called directly to close a frame. + virtual void OnClose(); + // Respond to a window finishing its closure. i.e. when a fading window has fully finished its fadeout. + virtual void OnFinishedClose(); + // Minimize the window on the taskbar. + MESSAGE_FUNC( OnMinimize, "Minimize" ); + // Called when minimize-to-systray button is pressed (does nothing by default) + virtual void OnMinimizeToSysTray(); + // the frame close button was pressed + MESSAGE_FUNC( OnCloseFrameButtonPressed, "CloseFrameButtonPressed" ); + // Add the child to the focus nav group + virtual void OnChildAdded(VPANEL child); + // settings + virtual void ApplySettings(KeyValues *inResourceData); + // records the settings into the resource data + virtual void GetSettings(KeyValues *outResourceData); + virtual const char *GetDescription( void ); + + // gets the default position and size on the screen to appear the first time (defaults to centered) + virtual bool GetDefaultScreenPosition(int &x, int &y, int &wide, int &tall); + + // painting + virtual void PaintBackground(); + + // per-frame thinking, used for transition effects + virtual void OnThink(); + + // screen size + virtual void OnScreenSizeChanged(int iOldWide, int iOldTall); + + // Get the size of the panel inside the frame edges. + virtual void GetClientArea(int &x, int &y, int &wide, int &tall); + + // user configuration settings + // this is used for any control details the user wants saved between sessions + // eg. dialog positions, last directory opened, list column width + virtual void ApplyUserConfigSettings(KeyValues *userConfig); + + // returns user config settings for this control + virtual void GetUserConfigSettings(KeyValues *userConfig); + + // optimization, return true if this control has any user config settings + virtual bool HasUserConfigSettings(); + +private: + MESSAGE_FUNC_CHARPTR( InternalSetTitle, "SetTitle", text ); + MESSAGE_FUNC( InternalFlashWindow, "FlashWindow" ); + MESSAGE_FUNC_PARAMS( OnDialogVariablesChanged, "DialogVariables", dialogVariables ); + + void SetupResizeCursors(); + void LayoutProportional( FrameButton *bt); + void FinishClose(); + void OnFrameFocusChanged(bool bHasFocus); + + Color _titleBarBgColor; + Color _titleBarDisabledBgColor; + Color _titleBarFgColor; + Color _titleBarDisabledFgColor; + Color m_InFocusBgColor; + Color m_OutOfFocusBgColor; + TextImage *_title; + +#if !defined( _X360 ) + Panel *_topGrip; + Panel *_bottomGrip; + Panel *_leftGrip; + Panel *_rightGrip; + Panel *_topLeftGrip; + Panel *_topRightGrip; + Panel *_bottomLeftGrip; + Panel *_bottomRightGrip; + Panel *_captionGrip; + FrameButton *_minimizeButton; + FrameButton *_maximizeButton; + FrameButton *_minimizeToSysTrayButton; + FrameButton *_closeButton; + FrameSystemButton *_menuButton; + Menu *_sysMenu; +#endif + + float m_flTransitionEffectTime; + float m_flFocusTransitionEffectTime; + int m_iClientInsetX; + int m_iClientInsetY; + int m_iTitleTextInsetX; + int m_nGripperWidth; + VPANEL m_hPreviousModal; + HFont m_hCustomTitleFont; + + bool _sizeable : 1; + bool _moveable : 1; + bool m_bHasFocus : 1; + bool _flashWindow : 1; + bool _nextFlashState : 1; + bool _drawTitleBar : 1; + bool m_bPreviouslyVisible : 1; + bool m_bFadingOut : 1; + bool m_bDeleteSelfOnClose : 1; + bool m_bDisableFadeEffect : 1; + bool m_bClipToParent : 1; + bool m_bSmallCaption : 1; + bool m_bChainKeysToParent : 1; + bool m_bPrimed : 1; + bool m_iClientInsetXOverridden : 1; + + CPanelAnimationVarAliasType( int, m_iTitleTextInsetXOverride, "titletextinsetX", "0", "proportional_int" ); + CPanelAnimationVar( int, m_iTitleTextInsetYOverride, "titletextinsetY", "0" ); +}; + +} // namespace vgui + +#endif // VGUI_FRAME_H diff --git a/sp/src/public/vgui_controls/GraphPanel.h b/sp/src/public/vgui_controls/GraphPanel.h new file mode 100644 index 00000000..e2c2bfe4 --- /dev/null +++ b/sp/src/public/vgui_controls/GraphPanel.h @@ -0,0 +1,81 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef GRAPHPANEL_H +#define GRAPHPANEL_H +#ifdef _WIN32 +#pragma once +#endif + +#include +#include "utllinkedlist.h" +#include "utlvector.h" + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Holds and displays a chart +//----------------------------------------------------------------------------- +class GraphPanel : public Panel +{ + DECLARE_CLASS_SIMPLE( GraphPanel, Panel ); + +public: + GraphPanel(Panel *parent, const char *name); + + // domain settings (x-axis settings) + // sets the window of samples to display + void SetDisplayDomainSize(float size); + // sets the range of samples the graph should keep + // should be set to the max you would set the display domain size + void SetMaxDomainSize(float size); + // sets the minimum domain that will be displayed; used to collapse samples + void SetMinDomainSize(float size); + + // range settings (y-axis settings) + void SetUseFixedRange(float lowRange, float highRange); + void SetUseDynamicRange(float *rangeList, int numRanges); + void GetDisplayedRange(float &lowRange, float &highRange); + + // adds an item to the end of the list + // sampleEnd is assumed to be the trailing edge of the sample + // assumes that the samples are fairly evenly spaced (not much more work to do to fix this though) + void AddItem(float sampleEnd, float sampleValue); + +protected: + virtual void Paint(); + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme *pScheme); + +private: + int GetVisibleItemCount(); + + struct Sample_t + { + float sampleEnd; + float value; + }; + CUtlLinkedList m_Samples; + + // the window to show + float m_flDomainSize; + float m_flMaxDomainSize, m_flMinDomainSize; + bool m_bMaxDomainSizeSet; + + // range + float m_flLowRange, m_flHighRange; + bool m_bUseDynamicRange; + CUtlVector m_RangeList; + + // rendering + int m_iGraphBarWidth; + int m_iGraphBarGapWidth; +}; + +} // namespace vgui + +#endif // GRAPHPANEL_H diff --git a/sp/src/public/vgui_controls/HTML.h b/sp/src/public/vgui_controls/HTML.h new file mode 100644 index 00000000..59e76770 --- /dev/null +++ b/sp/src/public/vgui_controls/HTML.h @@ -0,0 +1,336 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Creates a HTML control +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef HTML_H +#define HTML_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include +#include +#include +#include +#ifndef VERSION_SAFE_STEAM_API_INTERFACES +#define VERSION_SAFE_STEAM_API_INTERFACES +#endif +#include "steam/steam_api.h" + +class HTMLComboBoxHost; +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Control to display HTML content +// This control utilises a hidden IE window to render a HTML page for you. +// It can load any valid URL (i.e local files or web pages), you cannot dynamically change the +// content however (internally to the control that is). +//----------------------------------------------------------------------------- +class HTML: public Panel +{ + DECLARE_CLASS_SIMPLE( HTML, Panel ); + // TODO::STYLE + //DECLARE_STYLE_BASE( "HTML" ); +public: + + HTML(Panel *parent,const char *name, bool allowJavaScript = false, bool bPopupWindow = false); + ~HTML(); + + // IHTML pass through functions + virtual void OpenURL( const char *URL, const char *pchPostData, bool bForce = false ); + virtual bool StopLoading(); + virtual bool Refresh(); + virtual void OnMove(); + virtual void RunJavascript( const char *pchScript ); + virtual void GoBack(); + virtual void GoForward(); + virtual bool BCanGoBack(); + virtual bool BCanGoFoward(); + + // event functions you can override and specialize behavior of + virtual bool OnStartRequest( const char *url, const char *target, const char *pchPostData, bool bIsRedirect ); + virtual void OnFinishRequest(const char *url, const char *pageTitle, const CUtlMap < CUtlString, CUtlString > &headers ) {} + virtual void OnSetHTMLTitle( const char *pchTitle ) {} + virtual void OnLinkAtPosition( const char *pchURL ) {} + virtual void OnURLChanged( const char *url, const char *pchPostData, bool bIsRedirect ) {} + + virtual bool OnOpenNewTab( const char *pchURL, bool bForeground ) { return false; } + + // configuration + virtual void SetScrollbarsEnabled(bool state); + virtual void SetContextMenuEnabled(bool state); + virtual void SetViewSourceEnabled( bool state ); + virtual void NewWindowsOnly( bool state ); + + bool IsScrolledToBottom(); + bool IsScrollbarVisible(); + + // url handlers, lets you have web page links fire vgui events + // use to have custom web page links, eg. "steam://open/subscriptionpage" + // message contains "CustomURL", "url" + virtual void AddCustomURLHandler(const char *customProtocolName, vgui::Panel *target); + + // overridden to paint our special web browser texture + virtual void Paint(); + + // pass messages to the texture component to tell it about resizes + virtual void OnSizeChanged(int wide,int tall); + + // pass mouse clicks through + virtual void OnMousePressed(MouseCode code); + virtual void OnMouseReleased(MouseCode code); + virtual void OnCursorMoved(int x,int y); + virtual void OnMouseDoublePressed(MouseCode code); + virtual void OnKeyTyped(wchar_t unichar); + virtual void OnKeyCodeTyped(KeyCode code); + virtual void OnKeyCodeReleased(KeyCode code); + virtual void PerformLayout(); + virtual void OnMouseWheeled(int delta); + virtual void PostChildPaint(); + + /* message posting: + + "HTMLSliderMoved" - indicates the scrollbar has moved + + "OnURLChanged" - indicates a new URL is being loaded + "url" + "postdata" + + "OnFinishRequest" - indicates all url loaded has completed + + "HTMLBackRequested" - mouse4 has been pressed on the dialog + "HTMLForwardRequested" - mouse5 has been pressed on the dialog + + "SecurityStatus" - indicates the SSL status of the page (disabled,good,bad) + "url" + "secure" - true if an ssl page + "certerror" - true if there is a cert error loading the page + "isevcert" - true if this is an EV style cert + "certname" - name of the entity this cert is issued to + */ + + MESSAGE_FUNC_INT( OnSetCursorVGUI, "SetCursor", cursor ); + + virtual void OnCommand( const char *pchCommand ); + + void AddHeader( const char *pchHeader, const char *pchValue ); + void OnKillFocus(); + void OnSetFocus(); + + void Find( const char *pchSubStr ); + void StopFind(); + void FindNext(); + void FindPrevious(); + void ShowFindDialog(); + void HideFindDialog(); + bool FindDialogVisible(); + int HorizontalScrollMax() { return m_scrollHorizontal.m_nMax; } + int VerticalScrollMax() { return m_scrollVertical.m_nMax; } + + void GetLinkAtPosition( int x, int y ); + + void HidePopup(); + +#ifdef DBGFLAG_VALIDATE + virtual void Validate( CValidator &validator, const char *pchName ) + { + ValidateObj( m_CustomURLHandlers ); + BaseClass::Validate( validator, pchName ); + } +#endif // DBGFLAG_VALIDATE + + void PaintComboBox(); + ISteamHTMLSurface *SteamHTMLSurface() { return m_SteamAPIContext.SteamHTMLSurface(); } + + void OnHTMLMouseMoved( int x, int y ) + { + if ( m_SteamAPIContext.SteamHTMLSurface() ) + m_SteamAPIContext.SteamHTMLSurface()->MouseMove( m_unBrowserHandle, x, y ); + } + +protected: + virtual void ApplySchemeSettings( IScheme *pScheme ); + + friend class HTMLComboBoxHost; + vgui::Menu *m_pContextMenu; + + +private: + STEAM_CALLBACK( HTML, BrowserNeedsPaint, HTML_NeedsPaint_t, m_NeedsPaint ); + STEAM_CALLBACK( HTML, BrowserComboNeedsPaint, HTML_ComboNeedsPaint_t, m_ComboNeedsPaint ); + STEAM_CALLBACK( HTML, BrowserStartRequest, HTML_StartRequest_t, m_StartRequest ); + STEAM_CALLBACK( HTML, BrowserURLChanged, HTML_URLChanged_t, m_URLChanged ); + STEAM_CALLBACK( HTML, BrowserFinishedRequest, HTML_FinishedRequest_t, m_FinishedRequest ); + STEAM_CALLBACK( HTML, BrowserShowPopup, HTML_ShowPopup_t, m_ShowPopup ); + STEAM_CALLBACK( HTML, BrowserHidePopup, HTML_HidePopup_t, m_HidePopup ); + STEAM_CALLBACK( HTML, BrowserSizePopup, HTML_SizePopup_t, m_SizePopup ); + + STEAM_CALLBACK( HTML, BrowserOpenNewTab, HTML_OpenLinkInNewTab_t, m_LinkInNewTab ); + STEAM_CALLBACK( HTML, BrowserSetHTMLTitle, HTML_ChangedTitle_t, m_ChangeTitle ); + STEAM_CALLBACK( HTML, BrowserPopupHTMLWindow, HTML_NewWindow_t, m_NewWindow ); + STEAM_CALLBACK( HTML, BrowserFileLoadDialog, HTML_FileOpenDialog_t, m_FileLoadDialog ); + STEAM_CALLBACK( HTML, BrowserSearchResults, HTML_SearchResults_t, m_SearchResults ); + STEAM_CALLBACK( HTML, BrowserClose, HTML_CloseBrowser_t, m_CloseBrowser ); + STEAM_CALLBACK( HTML, BrowserHorizontalScrollBarSizeResponse, HTML_HorizontalScroll_t, m_HorizScroll ); + STEAM_CALLBACK( HTML, BrowserVerticalScrollBarSizeResponse, HTML_VerticalScroll_t, m_VertScroll ); + STEAM_CALLBACK( HTML, BrowserLinkAtPositionResponse, HTML_LinkAtPosition_t, m_LinkAtPosResp ); + STEAM_CALLBACK( HTML, BrowserJSAlert, HTML_JSAlert_t, m_JSAlert ); + STEAM_CALLBACK( HTML, BrowserJSConfirm, HTML_JSConfirm_t, m_JSConfirm ); + STEAM_CALLBACK( HTML, BrowserCanGoBackandForward, HTML_CanGoBackAndForward_t, m_CanGoBackForward ); + STEAM_CALLBACK( HTML, BrowserSetCursor, HTML_SetCursor_t, m_SetCursor ); + STEAM_CALLBACK( HTML, BrowserStatusText, HTML_StatusText_t, m_StatusText ); + STEAM_CALLBACK( HTML, BrowserShowToolTip, HTML_ShowToolTip_t, m_ShowTooltip ); + STEAM_CALLBACK( HTML, BrowserUpdateToolTip, HTML_UpdateToolTip_t, m_UpdateTooltip ); + STEAM_CALLBACK( HTML, BrowserHideToolTip, HTML_HideToolTip_t, m_HideTooltip ); + + void OnBrowserReady( HTML_BrowserReady_t *pBrowserReady, bool bIOFailure ); + + void PostURL(const char *URL, const char *pchPostData, bool force); + virtual void BrowserResize(); + void UpdateSizeAndScrollBars(); + MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); + MESSAGE_FUNC_CHARPTR( OnFileSelected, "FileSelected", fullpath ); + MESSAGE_FUNC( OnFileSelectionCancelled, "FileSelectionCancelled" ); + MESSAGE_FUNC_PTR( OnTextChanged, "TextChanged", panel ); + MESSAGE_FUNC_PTR( OnEditNewLine, "TextNewLine", panel ); + MESSAGE_FUNC_INT( DismissJSDialog, "DismissJSDialog", result ); + + vgui::Panel *m_pInteriorPanel; + vgui::ScrollBar *_hbar,*_vbar; + vgui::DHANDLE m_hFileOpenDialog; + class CHTMLFindBar : public vgui::EditablePanel + { + DECLARE_CLASS_SIMPLE( CHTMLFindBar, EditablePanel ); + public: + CHTMLFindBar( HTML *parent ); + void SetText( const char *pchText ) { m_pFindBar->SetText( pchText ); } + void GetText( char *pText, int ccText ) { m_pFindBar->GetText( pText, ccText ); } + void OnCommand( const char *pchCmd ); + void ShowCountLabel() { m_pFindCountLabel->SetVisible( true ); } + void HideCountLabel() { m_pFindCountLabel->SetVisible( false ); } + void SetHidden( bool bState ) { m_bHidden = bState; } + bool BIsHidden() { return m_bHidden; } + + private: + vgui::TextEntry *m_pFindBar; + vgui::HTML *m_pParent; + vgui::Label *m_pFindCountLabel; + bool m_bHidden; + }; + + CHTMLFindBar *m_pFindBar; + HTMLComboBoxHost *m_pComboBoxHost; + + int m_iMouseX,m_iMouseY; // where the mouse is on the control + + int m_iScrollBorderX,m_iScrollBorderY; + int m_iWideLastHTMLSize, m_iTalLastHTMLSize; + int m_iCopyLinkMenuItemID; + + bool m_bScrollBarEnabled; + bool m_bContextMenuEnabled; + int m_iScrollbarSize; + bool m_bNewWindowsOnly; + int m_nViewSourceAllowedIndex; + CUtlString m_sDragURL; + int m_iDragStartX, m_iDragStartY; + + struct CustomURLHandler_t + { + PHandle hPanel; + char url[32]; + }; + CUtlVector m_CustomURLHandlers; + + int m_iHTMLTextureID; // vgui texture id + // Track the texture width and height requested so we can tell + // when the size has changed and reallocate the texture. + int m_allocedTextureWidth; + int m_allocedTextureHeight; + int m_iComboBoxTextureID; // vgui texture id of the combo box + bool m_bNeedsFullTextureUpload; + int m_allocedComboBoxWidth; + int m_allocedComboBoxHeight; + CUtlString m_sCurrentURL; // the url of our current page + // find in page state + bool m_bInFind; + CUtlString m_sLastSearchString; + + bool m_bCanGoBack; // cache of forward and back state + bool m_bCanGoForward; + + struct LinkAtPos_t + { + LinkAtPos_t() { m_nX = m_nY = 0; } + uint32 m_nX; + uint32 m_nY; + CUtlString m_sURL; + }; + LinkAtPos_t m_LinkAtPos; // cache for link at pos requests, because the request is async + bool m_bRequestingDragURL; // true if we need a response for a drag url loc + bool m_bRequestingCopyLink; // true if we wanted to copy the link under the cursor + + struct ScrollData_t + { + ScrollData_t() + { + m_bVisible = false; + m_nMax = m_nScroll = 0; + } + + bool operator==( ScrollData_t const &src ) const + { + return m_bVisible == src.m_bVisible && + m_nMax == src.m_nMax && + m_nScroll == src.m_nScroll; + } + + bool operator!=( ScrollData_t const &src ) const + { + return !operator==(src); + } + + + bool m_bVisible; // is the scroll bar visible + int m_nMax; // most amount of pixels we can scroll + int m_nScroll; // currently scrolled amount of pixels + float m_flZoom; // zoom level this scroll bar is for + }; + + ScrollData_t m_scrollHorizontal; // details of horizontal scroll bar + ScrollData_t m_scrollVertical; // details of vertical scroll bar + float m_flZoom; // current page zoom level + + CUtlString m_sPendingURLLoad; // cache of url to load if we get a PostURL before the cef object is mage + CUtlString m_sPendingPostData; // cache of the post data for above + + struct CustomCursorCache_t + { + CustomCursorCache_t() {} + CustomCursorCache_t( const void *pchData ) { m_pchData = pchData; } + float m_CacheTime; // the time we cached the cursor + CursorCode m_Cursor; // the vgui handle to it + const void *m_pchData; // the pointer to the cursor char data so we can detect the same cursor being used + bool operator==(const CustomCursorCache_t& rhs) const + { + return m_pchData == rhs.m_pchData ; + } + }; + CUtlVector m_vecHCursor; + + CSteamAPIContext m_SteamAPIContext; + HHTMLBrowser m_unBrowserHandle; + CCallResult< HTML, HTML_BrowserReady_t > m_SteamCallResultBrowserReady; +}; + +} // namespace vgui + +#endif // HTML_H diff --git a/sp/src/public/vgui_controls/Image.h b/sp/src/public/vgui_controls/Image.h new file mode 100644 index 00000000..9ed128e7 --- /dev/null +++ b/sp/src/public/vgui_controls/Image.h @@ -0,0 +1,80 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef IMAGE_H +#define IMAGE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include + +namespace vgui +{ + +class Panel; + +//----------------------------------------------------------------------------- +// Purpose: Basic image control +//----------------------------------------------------------------------------- +class Image : public IImage +{ +public: + Image(); + virtual ~Image(); + + // Set the position of the image + virtual void SetPos( int x, int y ); + // Get the position of the image + virtual void GetPos( int &x, int &y ); + // Get the size of the image + virtual void GetSize( int &wide, int &tall ); + virtual void GetContentSize( int &wide, int &tall ); + // Set the draw color + virtual void SetColor( Color color ); + // set the background color + virtual void SetBkColor( Color color ) { DrawSetColor( color ); } + // Get the draw color + virtual Color GetColor(); + virtual bool Evict(); + virtual int GetNumFrames(); + virtual void SetFrame( int nFrame ); + virtual HTexture GetID(); + virtual void SetRotation( int iRotation ) { return; }; + +protected: + virtual void SetSize(int wide, int tall); + virtual void DrawSetColor(Color color); + virtual void DrawSetColor(int r, int g, int b, int a); + virtual void DrawFilledRect(int x0, int y0, int x1, int y1); + virtual void DrawOutlinedRect(int x0, int y0, int x1, int y1); + virtual void DrawLine(int x0,int y0,int x1,int y1); + virtual void DrawPolyLine(int *px, int *py, int numPoints); + virtual void DrawSetTextFont(HFont font); + virtual void DrawSetTextColor(Color color); + virtual void DrawSetTextColor(int r, int g, int b, int a); + virtual void DrawSetTextPos(int x,int y); + virtual void DrawPrintText(const wchar_t *str, int strlen); + virtual void DrawPrintText(int x, int y, const wchar_t *str, int strlen); + virtual void DrawPrintChar(wchar_t ch); + virtual void DrawPrintChar(int x, int y, wchar_t ch); + virtual void DrawSetTexture(int id); + virtual void DrawTexturedRect(int x0, int y0, int x1, int y1); + virtual void Paint() = 0; + +private: + int _pos[2]; + int _size[2]; + Color _color; +}; + +} // namespace vgui + +#endif // IMAGE_H diff --git a/sp/src/public/vgui_controls/ImageList.h b/sp/src/public/vgui_controls/ImageList.h new file mode 100644 index 00000000..db9ec638 --- /dev/null +++ b/sp/src/public/vgui_controls/ImageList.h @@ -0,0 +1,56 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef IMAGELIST_H +#define IMAGELIST_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: holds a collection of images +// used by controls so that images can be refered to by indices +//----------------------------------------------------------------------------- +class ImageList +{ +public: + ImageList(bool deleteImagesWhenDone); + ~ImageList(); + + // adds a new image to the list, returning the index it was placed at + int AddImage(vgui::IImage *image); + + // returns the number of images + int GetImageCount(); + + // returns true if an index is valid + bool IsValidIndex(int imageIndex); + + // sets an image at a specified index, growing and adding NULL images if necessary + void SetImageAtIndex(int index, vgui::IImage *image); + + // gets an image, imageIndex is of range [0, GetImageCount) + // image index 0 is always the blank image + vgui::IImage *GetImage(int imageIndex); + +private: + CUtlVector m_Images; + bool m_bDeleteImagesWhenDone; +}; + + +} // namespace vgui + +#endif // IMAGELIST_H diff --git a/sp/src/public/vgui_controls/ImagePanel.h b/sp/src/public/vgui_controls/ImagePanel.h new file mode 100644 index 00000000..bba8f88b --- /dev/null +++ b/sp/src/public/vgui_controls/ImagePanel.h @@ -0,0 +1,92 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef IMAGEPANEL_H +#define IMAGEPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class IImage; + +//----------------------------------------------------------------------------- +// Purpose: Panel that holds a single image +//----------------------------------------------------------------------------- +class ImagePanel : public Panel +{ + DECLARE_CLASS_SIMPLE( ImagePanel, Panel ); +public: + ImagePanel(Panel *parent, const char *name); + ~ImagePanel(); + + virtual void SetImage(IImage *image); + virtual void SetImage(const char *imageName); + virtual IImage *GetImage(); + char *GetImageName(); + + void SetShouldCenterImage( bool state ) { m_bCenterImage = state; } + bool GetShouldCenterImage() const { return m_bCenterImage; } + + // sets whether or not the image should scale to fit the size of the ImagePanel (defaults to false) + void SetShouldScaleImage( bool state ); + bool GetShouldScaleImage(); + void SetScaleAmount( float scale ); + float GetScaleAmount( void ); + + void SetTileImage( bool bTile ) { m_bTileImage = bTile; } + + // set the color to fill with, if no image is specified + void SetFillColor( Color col ); + Color GetFillColor(); + + virtual Color GetDrawColor( void ); + virtual void SetDrawColor( Color drawColor ); + + virtual void ApplySettings(KeyValues *inResourceData); + + // unhooks and evicts image if possible, caller must re-establish + bool EvictImage(); + + int GetNumFrames(); + void SetFrame( int nFrame ); + + void SetRotation( int iRotation ) { m_iRotation = iRotation; } + +protected: + virtual void PaintBackground(); + virtual void GetSettings(KeyValues *outResourceData); + virtual const char *GetDescription(); + virtual void OnSizeChanged(int newWide, int newTall); + virtual void ApplySchemeSettings( IScheme *pScheme ); + +private: + IImage *m_pImage; + char *m_pszImageName; + char *m_pszFillColorName; + char *m_pszDrawColorName; + bool m_bPositionImage; + bool m_bCenterImage; + bool m_bScaleImage; + bool m_bTileImage; + bool m_bTileHorizontally; + bool m_bTileVertically; + float m_fScaleAmount; + Color m_FillColor; + Color m_DrawColor; + int m_iRotation; +}; + +} // namespace vgui + +#endif // IMAGEPANEL_H diff --git a/sp/src/public/vgui_controls/InputDialog.h b/sp/src/public/vgui_controls/InputDialog.h new file mode 100644 index 00000000..00b8d6f5 --- /dev/null +++ b/sp/src/public/vgui_controls/InputDialog.h @@ -0,0 +1,106 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef INPUTDIALOG_H +#define INPUTDIALOG_H +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class Label; +class Button; +class TextEntry; + + +//----------------------------------------------------------------------------- +// Purpose: Utility dialog base class - just has context kv and ok/cancel buttons +//----------------------------------------------------------------------------- +class BaseInputDialog : public Frame +{ + DECLARE_CLASS_SIMPLE( BaseInputDialog, Frame ); + +public: + BaseInputDialog( vgui::Panel *parent, const char *title ); + ~BaseInputDialog(); + + void DoModal( KeyValues *pContextKeyValues = NULL ); + +protected: + virtual void PerformLayout(); + virtual void PerformLayout( int x, int y, int w, int h ) {} + + // command buttons + virtual void OnCommand( const char *command ); + + void CleanUpContextKeyValues(); + KeyValues *m_pContextKeyValues; + +private: + vgui::Button *m_pCancelButton; + vgui::Button *m_pOKButton; +}; + +//----------------------------------------------------------------------------- +// Purpose: Utility dialog, used to ask yes/no questions of the user +//----------------------------------------------------------------------------- +class InputMessageBox : public BaseInputDialog +{ + DECLARE_CLASS_SIMPLE( InputMessageBox, BaseInputDialog ); + +public: + InputMessageBox( vgui::Panel *parent, const char *title, char const *prompt ); + ~InputMessageBox(); + +protected: + virtual void PerformLayout( int x, int y, int w, int h ); + +private: + vgui::Label *m_pPrompt; +}; + +//----------------------------------------------------------------------------- +// Purpose: Utility dialog, used to let user type in some text +//----------------------------------------------------------------------------- +class InputDialog : public BaseInputDialog +{ + DECLARE_CLASS_SIMPLE( InputDialog, BaseInputDialog ); + +public: + InputDialog( vgui::Panel *parent, const char *title, char const *prompt, char const *defaultValue = "" ); + ~InputDialog(); + + void SetMultiline( bool state ); + + /* action signals + + "InputCompleted" + "text" - the text entered + + "InputCanceled" + */ + void AllowNumericInputOnly( bool bOnlyNumeric ); + +protected: + virtual void PerformLayout( int x, int y, int w, int h ); + + // command buttons + virtual void OnCommand(const char *command); + +private: + vgui::Label *m_pPrompt; + vgui::TextEntry *m_pInput; +}; + +} // namespace vgui + + +#endif // INPUTDIALOG_H diff --git a/sp/src/public/vgui_controls/KeyBindingHelpDialog.h b/sp/src/public/vgui_controls/KeyBindingHelpDialog.h new file mode 100644 index 00000000..3e4d0ede --- /dev/null +++ b/sp/src/public/vgui_controls/KeyBindingHelpDialog.h @@ -0,0 +1,63 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef KEYBINDINGHELPDIALOG_H +#define KEYBINDINGHELPDIALOG_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/Frame.h" +#include "vgui/KeyCode.h" + +namespace vgui +{ + +class ListPanel; +class CKeyBoardEditorDialog; + +//----------------------------------------------------------------------------- +// Purpose: Dialog for use in editing keybindings +//----------------------------------------------------------------------------- +class CKeyBindingHelpDialog : public Frame +{ + DECLARE_CLASS_SIMPLE( CKeyBindingHelpDialog, Frame ); + +public: + CKeyBindingHelpDialog( Panel *parent, Panel *panelToView, KeyBindingContextHandle_t handle, KeyCode code, int modifiers ); + ~CKeyBindingHelpDialog(); + + virtual void OnCommand( char const *cmd ); + virtual void OnKeyCodeTyped(vgui::KeyCode code); + + // The key originally bound to help was pressed + void HelpKeyPressed(); +private: + + virtual void OnTick(); + + bool IsHelpKeyStillBeingHeld(); + + void PopulateList(); + void GetMappingList( Panel *panel, CUtlVector< PanelKeyBindingMap * >& maps ); + + void AnsiText( char const *token, char *out, size_t buflen ); + + vgui::PHandle m_hPanel; + KeyBindingContextHandle_t m_Handle; + KeyCode m_KeyCode; + int m_Modifiers; + + ListPanel *m_pList; + double m_flShowTime; + bool m_bPermanent; + + DHANDLE< CKeyBoardEditorDialog > m_hKeyBindingsEditor; +}; + +} + +#endif // KEYBINDINGHELPDIALOG_H diff --git a/sp/src/public/vgui_controls/KeyBindingMap.h b/sp/src/public/vgui_controls/KeyBindingMap.h new file mode 100644 index 00000000..16641c76 --- /dev/null +++ b/sp/src/public/vgui_controls/KeyBindingMap.h @@ -0,0 +1,225 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef KEYBINDINGMAP_H +#define KEYBINDINGMAP_H +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/utlvector.h" + +// more flexible than default pointers to members code required for casting member function pointers +//#pragma pointers_to_members( full_generality, virtual_inheritance ) + +namespace vgui +{ + +class Panel; + +enum +{ + MODIFIER_SHIFT = ( 1 << 0 ), + MODIFIER_CONTROL = ( 1 << 1 ), + MODIFIER_ALT = ( 1 << 2 ), +}; + +//----------------------------------------------------------------------------- +// Purpose: An actual keybinding, where bindingname references a bindingmap mentioned below +//----------------------------------------------------------------------------- +struct BoundKey_t +{ + BoundKey_t(); + BoundKey_t( const BoundKey_t& src ); + ~BoundKey_t(); + BoundKey_t& operator =( const BoundKey_t& src ); + + bool isbuiltin; // whether this was by the #DECLARE macros or via code/parsing a config file + char const *bindingname; // what it's bound to + int keycode; // vgui keycode + int modifiers; // which modifiers +}; + +//----------------------------------------------------------------------------- +// Purpose: Single item in a message map +// Contains the information to map a string message name with parameters +// to a function call +//----------------------------------------------------------------------------- +struct KeyBindingMap_t +{ + KeyBindingMap_t(); + KeyBindingMap_t( const KeyBindingMap_t& src ); + ~KeyBindingMap_t(); + + char const *bindingname; // for the script file + ALIGN16 MessageFunc_t func; + char const *helpstring; // e.g., #KeybindingPasteHelp + char const *docstring; // e.g., #KeybindingPasteHelp + bool passive; // dispatch command, but still chain +}; + +#define DECLARE_KEYBINDINGMAP( className ) \ + static void KB_AddToMap \ + ( \ + char const *bindingname, \ + vgui::KeyCode defaultcode, \ + int default_modifiers, \ + vgui::MessageFunc_t function, \ + char const *helpstring, \ + char const *docstring, \ + bool passive \ + ) \ + { \ + vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ + \ + vgui::KeyBindingMap_t entry; \ + entry.bindingname = bindingname; \ + \ + entry.func = function; \ + \ + entry.helpstring = helpstring; \ + entry.docstring = docstring; \ + \ + entry.passive = passive; \ + \ + map->entries.AddToTail( entry ); \ + \ + vgui::BoundKey_t kb; \ + kb.isbuiltin = true; \ + kb.bindingname = bindingname; \ + kb.keycode = defaultcode; \ + kb.modifiers = default_modifiers; \ + map->defaultkeys.AddToTail( kb ); \ + map->boundkeys.AddToTail( kb ); \ + } \ + \ + static void KB_ChainToMap( void ) \ + { \ + static bool chained = false; \ + if ( chained ) \ + return; \ + chained = true; \ + vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ + map->pfnClassName = &GetPanelClassName; \ + if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ + { \ + map->baseMap = vgui::FindOrAddPanelKeyBindingMap( GetPanelBaseClassName() ); \ + } \ + } \ + \ + static void KB_AddBoundKey \ + ( \ + char const *bindingname, \ + int keycode, \ + int modifiers \ + ) \ + { \ + vgui::PanelKeyBindingMap *map = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ + vgui::BoundKey_t kb; \ + kb.isbuiltin = true; \ + kb.bindingname = bindingname; \ + kb.keycode = keycode; \ + kb.modifiers = modifiers; \ + map->defaultkeys.AddToTail( kb ); \ + map->boundkeys.AddToTail( kb ); \ + } \ + \ + class className##_RegisterKBMap; \ + friend class className##_RegisterKBMap; \ + class className##_RegisterKBMap \ + { \ + public: \ + className##_RegisterKBMap() \ + { \ + className::KB_ChainToMap(); \ + } \ + }; \ + className##_RegisterKBMap m_RegisterClassKB; \ + \ + virtual vgui::PanelKeyBindingMap *GetKBMap() \ + { \ + static vgui::PanelKeyBindingMap *s_pMap = vgui::FindOrAddPanelKeyBindingMap( GetPanelClassName() ); \ + return s_pMap; \ + } + +#define _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, passive ) \ + class PanelKBMapFunc_##name; \ + friend class PanelKBMapFunc_##name; \ + class PanelKBMapFunc_##name \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + KB_AddToMap( #name, keycode, modifiers, (vgui::MessageFunc_t)&ThisClass::function, help, doc, passive ); \ + } \ + } \ + PanelKBMapFunc_##name() \ + { \ + PanelKBMapFunc_##name::InitVar(); \ + } \ + }; \ + PanelKBMapFunc_##name m_##name##_register; + +#define _KBBindKeyCommon( name, keycode, modifiers, _classname ) \ + class PanelKBBindFunc_##_classname; \ + friend class PanelKBBindFunc_##_classname; \ + class PanelKBBindFunc_##_classname \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + KB_AddBoundKey( #name, keycode, modifiers ); \ + } \ + } \ + PanelKBBindFunc_##_classname() \ + { \ + PanelKBBindFunc_##_classname::InitVar(); \ + } \ + }; \ + PanelKBBindFunc_##_classname m_##_classname##_bindkey_register; + +#define KEYBINDING_FUNC( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, false ); virtual void function() +#define KEYBINDING_FUNC_NODECLARE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, false ); +#define KEYBINDING_FUNC_PASSIVE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, true ); virtual void function() +#define KEYBINDING_FUNC_PASSIVE_NODECLARE( name, keycode, modifiers, function, help, doc ) _KBMapFuncCommonFunc( name, keycode, modifiers, function, help, doc, true ); + +// For definding additional (non-default) keybindings +#define KEYBINDING_ADDBINDING( name, keycode, modifiers ) _KBBindKeyCommon( name, keycode, modifiers, name ); +#define KEYBINDING_ADDBINDING_MULTIPLE( name, keycode, modifiers, _classname ) _KBBindKeyCommon( name, keycode, modifiers, _classname ); + +// mapping, one per class +struct PanelKeyBindingMap +{ + PanelKeyBindingMap() + { + baseMap = NULL; + pfnClassName = NULL; + processed = false; + } + + CUtlVector< KeyBindingMap_t > entries; + bool processed; + PanelKeyBindingMap *baseMap; + CUtlVector< BoundKey_t > defaultkeys; + CUtlVector< BoundKey_t > boundkeys; + char const *(*pfnClassName)( void ); +}; + +PanelKeyBindingMap *FindPanelKeyBindingMap( char const *className ); +PanelKeyBindingMap *FindOrAddPanelKeyBindingMap( char const *className ); + +} // namespace vgui + + +#endif // KEYBINDINGMAP_H diff --git a/sp/src/public/vgui_controls/KeyBoardEditorDialog.h b/sp/src/public/vgui_controls/KeyBoardEditorDialog.h new file mode 100644 index 00000000..209c86f7 --- /dev/null +++ b/sp/src/public/vgui_controls/KeyBoardEditorDialog.h @@ -0,0 +1,138 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef KEYBOARDEDITORDIALOG_H +#define KEYBOARDEDITORDIALOG_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/Frame.h" +#include "vgui_controls/PropertySheet.h" +#include "vgui_controls/PropertyPage.h" + +class VControlsListPanel; + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Dialog for use in editing keybindings +//----------------------------------------------------------------------------- +class CKeyBoardEditorPage : public EditablePanel +{ + DECLARE_CLASS_SIMPLE( CKeyBoardEditorPage, EditablePanel ); + +public: + CKeyBoardEditorPage( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle ); + ~CKeyBoardEditorPage(); + + void SetKeybindingsSaveFile( char const *filename, char const *pathID = 0 ); + + virtual void OnKeyCodeTyped(vgui::KeyCode code); + + virtual void ApplySchemeSettings( IScheme *scheme ); + + void OnSaveChanges(); + void OnRevert(); + void OnUseDefaults(); + +protected: + + virtual void OnPageHide(); + + virtual void OnCommand( char const *cmd ); + + void PopulateList(); + + void GetMappingList( Panel *panel, CUtlVector< PanelKeyBindingMap * >& maps ); + int GetMappingCount( Panel *panel ); + + void BindKey( vgui::KeyCode code ); + + // Trap row selection message + MESSAGE_FUNC( ItemSelected, "ItemSelected" ); + MESSAGE_FUNC_INT( OnClearBinding, "ClearBinding", item ); + + void SaveMappings(); + void UpdateCurrentMappings(); + void RestoreMappings(); + void ApplyMappings(); + +protected: + void AnsiText( char const *token, char *out, size_t buflen ); + + Panel *m_pPanel; + KeyBindingContextHandle_t m_Handle; + + VControlsListPanel *m_pList; + + struct SaveMapping_t + { + SaveMapping_t(); + SaveMapping_t( const SaveMapping_t& src ); + + PanelKeyBindingMap *map; + CUtlVector< BoundKey_t > current; + CUtlVector< BoundKey_t > original; + }; + + CUtlVector< SaveMapping_t * > m_Save; +}; + + +//----------------------------------------------------------------------------- +// Purpose: Dialog for use in editing keybindings +//----------------------------------------------------------------------------- +class CKeyBoardEditorSheet : public PropertySheet +{ + DECLARE_CLASS_SIMPLE( CKeyBoardEditorSheet, PropertySheet ); + +public: + CKeyBoardEditorSheet( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle ); + + void SetKeybindingsSaveFile( char const *filename, char const *pathID = 0 ); + + void OnSaveChanges(); + void OnRevert(); + void OnUseDefaults(); + +protected: + + vgui::PHandle m_hPanel; + KeyBindingContextHandle_t m_Handle; + bool m_bSaveToExternalFile; + CUtlSymbol m_SaveFileName; + CUtlSymbol m_SaveFilePathID; + Color m_clrAlteredItem; +}; + +//----------------------------------------------------------------------------- +// Purpose: Dialog for use in editing keybindings +//----------------------------------------------------------------------------- +class CKeyBoardEditorDialog : public Frame +{ + DECLARE_CLASS_SIMPLE( CKeyBoardEditorDialog, Frame ); + +public: + CKeyBoardEditorDialog( Panel *parent, Panel *panelToEdit, KeyBindingContextHandle_t handle ); + + void SetKeybindingsSaveFile( char const *filename, char const *pathID = 0 ); + + virtual void OnCommand( char const *cmd ); + +private: + CKeyBoardEditorSheet *m_pKBEditor; + + Button *m_pSave; + Button *m_pCancel; + Button *m_pRevert; + Button *m_pUseDefaults; +}; + +} + +#endif // KEYBOARDEDITORDIALOG_H diff --git a/sp/src/public/vgui_controls/KeyRepeat.h b/sp/src/public/vgui_controls/KeyRepeat.h new file mode 100644 index 00000000..83d30a33 --- /dev/null +++ b/sp/src/public/vgui_controls/KeyRepeat.h @@ -0,0 +1,79 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef KEYREPEAT_H +#define KEYREPEAT_H +#ifdef _WIN32 +#pragma once +#endif + +#include + +namespace vgui +{ + +enum KEYREPEAT_ALIASES +{ + KR_ALIAS_UP, + KR_ALIAS_DOWN, + KR_ALIAS_LEFT, + KR_ALIAS_RIGHT, + + FM_NUM_KEYREPEAT_ALIASES, +}; + +class CKeyRepeatHandler +{ +public: + CKeyRepeatHandler() + { + Reset(); + for ( int i = 0; i < FM_NUM_KEYREPEAT_ALIASES; i++ ) + { + m_flRepeatTimes[i] = 0.16; + } + } + + void Reset( void ) { memset( m_bAliasDown, 0, sizeof(bool) * FM_NUM_KEYREPEAT_ALIASES ); m_bHaveKeyDown = false; } + void KeyDown( vgui::KeyCode code ); + void KeyUp( vgui::KeyCode code ); + vgui::KeyCode KeyRepeated( void ); + void SetKeyRepeatTime( vgui::KeyCode code, float flRepeat ); + +private: + int GetIndexForCode( vgui::KeyCode code ) + { + switch ( code ) + { + case KEY_XBUTTON_DOWN: + case KEY_XSTICK1_DOWN: + return KR_ALIAS_DOWN; break; + case KEY_XBUTTON_UP: + case KEY_XSTICK1_UP: + return KR_ALIAS_UP; break; + case KEY_XBUTTON_LEFT: + case KEY_XSTICK1_LEFT: + return KR_ALIAS_LEFT; break; + case KEY_XBUTTON_RIGHT: + case KEY_XSTICK1_RIGHT: + return KR_ALIAS_RIGHT; break; + default: + break; + } + return -1; + } + +private: + bool m_bAliasDown[FM_NUM_KEYREPEAT_ALIASES]; + float m_flRepeatTimes[FM_NUM_KEYREPEAT_ALIASES]; + float m_flNextKeyRepeat; + bool m_bHaveKeyDown; +}; + + +} // namespace vgui + +#endif // KEYREPEAT_H diff --git a/sp/src/public/vgui_controls/Label.h b/sp/src/public/vgui_controls/Label.h new file mode 100644 index 00000000..53422f76 --- /dev/null +++ b/sp/src/public/vgui_controls/Label.h @@ -0,0 +1,225 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef LABEL_H +#define LABEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "utlvector.h" +#include "vgui/VGUI.h" +#include "vgui_controls/Panel.h" +#include "vgui_controls/PHandle.h" + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Contains and displays a set of images +// By default starts with one TextImage +//----------------------------------------------------------------------------- +class Label : public Panel +{ + DECLARE_CLASS_SIMPLE( Label, Panel ); + +public: + // Constructors + Label(Panel *parent, const char *panelName, const char *text); + Label(Panel *parent, const char *panelName, const wchar_t *wszText); + ~Label(); + +public: + // Take the string and looks it up in the localization file to convert it to unicode + virtual void SetText(const char *tokenName); + + // Set unicode text directly + virtual void SetText(const wchar_t *unicodeString, bool bClearUnlocalizedSymbol = false ); + + // Get the current text + virtual void GetText(OUT_Z_BYTECAP(bufferLen) char *textOut, int bufferLen); + virtual void GetText(OUT_Z_BYTECAP(bufLenInBytes) wchar_t *textOut, int bufLenInBytes); + + // Content alignment + // Get the size of the content within the label + virtual void GetContentSize(int &wide, int &tall); + + // Set how the content aligns itself within the label + // alignment code, used to determine how the images are layed out within the Label + enum Alignment + { + a_northwest = 0, + a_north, + a_northeast, + a_west, + a_center, + a_east, + a_southwest, + a_south, + a_southeast, + }; + + virtual void SetContentAlignment(Alignment alignment); + virtual void SetEnabled(bool state); + // Additional offset at the Start of the text (from whichever sides it is aligned) + virtual void SetTextInset(int xInset, int yInset); + virtual void GetTextInset(int *xInset, int *yInset ); + + // Text colors + virtual void SetFgColor(Color color); + virtual Color GetFgColor(); + + // colors to use when the label is disabled + virtual void SetDisabledFgColor1(Color color); + virtual void SetDisabledFgColor2(Color color); + virtual Color GetDisabledFgColor1(); + virtual Color GetDisabledFgColor2(); + + // Set whether the text is displayed bright or dull + enum EColorState + { + CS_NORMAL, + CS_DULL, + CS_BRIGHT, + }; + virtual void SetTextColorState(EColorState state); + + // Font + virtual void SetFont(HFont font); + virtual HFont GetFont(); + + // Hotkey + virtual Panel *HasHotkey(wchar_t key); + virtual void SetHotkey(wchar_t key); + virtual wchar_t GetHotKey(); + + // Labels can be associated with controls, and alter behaviour based on the associates behaviour + // If the associate is disabled, so are we + // If the associate has focus, we may alter how we draw + // If we get a hotkey press or focus message, we forward the focus to the associate + virtual void SetAssociatedControl(Panel *control); + + // Multiple image handling + // Images are drawn from left to right across the label, ordered by index + // By default there is a TextImage in position 0 (see GetTextImage()/SetTextImageIndex()) + virtual int AddImage(IImage *image, int preOffset); // Return the index the image was placed in + virtual void SetImageAtIndex(int index, IImage *image, int preOffset); + virtual void SetImagePreOffset(int index, int preOffset); // Set the offset in pixels before the image + virtual IImage *GetImageAtIndex(int index); + virtual int GetImageCount(); + virtual void ClearImages(); + virtual void ResetToSimpleTextImage(); + // fixes the layout bounds of the image within the label + virtual void SetImageBounds(int index, int x, int width); + + // Teturns a pointer to the default text image + virtual TextImage *GetTextImage(); + + // Moves where the default text image is within the image array (it starts in position 0) + // Setting it to -1 removes it from the image list + // Returns the index the default text image was previously in + virtual int SetTextImageIndex(int newIndex); + + // Message handling + // outputData - keyName is the name of the attribute requested. + // for Labels "text" is an option that returns the default text image text + // returns true on success in finding the requested value. false on failure. + virtual bool RequestInfo(KeyValues *outputData); + /* INFO HANDLING + "GetText" + returns: + "text" - text contained in the label + */ + + /* CUSTOM MESSAGE HANDLING + "SetText" + input: "text" - label text is set to be this string + */ + + virtual void SizeToContents(); + + // the +8 is padding to the content size + // the code which uses it should really set that itself; + // however a lot of existing code relies on this + enum Padding + { + Content = 8, + }; + + void SetWrap( bool bWrap ); + void SetCenterWrap( bool bWrap ); + + void SetAllCaps( bool bAllCaps ); + +protected: + virtual void PerformLayout(); + virtual wchar_t CalculateHotkey(const char *text); + virtual wchar_t CalculateHotkey(const wchar_t *text); + virtual void ComputeAlignment(int &tx0, int &ty0, int &tx1, int &ty1); + virtual void Paint(); + MESSAGE_FUNC_PARAMS( OnSetText, "SetText", params ); + virtual void DrawDashedLine(int x0, int y0, int x1, int y1, int dashLen, int gapLen); + virtual void OnRequestFocus(VPANEL subFocus, VPANEL defaultPanel); + MESSAGE_FUNC( OnHotkeyPressed, "Hotkey" ); + virtual void OnMousePressed(MouseCode code); + virtual void OnSizeChanged(int wide, int tall); + + // makes sure that the maxIndex will be a valid index + virtual void EnsureImageCapacity(int maxIndex); + + // editing + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void GetSettings( KeyValues *outResourceData ); + virtual void ApplySettings( KeyValues *inResourceData ); + virtual const char *GetDescription( void ); + + MESSAGE_FUNC_PARAMS( OnDialogVariablesChanged, "DialogVariables", dialogVariables ); + + void HandleAutoSizing( void ); + +private: + void Init(); + + Alignment _contentAlignment; + TextImage *_textImage; // this is the textImage, if the full text will not + // fit we put as much as we can and add an elipsis (...) + struct TImageInfo + { + IImage *image; + short offset; + short xpos; + short width; + }; + CUtlVector _imageDar; + + int _textInset[2]; + Color _disabledFgColor1; + Color _disabledFgColor2; + Color _associateColor; + int _textImageIndex; // index in the image array that the default _textimage resides + EColorState _textColorState; + + PHandle _associate; + char *_associateName; + + char *_fontOverrideName; + + wchar_t _hotkey; // the hotkey contained in the text + + bool m_bWrap; + bool m_bCenterWrap; + bool m_bAllCaps; + bool m_bAutoWideToContents; + bool m_bAutoWideDirty; + bool m_bUseProportionalInsets; + +}; + +} // namespace vgui + +#endif // LABEL_H diff --git a/sp/src/public/vgui_controls/ListPanel.h b/sp/src/public/vgui_controls/ListPanel.h new file mode 100644 index 00000000..9248856e --- /dev/null +++ b/sp/src/public/vgui_controls/ListPanel.h @@ -0,0 +1,371 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef LISTPANEL_H +#define LISTPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include +#include + +class KeyValues; + +namespace vgui +{ + +class ScrollBar; +class TextImage; +class ImagePanel; +class Label; +class Button; +class IDraggerEvent; +class FastSortListPanelItem; + +//----------------------------------------------------------------------------- +// Purpose: Generic class for ListPanel items +//----------------------------------------------------------------------------- +class ListPanelItem +{ +public: + ListPanelItem() : + kv( 0 ), + userData( 0 ), + m_pDragData( 0 ), + m_bImage( false ), + m_nImageIndex( -1 ), + m_nImageIndexSelected( -1 ), + m_pIcon( 0 ) + { + } + + KeyValues *kv; + unsigned int userData; + KeyValues *m_pDragData; + bool m_bImage; + int m_nImageIndex; + int m_nImageIndexSelected; + IImage *m_pIcon; +}; + +typedef int __cdecl SortFunc( + ListPanel *pPanel, + const ListPanelItem &item1, + const ListPanelItem &item2 ); + +//----------------------------------------------------------------------------- +// Purpose: A spread-sheet type data view, similar to MFC's +//----------------------------------------------------------------------------- +class ListPanel : public Panel +{ + DECLARE_CLASS_SIMPLE( ListPanel, Panel ); + +public: + ListPanel(Panel *parent, const char *panelName); + ~ListPanel(); + + // COLUMN HANDLING + // all indices are 0 based, limit of 255 columns + // columns are resizable by default + enum ColumnFlags_e + { + COLUMN_FIXEDSIZE = 0x01, // set to have the column be a fixed size + COLUMN_RESIZEWITHWINDOW = 0x02, // set to have the column grow with the parent dialog growing + COLUMN_IMAGE = 0x04, // set if the column data is not text, but instead the index of the image to display + COLUMN_HIDDEN = 0x08, // column is hidden by default + COLUMN_UNHIDABLE = 0x10, // column is unhidable + }; + + // adds a column header + virtual void AddColumnHeader(int index, const char *columnName, const char *columnText, int startingWidth, int minWidth, int maxWidth, int columnFlags = 0); + virtual void AddColumnHeader(int index, const char *columnName, const char *columnText, int width, int columnFlags = 0); + + virtual void RemoveColumn(int column); // removes a column + virtual int FindColumn(const char *columnName); + virtual void SetColumnHeaderHeight( int height ); + virtual void SetColumnHeaderText(int column, const char *text); + virtual void SetColumnHeaderText(int column, wchar_t *text); + virtual void SetColumnHeaderImage(int column, int imageListIndex); + virtual void SetColumnHeaderTooltip(int column, const char *tooltipText); + virtual void SetColumnTextAlignment( int column, int align ); + + // Get information about the column headers. + virtual int GetNumColumnHeaders() const; + virtual bool GetColumnHeaderText( int index, char *pOut, int maxLen ); + + virtual void SetSortFunc(int column, SortFunc *func); + virtual void SetSortColumn(int column); + virtual void SortList( void ); + virtual void SetColumnSortable(int column, bool sortable); + virtual void SetColumnVisible(int column, bool visible); + int GetSortColumn() const; + + // sets whether the user can add/remove columns (defaults to off) + virtual void SetAllowUserModificationOfColumns(bool allowed); + + // DATA HANDLING + // data->GetName() is used to uniquely identify an item + // data sub items are matched against column header name to be used in the table + virtual int AddItem(const KeyValues *data, unsigned int userData, bool bScrollToItem, bool bSortOnAdd); // Takes a copy of the data for use in the table. Returns the index the item is at. + void SetItemDragData( int itemID, const KeyValues *data ); // Makes a copy of the keyvalues to store in the table. Used when dragging from the table. Only used if the caller enables drag support + virtual int GetItemCount( void ); // returns the number of VISIBLE items + virtual int GetItem(const char *itemName); // gets the row index of an item by name (data->GetName()) + virtual KeyValues *GetItem(int itemID); // returns pointer to data the row holds + virtual int GetItemCurrentRow(int itemID); // returns -1 if invalid index or item not visible + virtual int GetItemIDFromRow(int currentRow); // returns -1 if invalid row + virtual unsigned int GetItemUserData(int itemID); + virtual ListPanelItem *GetItemData(int itemID); + virtual void SetUserData( int itemID, unsigned int userData ); + virtual int GetItemIDFromUserData( unsigned int userData ); + virtual void ApplyItemChanges(int itemID); // applies any changes to the data, performed by modifying the return of GetItem() above + virtual void RemoveItem(int itemID); // removes an item from the table (changing the indices of all following items) + virtual void RereadAllItems(); // updates the view with the new data + + virtual void RemoveAll(); // clears and deletes all the memory used by the data items + virtual void DeleteAllItems(); // obselete, use RemoveAll(); + + virtual void GetCellText(int itemID, int column, OUT_Z_BYTECAP(bufferSizeInBytes) wchar_t *buffer, int bufferSizeInBytes); // returns the data held by a specific cell + virtual IImage *GetCellImage(int itemID, int column); //, ImagePanel *&buffer); // returns the image held by a specific cell + + // Use these until they return InvalidItemID to iterate all the items. + virtual int FirstItem() const; + virtual int NextItem( int iItem ) const; + + virtual int InvalidItemID() const; + virtual bool IsValidItemID(int itemID); + + // sets whether the dataitem is visible or not + // it is removed from the row list when it becomes invisible, but stays in the indexes + // this is much faster than a normal remove + virtual void SetItemVisible(int itemID, bool state); + virtual void SetItemDisabled(int itemID, bool state ); + bool IsItemVisible( int itemID ); + + virtual void SetFont(HFont font); + + // image handling + virtual void SetImageList(ImageList *imageList, bool deleteImageListWhenDone); + + // SELECTION + + // returns the count of selected items + virtual int GetSelectedItemsCount(); + + // returns the selected item by selection index, valid in range [0, GetNumSelectedRows) + virtual int GetSelectedItem(int selectionIndex); + + // sets no item as selected + virtual void ClearSelectedItems(); + + virtual bool IsItemSelected( int itemID ); + + // adds a item to the select list + virtual void AddSelectedItem( int itemID ); + + // sets this single item as the only selected item + virtual void SetSingleSelectedItem( int itemID ); + + // returns the selected column, -1 for particular column selected + virtual int GetSelectedColumn(); + + // whether or not to select specific cells (off by default) + virtual void SetSelectIndividualCells(bool state); + + // whether or not multiple cells/rows can be selected + void SetMultiselectEnabled( bool bState ); + bool IsMultiselectEnabled() const; + + // sets a single cell - all other previous rows are cleared + virtual void SetSelectedCell(int row, int column); + + virtual bool GetCellAtPos(int x, int y, int &row, int &column); // returns true if any found, row and column are filled out. x, y are in screen space + virtual bool GetCellBounds( int row, int column, int& x, int& y, int& wide, int& tall ); + + // sets the text which is displayed when the list is empty + virtual void SetEmptyListText(const char *text); + virtual void SetEmptyListText(const wchar_t *text); + + // relayout the scroll bar in response to changing the items in the list panel + // do this if you RemoveAll() + void ResetScrollBar(); + + // Attaches drag data to a particular item + virtual void OnCreateDragData( KeyValues *msg ); + + void SetIgnoreDoubleClick( bool state ); + + // set up a field for editing + virtual void EnterEditMode(int itemID, int column, vgui::Panel *editPanel); + + // leaves editing mode + virtual void LeaveEditMode(); + + // returns true if we are currently in inline editing mode + virtual bool IsInEditMode(); + + MESSAGE_FUNC_INT( ResizeColumnToContents, "ResizeColumnToContents", column ); + +#ifdef _X360 + virtual void NavigateTo(); +#endif + /// Version number for file format of user config. This defaults to 1, + /// and if you rearrange columns you can increment it to cause any old + /// user configs (which will be screwed up) to be discarded. + int m_nUserConfigFileVersion; + +protected: + // PAINTING + virtual Panel *GetCellRenderer(int row, int column); + + // overrides + virtual void OnMouseWheeled(int delta); + virtual void OnSizeChanged(int wide, int tall); + virtual void PerformLayout(); + virtual void Paint(); + virtual void PaintBackground(); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void OnMousePressed( MouseCode code ); + virtual void OnMouseDoublePressed( MouseCode code ); +#ifdef _X360 + virtual void OnKeyCodePressed(KeyCode code); +#else + virtual void OnKeyCodePressed( KeyCode code ); +#endif + MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); + MESSAGE_FUNC_INT_INT( OnColumnResized, "ColumnResized", column, delta ); + MESSAGE_FUNC_INT( OnSetSortColumn, "SetSortColumn", column ); + MESSAGE_FUNC( OpenColumnChoiceMenu, "OpenColumnChoiceMenu" ); + MESSAGE_FUNC_INT( OnToggleColumnVisible, "ToggleColumnVisible", col ); + virtual float GetRowsPerPage(); + virtual int GetStartItem(); + + // user configuration + virtual void ApplyUserConfigSettings(KeyValues *userConfig); + virtual void GetUserConfigSettings(KeyValues *userConfig); + virtual bool HasUserConfigSettings(); + + /* MESSAGES SENT + "ItemSelected" - query which items are selected + "ItemDeselected" - query which items are selected + */ + +public: + virtual void SetSortColumnEx( int iPrimarySortColumn, int iSecondarySortColumn, bool bSortAscending ); + void GetSortColumnEx( int &iPrimarySortColumn, int &iSecondarySortColumn, bool &bSortAscending ) const; + +private: + // Cleans up allocations associated with a particular item + void CleanupItem( FastSortListPanelItem *data ); + + // adds the item into the column indexes + void IndexItem(int itemID); + + // Purpose: + void UpdateSelection( vgui::MouseCode code, int x, int y, int row, int column ); + + // Handles multiselect + void HandleMultiSelection( int itemID, int row, int column ); + + // Handles addselect + void HandleAddSelection( int itemID, int row, int column ); + + // pre-sorted columns + struct IndexItem_t + { + ListPanelItem *dataItem; + int duplicateIndex; + }; + typedef CUtlRBTree IndexRBTree_t; + + struct column_t + { + Button *m_pHeader; + int m_iMinWidth; + int m_iMaxWidth; + bool m_bResizesWithWindow; + Panel *m_pResizer; + SortFunc *m_pSortFunc; + bool m_bTypeIsText; + bool m_bHidden; + bool m_bUnhidable; + IndexRBTree_t m_SortedTree; + int m_nContentAlignment; + }; + + // list of the column headers + CUtlLinkedList m_ColumnsData; + + // persistent list of all columns ever created, indexes into m_ColumnsData - used for matching up DATAITEM m_SortedTreeIndexes + CUtlVector m_ColumnsHistory; + + // current list of columns, indexes into m_ColumnsData + CUtlVector m_CurrentColumns; + + int m_iColumnDraggerMoved; // which column dragger was moved->which header to resize + int m_lastBarWidth; + + CUtlLinkedList m_DataItems; + CUtlVector m_VisibleItems; + + // set to true if the table needs to be sorted before it's drawn next + int m_iSortColumn; + int m_iSortColumnSecondary; + + void ResortColumnRBTree(int col); + static bool RBTreeLessFunc(vgui::ListPanel::IndexItem_t &item1, vgui::ListPanel::IndexItem_t &item2); + + TextImage *m_pTextImage; // used in rendering + ImagePanel *m_pImagePanel; // used in rendering + Label *m_pLabel; // used in rendering + ScrollBar *m_hbar; + ScrollBar *m_vbar; + + int m_iSelectedColumn; + + bool m_bNeedsSort : 1; + bool m_bSortAscending : 1; + bool m_bSortAscendingSecondary : 1; + bool m_bCanSelectIndividualCells : 1; + bool m_bShiftHeldDown : 1; + bool m_bMultiselectEnabled : 1; + bool m_bAllowUserAddDeleteColumns : 1; + bool m_bDeleteImageListWhenDone : 1; + bool m_bIgnoreDoubleClick : 1; + + int m_iHeaderHeight; + int m_iRowHeight; + + // selection data + CUtlVector m_SelectedItems; // array of selected rows + int m_LastItemSelected; // remember the last row selected for future shift clicks + + int m_iTableStartX; + int m_iTableStartY; + + Color m_LabelFgColor; + Color m_DisabledColor; + Color m_SelectionFgColor; + Color m_DisabledSelectionFgColor; + + ImageList *m_pImageList; + TextImage *m_pEmptyListText; + + PHandle m_hEditModePanel; + int m_iEditModeItemID; + int m_iEditModeColumn; + + void ResetColumnHeaderCommands(); +}; + +} + +#endif // LISTPANEL_H diff --git a/sp/src/public/vgui_controls/ListViewPanel.h b/sp/src/public/vgui_controls/ListViewPanel.h new file mode 100644 index 00000000..39f1bec7 --- /dev/null +++ b/sp/src/public/vgui_controls/ListViewPanel.h @@ -0,0 +1,121 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef LISTVIEWPANEL_H +#define LISTVIEWPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class ListViewPanel; +typedef bool (*ListViewSortFunc_t)(KeyValues *kv1, KeyValues *kv2); + +class ListViewItem; + +//----------------------------------------------------------------------------- +// Purpose: List Ctrl Panel with each item having an icon and text after it +//----------------------------------------------------------------------------- +class ListViewPanel : public Panel +{ + DECLARE_CLASS_SIMPLE( ListViewPanel, Panel ); + +public: + ListViewPanel(Panel *parent, const char *panelName); + ~ListViewPanel(); + + virtual int AddItem(const KeyValues *data, bool bScrollToItem, bool bSortOnAdd); + virtual int GetItemCount(); + virtual KeyValues *GetItem(int itemID); + virtual void ApplyItemChanges(int itemID); + virtual void RemoveItem(int itemID); + virtual void DeleteAllItems(); + virtual int GetItemIDFromPos(int iPos); // valid from [0, GetItemCount) + + virtual int InvalidItemID(); + virtual bool IsValidItemID(int itemID); + + virtual void ScrollToItem(int itemID); + + virtual void SetSortFunc(ListViewSortFunc_t func); + virtual void SortList(); + + // image handling + virtual void SetImageList(ImageList *imageList, bool deleteImageListWhenDone); + + virtual void SetFont(HFont font); + + // returns the count of selected items + virtual int GetSelectedItemsCount(); + + // returns the selected item by selection index, valid in range [0, GetNumSelectedRows) + virtual int GetSelectedItem(int selectionIndex); + + // sets no item as selected + virtual void ClearSelectedItems(); + + // adds a item to the select list + virtual void AddSelectedItem(int itemID); + + // sets this single item as the only selected item + virtual void SetSingleSelectedItem(int itemID); + +protected: + // overrides + virtual void OnMouseWheeled(int delta); + virtual void OnSizeChanged(int wide, int tall); + virtual void PerformLayout(); + virtual void Paint(); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void OnMousePressed( MouseCode code); + virtual void OnMouseDoublePressed( MouseCode code); + virtual void OnKeyCodeTyped( KeyCode code); + virtual void OnKeyTyped(wchar_t unichar); + MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); + virtual int GetItemsPerColumn(); + +private: + ScrollBar *m_hbar; + + friend class ListViewItem; + void OnItemMousePressed(ListViewItem* pItem, MouseCode code); + void OnItemMouseDoublePressed(ListViewItem* pItem, MouseCode code); + int GetItemsMaxWidth(); + int GetItemIndex(int itemID); + void OnShiftSelect(int itemID); + void FinishKeyPress(int itemID); + + CUtlLinkedList m_DataItems; + CUtlVector m_SortedItems; + ListViewSortFunc_t m_pSortFunc; + + int m_iRowHeight; + HFont m_hFont; + + Color m_LabelFgColor; + Color m_SelectionFgColor; + + // selection data + CUtlVector m_SelectedItems; + int m_LastSelectedItemID; + int m_ShiftStartItemID; + + bool m_bNeedsSort; + bool m_bDeleteImageListWhenDone; + ImageList *m_pImageList; +}; + + +} + +#endif // LISTVIEWPANEL_H diff --git a/sp/src/public/vgui_controls/Menu.h b/sp/src/public/vgui_controls/Menu.h new file mode 100644 index 00000000..2b374373 --- /dev/null +++ b/sp/src/public/vgui_controls/Menu.h @@ -0,0 +1,356 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef MENU_H +#define MENU_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include + +namespace vgui +{ + +class MenuItem; +class ScrollBar; +class MenuSeparator; + +//----------------------------------------------------------------------------- +// Purpose: A menu is a list of items that can be selected with one click, navigated +// with arrow keys and/or hot keys, and have a lit behavior when mouse over. +// It is NOT the button which opens the menu, but only the menu itself. +// +// Behaviour spec: +// Menu navigation can be done in 2 modes, via keyboard keys and via mouse. +// Clicking on menu button opens menu. +// Only one item in a menu is highlighted at a time. +// Only one submenu in a menu is open at a time. +// Disabled menuitems get highlighted via mouse and keys but will not activate. +// +// Mouse: +// Moving mouse into a menuitem highlights it. +// If the menuitem has a cascading menu, the menu opens when the mouse enters +// the menuitem. The cascading menuitem stays highlighted while its menu is open. +// No submenu items are highlighted by default. +// Moving the mouse into another menuitem closes any previously open submenus in the list. +// Clicking once in the menu item activates the menu item and closes all menus. +// Moving the mouse off a menuitem unhighlights it. +// The scroll bar arrows can be used to move up/down the menu one item at a time. +// The clicking and dragging on the scroll bar nob also scrolls the menu items. +// If a highlighed menuitem scrolls off, and the user then begins navigating via keys, +// the menu will snap the scroll bar so the highlighted item is visible. +// If user has been navigating via keys, moving the mouse over a menu item +// highlights it. +// Mousewheel: +// You must have the mouse inside the menu/scroll bar to use the wheel. +// The mouse wheel moves the highlighted menuitem up or down the list. +// If the list has no scroll bar the wheel will cycle from the bottom of the list +// to the top of the list and vice versa. +// If the list has a scrollbar the mouse wheel will stop at the top or bottom +// of the list. +// If the mouse is over the scroll bar no items are highlighted. +// Keyboard: +// When a menu is opened, no items are highlighted. +// If a menuitem has a cascading menu it does not open when the item is highlighted. +// The down arrow selects the next item in the list. +// (first item if none are highlighted and there is a scrollbar). +// The up arrow selects the previous item in the list +// (first item if none are highlighted and there is a scrollbar, last item if none are +// highlighted and there is no scrollbar). +// Selecting a new menuitem closes any previously open submenus in the list. +// The enter key activates the selected item and closes all menus. +// If the selected item has a cascading menu, activating it opens its submenu. +// These may also be activated by pressing the right arrow. +// Pressing the left arrow closes the submenu. +// When the submenu is opened the cascading menuitem stays highlighted. +// No items in the submenu are highlighted when it is opened. +// +// Note: Cascading menuitems in menus with a scrollbar is not supported. +// Its a clunky UI and if we want this we should design a better solution, +// perhaps along the lines of how explorer's bookmarks does it. +// It currently functions, but there are some arm/disarm bugs. +// +// +//----------------------------------------------------------------------------- +class Menu : public Panel +{ + DECLARE_CLASS_SIMPLE( Menu, Panel ); + friend class MenuItem; +public: + enum MenuDirection_e + { + LEFT, + RIGHT, + UP, + DOWN, + CURSOR, // make the menu appear under the mouse cursor + ALIGN_WITH_PARENT, // make the menu appear under the parent + }; + + Menu(Panel *parent, const char *panelName); + ~Menu(); + + static void PlaceContextMenu( Panel *parent, Menu *menu ); + static void OnInternalMousePressed( Panel *other, MouseCode code ); + + virtual void PositionRelativeToPanel( Panel *reference, MenuDirection_e direction, int nAdditionalYOffset = 0, bool showMenu = false ); + + // the menu. For combo boxes, it's the edit/field, etc. etc. + + // Add a simple text item to the menu + virtual int AddMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, const KeyValues *userData = NULL ); + virtual int AddMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, const KeyValues *userData = NULL ); + + virtual int AddMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target , const KeyValues *userData = NULL); + virtual int AddMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target , const KeyValues *userData = NULL); + + virtual int AddMenuItem( const char *itemText, const char *command, Panel *target , const KeyValues *userData = NULL); + virtual int AddMenuItem( const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); + virtual int AddMenuItem( const char *itemText, Panel *target, const KeyValues *userData = NULL ); + + // Add a checkable item to the menu + virtual int AddCheckableMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, const KeyValues *userData = NULL ); + virtual int AddCheckableMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, const KeyValues *userData = NULL ); + + virtual int AddCheckableMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); + virtual int AddCheckableMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); + + virtual int AddCheckableMenuItem( const char *itemText, const char *command, Panel *target , const KeyValues *userData = NULL); + virtual int AddCheckableMenuItem( const char *itemText, KeyValues *message, Panel *target, const KeyValues *userData = NULL ); + virtual int AddCheckableMenuItem( const char *itemText, Panel *target, const KeyValues *userData = NULL ); + + // Add a cascading menu item to the menu + virtual int AddCascadingMenuItem( const char *itemName, const char *itemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + virtual int AddCascadingMenuItem( const char *itemName, const wchar_t *wszItemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + + virtual int AddCascadingMenuItem( const char *itemName, const char *itemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + virtual int AddCascadingMenuItem( const char *itemName, const wchar_t *wszItemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + + virtual int AddCascadingMenuItem( const char *itemText, const char *command, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + virtual int AddCascadingMenuItem( const char *itemText, KeyValues *message, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + virtual int AddCascadingMenuItem( const char *itemText, Panel *target, Menu *cascadeMenu, const KeyValues *userData = NULL ); + + // Add a custom panel to the menu + virtual int AddMenuItem( MenuItem *panel ); + + virtual void AddSeparator(); + virtual void AddSeparatorAfterItem( int itemID ); + + // Sets the values of a menu item at the specified index + virtual void UpdateMenuItem(int itemID, const char *itemText,KeyValues *message, const KeyValues *userData = NULL); + virtual void UpdateMenuItem(int itemID, const wchar_t *wszItemText,KeyValues *message, const KeyValues *userData = NULL); + + virtual void MoveMenuItem( int itemID, int moveBeforeThisItemID ); + + virtual bool IsValidMenuID(int itemID); + virtual int GetInvalidMenuID(); + + KeyValues *GetItemUserData(int itemID); + void GetItemText(int itemID, wchar_t *text, int bufLenInBytes); + void GetItemText(int itemID, char *text, int bufLenInBytes); + + virtual void SetItemEnabled(const char *itemName, bool state); + virtual void SetItemEnabled(int itemID, bool state); + virtual void SetItemVisible(const char *itemName, bool visible); + virtual void SetItemVisible(int itemID, bool visible); + + // Remove a single item + void DeleteItem( int itemID ); + + // Clear the menu, deleting all the menu items within + void DeleteAllItems(); + + // Override the auto-width setting with a single fixed width + virtual void SetFixedWidth( int width ); + + // Sets the content alignment of all items in the menu + void SetContentAlignment( Label::Alignment alignment ); + + // sets the height of each menu item + virtual void SetMenuItemHeight(int itemHeight); + virtual int GetMenuItemHeight() const; + + // Set the max number of items visible (scrollbar appears with more) + virtual void SetNumberOfVisibleItems( int numItems ); + + // Add the menu to the menu manager (see Menu::SetVisible())? + void EnableUseMenuManager( bool bUseMenuManager ); + + // Set up the menu items layout + virtual void PerformLayout( void ); + + virtual void SetBorder(class IBorder *border); + virtual void ApplySchemeSettings(IScheme *pScheme); + + // Set type ahead behaviour + enum MenuTypeAheadMode + { + COMPAT_MODE = 0, + HOT_KEY_MODE, + TYPE_AHEAD_MODE, + }; + virtual void SetTypeAheadMode(MenuTypeAheadMode mode); + virtual int GetTypeAheadMode(); + + // Hotkey handling + virtual void OnKeyTyped(wchar_t unichar); + // Menu nagivation etc. + virtual void OnKeyCodeTyped( KeyCode code ); + + // Visibility + virtual void SetVisible(bool state); + + // Activates item in the menu list, as if that menu item had been selected by the user + virtual void ActivateItem(int itemID); + virtual void SilentActivateItem(int itemID); // activate item, but don't fire the action signal + virtual void ActivateItemByRow(int row); + virtual int GetActiveItem(); // returns the itemID (not the row) of the active item + + // Return the number of items currently in the menu list + virtual int GetItemCount(); + + // return the menuID of the n'th item in the menu list, valid from [0, GetItemCount) + virtual int GetMenuID(int index); + + // Return the number of items currently visible in the menu list + int GetCurrentlyVisibleItemsCount(); + + MenuItem *GetMenuItem(int itemID); + void CloseOtherMenus(MenuItem *item); + virtual void OnKillFocus(); + + int GetMenuMode(); + enum MenuMode + { + MOUSE = 0, + KEYBOARD, + }; + + void SetCurrentlyHighlightedItem(int itemID); + int GetCurrentlyHighlightedItem(); + void ClearCurrentlyHighlightedItem(); + + // Set the checked state of a checkable menuItem + void SetMenuItemChecked(int itemID, bool state); + bool IsChecked(int index); // check if item is checked. + + + void SetMinimumWidth(int width); + int GetMinimumWidth(); + + // baseclass overrides to chain colors through to cascade menus + virtual void SetFgColor( Color newColor ); + virtual void SetBgColor( Color newColor ); + + virtual void SetFont( HFont font ); + + // Pass in NULL hotkey to remove hotkey + void SetCurrentKeyBinding( int itemID, char const *hotkey ); + + void ForceCalculateWidth(); + + void SetUseFallbackFont( bool bState, HFont hFallback ); + +protected: + // helper functions + int AddMenuItemCharCommand(MenuItem *item, const char *command, Panel *target, const KeyValues *userData); + int AddMenuItemKeyValuesCommand(MenuItem *item, KeyValues *message, Panel *target, const KeyValues *userData); + + // vgui result reporting + virtual void OnCommand( const char *command ); + MESSAGE_FUNC_PTR( OnMenuItemSelected, "MenuItemSelected", panel ); + virtual void AddScrollBar(); + virtual void RemoveScrollBar(); + MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); + virtual void Paint(); + virtual void LayoutMenuBorder(); + virtual void MakeItemsVisibleInScrollRange( int maxVisibleItems, int nNumPixelsAvailable ); + virtual void OnMouseWheeled(int delta); + // Alternate OnKeyTyped behaviors + virtual void OnHotKey(wchar_t unichar); + virtual void OnTypeAhead(wchar_t unichar); + + int CountVisibleItems(); + void ComputeWorkspaceSize( int& workWide, int& workTall ); + int ComputeFullMenuHeightWithInsets(); + + void CalculateWidth(); + + void LayoutScrollBar(); + void PositionCascadingMenu(); + void SizeMenuItems(); + void OnCursorMoved(int x, int y); + void OnKeyCodePressed(KeyCode code); + void OnMenuClose(); + MESSAGE_FUNC( OnKeyModeSet, "KeyModeSet" ); + + void SetCurrentlySelectedItem(MenuItem *item); + void SetCurrentlySelectedItem(int itemID); + MESSAGE_FUNC_INT( OnCursorEnteredMenuItem, "CursorEnteredMenuItem", VPanel); + MESSAGE_FUNC_INT( OnCursorExitedMenuItem, "CursorExitedMenuItem", VPanel); + + void MoveAlongMenuItemList(int direction, int loopCount); + + enum + { + DEFAULT_MENU_ITEM_HEIGHT = 22, // height of items in the menu + MENU_UP = -1, // used for moving up/down list of menu items in the menu + MENU_DOWN = 1 + }; + +#ifdef DBGFLAG_VALIDATE + virtual void Validate( CValidator &validator, char *pchName ); +#endif // DBGFLAG_VALIDATE + +private: + MenuItem *GetParentMenuItem(); + + int m_iMenuItemHeight; + int m_iFixedWidth; + int m_iMinimumWidth; // a minimum width the menu has to be if it is not fixed width + int m_iNumVisibleLines; // number of items in menu before scroll bar adds on + ScrollBar *m_pScroller; + + CUtlLinkedList m_MenuItems; + + CUtlVector m_VisibleSortedItems; + CUtlVector m_SortedItems; // used for visual + CUtlVector m_Separators; // menu item ids after which separators should be shown + CUtlVector m_SeparatorPanels; + + bool _sizedForScrollBar: 1 ; // whether menu has been sized for a scrollbar + bool m_bUseFallbackFont : 1; + bool _recalculateWidth : 1; + bool m_bUseMenuManager : 1; + + int _menuWide; + int m_iCurrentlySelectedItemID; + int m_iInputMode; + int m_iCheckImageWidth; // the size of the check box spot on a checkable menu. + int m_iProportionalScrollBarSize; + Label::Alignment m_Alignment; + Color _borderDark; + int m_iActivatedItem; + HFont m_hItemFont; + HFont m_hFallbackItemFont; + + // for managing type ahead + #define TYPEAHEAD_BUFSIZE 256 + MenuTypeAheadMode m_eTypeAheadMode; + wchar_t m_szTypeAheadBuf[TYPEAHEAD_BUFSIZE]; + int m_iNumTypeAheadChars; + double m_fLastTypeAheadTime; +}; + +} // namespace vgui + +#endif // MENU_H diff --git a/sp/src/public/vgui_controls/MenuBar.h b/sp/src/public/vgui_controls/MenuBar.h new file mode 100644 index 00000000..01ccc06a --- /dev/null +++ b/sp/src/public/vgui_controls/MenuBar.h @@ -0,0 +1,54 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MENUBAR_H +#define MENUBAR_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class MenuBar : public Panel +{ + DECLARE_CLASS_SIMPLE( MenuBar, Panel ); + +public: + MenuBar(Panel *parent, const char *panelName); + ~MenuBar(); + + virtual void AddButton(MenuButton *button); // add button to end of menu list + virtual void AddMenu( const char *pButtonName, Menu *pMenu ); + + virtual void GetContentSize( int& w, int&h ); + +protected: + virtual void OnKeyCodeTyped(KeyCode code); + virtual void OnKeyTyped(wchar_t unichar); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void PerformLayout(); + virtual void Paint(); + MESSAGE_FUNC( OnMenuClose, "MenuClose" ); + MESSAGE_FUNC_INT( OnCursorEnteredMenuButton, "CursorEnteredMenuButton", VPanel); + +private: + CUtlVector m_pMenuButtons; + int m_nRightEdge; +}; + +} // namespace vgui + +#endif // MENUBAR_H + diff --git a/sp/src/public/vgui_controls/MenuButton.h b/sp/src/public/vgui_controls/MenuButton.h new file mode 100644 index 00000000..a90fb236 --- /dev/null +++ b/sp/src/public/vgui_controls/MenuButton.h @@ -0,0 +1,82 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MENUBUTTON_H +#define MENUBUTTON_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include "vgui_controls/Menu.h" + +namespace vgui +{ + +class Menu; +class TextImage; + +//----------------------------------------------------------------------------- +// Purpose: Button that displays a menu when pressed +//----------------------------------------------------------------------------- +class MenuButton : public Button +{ + DECLARE_CLASS_SIMPLE( MenuButton, Button ); + +public: + MenuButton(Panel *parent, const char *panelName, const char *text); + ~MenuButton(); + + // functions designed to be overriden + virtual void OnShowMenu(Menu *menu) {} + virtual void OnHideMenu(Menu *menu) {} + virtual int OnCheckMenuItemCount() { return 0; } + + virtual void SetMenu(Menu *menu); + virtual void HideMenu(void); + virtual void DrawFocusBorder(int tx0, int ty0, int tx1, int ty1); + MESSAGE_FUNC( OnMenuClose, "MenuClose" ); + MESSAGE_FUNC_PARAMS( OnKillFocus, "KillFocus", kv ); // called after the panel loses the keyboard focus + virtual void DoClick(); + virtual void SetOpenOffsetY(int yOffset); + + virtual bool CanBeDefaultButton(void); + + // sets the direction in which the menu opens from the button, defaults to down + virtual void SetOpenDirection(Menu::MenuDirection_e direction); + + virtual void OnKeyCodeTyped(KeyCode code); + virtual void OnCursorEntered(); + + virtual void Paint(); + virtual void PerformLayout(); + virtual void ApplySchemeSettings( IScheme *pScheme ); + virtual void OnCursorMoved( int x, int y ); + + // This style is like the IE "back" button where the left side acts like a regular button, the the right side has a little + // combo box dropdown indicator and presents and submenu + void SetDropMenuButtonStyle( bool state ); + bool IsDropMenuButtonStyle() const; + + Menu *GetMenu(); + +private: + + Menu *m_pMenu; + Menu::MenuDirection_e m_iDirection; + + int _openOffsetY; // vertical offset of menu from the menu button + + bool m_bDropMenuButtonStyle : 1; + TextImage *m_pDropMenuImage; + int m_nImageIndex; +}; + +}; // namespace vgui + +#endif // MENUBUTTON_H diff --git a/sp/src/public/vgui_controls/MenuItem.h b/sp/src/public/vgui_controls/MenuItem.h new file mode 100644 index 00000000..6baa512e --- /dev/null +++ b/sp/src/public/vgui_controls/MenuItem.h @@ -0,0 +1,136 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MENUITEM_H +#define MENUITEM_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include + +namespace vgui +{ + +class IBorder; +class TextImage; +class Menu; +class Image; + +//----------------------------------------------------------------------------- +// Purpose: The items in a menu +// MenuItems MUST have the Menu class as parents. +//----------------------------------------------------------------------------- +class MenuItem : public Button +{ + DECLARE_CLASS_SIMPLE( MenuItem, Button ); + +public: + MenuItem(Menu *parent, const char *panelName, const char *text, Menu *cascadeMenu = NULL, bool checkable = false); + MenuItem(Menu *parent, const char *panelName, const wchar_t *wszText, Menu *cascadeMenu = NULL, bool checkable = false); + ~MenuItem(); + + virtual void Paint(); + + // Activate the menu item as if it had been selected by the user + virtual void FireActionSignal(); + + virtual bool CanBeDefaultButton(void); + + // Handle mouse cursor entering a MenuItem. + void OnCursorEntered(); + // Handle mouse cursor exiting a MenuItem. + void OnCursorExited(); + + // Close the cascading menu if we have one. + void CloseCascadeMenu(); + + // Pass kill focus events up to parent on loss of focus + MESSAGE_FUNC( OnKillFocus, "MenuClose" ); + + // Return true if this item triggers a cascading menu + bool HasMenu(); + + // Set the size of the text portion of the label. + void SetTextImageSize(int wide, int tall); + + //Return the size of the text portion of the label. + void GetTextImageSize(int &wide, int &tall); + + // Return the size of the arrow portion of the label. + void GetArrowImageSize(int &wide, int &tall); + + // Return the size of the check portion of the label. + void GetCheckImageSize(int &wide, int &tall); + + // Return the menu that this menuItem contains + Menu *GetMenu(); + + virtual void PerformLayout(); + + // Respond to cursor movement + void OnCursorMoved(int x, int y); + + // Highlight item + MESSAGE_FUNC( ArmItem, "ArmItem" ); + // Unhighlight item. + MESSAGE_FUNC( DisarmItem, "DisarmItem" ); + + // is the item highlighted? + bool IsItemArmed(); + + // Open cascading menu if there is one. + void OpenCascadeMenu(); + + bool IsCheckable(); + bool IsChecked(); + + // Set a checkable menuItem checked or unchecked. + void SetChecked(bool state); + + KeyValues *GetUserData(); + void SetUserData(const KeyValues *kv); + + int GetActiveItem() { if ( m_pCascadeMenu ) { return m_pCascadeMenu->GetActiveItem(); } else { return 0; }} + + Menu *GetParentMenu(); + + void SetCurrentKeyBinding( char const *keyName ); + + virtual void GetContentSize( int& cw, int &ch ); + +protected: + void OnKeyCodeReleased(KeyCode code); + void OnMenuClose(); + MESSAGE_FUNC( OnKeyModeSet, "KeyModeSet" ); + + // vgui overrides + virtual void Init( void ); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); + +private: + enum { CHECK_INSET = 6 }; + Menu *m_pCascadeMenu; // menu triggered to open upon selecting this menu item + bool m_bCheckable; // can this menu item have a little check to the left of it when you select it? + bool m_bChecked; // whether item is checked or not. + TextImage *m_pCascadeArrow; // little arrow that appears to the right of menuitems that open a menu + Image *m_pCheck; // the check that appears to the left of checked menu items + TextImage *m_pBlankCheck; // a blank image same size as the check for when items are not checked. + + TextImage *m_pCurrentKeyBinding; // An optional indicator for the key currently bound to this menu item + + KeyValues *m_pUserData; + +}; + +} // namespace vgui + +#endif // MENUITEM_H diff --git a/sp/src/public/vgui_controls/MessageBox.h b/sp/src/public/vgui_controls/MessageBox.h new file mode 100644 index 00000000..47918223 --- /dev/null +++ b/sp/src/public/vgui_controls/MessageBox.h @@ -0,0 +1,98 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MESSAGEBOX_H +#define MESSAGEBOX_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +// prevent windows macros from messing with the class +#ifdef MessageBox +#undef MessageBox +#endif + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Popup discardable message box +//----------------------------------------------------------------------------- +class MessageBox : public Frame +{ + DECLARE_CLASS_SIMPLE( MessageBox, Frame ); + +public: + // title - Text to be displayed in the title bar of the window + // text - Text message in the message box + // startMinimized - wether message box starts minimized. Starts invisible by default + // parent - parent panel of the message box, by default it has no parent. This will keep the box visible until the OK button is pressed. + MessageBox(const char *title, const char *text, Panel *parent = NULL); + MessageBox(const wchar_t *wszTitle, const wchar_t *wszText, Panel *parent = NULL); + ~MessageBox(); + + // Put the message box into a modal state + virtual void DoModal(Frame *pFrameOver = NULL); + + // make the message box appear and in a modeless state + virtual void ShowWindow(Frame *pFrameOver = NULL); + + // Set a string command to be sent when the OK button is pressed + // Use AddActionSignalTarget() to mark yourself as a recipient of the command + virtual void SetCommand(const char *command); + virtual void SetCommand(KeyValues *command); + + // Set the visibility of the OK button. + virtual void SetOKButtonVisible(bool state); + + // Set the text on the OK button + virtual void SetOKButtonText(const char *buttonText); + virtual void SetOKButtonText(const wchar_t *wszButtonText); + + // Cancel button (off by default) + void SetCancelButtonVisible(bool state); + void SetCancelButtonText(const char *buttonText); + void SetCancelButtonText(const wchar_t *wszButtonText); + void SetCancelCommand( KeyValues *command ); + + // Toggles visibility of the close box. + virtual void DisableCloseButton(bool state); + + virtual void OnCommand( const char *pCommand ); + + // Shows the message box over the cursor + void ShowMessageBoxOverCursor( bool bEnable ); + +protected: + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme *pScheme); + +protected: + Button *m_pOkButton; + Button *m_pCancelButton; + Label *m_pMessageLabel; + +private: + MESSAGE_FUNC( OnShutdownRequest, "ShutdownRequest" ); + + void Init(); + + KeyValues *m_OkCommand; + KeyValues *m_CancelCommand; + vgui::Frame *m_pFrameOver; + bool m_bNoAutoClose : 1; + bool m_bShowMessageBoxOverCursor : 1; +}; + +} // namespace vgui + + +#endif // MESSAGEBOX_H diff --git a/sp/src/public/vgui_controls/MessageDialog.h b/sp/src/public/vgui_controls/MessageDialog.h new file mode 100644 index 00000000..191bb2b6 --- /dev/null +++ b/sp/src/public/vgui_controls/MessageDialog.h @@ -0,0 +1,154 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Contains the CMessageDialog declaration +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MESSAGEDIALOG_H +#define MESSAGEDIALOG_H +#ifdef _WIN32 +#pragma once +#endif + +// styles +#define MD_WARNING 0x0001 +#define MD_ERROR 0x0002 + +// button configurations +#define MD_OK 0x0004 // 1 button - OK +#define MD_CANCEL 0x0008 // 1 button - CANCEL +#define MD_OKCANCEL 0x0010 // 2 buttons - OK and CANCEL +#define MD_YESNO 0x0020 // 2 buttons - YES and NO + +// behavior +#define MD_SIMPLEFRAME 0x0100 // legacy corners +#define MD_COMMANDAFTERCLOSE 0x0200 // send command at dialog termination (i.e. after fade) +#define MD_RESTRICTPAINT 0x0400 // only paint this dialog (hide any other ui elements) +#define MD_COMMANDONFORCECLOSE 0x0800 // send command when the dialog is closed assuming A input + +// dialog type +enum EDialogType +{ + MD_SAVE_BEFORE_QUIT, + MD_QUIT_CONFIRMATION, + MD_QUIT_CONFIRMATION_TF, + MD_KICK_CONFIRMATION, + MD_CLIENT_KICKED, + MD_LOST_HOST, + MD_LOST_SERVER, + MD_SEARCHING_FOR_GAMES, + MD_CREATING_GAME, + MD_MODIFYING_SESSION, + MD_SESSION_SEARCH_FAILED, + MD_SESSION_CREATE_FAILED, + MD_SESSION_CONNECTING, + MD_SESSION_CONNECT_NOTAVAILABLE, + MD_SESSION_CONNECT_SESSIONFULL, + MD_SESSION_CONNECT_FAILED, + MD_EXIT_SESSION_CONFIRMATION, + MD_STORAGE_DEVICES_NEEDED, + MD_STORAGE_DEVICES_CHANGED, + MD_STORAGE_DEVICES_TOO_FULL, + MD_NOT_ONLINE_ENABLED, + MD_NOT_ONLINE_SIGNEDIN, + MD_DEFAULT_CONTROLS_CONFIRM, + MD_AUTOSAVE_EXPLANATION, + MD_COMMENTARY_EXPLANATION, + MD_COMMENTARY_EXPLANATION_MULTI, + MD_COMMENTARY_CHAPTER_UNLOCK_EXPLANATION, + MD_SAVE_BEFORE_LANGUAGE_CHANGE, + MD_SAVE_BEFORE_NEW_GAME, + MD_SAVE_BEFORE_LOAD, + MD_DELETE_SAVE_CONFIRM, + MD_SAVE_OVERWRITE, + MD_SAVING_WARNING, + MD_SAVE_COMPLETE, + MD_STANDARD_SAMPLE, + MD_WARNING_SAMPLE, + MD_ERROR_SAMPLE, + MD_PROMPT_SIGNIN, + MD_PROMPT_SIGNIN_REQUIRED, + MD_PROMPT_STORAGE_DEVICE, + MD_PROMPT_STORAGE_DEVICE_REQUIRED, + MD_DISCONNECT_CONFIRMATION, + MD_DISCONNECT_CONFIRMATION_HOST, + MD_LOAD_FAILED_WARNING, + MD_OPTION_CHANGE_FROM_X360_DASHBOARD, + MD_STORAGE_DEVICES_CORRUPT, + MD_CHECKING_STORAGE_DEVICE +}; + +#include "vgui_controls/Frame.h" +#include "vgui_controls/Label.h" +#include "vgui_controls/AnimatingImagePanel.h" +#include "vgui_controls/ImagePanel.h" + +//----------------------------------------------------------------------------- +// Purpose: Simple modal dialog box for Xbox 360 warnings and messages +//----------------------------------------------------------------------------- +class CMessageDialog : public vgui::Frame +{ + DECLARE_CLASS_SIMPLE( CMessageDialog, vgui::Frame ); + +public: + CMessageDialog( vgui::Panel *parent, const uint nType, const char *pTitle, const char *pMsg, const char *pCmdA, const char *pCmdB, vgui::Panel *pParent, bool bShowActivity ); + ~CMessageDialog(); + + enum + { + BTN_INVALID = -1, + BTN_B, + BTN_A, + MAX_BUTTONS, + }; + + struct ButtonLabel_s + { + vgui::Label *pIcon; + vgui::Label *pText; + int nWide; + bool bCreated; + }; + + virtual void OnKeyCodePressed( vgui::KeyCode code ); + virtual void ApplySchemeSettings( vgui::IScheme *pScheme ); + virtual void ApplySettings( KeyValues *inResourceData ); + virtual void PaintBackground(); + uint GetType( void ); + void SetControlSettingsKeys( KeyValues *pKeys ); + +private: + void CreateButtonLabel( ButtonLabel_s *pButton, const char *pIcon, const char *pText ); + void DoCommand( int button ); + + vgui::Panel *m_pCreator; + + vgui::Label *m_pTitle; + vgui::Label *m_pMsg; + vgui::ImagePanel *m_pBackground; + + vgui::AnimatingImagePanel *m_pAnimatingPanel; + + vgui::HFont m_hButtonFont; + vgui::HFont m_hTextFont; + uint m_nType; + Color m_ButtonTextColor; + int m_ButtonPressed; + KeyValues *m_pControlSettings; + + int m_FooterTall; + int m_ButtonMargin; + Color m_clrNotSimpleBG; + Color m_clrNotSimpleBGBlack; + int m_ButtonIconLabelSpace; + + int m_ActivityIndent; + + bool m_bShowActivity; // should we show an animating image panel? + + ButtonLabel_s m_Buttons[MAX_BUTTONS]; + char *m_pCommands[MAX_BUTTONS]; +}; + +#endif // MESSAGEDIALOG_H diff --git a/sp/src/public/vgui_controls/MessageMap.h b/sp/src/public/vgui_controls/MessageMap.h new file mode 100644 index 00000000..226c0adc --- /dev/null +++ b/sp/src/public/vgui_controls/MessageMap.h @@ -0,0 +1,381 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef MESSAGEMAP_H +#define MESSAGEMAP_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/utlvector.h" + +// more flexible than default pointers to members code required for casting member function pointers +//#pragma pointers_to_members( full_generality, virtual_inheritance ) + +namespace vgui +{ + +////////////// MESSAGEMAP DEFINITIONS ////////////// + + +//----------------------------------------------------------------------------- +// Purpose: parameter data type enumeration +// used internal but the shortcut macros require this to be exposed +//----------------------------------------------------------------------------- +enum DataType_t +{ + DATATYPE_VOID, + DATATYPE_CONSTCHARPTR, + DATATYPE_INT, + DATATYPE_FLOAT, + DATATYPE_PTR, + DATATYPE_BOOL, + DATATYPE_KEYVALUES, + DATATYPE_CONSTWCHARPTR, + DATATYPE_UINT64, + DATATYPE_HANDLE, // It's an int, really +}; + +#ifdef WIN32 +class __virtual_inheritance Panel; +#else +class Panel; +#endif +typedef unsigned int VPANEL; + +typedef void (Panel::*MessageFunc_t)(void); + +//----------------------------------------------------------------------------- +// Purpose: Single item in a message map +// Contains the information to map a string message name with parameters +// to a function call +//----------------------------------------------------------------------------- +#pragma warning(disable:4121) +struct MessageMapItem_t +{ + const char *name; + // VC6 aligns this to 16-bytes. Since some of the code has been compiled with VC6, + // we need to enforce the alignment on later compilers to remain compatible. + ALIGN16 MessageFunc_t func; + + int numParams; + + DataType_t firstParamType; + const char *firstParamName; + + DataType_t secondParamType; + const char *secondParamName; + + int nameSymbol; + int firstParamSymbol; + int secondParamSymbol; +}; + +#define DECLARE_PANELMESSAGEMAP( className ) \ + static void AddToMap( char const *scriptname, vgui::MessageFunc_t function, int paramCount, int p1type, const char *p1name, int p2type, const char *p2name ) \ + { \ + vgui::PanelMessageMap *map = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ + \ + vgui::MessageMapItem_t entry; \ + entry.name = scriptname; \ + entry.func = function; \ + entry.numParams = paramCount; \ + entry.firstParamType = (vgui::DataType_t)p1type; \ + entry.firstParamName = p1name; \ + entry.secondParamType = (vgui::DataType_t)p2type; \ + entry.secondParamName = p2name; \ + entry.nameSymbol = 0; \ + entry.firstParamSymbol = 0; \ + entry.secondParamSymbol = 0; \ + \ + map->entries.AddToTail( entry ); \ + } \ + \ + static void ChainToMap( void ) \ + { \ + static bool chained = false; \ + if ( chained ) \ + return; \ + chained = true; \ + vgui::PanelMessageMap *map = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ + map->pfnClassName = &GetPanelClassName; \ + if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ + { \ + map->baseMap = vgui::FindOrAddPanelMessageMap( GetPanelBaseClassName() ); \ + } \ + } \ + \ + class className##_RegisterMap; \ + friend class className##_RegisterMap; \ + class className##_RegisterMap \ + { \ + public: \ + className##_RegisterMap() \ + { \ + className::ChainToMap(); \ + } \ + }; \ + className##_RegisterMap m_RegisterClass; \ + \ + virtual vgui::PanelMessageMap *GetMessageMap() \ + { \ + static vgui::PanelMessageMap *s_pMap = vgui::FindOrAddPanelMessageMap( GetPanelClassName() ); \ + return s_pMap; \ + } + +#if !defined( _XBOX ) +#define VGUI_USEKEYBINDINGMAPS 1 +#endif + +#if defined( VGUI_USEKEYBINDINGMAPS ) + +#define DECLARE_CLASS_SIMPLE( className, baseClassName ) \ + typedef baseClassName BaseClass; \ + typedef className ThisClass; \ +public: \ + DECLARE_PANELMESSAGEMAP( className ); \ + DECLARE_PANELANIMATION( className ); \ + DECLARE_KEYBINDINGMAP( className ); \ + static char const *GetPanelClassName() { return #className; } \ + static char const *GetPanelBaseClassName() { return #baseClassName; } + +#define DECLARE_CLASS_SIMPLE_NOBASE( className ) \ + typedef className ThisClass; \ +public: \ + DECLARE_PANELMESSAGEMAP( className ); \ + DECLARE_PANELANIMATION( className ); \ + DECLARE_KEYBINDINGMAP( className ); \ + static char const *GetPanelClassName() { return #className; } \ + static char const *GetPanelBaseClassName() { return NULL; } + +#else // no keybinding maps + +#define DECLARE_CLASS_SIMPLE( className, baseClassName ) \ + typedef baseClassName BaseClass; \ + typedef className ThisClass; \ +public: \ + DECLARE_PANELMESSAGEMAP( className ); \ + DECLARE_PANELANIMATION( className ); \ + static char const *GetPanelClassName() { return #className; } \ + static char const *GetPanelBaseClassName() { return #baseClassName; } + +#define DECLARE_CLASS_SIMPLE_NOBASE( className ) \ + typedef className ThisClass; \ +public: \ + DECLARE_PANELMESSAGEMAP( className ); \ + DECLARE_PANELANIMATION( className ); \ + static char const *GetPanelClassName() { return #className; } \ + static char const *GetPanelBaseClassName() { return NULL; } + +#endif // !VGUI_USEKEYBINDINGMAPS + +#define _MessageFuncCommon( name, scriptname, paramCount, p1type, p1name, p2type, p2name ) \ + class PanelMessageFunc_##name; \ + friend class PanelMessageFunc_##name; \ + class PanelMessageFunc_##name \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + AddToMap( scriptname, (vgui::MessageFunc_t)&ThisClass::name, paramCount, p1type, p1name, p2type, p2name ); \ + } \ + } \ + PanelMessageFunc_##name() \ + { \ + PanelMessageFunc_##name::InitVar(); \ + } \ + }; \ + PanelMessageFunc_##name m_##name##_register; \ + +// Use this macro to define a message mapped function +// must end with a semicolon ';', or with a function +// no parameter +#define MESSAGE_FUNC( name, scriptname ) _MessageFuncCommon( name, scriptname, 0, 0, 0, 0, 0 ); virtual void name( void ) + +// one parameter +#define MESSAGE_FUNC_INT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_INT, #p1, 0, 0 ); virtual void name( int p1 ) +#define MESSAGE_FUNC_UINT64( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_UINT64, #p1, 0, 0 ); virtual void name( uint64 p1 ) +#define MESSAGE_FUNC_PTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_PTR, #p1, 0, 0 ); virtual void name( vgui::Panel *p1 ) +#define MESSAGE_FUNC_HANDLE( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_HANDLE, #p1, 0, 0 ); virtual void name( vgui::VPANEL p1 ) +#define MESSAGE_FUNC_ENUM( name, scriptname, t1, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_INT, #p1, 0, 0 ); virtual void name( t1 p1 ) +#define MESSAGE_FUNC_FLOAT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_FLOAT, #p1, 0, 0 ); virtual void name( float p1 ) +#define MESSAGE_FUNC_CHARPTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_CONSTCHARPTR, #p1, 0, 0 ); virtual void name( const char *p1 ) +#define MESSAGE_FUNC_WCHARPTR( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_CONSTWCHARPTR, #p1, 0, 0 ); virtual void name( const wchar_t *p1 ) + +// two parameters +#define MESSAGE_FUNC_INT_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( int p1, int p2 ) +#define MESSAGE_FUNC_PTR_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( vgui::Panel *p1, int p2 ) +#define MESSAGE_FUNC_HANDLE_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( vgui::VPANEL p1, int p2 ) +#define MESSAGE_FUNC_ENUM_ENUM( name, scriptname, t1, p1, t2, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_INT, #p2 ); virtual void name( t1 p1, t2 p2 ) +#define MESSAGE_FUNC_INT_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( int p1, const char *p2 ) +#define MESSAGE_FUNC_PTR_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( vgui::Panel *p1, const char *p2 ) +#define MESSAGE_FUNC_HANDLE_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( vgui::VPANEL p1, const char *p2 ) +#define MESSAGE_FUNC_PTR_WCHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_PTR, #p1, vgui::DATATYPE_CONSTWCHARPTR, #p2 ); virtual void name( vgui::Panel *p1, const wchar_t *p2 ) +#define MESSAGE_FUNC_HANDLE_WCHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_HANDLE, #p1, vgui::DATATYPE_CONSTWCHARPTR, #p2 ); virtual void name( vgui::VPANEL p1, const wchar_t *p2 ) +#define MESSAGE_FUNC_CHARPTR_CHARPTR( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_CONSTCHARPTR, #p1, vgui::DATATYPE_CONSTCHARPTR, #p2 ); virtual void name( const char *p1, const char *p2 ) + +// unlimited parameters (passed in the whole KeyValues) +#define MESSAGE_FUNC_PARAMS( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_KEYVALUES, NULL, 0, 0 ); virtual void name( KeyValues *p1 ) + +// no-virtual function version +#define MESSAGE_FUNC_NV( name, scriptname ) _MessageFuncCommon( name, scriptname, 0, 0, 0, 0, 0 ); void name( void ) +#define MESSAGE_FUNC_NV_INT( name, scriptname, p1 ) _MessageFuncCommon( name, scriptname, 1, vgui::DATATYPE_INT, #p1, 0, 0 ); void name( int p1 ) +#define MESSAGE_FUNC_NV_INT_INT( name, scriptname, p1, p2 ) _MessageFuncCommon( name, scriptname, 2, vgui::DATATYPE_INT, #p1, vgui::DATATYPE_INT, #p2 ); void name( int p1, int p2 ) + + +// mapping, one per class +struct PanelMessageMap +{ + PanelMessageMap() + { + baseMap = NULL; + pfnClassName = NULL; + processed = false; + } + + CUtlVector< MessageMapItem_t > entries; + bool processed; + PanelMessageMap *baseMap; + char const *(*pfnClassName)( void ); +}; + +PanelMessageMap *FindPanelMessageMap( char const *className ); +PanelMessageMap *FindOrAddPanelMessageMap( char const *className ); + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// OBSELETE MAPPING FUNCTIONS, USE ABOVE +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// no parameters +#define MAP_MESSAGE( type, name, func ) { name, (vgui::MessageFunc_t)(&type::func), 0 } + +// implicit single parameter (params is the data store) +#define MAP_MESSAGE_PARAMS( type, name, func ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_KEYVALUES, NULL } + +// single parameter +#define MAP_MESSAGE_PTR( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_PTR, param1 } +#define MAP_MESSAGE_INT( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_INT, param1 } +#define MAP_MESSAGE_BOOL( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_BOOL, param1 } +#define MAP_MESSAGE_FLOAT( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_FLOAT, param1 } +#define MAP_MESSAGE_PTR( type, name, func, param1 ) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_PTR, param1 } +#define MAP_MESSAGE_CONSTCHARPTR( type, name, func, param1) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_CONSTCHARPTR, param1 } +#define MAP_MESSAGE_CONSTWCHARPTR( type, name, func, param1) { name, (vgui::MessageFunc_t)(&type::func), 1, vgui::DATATYPE_CONSTWCHARPTR, param1 } + +// two parameters +#define MAP_MESSAGE_INT_INT( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_INT, param1, vgui::DATATYPE_INT, param2 } +#define MAP_MESSAGE_PTR_INT( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_INT, param2 } +#define MAP_MESSAGE_INT_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_INT, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } +#define MAP_MESSAGE_PTR_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } +#define MAP_MESSAGE_PTR_CONSTWCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_PTR, param1, vgui::DATATYPE_CONSTWCHARPTR, param2 } +#define MAP_MESSAGE_CONSTCHARPTR_CONSTCHARPTR( type, name, func, param1, param2 ) { name, (vgui::MessageFunc_t)&type::func, 2, vgui::DATATYPE_CONSTCHARPTR, param1, vgui::DATATYPE_CONSTCHARPTR, param2 } + +// if more parameters are needed, just use MAP_MESSAGE_PARAMS() and pass the keyvalue set into the function + +//----------------------------------------------------------------------------- +// Purpose: stores the list of objects in the hierarchy +// used to iterate through an object's message maps +//----------------------------------------------------------------------------- +struct PanelMap_t +{ + MessageMapItem_t *dataDesc; + int dataNumFields; + const char *dataClassName; + PanelMap_t *baseMap; + int processed; +}; + +// for use in class declarations +// declares the static variables and functions needed for the data description iteration +#define DECLARE_PANELMAP() \ + static vgui::PanelMap_t m_PanelMap; \ + static vgui::MessageMapItem_t m_MessageMap[]; \ + virtual vgui::PanelMap_t *GetPanelMap( void ); + +// could embed typeid() into here as well? +#define IMPLEMENT_PANELMAP( derivedClass, baseClass ) \ + vgui::PanelMap_t derivedClass::m_PanelMap = { derivedClass::m_MessageMap, ARRAYSIZE(derivedClass::m_MessageMap), #derivedClass, &baseClass::m_PanelMap }; \ + vgui::PanelMap_t *derivedClass::GetPanelMap( void ) { return &m_PanelMap; } + +typedef vgui::Panel *( *PANELCREATEFUNC )( void ); + +//----------------------------------------------------------------------------- +// Purpose: Used by DECLARE_BUILD_FACTORY macro to create a linked list of +// instancing functions +//----------------------------------------------------------------------------- +class CBuildFactoryHelper +{ +public: + // Static list of helpers + static CBuildFactoryHelper *m_sHelpers; + +public: + // Construction + CBuildFactoryHelper( char const *className, PANELCREATEFUNC func ); + + // Accessors + CBuildFactoryHelper *GetNext( void ); + + char const *GetClassName() const; + + vgui::Panel *CreatePanel(); + + static vgui::Panel *InstancePanel( char const *className ); + static void GetFactoryNames( CUtlVector< char const * >& list ); +private: + + static bool HasFactory( char const *className ); + + // Next factory in list + CBuildFactoryHelper *m_pNext; + + int m_Type; + PANELCREATEFUNC m_CreateFunc; + char const *m_pClassName; +}; + +// This is the macro which implements creation of each type of panel +// It creates a function which instances an object of the specified type +// It them hooks that function up to the helper list so that the CHud objects can create +// the elements by name, with no header file dependency, etc. +#define DECLARE_BUILD_FACTORY( className ) \ + static vgui::Panel *Create_##className( void ) \ + { \ + return new className( NULL, NULL ); \ + }; \ + static vgui::CBuildFactoryHelper g_##className##_Helper( #className, Create_##className );\ + className *g_##className##LinkerHack = NULL; + +#define DECLARE_BUILD_FACTORY_DEFAULT_TEXT( className, defaultText ) \ + static vgui::Panel *Create_##className( void ) \ + { \ + return new className( NULL, NULL, #defaultText ); \ + }; \ + static vgui::CBuildFactoryHelper g_##className##_Helper( #className, Create_##className );\ + className *g_##className##LinkerHack = NULL; + +// This one allows passing in a special function with calls new panel( xxx ) with arbitrary default parameters +#define DECLARE_BUILD_FACTORY_CUSTOM( className, createFunc ) \ + static vgui::CBuildFactoryHelper g_##className##_Helper( #className, createFunc );\ + className *g_##className##LinkerHack = NULL; + +#define DECLARE_BUILD_FACTORY_CUSTOM_ALIAS( className, factoryName, createFunc ) \ + static vgui::CBuildFactoryHelper g_##factoryName##_Helper( #factoryName, createFunc );\ + className *g_##factoryName##LinkerHack = NULL; + +} // namespace vgui + + +#endif // MESSAGEMAP_H diff --git a/sp/src/public/vgui_controls/PHandle.h b/sp/src/public/vgui_controls/PHandle.h new file mode 100644 index 00000000..959ee4a9 --- /dev/null +++ b/sp/src/public/vgui_controls/PHandle.h @@ -0,0 +1,86 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PHANDLE_H +#define PHANDLE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include + +namespace vgui +{ + +class Panel; + +//----------------------------------------------------------------------------- +// Purpose: Safe pointer class for handling Panel or derived panel classes +//----------------------------------------------------------------------------- +class PHandle +{ +public: + PHandle() : m_iPanelID(INVALID_PANEL) {} //m_iSerialNumber(0), m_pListEntry(0) {} + + Panel *Get(); + Panel *Set( Panel *pPanel ); + Panel *Set( HPanel hPanel ); + + operator Panel *() { return Get(); } + Panel * operator ->() { return Get(); } + Panel * operator = (Panel *pPanel) { return Set(pPanel); } + + bool operator == (Panel *pPanel) { return (Get() == pPanel); } + operator bool () { return Get() != 0; } + +private: + HPanel m_iPanelID; +}; + +//----------------------------------------------------------------------------- +// Purpose: Safe pointer class to just convert between VPANEL's and PHandle +//----------------------------------------------------------------------------- +class VPanelHandle +{ +public: + VPanelHandle() : m_iPanelID(INVALID_PANEL) {} + + VPANEL Get(); + VPANEL Set( VPANEL pPanel ); + + operator VPANEL () { return Get(); } + VPANEL operator = (VPANEL pPanel) { return Set(pPanel); } + + bool operator == (VPANEL pPanel) { return (Get() == pPanel); } + operator bool () { return Get() != 0; } + +private: + HPanel m_iPanelID; +}; + +//----------------------------------------------------------------------------- +// Purpose: DHANDLE is a templated version of PHandle +//----------------------------------------------------------------------------- +template< class PanelType > +class DHANDLE : public PHandle +{ +public: + PanelType *Get() { return (PanelType *)PHandle::Get(); } + PanelType *Set( PanelType *pPanel ) { return (PanelType *)PHandle::Set(pPanel); } + PanelType *Set( HPanel hPanel ) { return (PanelType *)PHandle::Set(hPanel); } + + operator PanelType *() { return (PanelType *)PHandle::Get(); } + PanelType * operator ->() { return (PanelType *)PHandle::Get(); } + PanelType * operator = (PanelType *pPanel) { return (PanelType *)PHandle::Set(pPanel); } + bool operator == (Panel *pPanel) { return (PHandle::Get() == pPanel); } + operator bool () { return PHandle::Get() != NULL; } +}; + +}; + +#endif // PHANDLE_H diff --git a/sp/src/public/vgui_controls/Panel.h b/sp/src/public/vgui_controls/Panel.h new file mode 100644 index 00000000..07b63d8d --- /dev/null +++ b/sp/src/public/vgui_controls/Panel.h @@ -0,0 +1,1021 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef PANEL_H +#define PANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/utlflags.h" +#include "vgui/VGUI.h" +#include "vgui/Dar.h" +#include "vgui_controls/MessageMap.h" +#if defined( VGUI_USEKEYBINDINGMAPS ) +#include "vgui_controls/KeyBindingMap.h" +#endif +#include "vgui/IClientPanel.h" +#include "vgui/IScheme.h" +#include "vgui_controls/Controls.h" +#include "vgui_controls/PHandle.h" +#include "vgui_controls/PanelAnimationVar.h" +#include "Color.h" +#include "vstdlib/IKeyValuesSystem.h" +#include "tier1/utlsymbol.h" +#include "vgui_controls/BuildGroup.h" + +// undefine windows function macros that overlap +#ifdef PostMessage +#undef PostMessage +#endif + +#ifdef SetCursor +#undef SetCursor +#endif + +class CUtlBuffer; + +namespace vgui +{ + +#if !defined( _X360 ) +#define VGUI_USEDRAGDROP 1 +#endif + +#if defined( VGUI_USEKEYBINDINGMAPS ) +struct PanelKeyBindingMap; +#endif +//----------------------------------------------------------------------------- +// Purpose: Helper functions to construct vgui panels +// +// SETUP_PANEL - will make a panel ready for use right now (i.e setup its colors, borders, fonts, etc) +// +template< class T > +inline T *SETUP_PANEL(T *panel) +{ + panel->MakeReadyForUse(); + return panel; +} + +// +// CREATE_PANEL - creates a panel that is ready to use right now +// +// example of use = to set the FG Color of a panel inside of a constructor (i.e before ApplySchemeSettings() has been run on the child) +// +#define CREATE_PANEL(type, parent, name) (SETUP_PANEL(new type(parent, name))) + +//----------------------------------------------------------------------------- +// Purpose: Drag/drop support context info (could defined within Panel...) +//----------------------------------------------------------------------------- +#if defined( VGUI_USEDRAGDROP ) +struct DragDrop_t; +class Menu; +#endif + +//----------------------------------------------------------------------------- +// Purpose: Macro to handle Colors that can be overridden in .res files +//----------------------------------------------------------------------------- +struct OverridableColorEntry +{ + char const *name() { return m_pszScriptName; } + + char const *m_pszScriptName; + Color *m_pColor; + Color m_colFromScript; + bool m_bOverridden; +}; + +#define REGISTER_COLOR_AS_OVERRIDABLE( name, scriptname ) \ + AddToOverridableColors( &name, scriptname ); + + + +//----------------------------------------------------------------------------- +// Purpose: For hudanimations.txt scripting of vars +//----------------------------------------------------------------------------- +class IPanelAnimationPropertyConverter +{ +public: + virtual void GetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) = 0; + virtual void SetData( Panel *panel, KeyValues *kv, PanelAnimationMapEntry *entry ) = 0; + virtual void InitFromDefault( Panel *panel, PanelAnimationMapEntry *entry ) = 0; +}; + +#if defined( VGUI_USEKEYBINDINGMAPS ) +enum KeyBindingContextHandle_t +{ + INVALID_KEYBINDINGCONTEXT_HANDLE = 0xffffffff, +}; +#endif + +class IForceVirtualInheritancePanel +{ + // We need Panel to use virtual inheritance so that + // pointers to its members are max size. + // This is due to a limitation in C++ with ahead + // declarations of points to members as used in MessageMap. +}; + +//============================================================================= +// HPE_BEGIN: +// [tj] bitwise defines for rounded corners +//============================================================================= +#define PANEL_ROUND_CORNER_TOP_LEFT (1 << 0) +#define PANEL_ROUND_CORNER_TOP_RIGHT (1 << 1) +#define PANEL_ROUND_CORNER_BOTTOM_LEFT (1 << 2) +#define PANEL_ROUND_CORNER_BOTTOM_RIGHT (1 << 3) +#define PANEL_ROUND_CORNER_ALL PANEL_ROUND_CORNER_TOP_LEFT | PANEL_ROUND_CORNER_TOP_RIGHT | PANEL_ROUND_CORNER_BOTTOM_LEFT | PANEL_ROUND_CORNER_BOTTOM_RIGHT +//============================================================================= +// HPE_END +//=============================================================================//----------------------------------------------------------------------------- +// Purpose: Base interface to all vgui windows +// All vgui controls that receive message and/or have a physical presence +// on screen are be derived from Panel. +// This is designed as an easy-access to the vgui-functionality; for more +// low-level access to vgui functions use the IPanel/IClientPanel interfaces directly +//----------------------------------------------------------------------------- +class Panel : public IClientPanel, virtual IForceVirtualInheritancePanel +{ + DECLARE_CLASS_SIMPLE_NOBASE( Panel ); + +public: + // For property mapping + static void InitPropertyConverters( void ); + static void AddPropertyConverter( char const *typeName, IPanelAnimationPropertyConverter *converter ); + + //----------------------------------------------------------------------------- + // CONSTRUCTORS + // these functions deal with the creation of the Panel + // the Panel automatically gets a handle to a vgui-internal panel, the ipanel(), upon construction + // vgui interfaces deal only with ipanel(), not Panel directly + Panel(); + Panel(Panel *parent); + Panel(Panel *parent, const char *panelName); + Panel(Panel *parent, const char *panelName, HScheme scheme); + + virtual ~Panel(); + + // returns pointer to Panel's vgui VPanel interface handle + virtual VPANEL GetVPanel() { return _vpanel; } + HPanel ToHandle() const; + + virtual void Init( int x, int y, int wide, int tall ); + + //----------------------------------------------------------------------------- + // PANEL METHODS + // these functions all manipulate panels + // they cannot be derived from + void SetName(const char *panelName); // sets the name of the panel - used as an identifier + const char *GetName(); // returns the name of this panel... never NULL + const char *GetClassName(); // returns the class name of the panel (eg. Panel, Label, Button, etc.) + + void MakeReadyForUse(); // fully construct this panel so its ready for use right now (i.e fonts loaded, colors set, default label text set, ...) + + // panel position & size + // all units are in pixels + void SetPos(int x,int y); // sets position of panel, in local space (ie. relative to parent's position) + void GetPos(int &x,int &y); // gets local position of panel + void SetSize(int wide,int tall); // sets size of panel + void GetSize(int &wide, int &tall); // gets size of panel + void SetBounds(int x, int y, int wide, int tall); // combination of SetPos/SetSize + void GetBounds(int &x, int &y, int &wide, int &tall); // combination of GetPos/GetSize + int GetWide(); // returns width of panel + void SetWide(int wide); // sets width of panel + int GetTall(); // returns height of panel + void SetTall(int tall); // sets height of panel + void SetMinimumSize(int wide,int tall); // sets the minimum size the panel can go + void GetMinimumSize(int& wide,int& tall); // gets the minimum size + bool IsBuildModeEditable(); // editable in the buildModeDialog? + void SetBuildModeEditable(bool state); // set buildModeDialog editable + bool IsBuildModeDeletable(); // deletable in the buildModeDialog? + void SetBuildModeDeletable(bool state); // set buildModeDialog deletable + bool IsBuildModeActive(); // true if we're currently in edit mode + void SetZPos(int z); // sets Z ordering - lower numbers are always behind higher z's + int GetZPos( void ); + void SetAlpha(int alpha); // sets alpha modifier for panel and all child panels [0..255] + int GetAlpha(); // returns the current alpha + + // panel visibility + // invisible panels and their children do not drawn, updated, or receive input messages + virtual void SetVisible(bool state); + virtual bool IsVisible(); + + // painting + virtual VPANEL IsWithinTraverse(int x, int y, bool traversePopups); // recursive; returns a pointer to the panel at those coordinates + MESSAGE_FUNC( Repaint, "Repaint" ); // marks the panel as needing to be repainted + virtual void PostMessage(VPANEL target, KeyValues *message, float delaySeconds = 0.0f); + + bool IsWithin(int x, int y); //in screen space + void LocalToScreen(int &x, int &y); + void ScreenToLocal(int &x, int &y); + void ParentLocalToScreen(int &x, int &y); + void MakePopup(bool showTaskbarIcon = true,bool disabled = false); // turns the panel into a popup window (ie. can draw outside of it's parents space) + virtual void OnMove(); + + // panel hierarchy + virtual Panel *GetParent(); + virtual VPANEL GetVParent(); + virtual void SetParent(Panel *newParent); + virtual void SetParent(VPANEL newParent); + virtual bool HasParent(VPANEL potentialParent); + + int GetChildCount(); + Panel *GetChild(int index); + virtual CUtlVector< VPANEL > &GetChildren(); + int FindChildIndexByName( const char *childName ); + Panel *FindChildByName(const char *childName, bool recurseDown = false); + Panel *FindSiblingByName(const char *siblingName); + void CallParentFunction(KeyValues *message); + + template + T *FindControl( const char *pszName, bool recurseDown = false ) { return dynamic_cast( FindChildByName( pszName, recurseDown ) ); } + + virtual void SetAutoDelete(bool state); // if set to true, panel automatically frees itself when parent is deleted + virtual bool IsAutoDeleteSet(); + virtual void DeletePanel(); // simply does a { delete this; } + + // messaging + virtual void AddActionSignalTarget(Panel *messageTarget); + virtual void AddActionSignalTarget(VPANEL messageTarget); + virtual void RemoveActionSignalTarget(Panel *oldTarget); + virtual void PostActionSignal(KeyValues *message); // sends a message to the current actionSignalTarget(s) + virtual bool RequestInfoFromChild(const char *childName, KeyValues *outputData); + virtual void PostMessageToChild(const char *childName, KeyValues *messsage); + virtual void PostMessage(Panel *target, KeyValues *message, float delaySeconds = 0.0f); + virtual bool RequestInfo(KeyValues *outputData); // returns true if output is successfully written. You should always chain back to the base class if info request is not handled + virtual bool SetInfo(KeyValues *inputData); // sets a specified value in the control - inverse of the above + virtual void SetSilentMode( bool bSilent ); //change the panel's silent mode; if silent, the panel will not post any action signals + + // install a mouse handler + virtual void InstallMouseHandler( Panel *pHandler ); // mouse events will be send to handler panel instead of this panel + + // drawing state + virtual void SetEnabled(bool state); + virtual bool IsEnabled(); + virtual bool IsPopup(); // has a parent, but is in it's own space + virtual void GetClipRect(int &x0, int &y0, int &x1, int &y1); + virtual void MoveToFront(); + + // pin positions for auto-layout + enum PinCorner_e + { + PIN_TOPLEFT = 0, + PIN_TOPRIGHT, + PIN_BOTTOMLEFT, + PIN_BOTTOMRIGHT, + + // For sibling pinning + PIN_CENTER_TOP, + PIN_CENTER_RIGHT, + PIN_CENTER_BOTTOM, + PIN_CENTER_LEFT, + }; + + // specifies the auto-resize directions for the panel + enum AutoResize_e + { + AUTORESIZE_NO = 0, + AUTORESIZE_RIGHT, + AUTORESIZE_DOWN, + AUTORESIZE_DOWNANDRIGHT, + }; + + // Sets the pin corner for non-resizing panels + void SetPinCorner( PinCorner_e pinCorner, int nOffsetX, int nOffsetY ); + + // Sets the pin corner + resize mode for resizing panels + void SetAutoResize( PinCorner_e pinCorner, AutoResize_e resizeDir, int nPinOffsetX, int nPinOffsetY, int nUnpinnedCornerOffsetX, int nUnpinnedCornerOffsetY ); + + AutoResize_e GetAutoResize(); + PinCorner_e GetPinCorner(); + + // Gets the relative offset of the control from the pinned + non-pinned corner (for resizing) + void GetPinOffset( int &dx, int &dy ); + void GetResizeOffset( int &dx, int &dy ); + + void PinToSibling( const char *pszSibling, PinCorner_e pinOurCorner, PinCorner_e pinSibling ); + void UpdateSiblingPin( void ); + + // colors + virtual void SetBgColor(Color color); + virtual void SetFgColor(Color color); + virtual Color GetBgColor(); + virtual Color GetFgColor(); + + virtual void SetCursor(HCursor cursor); + virtual HCursor GetCursor(); + virtual void SetCursorAlwaysVisible( bool visible ); + virtual void RequestFocus(int direction = 0); + virtual bool HasFocus(); + virtual void InvalidateLayout(bool layoutNow = false, bool reloadScheme = false); + virtual bool RequestFocusPrev(VPANEL panel = NULL); + virtual bool RequestFocusNext(VPANEL panel = NULL); + // tab positioning + virtual void SetTabPosition(int position); + virtual int GetTabPosition(); + // border + virtual void SetBorder(IBorder *border); + virtual IBorder *GetBorder(); + virtual void SetPaintBorderEnabled(bool state); + virtual void SetPaintBackgroundEnabled(bool state); + virtual void SetPaintEnabled(bool state); + virtual void SetPostChildPaintEnabled(bool state); + virtual void SetPaintBackgroundType(int type); // 0 for normal(opaque), 1 for single texture from Texture1, and 2 for rounded box w/ four corner textures + virtual void GetInset(int &left, int &top, int &right, int &bottom); + virtual void GetPaintSize(int &wide, int &tall); + virtual void SetBuildGroup(BuildGroup *buildGroup); + virtual bool IsBuildGroupEnabled(); + virtual bool IsCursorNone(); + virtual bool IsCursorOver(); // returns true if the cursor is currently over the panel + virtual void MarkForDeletion(); // object will free it's memory next tick + virtual bool IsLayoutInvalid(); // does this object require a perform layout? + virtual Panel *HasHotkey(wchar_t key); // returns the panel that has this hotkey + virtual bool IsOpaque(); + bool IsRightAligned(); // returns true if the settings are aligned to the right of the screen + bool IsBottomAligned(); // returns true if the settings are aligned to the bottom of the screen + + // scheme access functions + virtual HScheme GetScheme(); + virtual void SetScheme(const char *tag); + virtual void SetScheme(HScheme scheme); + virtual Color GetSchemeColor(const char *keyName,IScheme *pScheme); + virtual Color GetSchemeColor(const char *keyName, Color defaultColor,IScheme *pScheme); + + // called when scheme settings need to be applied; called the first time before the panel is painted + virtual void ApplySchemeSettings(IScheme *pScheme); + + // interface to build settings + // takes a group of settings and applies them to the control + virtual void ApplySettings(KeyValues *inResourceData); + + // records the settings into the resource data + virtual void GetSettings(KeyValues *outResourceData); + + // gets a description of the resource for use in the UI + // format: ... + // unknown types as just displayed as strings in the UI (for future UI expansion) + virtual const char *GetDescription(); + + // returns the name of the module that this instance of panel was compiled into + virtual const char *GetModuleName(); + + // user configuration settings + // this is used for any control details the user wants saved between sessions + // eg. dialog positions, last directory opened, list column width + virtual void ApplyUserConfigSettings(KeyValues *userConfig); + + // returns user config settings for this control + virtual void GetUserConfigSettings(KeyValues *userConfig); + + // optimization, return true if this control has any user config settings + virtual bool HasUserConfigSettings(); + + // message handlers + // override to get access to the message + // override to get access to the message + virtual void OnMessage(const KeyValues *params, VPANEL fromPanel); // called when panel receives message; must chain back + MESSAGE_FUNC_CHARPTR( OnCommand, "Command", command ); // called when a panel receives a command + MESSAGE_FUNC( OnMouseCaptureLost, "MouseCaptureLost" ); // called after the panel loses mouse capture + MESSAGE_FUNC( OnSetFocus, "SetFocus" ); // called after the panel receives the keyboard focus + MESSAGE_FUNC( OnKillFocus, "KillFocus" ); // called after the panel loses the keyboard focus + MESSAGE_FUNC( OnDelete, "Delete" ); // called to delete the panel; Panel::OnDelete() does simply { delete this; } + virtual void OnThink(); // called every frame before painting, but only if panel is visible + virtual void OnChildAdded(VPANEL child); // called when a child has been added to this panel + virtual void OnSizeChanged(int newWide, int newTall); // called after the size of a panel has been changed + + // called every frame if ivgui()->AddTickSignal() is called + virtual void OnTick(); + + // input messages + MESSAGE_FUNC_INT_INT( OnCursorMoved, "OnCursorMoved", x, y ); + virtual void OnCursorEntered(); + virtual void OnCursorExited(); + virtual void OnMousePressed(MouseCode code); + virtual void OnMouseDoublePressed(MouseCode code); + virtual void OnMouseReleased(MouseCode code); + virtual void OnMouseWheeled(int delta); + + // Trip pressing (e.g., select all text in a TextEntry) requires this to be enabled + virtual void SetTriplePressAllowed( bool state ); + virtual bool IsTriplePressAllowed() const; + virtual void OnMouseTriplePressed( MouseCode code ); + + static char const *KeyCodeToString( KeyCode code ); + static wchar_t const *KeyCodeToDisplayString( KeyCode code ); + static wchar_t const *KeyCodeModifiersToDisplayString( KeyCode code, int modifiers ); // L"Ctrl+Alt+Shift+Backspace" + + static KeyCode StringToKeyCode( char const *str ); +#if defined( VGUI_USEKEYBINDINGMAPS ) + static KeyBindingContextHandle_t CreateKeyBindingsContext( char const *filename, char const *pathID = 0 ); + virtual void SetKeyBindingsContext( KeyBindingContextHandle_t handle ); + virtual KeyBindingContextHandle_t GetKeyBindingsContext() const; + virtual bool IsValidKeyBindingsContext() const; + + static int GetPanelsWithKeyBindingsCount( KeyBindingContextHandle_t handle ); + static Panel *GetPanelWithKeyBindings( KeyBindingContextHandle_t handle, int index ); + + static void RevertKeyBindings( KeyBindingContextHandle_t handle ); + + static void ReloadKeyBindings( KeyBindingContextHandle_t handle ); + static void SaveKeyBindings( KeyBindingContextHandle_t handle ); + static void SaveKeyBindingsToFile( KeyBindingContextHandle_t handle, char const *filename, char const *pathID = 0 ); + static void LoadKeyBindings( KeyBindingContextHandle_t handle ); + static void LoadKeyBindingsForOnePanel( KeyBindingContextHandle_t handle, Panel *panelOfInterest ); + + // OnKeyCodeTyped hooks into here for action + virtual bool IsKeyRebound( KeyCode code, int modifiers ); + // If a panel implements this and returns true, then the IsKeyRebound check will fail and OnKeyCodeTyped messages will pass through.. + // sort of like setting the SetAllowKeyBindingChainToParent flag to false for specific keys + virtual bool IsKeyOverridden( KeyCode code, int modifiers ); + + virtual void AddKeyBinding( char const *bindingName, int keycode, int modifiers ); + + KeyBindingMap_t *LookupBinding( char const *bindingName ); + KeyBindingMap_t *LookupBindingByKeyCode( KeyCode code, int modifiers ); + void LookupBoundKeys( char const *bindingName, CUtlVector< BoundKey_t * >& list ); + BoundKey_t *LookupDefaultKey( char const *bindingName ); + PanelKeyBindingMap *LookupMapForBinding( char const *bindingName ); + + // Returns the number of keybindings + int GetKeyMappingCount( ); + + void RevertKeyBindingsToDefault(); + void RemoveAllKeyBindings(); + void ReloadKeyBindings(); + virtual void EditKeyBindings(); + + // calls RevertKeyBindingsToDefault() and then LoadKeyBindingsForOnePanel( GetKeyBindingsContext(), this ); + void SaveKeyBindingsToBuffer( int level, CUtlBuffer& buf ); + bool ParseKeyBindings( KeyValues *kv ); + + virtual char const *GetKeyBindingsFile() const; + virtual char const *GetKeyBindingsFilePathID() const; + + // Set this to false to disallow IsKeyRebound chaining to GetParent() Panels... + void SetAllowKeyBindingChainToParent( bool state ); + bool IsKeyBindingChainToParentAllowed() const; +#endif // VGUI_USEKEYBINDINGMAPS + + // base implementation forwards Key messages to the Panel's parent + // - override to 'swallow' the input + virtual void OnKeyCodePressed(KeyCode code); + virtual void OnKeyCodeTyped(KeyCode code); + virtual void OnKeyTyped(wchar_t unichar); + virtual void OnKeyCodeReleased(KeyCode code); + virtual void OnKeyFocusTicked(); // every window gets key ticked events + + // forwards mouse messages to the panel's parent + MESSAGE_FUNC( OnMouseFocusTicked, "OnMouseFocusTicked" ); + + // message handlers that don't go through the message pump + virtual void PaintBackground(); + virtual void Paint(); + virtual void PaintBorder(); + virtual void PaintBuildOverlay(); // the extra drawing for when in build mode + virtual void PostChildPaint(); + virtual void PerformLayout(); + + // this enables message mapping for this class - requires matching IMPLEMENT_PANELDESC() in the .cpp file + DECLARE_PANELMAP(); + + virtual VPANEL GetCurrentKeyFocus(); + + // returns a pointer to the tooltip object associated with the panel + // creates a new one if none yet exists + BaseTooltip *GetTooltip(); + void SetTooltip( BaseTooltip *pToolTip, const char *pszText ); + + /// Returns the effective tooltip text to use, whether stored + /// locally in this panel, or in the tooltip object. Returns + /// an empty string if no tooltip text + const char *GetEffectiveTooltipText() const; + + // proportional mode settings + virtual bool IsProportional() { return _flags.IsFlagSet( IS_PROPORTIONAL ); } + virtual void SetProportional(bool state); + + // input interest + virtual void SetMouseInputEnabled( bool state ); + virtual void SetKeyBoardInputEnabled( bool state ); + virtual bool IsMouseInputEnabled(); + virtual bool IsKeyBoardInputEnabled(); + + virtual void DrawTexturedBox( int x, int y, int wide, int tall, Color color, float normalizedAlpha ); + virtual void DrawBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha, bool hollow = false ); + virtual void DrawBoxFade(int x, int y, int wide, int tall, Color color, float normalizedAlpha, unsigned int alpha0, unsigned int alpha1, bool bHorizontal, bool hollow = false ); + virtual void DrawHollowBox(int x, int y, int wide, int tall, Color color, float normalizedAlpha ); + //============================================================================= + // HPE_BEGIN: + //============================================================================= + + // [menglish] Draws a hollow box similar to the already existing draw hollow box function, but takes the indents as params + virtual void DrawHollowBox( int x, int y, int wide, int tall, Color color, float normalizedAlpha, int cornerWide, int cornerTall ); + + // [tj] Simple getters and setters to decide which corners to draw rounded + unsigned char GetRoundedCorners() { return m_roundedCorners; } + void SetRoundedCorners (unsigned char cornerFlags) { m_roundedCorners = cornerFlags; } + bool ShouldDrawTopLeftCornerRounded() { return ( m_roundedCorners & PANEL_ROUND_CORNER_TOP_LEFT ) != 0; } + bool ShouldDrawTopRightCornerRounded() { return ( m_roundedCorners & PANEL_ROUND_CORNER_TOP_RIGHT ) != 0; } + bool ShouldDrawBottomLeftCornerRounded() { return ( m_roundedCorners & PANEL_ROUND_CORNER_BOTTOM_LEFT ) != 0; } + bool ShouldDrawBottomRightCornerRounded() { return ( m_roundedCorners & PANEL_ROUND_CORNER_BOTTOM_RIGHT ) != 0; } + + //============================================================================= + // HPE_END + //============================================================================= + +// Drag Drop Public interface + + virtual void SetDragEnabled( bool enabled ); + virtual bool IsDragEnabled() const; + + virtual void SetShowDragHelper( bool enabled ); + + // Called if drag drop is started but not dropped on top of droppable panel... + virtual void OnDragFailed( CUtlVector< KeyValues * >& msglist ); + + // Use this to prevent chaining up from a parent which can mess with mouse functionality if you don't want to chain up from a child panel to the best + // draggable parent. + virtual void SetBlockDragChaining( bool block ); + virtual bool IsBlockingDragChaining() const; + + virtual int GetDragStartTolerance() const; + virtual void SetDragSTartTolerance( int nTolerance ); + + // If hover context time is non-zero, then after the drop cursor is hovering over the panel for that amount of time + // the Show hover context menu function will be invoked + virtual void SetDropEnabled( bool enabled, float m_flHoverContextTime = 0.0f ); + virtual bool IsDropEnabled() const; + + // Called if m_flHoverContextTime was non-zero, allows droppee to preview the drop data and show an appropriate menu + // Return false if not using context menu + virtual bool GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& msglist ); + virtual void OnDropContextHoverShow( CUtlVector< KeyValues * >& msglist ); + virtual void OnDropContextHoverHide( CUtlVector< KeyValues * >& msglist ); + +#if defined( VGUI_USEDRAGDROP ) + virtual DragDrop_t *GetDragDropInfo(); +#endif + // For handling multiple selections... + virtual void OnGetAdditionalDragPanels( CUtlVector< Panel * >& dragabbles ); + + virtual void OnCreateDragData( KeyValues *msg ); + // Called to see if a drop enabled panel can accept the specified data blob + virtual bool IsDroppable( CUtlVector< KeyValues * >& msglist ); + + // Mouse is on draggable panel and has started moving, but is not over a droppable panel yet + virtual void OnDraggablePanelPaint(); + // Mouse is now over a droppable panel + virtual void OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels ); + + virtual void OnPanelDropped( CUtlVector< KeyValues * >& msglist ); + + // called on droptarget when draggable panel entered/exited droptarget + virtual void OnPanelEnteredDroppablePanel( CUtlVector< KeyValues * >& msglist ); + virtual void OnPanelExitedDroppablePanel ( CUtlVector< KeyValues * >& msglist ); + + // Chains up to any parent marked DropEnabled + virtual Panel *GetDropTarget( CUtlVector< KeyValues * >& msglist ); + // Chains up to first parent marked DragEnabled + virtual Panel *GetDragPanel(); + virtual bool IsBeingDragged(); + virtual HCursor GetDropCursor( CUtlVector< KeyValues * >& msglist ); + + Color GetDropFrameColor(); + Color GetDragFrameColor(); + + // Can override to require custom behavior to start the drag state + virtual bool CanStartDragging( int startx, int starty, int mx, int my ); + + // Draws a filled rect of specified bounds, but omits the bounds of the skip panel from those bounds + virtual void FillRectSkippingPanel( const Color &clr, int x, int y, int w, int h, Panel *skipPanel ); + + virtual int GetPaintBackgroundType(); + virtual void GetCornerTextureSize( int& w, int& h ); + + bool IsChildOfModalSubTree(); + bool IsChildOfSurfaceModalPanel(); + + bool ShouldHandleInputMessage(); + + virtual void SetSkipChildDuringPainting( Panel *child ); + + // If this is set, then the drag drop won't occur until the mouse leaves the drag panels current rectangle + void SetStartDragWhenMouseExitsPanel( bool state ); + bool IsStartDragWhenMouseExitsPanel() const; + + void DisableMouseInputForThisPanel( bool bDisable ); + bool IsMouseInputDisabledForThisPanel() const; + + bool GetForceStereoRenderToFrameBuffer() const { return m_bForceStereoRenderToFrameBuffer; } + void SetForceStereoRenderToFrameBuffer( bool bForce ) { m_bForceStereoRenderToFrameBuffer = bForce; } + + void PostMessageToAllSiblings( KeyValues *msg, float delaySeconds = 0.0f ); + template< class S > + void PostMessageToAllSiblingsOfType( KeyValues *msg, float delaySeconds = 0.0f ); + + void SetConsoleStylePanel( bool bConsoleStyle ); + bool IsConsoleStylePanel() const; + + void SetParentNeedsCursorMoveEvents( bool bNeedsEvents ) { m_bParentNeedsCursorMoveEvents = bNeedsEvents; } + bool ParentNeedsCursorMoveEvents() const { return m_bParentNeedsCursorMoveEvents; } + + int ComputePos( const char *pszInput, int &nPos, const int& nSize, const int& nParentSize, const bool& bX ); + + // For 360: support directional navigation between UI controls via dpad + enum NAV_DIRECTION { ND_UP, ND_DOWN, ND_LEFT, ND_RIGHT, ND_BACK, ND_NONE }; + virtual Panel* NavigateUp(); + virtual Panel* NavigateDown(); + virtual Panel* NavigateLeft(); + virtual Panel* NavigateRight(); + virtual Panel* NavigateActivate(); + virtual Panel* NavigateBack(); + virtual void NavigateTo(); + virtual void NavigateFrom(); + virtual void NavigateToChild( Panel *pNavigateTo ); //mouse support + // if set, Panel gets PerformLayout called after the camera and the renderer's m_matrixWorldToScreen has been setup, so panels can be correctly attached to entities in the world + inline void SetWorldPositionCurrentFrame( bool bWorldPositionCurrentFrame ) { m_bWorldPositionCurrentFrame = bWorldPositionCurrentFrame; } + inline bool GetWorldPositionCurrentFrame() { return m_bWorldPositionCurrentFrame; } + + Panel* SetNavUp( Panel* navUp ); + Panel* SetNavDown( Panel* navDown ); + Panel* SetNavLeft( Panel* navLeft ); + Panel* SetNavRight( Panel* navRight ); + Panel* SetNavToRelay( Panel* navToRelay ); + Panel* SetNavActivate( Panel* navActivate ); + Panel* SetNavBack( Panel* navBack ); + NAV_DIRECTION GetLastNavDirection(); + MESSAGE_FUNC_CHARPTR( OnNavigateTo, "OnNavigateTo", panelName ); + MESSAGE_FUNC_CHARPTR( OnNavigateFrom, "OnNavigateFrom", panelName ); + +// Drag Drop protected/internal interface +protected: + + virtual void OnStartDragging(); + virtual void OnContinueDragging(); + virtual void OnFinishDragging( bool mousereleased, MouseCode code, bool aborted = false ); + + virtual void DragDropStartDragging(); + + virtual void GetDragData( CUtlVector< KeyValues * >& list ); + virtual void CreateDragData(); + + virtual void PaintTraverse(bool Repaint, bool allowForce = true); + +protected: + MESSAGE_FUNC_ENUM_ENUM( OnRequestFocus, "OnRequestFocus", VPANEL, subFocus, VPANEL, defaultPanel); + MESSAGE_FUNC_INT_INT( OnScreenSizeChanged, "OnScreenSizeChanged", oldwide, oldtall ); + virtual void *QueryInterface(EInterfaceID id); + + void AddToOverridableColors( Color *pColor, char const *scriptname ) + { + int iIdx = m_OverridableColorEntries.AddToTail(); + m_OverridableColorEntries[iIdx].m_pszScriptName = scriptname; + m_OverridableColorEntries[iIdx].m_pColor = pColor; + m_OverridableColorEntries[iIdx].m_bOverridden = false; + } + + void ApplyOverridableColors( void ); + void SetOverridableColor( Color *pColor, const Color &newColor ); + +public: + void SetNavUp( const char* controlName ); + void SetNavDown( const char* controlName ); + void SetNavLeft( const char* controlName ); + void SetNavRight( const char* controlName ); + void SetNavToRelay( const char* controlName ); + void SetNavActivate( const char* controlName ); + void SetNavBack( const char* controlName ); + + /* + Will recursively look for the next visible panel in the navigation chain, parameters are for internal use. + It will stop looking if first == nextpanel (to prevent infinite looping). + */ + Panel* GetNavUp( Panel *first = NULL ); + Panel* GetNavDown( Panel *first = NULL ); + Panel* GetNavLeft( Panel *first = NULL ); + Panel* GetNavRight( Panel *first = NULL ); + Panel* GetNavToRelay( Panel *first = NULL ); + Panel* GetNavActivate( Panel *first = NULL ); + Panel* GetNavBack( Panel *first = NULL ); + + const char* GetNavUpName( void ) const { return m_sNavUpName.String(); } + const char* GetNavDownName( void ) const { return m_sNavDownName.String(); } + const char* GetNavLeftName( void ) const { return m_sNavLeftName.String(); } + const char* GetNavRightName( void ) const { return m_sNavRightName.String(); } + const char* GetNavToRelayName( void ) const { return m_sNavToRelayName.String(); } + const char* GetNavActivateName( void ) const { return m_sNavActivateName.String(); } + const char* GetNavBackName( void ) const { return m_sNavBackName.String(); } + +protected: + //this will return m_NavDown and will not look for the next visible panel + Panel* GetNavUpPanel(); + Panel* GetNavDownPanel(); + Panel* GetNavLeftPanel(); + Panel* GetNavRightPanel(); + Panel* GetNavToRelayPanel(); + Panel* GetNavActivatePanel(); + Panel* GetNavBackPanel(); + + bool m_PassUnhandledInput; + NAV_DIRECTION m_LastNavDirection; + +private: + enum BuildModeFlags_t + { + BUILDMODE_EDITABLE = 1 << 0, + BUILDMODE_DELETABLE = 1 << 1, + BUILDMODE_SAVE_XPOS_RIGHTALIGNED = 1 << 2, + BUILDMODE_SAVE_XPOS_CENTERALIGNED = 1 << 3, + BUILDMODE_SAVE_YPOS_BOTTOMALIGNED = 1 << 4, + BUILDMODE_SAVE_YPOS_CENTERALIGNED = 1 << 5, + BUILDMODE_SAVE_WIDE_FULL = 1 << 6, + BUILDMODE_SAVE_TALL_FULL = 1 << 7, + BUILDMODE_SAVE_PROPORTIONAL_TO_PARENT = 1 << 8, + BUILDMODE_SAVE_WIDE_PROPORTIONAL = 1 << 9, + BUILDMODE_SAVE_TALL_PROPORTIONAL = 1 << 10, + BUILDMODE_SAVE_XPOS_PROPORTIONAL_SELF = 1 << 11, + BUILDMODE_SAVE_YPOS_PROPORTIONAL_SELF = 1 << 12, + BUILDMODE_SAVE_WIDE_PROPORTIONAL_TALL = 1 << 13, + BUILDMODE_SAVE_TALL_PROPORTIONAL_WIDE = 1 << 14, + BUILDMODE_SAVE_XPOS_PROPORTIONAL_PARENT = 1 << 15, + BUILDMODE_SAVE_YPOS_PROPORTIONAL_PARENT = 1 << 16 + }; + + enum PanelFlags_t + { + MARKED_FOR_DELETION = 0x0001, + NEEDS_REPAINT = 0x0002, + PAINT_BORDER_ENABLED = 0x0004, + PAINT_BACKGROUND_ENABLED = 0x0008, + PAINT_ENABLED = 0x0010, + POST_CHILD_PAINT_ENABLED = 0x0020, + AUTODELETE_ENABLED = 0x0040, + NEEDS_LAYOUT = 0x0080, + NEEDS_SCHEME_UPDATE = 0x0100, + NEEDS_DEFAULT_SETTINGS_APPLIED = 0x0200, +#if defined( VGUI_USEKEYBINDINGMAPS ) + ALLOW_CHAIN_KEYBINDING_TO_PARENT = 0x0400, +#endif + IN_PERFORM_LAYOUT = 0x0800, + IS_PROPORTIONAL = 0x1000, + TRIPLE_PRESS_ALLOWED = 0x2000, + DRAG_REQUIRES_PANEL_EXIT = 0x4000, + IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY = 0x8000, + ALL_FLAGS = 0xFFFF, + }; + + int ComputeWide( KeyValues *inResourceData, int nParentWide, int nParentTall, bool bComputingForTall ); + int ComputeTall( KeyValues *inResourceData, int nParentWide, int nParentTall, bool bComputingForWide ); + + // used to get the Panel * for users with only IClientPanel + virtual Panel *GetPanel() { return this; } + + // private methods + void Think(); + void PerformApplySchemeSettings(); + + void InternalPerformLayout(); + void InternalSetCursor(); + + MESSAGE_FUNC_INT_INT( InternalCursorMoved, "CursorMoved", xpos, ypos ); + MESSAGE_FUNC( InternalCursorEntered, "CursorEntered" ); + MESSAGE_FUNC( InternalCursorExited, "CursorExited" ); + + MESSAGE_FUNC_INT( InternalMousePressed, "MousePressed", code ); + MESSAGE_FUNC_INT( InternalMouseDoublePressed, "MouseDoublePressed", code ); + // Triple presses are synthesized + MESSAGE_FUNC_INT( InternalMouseTriplePressed, "MouseTriplePressed", code ); + MESSAGE_FUNC_INT( InternalMouseReleased, "MouseReleased", code ); + MESSAGE_FUNC_INT( InternalMouseWheeled, "MouseWheeled", delta ); + MESSAGE_FUNC_INT( InternalKeyCodePressed, "KeyCodePressed", code ); + MESSAGE_FUNC_INT( InternalKeyCodeTyped, "KeyCodeTyped", code ); + MESSAGE_FUNC_INT( InternalKeyTyped, "KeyTyped", unichar ); + MESSAGE_FUNC_INT( InternalKeyCodeReleased, "KeyCodeReleased", code ); + + MESSAGE_FUNC( InternalKeyFocusTicked, "KeyFocusTicked" ); + MESSAGE_FUNC( InternalMouseFocusTicked, "MouseFocusTicked" ); + + MESSAGE_FUNC( InternalInvalidateLayout, "Invalidate" ); + + MESSAGE_FUNC( InternalMove, "Move" ); + virtual void InternalFocusChanged(bool lost); // called when the focus gets changed + + void PreparePanelMap( PanelMap_t *panelMap ); + + bool InternalRequestInfo( PanelAnimationMap *map, KeyValues *outputData ); + bool InternalSetInfo( PanelAnimationMap *map, KeyValues *inputData ); + + PanelAnimationMapEntry *FindPanelAnimationEntry( char const *scriptname, PanelAnimationMap *map ); + + // Recursively invoke settings for PanelAnimationVars + void InternalApplySettings( PanelAnimationMap *map, KeyValues *inResourceData); + void InternalInitDefaultValues( PanelAnimationMap *map ); + + // Purpose: Loads panel details related to autoresize from the resource info + void ApplyAutoResizeSettings(KeyValues *inResourceData); + + void FindDropTargetPanel_R( CUtlVector< VPANEL >& panelList, int x, int y, VPANEL check ); + Panel *FindDropTargetPanel(); + + int GetProportionalScaledValue( int rootTall, int normalizedValue ); + +#if defined( VGUI_USEDRAGDROP ) + DragDrop_t *m_pDragDrop; + Color m_clrDragFrame; + Color m_clrDropFrame; +#endif + + BaseTooltip *m_pTooltips; + bool m_bToolTipOverridden; + + PHandle m_SkipChild; + long m_lLastDoublePressTime; + HFont m_infoFont; + +#if defined( VGUI_USEKEYBINDINGMAPS ) + KeyBindingContextHandle_t m_hKeyBindingsContext; +#endif + + // data + VPANEL _vpanel; // handle to a vgui panel + char *_panelName; // string name of the panel - only unique within the current context + IBorder *_border; + + CUtlFlags< unsigned short > _flags; // see PanelFlags_t + Dar _actionSignalTargetDar; // the panel to direct notify messages to ("Command", "TextChanged", etc.) + + CUtlVector m_OverridableColorEntries; + + Color _fgColor; // foreground color + Color _bgColor; // background color + + HBuildGroup _buildGroup; + + short m_nPinDeltaX; // Relative position of the pinned corner to the edge + short m_nPinDeltaY; + short m_nResizeDeltaX; // Relative position of the non-pinned corner to the edge + short m_nResizeDeltaY; + + HCursor _cursor; + unsigned short _buildModeFlags; // flags that control how the build mode dialog handles this panel + + byte _pinCorner : 4; // the corner of the dialog this panel is pinned to + byte _autoResizeDirection : 4; // the directions in which the panel will auto-resize to + + unsigned char _tabPosition; // the panel's place in the tab ordering + HScheme m_iScheme; // handle to the scheme to use + + bool m_bIsDMXSerialized : 1; // Is this a DMX panel? + bool m_bUseSchemeColors : 1; // Should we use colors from the scheme? + bool m_bIsSilent : 1; // should this panel PostActionSignals? + bool m_bIsConsoleStylePanel : 1; + bool m_bParentNeedsCursorMoveEvents : 1; + + // Sibling pinning + char *_pinToSibling; // string name of the sibling panel we're pinned to + byte _pinToSiblingCorner; // the corner of the sibling panel we're pinned to + byte _pinCornerToSibling; // the corner of our panel that we're pinning to our sibling + PHandle m_pinSibling; + + CUtlString m_sNavUpName; + PHandle m_NavUp; + + CUtlString m_sNavDownName; + PHandle m_NavDown; + + CUtlString m_sNavLeftName; + PHandle m_NavLeft; + + CUtlString m_sNavRightName; + PHandle m_NavRight; + + CUtlString m_sNavToRelayName; + PHandle m_NavToRelay; + + CUtlString m_sNavActivateName; + PHandle m_NavActivate; + + CUtlString m_sNavBackName; + PHandle m_NavBack; + +private: + + char *_tooltipText; // Tool tip text for panels that share tooltip panels with other panels + + PHandle m_hMouseEventHandler; + + bool m_bWorldPositionCurrentFrame; // if set, Panel gets PerformLayout called after the camera and the renderer's m_matrixWorldToScreen has been setup, so panels can be correctly attached to entities in the world + + bool m_bForceStereoRenderToFrameBuffer; + + CPanelAnimationVar( float, m_flAlpha, "alpha", "255" ); + + // 1 == Textured (TextureId1 only) + // 2 == Rounded Corner Box + CPanelAnimationVar( int, m_nPaintBackgroundType, "PaintBackgroundType", "0" ); + CPanelAnimationVarAliasType( int, m_nBgTextureId1, "Texture1", "vgui/hud/800corner1", "textureid" ); + CPanelAnimationVarAliasType( int, m_nBgTextureId2, "Texture2", "vgui/hud/800corner2", "textureid" ); + CPanelAnimationVarAliasType( int, m_nBgTextureId3, "Texture3", "vgui/hud/800corner3", "textureid" ); + CPanelAnimationVarAliasType( int, m_nBgTextureId4, "Texture4", "vgui/hud/800corner4", "textureid" ); + + //============================================================================= + // HPE_BEGIN: + // [tj] A bitset of flags to determine which corners should be rounded + //============================================================================= + unsigned char m_roundedCorners; + //============================================================================= + // HPE_END + //============================================================================= + friend class BuildGroup; + friend class BuildModeDialog; + friend class PHandle; + + // obselete, remove soon + void OnOldMessage(KeyValues *params, VPANEL ifromPanel); +}; + +inline void Panel::DisableMouseInputForThisPanel( bool bDisable ) +{ + _flags.SetFlag( IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY, bDisable ); +} + +inline bool Panel::IsMouseInputDisabledForThisPanel() const +{ + return _flags.IsFlagSet( IS_MOUSE_DISABLED_FOR_THIS_PANEL_ONLY ); +} + +#if 0 +// This function cannot be defined here because it requires on a full definition of +// KeyValues (to call KeyValues::MakeCopy()) whereas the rest of this header file +// assumes a forward declared definition of KeyValues. +template< class S > +inline void Panel::PostMessageToAllSiblingsOfType( KeyValues *msg, float delaySeconds /*= 0.0f*/ ) +{ + Panel *parent = GetParent(); + if ( parent ) + { + int nChildCount = parent->GetChildCount(); + for ( int i = 0; i < nChildCount; ++i ) + { + Panel *sibling = parent->GetChild( i ); + if ( sibling == this ) + continue; + if ( dynamic_cast< S * >( sibling ) ) + { + PostMessage( sibling->GetVPanel(), msg->MakeCopy(), delaySeconds ); + } + } + } + + msg->deleteThis(); +} +#endif + +class Button; + +struct SortedPanel_t +{ + SortedPanel_t( Panel *panel ); + + Panel *pPanel; + Button *pButton; +}; + +class CSortedPanelYLess +{ +public: + bool Less( const SortedPanel_t &src1, const SortedPanel_t &src2, void *pCtx ) + { + int nX1, nY1, nX2, nY2; + src1.pPanel->GetPos( nX1, nY1 ); + src2.pPanel->GetPos( nX2, nY2 ); + + if ( nY1 == nY2 ) + { + return ( nX1 < nX2 ); + } + + if ( nY1 < nY2 ) + { + return true; + } + + return false; + } +}; + + +void VguiPanelGetSortedChildPanelList( Panel *pParentPanel, void *pSortedPanels ); +void VguiPanelGetSortedChildButtonList( Panel *pParentPanel, void *pSortedPanels, char *pchFilter = NULL, int nFilterType = 0 ); +int VguiPanelNavigateSortedChildButtonList( void *pSortedPanels, int nDir ); + + +} // namespace vgui + + +#endif // PANEL_H diff --git a/sp/src/public/vgui_controls/PanelAnimationVar.h b/sp/src/public/vgui_controls/PanelAnimationVar.h new file mode 100644 index 00000000..24c41c8c --- /dev/null +++ b/sp/src/public/vgui_controls/PanelAnimationVar.h @@ -0,0 +1,161 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef PANELANIMATIONVAR_H +#define PANELANIMATIONVAR_H +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/utlvector.h" +#include + +#define DECLARE_PANELANIMATION( className ) \ + static void AddToAnimationMap( char const *scriptname, char const *type, char const *var, \ + char const *defaultvalue, bool array, PANELLOOKUPFUNC func ) \ + { \ + PanelAnimationMap *map = FindOrAddPanelAnimationMap( GetPanelClassName() ); \ + \ + PanelAnimationMapEntry entry; \ + entry.m_pszScriptName = scriptname; \ + entry.m_pszVariable = var; \ + entry.m_pszType = type; \ + entry.m_pszDefaultValue = defaultvalue; \ + entry.m_pfnLookup = func; \ + entry.m_bArray = array; \ + \ + map->entries.AddToTail( entry ); \ + } \ + \ + static void ChainToAnimationMap( void ) \ + { \ + static bool chained = false; \ + if ( chained ) \ + return; \ + chained = true; \ + PanelAnimationMap *map = FindOrAddPanelAnimationMap( GetPanelClassName() ); \ + map->pfnClassName = GetPanelClassName; \ + if ( map && GetPanelBaseClassName() && GetPanelBaseClassName()[0] ) \ + { \ + map->baseMap = FindOrAddPanelAnimationMap( GetPanelBaseClassName() ); \ + } \ + } \ + \ + class className##_Register; \ + friend class className##_Register; \ + class className##_Register \ + { \ + public: \ + className##_Register() \ + { \ + className::ChainToAnimationMap(); \ + } \ + }; \ + className##_Register m_RegisterAnimationClass; \ + \ + virtual PanelAnimationMap *GetAnimMap() \ + { \ + return FindOrAddPanelAnimationMap( GetPanelClassName() ); \ + } + +typedef void *( *PANELLOOKUPFUNC )( vgui::Panel *panel ); + +// Use this macro to define a variable which hudanimations.txt and hudlayout.res scripts can access +#define CPanelAnimationVarAliasType( type, name, scriptname, defaultvalue, typealias ) \ + class PanelAnimationVar_##name; \ + friend class PanelAnimationVar_##name; \ + static void *GetVar_##name( vgui::Panel *panel ) \ + { \ + return &(( ThisClass *)panel)->name; \ + } \ + class PanelAnimationVar_##name \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + AddToAnimationMap( scriptname, typealias, #name, defaultvalue, false, ThisClass::GetVar_##name ); \ + } \ + } \ + PanelAnimationVar_##name() \ + { \ + PanelAnimationVar_##name::InitVar(); \ + } \ + }; \ + PanelAnimationVar_##name m_##name##_register; \ + type name; + +#define CPanelAnimationVar( type, name, scriptname, defaultvalue ) \ + CPanelAnimationVarAliasType( type, name, scriptname, defaultvalue, #type ) + +// Use this macro to define a variable which hudanimations.txt and hudlayout.res scripts can access +#define CPanelAnimationStringVarAliasType( count, name, scriptname, defaultvalue, typealias ) \ + class PanelAnimationVar_##name; \ + friend class PanelAnimationVar_##name; \ + static void *GetVar_##name( vgui::Panel *panel ) \ + { \ + return &(( ThisClass *)panel)->name; \ + } \ + class PanelAnimationVar_##name \ + { \ + public: \ + static void InitVar() \ + { \ + static bool bAdded = false; \ + if ( !bAdded ) \ + { \ + bAdded = true; \ + AddToAnimationMap( scriptname, typealias, #name, defaultvalue, true, ThisClass::GetVar_##name ); \ + } \ + } \ + PanelAnimationVar_##name() \ + { \ + PanelAnimationVar_##name::InitVar(); \ + } \ + }; \ + PanelAnimationVar_##name m_##name##_register; \ + char name[ count ]; + +#define CPanelAnimationStringVar( count, name, scriptname, defaultvalue ) \ + CPanelAnimationStringVarAliasType( count, name, scriptname, defaultvalue, "string" ) + +struct PanelAnimationMapEntry +{ + char const *name() { return m_pszScriptName; } + char const *type() { return m_pszType; } + char const *defaultvalue() { return m_pszDefaultValue; } + bool isarray() { return m_bArray; } + + char const *m_pszScriptName; + char const *m_pszVariable; + char const *m_pszType; + char const *m_pszDefaultValue; + bool m_bArray; + + PANELLOOKUPFUNC m_pfnLookup; +}; + +struct PanelAnimationMap +{ + PanelAnimationMap() + { + baseMap = NULL; + pfnClassName = NULL; + } + + CUtlVector< PanelAnimationMapEntry > entries; + PanelAnimationMap *baseMap; + char const *(*pfnClassName)( void ); +}; + +PanelAnimationMap *FindPanelAnimationMap( char const *className ); +PanelAnimationMap *FindOrAddPanelAnimationMap( char const *className ); +void PanelAnimationDumpVars( char const *className ); + +#endif // PANELANIMATIONVAR_H diff --git a/sp/src/public/vgui_controls/PanelListPanel.h b/sp/src/public/vgui_controls/PanelListPanel.h new file mode 100644 index 00000000..c4a647e3 --- /dev/null +++ b/sp/src/public/vgui_controls/PanelListPanel.h @@ -0,0 +1,126 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PANELLISTPANEL_H +#define PANELLISTPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include + +class KeyValues; + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: A list of variable height child panels +// each list item consists of a label-panel pair. Height of the item is +// determined from the label. +//----------------------------------------------------------------------------- +class PanelListPanel : public EditablePanel +{ + DECLARE_CLASS_SIMPLE( PanelListPanel, Panel ); + +public: + PanelListPanel( vgui::Panel *parent, char const *panelName ); + ~PanelListPanel(); + + // DATA & ROW HANDLING + // The list now owns the panel + virtual int AddItem( Panel *labelPanel, Panel *panel ); + int GetItemCount() const; + int GetItemIDFromRow( int nRow ) const; + + // Iteration. Use these until they return InvalidItemID to iterate all the items. + int FirstItem() const; + int NextItem( int nItemID ) const; + int InvalidItemID() const; + + virtual Panel *GetItemLabel(int itemID); + virtual Panel *GetItemPanel(int itemID); + + ScrollBar* GetScrollbar() { return m_vbar; } + + virtual void RemoveItem(int itemID); // removes an item from the table (changing the indices of all following items) + virtual void DeleteAllItems(); // clears and deletes all the memory used by the data items + void RemoveAll(); + + // painting + virtual vgui::Panel *GetCellRenderer( int row ); + + // layout + void SetFirstColumnWidth( int width ); + int GetFirstColumnWidth(); + void SetNumColumns( int iNumColumns ); + int GetNumColumns( void ); + void MoveScrollBarToTop(); + + // selection + void SetSelectedPanel( Panel *panel ); + Panel *GetSelectedPanel(); + /* + On a panel being selected, a message gets sent to it + "PanelSelected" int "state" + where state is 1 on selection, 0 on deselection + */ + + void SetVerticalBufferPixels( int buffer ); + + void ScrollToItem( int itemNumber ); + + CUtlVector< int > *GetSortedVector( void ) + { + return &m_SortedItems; + } + + int ComputeVPixelsNeeded(); + +protected: + // overrides + virtual void OnSizeChanged(int wide, int tall); + MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position ); + virtual void PerformLayout(); + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void OnMouseWheeled(int delta); + +private: + + + enum { DEFAULT_HEIGHT = 24, PANELBUFFER = 5 }; + + typedef struct dataitem_s + { + // Always store a panel pointer + Panel *panel; + Panel *labelPanel; + } DATAITEM; + + // list of the column headers + + CUtlLinkedList m_DataItems; + CUtlVector m_SortedItems; + + ScrollBar *m_vbar; + Panel *m_pPanelEmbedded; + + PHandle m_hSelectedItem; + int m_iFirstColumnWidth; + int m_iNumColumns; + int m_iDefaultHeight; + int m_iPanelBuffer; + + CPanelAnimationVar( bool, m_bAutoHideScrollbar, "autohide_scrollbar", "0" ); +}; + +} +#endif // PANELLISTPANEL_H diff --git a/sp/src/public/vgui_controls/PerforceFileExplorer.h b/sp/src/public/vgui_controls/PerforceFileExplorer.h new file mode 100644 index 00000000..4d3dd876 --- /dev/null +++ b/sp/src/public/vgui_controls/PerforceFileExplorer.h @@ -0,0 +1,67 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Allows you to browse a directory structure, showing perforce files +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef PERFORCEFILEEXPLORER_H +#define PERFORCEFILEEXPLORER_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "tier1/utlstring.h" +#include "vgui_controls/Frame.h" + + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class PerforceFileList; +class ComboBox; +class Button; + + +//----------------------------------------------------------------------------- +// Contains a list of files, determines their perforce status +//----------------------------------------------------------------------------- +class PerforceFileExplorer : public vgui::Frame +{ + DECLARE_CLASS_SIMPLE( PerforceFileExplorer, Frame ); + +public: + // The context keyvalues are added to all messages sent by this dialog if they are specified + PerforceFileExplorer( Panel *parent, const char *pPanelName ); + ~PerforceFileExplorer(); + + // Inherited from Frame + virtual void ApplySchemeSettings( IScheme *pScheme ); + virtual void PerformLayout(); + +protected: + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", kv ); + MESSAGE_FUNC( OnItemDoubleClicked, "ItemDoubleClicked" ); + MESSAGE_FUNC( OnFolderUp, "FolderUp" ); + + void PopulateFileList(); + void PopulateDriveList(); + + // Returns the current directory + void SetCurrentDirectory( const char *pCurrentDirectory ); + + Button *m_pFolderUpButton; + ComboBox *m_pFullPathCombo; + PerforceFileList *m_pFileList; + CUtlString m_CurrentDirectory; +}; + + +} // namespace vgui + +#endif // PERFORCEFILEEXPLORER_H diff --git a/sp/src/public/vgui_controls/PerforceFileList.h b/sp/src/public/vgui_controls/PerforceFileList.h new file mode 100644 index 00000000..148b005c --- /dev/null +++ b/sp/src/public/vgui_controls/PerforceFileList.h @@ -0,0 +1,114 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Contains a list of files, determines their perforce status +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef PERFORCEFILELIST_H +#define PERFORCEFILELIST_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "tier1/utlstring.h" +#include "tier1/UtlStringMap.h" +#include "vgui_controls/ListPanel.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +struct P4File_t; + +namespace vgui +{ + class ListPanel; +} + + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Contains a list of files, determines their perforce status +//----------------------------------------------------------------------------- +class PerforceFileList : public vgui::ListPanel +{ + DECLARE_CLASS_SIMPLE( PerforceFileList, ListPanel ); + +public: + // The context keyvalues are added to all messages sent by this dialog if they are specified + PerforceFileList( Panel *parent, const char *pPanelName ); + ~PerforceFileList(); + + // Add a file to the file list. Note that this file may exist on disk or not + // and it may exist in perforce or not. It's specified as a full path on disk though. + // In the case where a file doesn't exist on disk, but it does exist in perforce + // specify where that file would appear on disk. + // This function returns the itemID of the added file + // If you already know the file exists or is a directory (or not), specify that in the call. + // -1 means autodetect whether the file exists or is a directory + int AddFile( const char *pFullPath, int nFileExists = -1, int nIsDirectory = -1 ); + + // Is a file already in the list? + bool IsFileInList( const char *pFullPath ); + + // Find the item ID associated with a particular file + int FindFile( const char *pFullPath ); + + // Remove all files from the list + void RemoveAllFiles(); + + // Refresh perforce information + void Refresh(); + + // Refresh perforce information manually + void RefreshPerforceState( int nItemID, bool bFileExists, P4File_t *pFileInfo ); + + // Is a particular list item a directory? + bool IsDirectoryItem( int nItemID ); + + // Returns the file associated with a particular item ID + const char *GetFile( int nItemID ); + + // Toggle showing deleted files or not + void ShowDeletedFiles( bool bShowDeletedFiles ); + + // Inherited from vgui::EditablePanel + virtual void ApplySchemeSettings( IScheme *pScheme ); + virtual void OnMouseDoublePressed( MouseCode code ); + + /* + messages sent: + "ItemDoubleClicked" // Called when an item is double-clicked + */ + +protected: + struct DirectoryInfo_t + { + CUtlString m_ClientSpec; + CUtlVector< int > m_ItemIDs; + }; + + // Add a file to the file list. + int AddFileToFileList( const char *pFullPath, bool bExistsOnDisk ); + + // Add a directory to the file list. + int AddDirectoryToFileList( const char *pFullPath, bool bExistsOnDisk ); + + // Add a directory to the directory list, returns client spec + void AddItemToDirectoryList( const char *pFullPath, int nItemID, bool bIsDirectory ); + + // Used to look up directories -> client specs + CUtlStringMap< DirectoryInfo_t > m_Directories; + + // Show deleted files? + bool m_bShowDeletedFiles; +}; + + +} // namespace vgui + +#endif // PERFORCEFILELIST_H diff --git a/sp/src/public/vgui_controls/ProgressBar.h b/sp/src/public/vgui_controls/ProgressBar.h new file mode 100644 index 00000000..a91269b1 --- /dev/null +++ b/sp/src/public/vgui_controls/ProgressBar.h @@ -0,0 +1,103 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PROGRESSBAR_H +#define PROGRESSBAR_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Status bar that visually displays discrete progress in the form +// of a segmented strip +//----------------------------------------------------------------------------- +class ProgressBar : public Panel +{ + DECLARE_CLASS_SIMPLE( ProgressBar, Panel ); + +public: + ProgressBar(Panel *parent, const char *panelName); + ~ProgressBar(); + + // 'progress' is in the range [0.0f, 1.0f] + MESSAGE_FUNC_FLOAT( SetProgress, "SetProgress", progress ); + float GetProgress(); + virtual void SetSegmentInfo( int gap, int width ); + + // utility function for calculating a time remaining string + static bool ConstructTimeRemainingString(OUT_Z_BYTECAP(outputBufferSizeInBytes) wchar_t *output, int outputBufferSizeInBytes, float startTime, float currentTime, float currentProgress, float lastProgressUpdateTime, bool addRemainingSuffix); + + void SetBarInset( int pixels ); + int GetBarInset( void ); + void SetMargin( int pixels ); + int GetMargin(); + + virtual void ApplySettings(KeyValues *inResourceData); + virtual void GetSettings(KeyValues *outResourceData); + virtual const char *GetDescription(); + + // returns the number of segment blocks drawn + int GetDrawnSegmentCount(); + + enum ProgressDir_e + { + PROGRESS_EAST, + PROGRESS_WEST, + PROGRESS_NORTH, + PROGRESS_SOUTH + }; + + int GetProgressDirection() const { return m_iProgressDirection; } + void SetProgressDirection( int val ) { m_iProgressDirection = val; } + +protected: + virtual void Paint(); + void PaintSegment( int &x, int &y, int tall, int wide ); + virtual void PaintBackground(); + virtual void ApplySchemeSettings(IScheme *pScheme); + MESSAGE_FUNC_PARAMS( OnDialogVariablesChanged, "DialogVariables", dialogVariables ); + /* CUSTOM MESSAGE HANDLING + "SetProgress" + input: "progress" - float value of the progress to set + */ + +protected: + int m_iProgressDirection; + float _progress; + +private: + int _segmentCount; + int _segmentGap; + int _segmentWide; + int m_iBarInset; + int m_iBarMargin; + char *m_pszDialogVar; +}; + +//----------------------------------------------------------------------------- +// Purpose: Non-segmented progress bar +//----------------------------------------------------------------------------- +class ContinuousProgressBar : public ProgressBar +{ + DECLARE_CLASS_SIMPLE( ContinuousProgressBar, ProgressBar ); + +public: + ContinuousProgressBar(Panel *parent, const char *panelName); + + virtual void Paint(); +}; + +} // namespace vgui + +#endif // PROGRESSBAR_H diff --git a/sp/src/public/vgui_controls/ProgressBox.h b/sp/src/public/vgui_controls/ProgressBox.h new file mode 100644 index 00000000..d5c321a4 --- /dev/null +++ b/sp/src/public/vgui_controls/ProgressBox.h @@ -0,0 +1,99 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PROGRESSBOX_H +#define PROGRESSBOX_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +// prevent windows macros from messing with the class +#ifdef ProgressBox +#undef ProgressBox +#endif + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Popup discardable message box +//----------------------------------------------------------------------------- +class ProgressBox : public Frame +{ + DECLARE_CLASS_SIMPLE( ProgressBox, Frame ); + +public: + // title - Text to be displayed in the title bar of the window + // text - Text message in the message box + // parent - parent panel of the message box, by default it has no parent. + ProgressBox(const char *title, const char *text, const char *pszUnknownTimeString, Panel *parent = NULL); + ProgressBox(const wchar_t *wszTitle, const wchar_t *wszText, const wchar_t *wszUnknownTimeString, Panel *parent = NULL); + ~ProgressBox(); + + // Put the message box into a modal state + virtual void DoModal(Frame *pFrameOver = NULL); + + // make the message box appear and in a modeless state + virtual void ShowWindow(Frame *pFrameOver = NULL); + + // updates progress bar, range [0, 1] + virtual void SetProgress(float progress); + + // sets the info text + virtual void SetText(const char *text); + + // toggles visibility of the close box. + virtual void SetCancelButtonVisible(bool state); + + // toggles the enabled state of the cancel button (for if it needs to be disabled part way through a process) + virtual void SetCancelButtonEnabled(bool state); + + /* custom messages: + + "ProgressBoxCancelled" + sent if the user pressed the cancel button (must be enabled & visible for this to happen) + + */ + +protected: + virtual void PerformLayout(); + virtual void OnClose(); + virtual void OnCloseFrameButtonPressed(); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void OnThink(); + virtual void OnCommand(const char *command); + virtual void OnTick(); + + // called when the update has been cancelled + virtual void OnCancel(); + +private: + MESSAGE_FUNC( OnShutdownRequest, "ShutdownRequest" ); + void Init(); + void UpdateTitle(); + + Label *m_pMessageLabel; + ProgressBar *m_pProgressBar; + Button *m_pCancelButton; + + wchar_t m_wszTitleString[128]; + wchar_t m_wcsInfoString[128]; + wchar_t m_wszUnknownTimeString[128]; + + float m_flFirstProgressUpdate; + float m_flLastProgressUpdate; + float m_flCurrentProgress; +}; + +} // namespace vgui + + +#endif // PROGRESSBOX_H diff --git a/sp/src/public/vgui_controls/PropertyDialog.h b/sp/src/public/vgui_controls/PropertyDialog.h new file mode 100644 index 00000000..32747f0a --- /dev/null +++ b/sp/src/public/vgui_controls/PropertyDialog.h @@ -0,0 +1,84 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PROPERTYDIALOG_H +#define PROPERTYDIALOG_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Simple frame that holds a property sheet +//----------------------------------------------------------------------------- +class PropertyDialog : public Frame +{ + DECLARE_CLASS_SIMPLE( PropertyDialog, Frame ); + +public: + PropertyDialog(Panel *parent, const char *panelName); + ~PropertyDialog(); + + // returns a pointer to the PropertySheet this dialog encapsulates + virtual PropertySheet *GetPropertySheet(); + + // wrapper for PropertySheet interface + virtual void AddPage(Panel *page, const char *title); + virtual Panel *GetActivePage(); + virtual void ResetAllData(); + virtual void ApplyChanges(); + + // sets the text on the OK/Cancel buttons, overriding the default + void SetOKButtonText(const char *text); + void SetCancelButtonText(const char *text); + void SetApplyButtonText(const char *text); + + // changes the visibility of the buttons + void SetOKButtonVisible(bool state); + void SetCancelButtonVisible(bool state); + void SetApplyButtonVisible(bool state); + + /* MESSAGES SENT + "ResetData" - sent when page is loaded. Data should be reloaded from document into controls. + "ApplyChanges" - sent when the OK / Apply button is pressed. Changed data should be written into document. + */ + +protected: + // Called when the OK button is pressed. Simply closes the dialog. + virtual bool OnOK(bool applyOnly); + + // called when the Cancel button is pressed + virtual void OnCancel(); + + // vgui overrides + virtual void PerformLayout(); + virtual void OnCommand(const char *command); + virtual void ActivateBuildMode(); + virtual void OnKeyCodeTyped(KeyCode code); + virtual void RequestFocus(int direction = 0); + + MESSAGE_FUNC( OnApplyButtonEnable, "ApplyButtonEnable" ); + void EnableApplyButton(bool bEnable); + +private: + PropertySheet *_propertySheet; + Button *_okButton; + Button *_cancelButton; + Button *_applyButton; + + CPanelAnimationVar( int, m_iSheetInsetBottom, "sheetinset_bottom", "32" ); +}; + +}; // vgui + +#endif // PROPERTYDIALOG_H diff --git a/sp/src/public/vgui_controls/PropertyPage.h b/sp/src/public/vgui_controls/PropertyPage.h new file mode 100644 index 00000000..8120ed06 --- /dev/null +++ b/sp/src/public/vgui_controls/PropertyPage.h @@ -0,0 +1,58 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PROPERTYPAGE_H +#define PROPERTYPAGE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Property page, as held by a set of property sheets +//----------------------------------------------------------------------------- +class PropertyPage : public EditablePanel +{ + DECLARE_CLASS_SIMPLE( PropertyPage, EditablePanel ); + +public: + PropertyPage(Panel *parent, const char *panelName); + ~PropertyPage(); + + // Called when page is loaded. Data should be reloaded from document into controls. + MESSAGE_FUNC( OnResetData, "ResetData" ); + + // Called when the OK / Apply button is pressed. Changed data should be written into document. + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + // called when the page is shown/hidden + MESSAGE_FUNC( OnPageShow, "PageShow" ); + MESSAGE_FUNC( OnPageHide, "PageHide" ); + + virtual void OnKeyCodeTyped(KeyCode code); + virtual bool HasUserConfigSettings() { return true; } + + virtual void SetVisible(bool state); + +protected: + // called to be notified of the tab button used to Activate this page + // if overridden this must be chained back to + MESSAGE_FUNC_PTR( OnPageTabActivated, "PageTabActivated", panel ); + +private: + PHandle _pageTab; +}; + +} // namespace vgui + +#endif // PROPERTYPAGE_H diff --git a/sp/src/public/vgui_controls/PropertySheet.h b/sp/src/public/vgui_controls/PropertySheet.h new file mode 100644 index 00000000..d6fdf88d --- /dev/null +++ b/sp/src/public/vgui_controls/PropertySheet.h @@ -0,0 +1,209 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PROPERTYSHEET_H +#define PROPERTYSHEET_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui/VGUI.h" +#include "vgui_controls/EditablePanel.h" +#include "vgui_controls/PHandle.h" +#include "utlvector.h" + +namespace vgui +{ + +class PageTab; +class ImagePanel; + +//----------------------------------------------------------------------------- +// Purpose: Tabbed property sheet. Holds and displays a set of Panel's +//----------------------------------------------------------------------------- +class PropertySheet : public EditablePanel +{ + DECLARE_CLASS_SIMPLE( PropertySheet, EditablePanel ); + +public: + PropertySheet(Panel *parent, const char *panelName, bool draggableTabs = false ); + PropertySheet(Panel *parent, const char *panelName,ComboBox *combo); + ~PropertySheet(); + + virtual bool IsDraggableTab() const; + void SetDraggableTabs( bool state ); + + // Adds a page to the sheet. The first page added becomes the active sheet. + virtual void AddPage(Panel *page, const char *title, char const *imageName = NULL, bool showContextMenu = false ); + + // sets the current page + virtual void SetActivePage(Panel *page); + + // sets the width, in pixels, of the page tab buttons. + virtual void SetTabWidth(int pixels); + + // Gets a pointer to the currently active page. + virtual Panel *GetActivePage(); + + // Removes (but doesn't delete) all pages + virtual void RemoveAllPages(); + + // Removes all the pages and marks all the pages for deletion. + virtual void DeleteAllPages(); + + // reloads the data in all the property page + virtual void ResetAllData(); + + // writes out any changed data to the doc + virtual void ApplyChanges(); + + // focus handling - passed on to current active page + virtual void RequestFocus(int direction = 0); + virtual bool RequestFocusPrev(VPANEL panel = NULL); + virtual bool RequestFocusNext(VPANEL panel = NULL); + + // returns the ith panel + virtual Panel *GetPage(int i); + + // deletes this panel from the sheet + virtual void DeletePage(Panel *panel); + // removes this panel from the sheet, sets its parent to NULL, but does not delete it + virtual void RemovePage(Panel *panel); + + // returns the current activated tab + virtual Panel *GetActiveTab(); + + // returns the title text of the tab + virtual void GetActiveTabTitle( char *textOut, int bufferLen ); + + // returns the title of tab "i" + virtual bool GetTabTitle( int i, char *textOut, int bufferLen ); + + // sets the title of tab "i" + virtual bool SetTabTitle( int i, char *pchTitle ); + + // returns the index of the active page + virtual int GetActivePageNum(); + + // returns the number of pages in the sheet + virtual int GetNumPages(); + + // disable the page with title "title" + virtual void DisablePage(const char *title); + + // enable the page with title "title" + virtual void EnablePage(const char *title); + + virtual void SetSmallTabs( bool state ); + virtual bool IsSmallTabs() const; + + /* MESSAGES SENT TO PAGES + "PageShow" - sent when a page is shown + "PageHide" - sent when a page is hidden + "ResetData" - sent when the data should be reloaded from doc + "ApplyChanges" - sent when data should be written to doc + */ + + virtual void OnPanelDropped( CUtlVector< KeyValues * >& msglist ); + virtual bool IsDroppable( CUtlVector< KeyValues * >& msglist ); + // Mouse is now over a droppable panel + virtual void OnDroppablePanelPaint( CUtlVector< KeyValues * >& msglist, CUtlVector< Panel * >& dragPanels ); + + void ShowContextButtons( bool state ); + bool ShouldShowContextButtons() const; + + int FindPage( Panel *page ) const; + + bool PageHasContextMenu( Panel *page ) const; + + void SetKBNavigationEnabled( bool state ); + bool IsKBNavigationEnabled() const; + + virtual bool HasUserConfigSettings() { return true; } + +protected: + virtual void PaintBorder(); + virtual void PerformLayout(); + virtual Panel *HasHotkey(wchar_t key); + virtual void ChangeActiveTab(int index); + virtual void OnKeyCodePressed(KeyCode code); + virtual void OnCommand(const char *command); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void ApplySettings(KeyValues *inResourceData); + + // internal message handlers + MESSAGE_FUNC_PTR( OnTabPressed, "TabPressed", panel ); + MESSAGE_FUNC_PTR_WCHARPTR( OnTextChanged, "TextChanged", panel, text ); + MESSAGE_FUNC_PARAMS( OnOpenContextMenu, "OpenContextMenu", params ); + MESSAGE_FUNC( OnApplyButtonEnable, "ApplyButtonEnable" ); + // called when default button has been set + MESSAGE_FUNC_HANDLE( OnDefaultButtonSet, "DefaultButtonSet", button ); + // called when the current default button has been set + MESSAGE_FUNC_HANDLE( OnCurrentDefaultButtonSet, "CurrentDefaultButtonSet", button); + MESSAGE_FUNC( OnFindDefaultButton, "FindDefaultButton" ); + +private: + + // enable/disable the page with title "title" + virtual void SetPageEnabled(const char *title,bool state); + + struct Page_t + { + Page_t() : + page( 0 ), + contextMenu( false ) + { + } + + Panel *page; + bool contextMenu; + }; + + CUtlVector m_Pages; + CUtlVector m_PageTabs; + Panel *_activePage; + PageTab *_activeTab; + int _tabWidth; + int _activeTabIndex; + ComboBox *_combo; + bool _showTabs; + bool _tabFocus; + + PHandle m_hPreviouslyActivePage; + float m_flPageTransitionEffectTime; + bool m_bSmallTabs; + HFont m_tabFont; + bool m_bDraggableTabs; + bool m_bContextButton; + bool m_bKBNavigationEnabled; + + CPanelAnimationVarAliasType( int, m_iTabXIndent, "tabxindent", "0", "proportional_int" ); + CPanelAnimationVarAliasType( int, m_iTabXDelta, "tabxdelta", "0", "proportional_int" ); + CPanelAnimationVarAliasType( bool, m_bTabFitText, "tabxfittotext", "1", "bool" ); + + //============================================================================= + // HPE_BEGIN: + // [tj] These variables have been split into the initially specified size + // and the currently set size. This is so we can always recalculate the + // new value for resolution changes. + //============================================================================= + CPanelAnimationVarAliasType( int, m_iSpecifiedTabHeight, "tabheight", "28", "int" ); + CPanelAnimationVarAliasType( int, m_iSpecifiedTabHeightSmall, "tabheight_small", "14", "int" ); + + int m_iTabHeight; + int m_iTabHeightSmall; + //============================================================================= + // HPE_END + //============================================================================= + + KeyValues *m_pTabKV; +}; + +}; // namespace vgui + +#endif // PROPERTYSHEET_H diff --git a/sp/src/public/vgui_controls/QueryBox.h b/sp/src/public/vgui_controls/QueryBox.h new file mode 100644 index 00000000..40e6e46f --- /dev/null +++ b/sp/src/public/vgui_controls/QueryBox.h @@ -0,0 +1,62 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Creates a Message box with a question in it and yes/no buttons +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef QUERYBOX_H +#define QUERYBOX_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Creates A Message box with a question in it and yes/no buttons +//----------------------------------------------------------------------------- +class QueryBox : public MessageBox +{ + DECLARE_CLASS_SIMPLE( QueryBox, MessageBox ); + +public: + QueryBox(const char *title, const char *queryText,vgui::Panel *parent = NULL ); + QueryBox(const wchar_t *wszTitle, const wchar_t *wszQueryText,vgui::Panel *parent = NULL); + ~QueryBox(); + + // Layout the window for drawing + virtual void PerformLayout(); + + // Set the keyvalues to send when ok button is hit + void SetOKCommand(KeyValues *keyValues); + + // Set the keyvalues to send when the cancel button is hit + void SetCancelCommand(KeyValues *keyValues); + + // Set the text on the Cancel button + void SetCancelButtonText(const char *buttonText); + void SetCancelButtonText(const wchar_t *wszButtonText); + + // Set a value of the ok command + void SetOKCommandValue(const char *keyName, int value); + +protected: + virtual void OnKeyCodeTyped( KeyCode code ); + virtual void OnKeyCodePressed( KeyCode code ); + virtual void OnCommand(const char *command); + Button *m_pCancelButton; + +private: + KeyValues *m_pCancelCommand; + KeyValues *m_pOkCommand; +}; + +} +#endif // QUERYBOX_H diff --git a/sp/src/public/vgui_controls/RadioButton.h b/sp/src/public/vgui_controls/RadioButton.h new file mode 100644 index 00000000..c21abbad --- /dev/null +++ b/sp/src/public/vgui_controls/RadioButton.h @@ -0,0 +1,112 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef RADIOBUTTON_H +#define RADIOBUTTON_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Radio buton image +//----------------------------------------------------------------------------- +class RadioImage : public TextImage +{ +public: + RadioImage(RadioButton *radioButton) : TextImage( "n" ) + { + _radioButton = radioButton; + + SetSize(20, 13); + } + + virtual void Paint(); + + virtual void SetColor(Color color) + { + _borderColor1 = color; + _borderColor2 = color; + _checkColor = color; + } + + Color _borderColor1; + Color _borderColor2; + Color _checkColor; + + Color _bgColor; + +private: + RadioButton *_radioButton; +}; + +//----------------------------------------------------------------------------- +// Purpose: Radio buttons are automatically selected into groups by who their +// parent is. At most one radio button is active at any time. +//----------------------------------------------------------------------------- +class RadioButton : public ToggleButton +{ + DECLARE_CLASS_SIMPLE( RadioButton, ToggleButton ); + +public: + RadioButton(Panel *parent, const char *panelName, const char *text); + ~RadioButton(); + + // Set the radio button checked. When a radio button is checked, a + // message is sent to all other radio buttons in the same group so + // they will become unchecked. + virtual void SetSelected(bool state); + + // Get the tab position of the radio button with the set of radio buttons + // A group of RadioButtons must have the same TabPosition, with [1, n] subtabpositions + virtual int GetSubTabPosition(); + virtual void SetSubTabPosition(int position); + + // Return the RadioButton's real tab position (its Panel one changes) + virtual int GetRadioTabPosition(); + + // Set the selection state of the radio button, but don't fire + // any action signals or messages to other radio buttons + virtual void SilentSetSelected(bool state); + +protected: + virtual void DoClick(); + + virtual void Paint(); + virtual void ApplySchemeSettings(IScheme *pScheme); + MESSAGE_FUNC_INT( OnRadioButtonChecked, "RadioButtonChecked", tabposition); + virtual void OnKeyCodeTyped(KeyCode code); + + virtual IBorder *GetBorder(bool depressed, bool armed, bool selected, bool keyfocus); + + virtual void ApplySettings(KeyValues *inResourceData); + virtual void GetSettings(KeyValues *outResourceData); + virtual const char *GetDescription(); + virtual void PerformLayout(); + + RadioButton *FindBestRadioButton(int direction); + +private: + RadioImage *_radioBoxImage; + int _oldTabPosition; + Color _selectedFgColor; + + int _subTabPosition; // tab position with the radio button list + + void InternalSetSelected(bool state, bool bFireEvents); +}; + +}; // namespace vgui + +#endif // RADIOBUTTON_H diff --git a/sp/src/public/vgui_controls/RichText.h b/sp/src/public/vgui_controls/RichText.h new file mode 100644 index 00000000..704ef08b --- /dev/null +++ b/sp/src/public/vgui_controls/RichText.h @@ -0,0 +1,297 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef RICHTEXT_H +#define RICHTEXT_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class ClickPanel; + +//----------------------------------------------------------------------------- +// Purpose: Non-editable display of a rich text control +//----------------------------------------------------------------------------- +class RichText : public Panel +{ + DECLARE_CLASS_SIMPLE( RichText, Panel ); + +public: + RichText(Panel *parent, const char *panelName); + ~RichText(); + + // text manipulation + virtual void SetText(const char *text); + virtual void SetText(const wchar_t *text); + void GetText(int offset, OUT_Z_BYTECAP(bufLenInBytes) wchar_t *buf, int bufLenInBytes); + void GetText(int offset, OUT_Z_BYTECAP(bufLenInBytes) char *pch, int bufLenInBytes); + + // configuration + void SetFont(HFont font); + + // inserts characters at the end of the stream + void InsertChar(wchar_t ch); + void InsertString(const char *text); + void InsertString(const wchar_t *wszText); + + // selection + void SelectNone(); + void SelectAllText(); + void SelectNoText(); + MESSAGE_FUNC( CutSelected, "DoCutSelected" ); + MESSAGE_FUNC( CopySelected, "DoCopySelected" ); + + // sets the RichText control interactive or not (meaning you can select/copy text in the window) + void SetPanelInteractive( bool bInteractive ){ m_bInteractive = bInteractive; } + + // sets the RichText scrollbar invisible if it's not going to be used + void SetUnusedScrollbarInvisible( bool bInvis ){ m_bUnusedScrollbarInvis = bInvis; } + + // cursor movement + void GotoTextStart(); // go to start of text buffer + void GotoTextEnd(); // go to end of text buffer + + // configuration + // sets visibility of scrollbar + void SetVerticalScrollbar(bool state); + // sets limit of number of characters insertable into field; set to -1 to remove maximum + // only works with if rich-edit is NOT enabled + void SetMaximumCharCount(int maxChars); + + // rich edit commands + void InsertColorChange(Color col); + // IndentChange doesn't take effect until the next newline character + void InsertIndentChange(int pixelsIndent); + // clickable text + // notification that text was clicked is through "TextClicked" message + void InsertClickableTextStart( const char *pchClickAction = NULL ); + void InsertClickableTextEnd(); + // inserts a string that needs to be scanned for urls/mailto commands to be made clickable + void InsertPossibleURLString(const char *text, Color URLTextColor, Color normalTextColor); + + void InsertFade( float flSustain, float flLength ); + + void ResetAllFades( bool bHold, bool bOnlyExpired = false, float flNewSustain = -1.0f ); + + // sets the height of the window so all text is visible. + // used by tooltips + void SetToFullHeight(); + int GetNumLines(); + + /* CUSTOM MESSAGE HANDLING + "SetText" + input: "text" - text is set to be this string + */ + + /* MESSAGE SENDING (to action signal targets) + "TextChanged" - sent when the text is edited by the user + + + "TextClicked" - sent when clickable text has been clicked on + "text" - the text that was clicked on + */ + + virtual bool RequestInfo(KeyValues *outputData); + /* INFO HANDLING + "GetText" + returns: + "text" - text contained in the text box + */ + virtual void SetFgColor( Color color ); + virtual void SetDrawOffsets( int ofsx, int ofsy ); + bool IsScrollbarVisible(); + + // sets how URL's are handled + // if set, a "URLClicked" "url" "" message will be sent to that panel + void SetURLClickedHandler( Panel *pPanelToHandleClickMsg ); + + void SetUnderlineFont( HFont font ); + + bool IsAllTextAlphaZero() const; + bool HasText() const; + + void SetDrawTextOnly(); + +protected: + virtual void OnThink(); + virtual void PerformLayout(); // layout the text in the window + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void Paint(); + + virtual void ApplySettings( KeyValues *inResourceData ); + virtual void GetSettings( KeyValues *outResourceData ); + virtual const char *GetDescription( void ); + MESSAGE_FUNC_WCHARPTR( OnSetText, "SetText", text ); + MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); // respond to scroll bar events + virtual void OnKillFocus(); + virtual void OnMouseWheeled(int delta); // respond to mouse wheel events + virtual void OnKeyCodeTyped(KeyCode code); //respond to keyboard events + + MESSAGE_FUNC_INT( OnClickPanel, "ClickPanel", index); + + virtual void OnCursorMoved(int x, int y); // respond to moving the cursor with mouse button down + virtual void OnMousePressed(MouseCode code); // respond to mouse down events + virtual void OnMouseDoublePressed(MouseCode code); + virtual void OnMouseReleased(MouseCode code); // respond to mouse up events + + virtual void OnMouseFocusTicked(); // do while window has mouse focus + virtual void OnCursorEntered(); // handle cursor entering window + virtual void OnCursorExited(); // handle cursor exiting window + + virtual void OnMouseCaptureLost(); + virtual void OnSizeChanged(int newWide, int newTall); + virtual void OnSetFocus(); + + // clickable url handling + int ParseTextStringForUrls(const char *text, int startPos, char *pchURLText, int cchURLText, char *pchURL, int cchURL, bool &clickable); + virtual void OnTextClicked(const wchar_t *text); + +#ifdef DBGFLAG_VALIDATE + virtual void Validate( CValidator &validator, char *pchName ); +#endif // DBGFLAG_VALIDATE + +protected: + ScrollBar *_vertScrollBar; // the scroll bar used in the window + +private: + int GetLineHeight(); + HFont GetDefaultFont(); + + const wchar_t *ResolveLocalizedTextAndVariables( char const *pchLookup, OUT_Z_BYTECAP(outbufsizeinbytes) wchar_t *outbuf, size_t outbufsizeinbytes ); + void CheckRecalcLineBreaks(); + + void GotoWordRight(); // move cursor to start of next word + void GotoWordLeft(); // move cursor to start of prev word + + void TruncateTextStream(); + bool GetSelectedRange(int& cx0,int& cx1); + void CursorToPixelSpace(int cursorPos, int &cx, int &cy); + int PixelToCursorSpace(int cx, int cy); + void AddAnotherLine(int &cx, int &cy); + void RecalculateDefaultState(int startIndex); + + void LayoutVerticalScrollBarSlider(); + void OpenEditMenu(); + void FinishingURL(int x, int y); + // Returns the character index the drawing should Start at + int GetStartDrawIndex(int &lineBreakIndexIndex); + int GetCursorLine(); + int GetClickableTextIndexStart(int startIndex); + void CreateEditMenu(); // create copy/cut/paste menu + + MESSAGE_FUNC_INT( MoveScrollBar, "MoveScrollBar", delta ); + MESSAGE_FUNC_INT( MoveScrollBarDirect, "MoveScrollBarDirect", delta ); + + // linebreak stream functions + void InvalidateLineBreakStream(); + void RecalculateLineBreaks(); + + struct TFade + { + float flFadeStartTime; + float flFadeLength; + float flFadeSustain; + int iOriginalAlpha; + }; + + // format stream - describes changes in formatting for the text stream + struct TFormatStream + { + // render state + Color color; + int pixelsIndent; + bool textClickable; + CUtlSymbol m_sClickableTextAction; + + TFade fade; + + // position in TextStream that these changes take effect + int textStreamIndex; + }; + + bool m_bResetFades; + bool m_bInteractive; + bool m_bUnusedScrollbarInvis; + bool m_bAllTextAlphaIsZero; + + // data + CUtlVector m_TextStream; // the text in the text window is stored in this buffer + CUtlVector m_LineBreaks; // an array that holds the index in the buffer to wrap lines at + CUtlVector m_FormatStream; // list of format changes + + bool m_bRecalcLineBreaks; + + int _recalculateBreaksIndex; // tells next linebreakindex index to Start recalculating line breaks + bool _invalidateVerticalScrollbarSlider; + int _cursorPos; // the position in the text buffer of the blinking cursor + bool _mouseSelection; // whether we are highlighting text or not (selecting text) + bool _mouseDragSelection; // tells weather mouse is outside window and button is down so we select text + int _select[2]; // select[1] is the offset in the text to where the cursor is currently + // select[0] is the offset to where the cursor was dragged to. or -1 if no drag. + int _pixelsIndent; + int _maxCharCount; // max number of chars that can be in the text buffer + HFont _font; // font of chars in the text buffer + HFont m_hFontUnderline; + Color _selectionColor; + Color _selectionTextColor; // color of the highlighted text + bool _currentTextClickable; + CUtlVector _clickableTextPanels; + int _clickableTextIndex; + Color _defaultTextColor; + int _drawOffsetX; + int _drawOffsetY; + + Panel *m_pInterior; + PHandle m_hPanelToHandleClickingURLs; + + + // sub-controls + Menu *m_pEditMenu; // cut/copy/paste popup + + char *m_pszInitialText; // initial text + + // saved state + bool _recalcSavedRenderState; + + struct TRenderState + { + // rendering positions + int x, y; + + // basic state + Color textColor; + int pixelsIndent; + bool textClickable; + + // index into our current position in the formatting stream + int formatStreamIndex; + }; + TRenderState m_CachedRenderState; // cached render state for the beginning of painting + + // updates a render state based on the formatting and color streams + // returns true if any state changed + bool UpdateRenderState(int textStreamPos, TRenderState &renderState); + void CalculateFade( TRenderState &renderState ); + + void GenerateRenderStateForTextStreamIndex(int textStreamIndex, TRenderState &renderState); + int FindFormatStreamIndexForTextStreamPos(int textStreamIndex); + + // draws a string of characters with the same formatting using the current render state + int DrawString(int iFirst, int iLast, TRenderState &renderState, HFont font); +}; + +} // namespace vgui + + +#endif // RICHTEXT_H diff --git a/sp/src/public/vgui_controls/RotatingProgressBar.h b/sp/src/public/vgui_controls/RotatingProgressBar.h new file mode 100644 index 00000000..400838c3 --- /dev/null +++ b/sp/src/public/vgui_controls/RotatingProgressBar.h @@ -0,0 +1,67 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef ROTATINGPROGRESSBAR_H +#define ROTATINGPROGRESSBAR_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include + +namespace vgui +{ + + //----------------------------------------------------------------------------- + // Purpose: Progress Bar that rotates an image around its center + //----------------------------------------------------------------------------- + class RotatingProgressBar : public ProgressBar + { + DECLARE_CLASS_SIMPLE( RotatingProgressBar, ProgressBar ); + + public: + RotatingProgressBar(Panel *parent, const char *panelName); + ~RotatingProgressBar(); + + virtual void ApplySettings(KeyValues *inResourceData); + virtual void ApplySchemeSettings(IScheme *pScheme); + + void SetImage( const char *imageName ); + + protected: + virtual void Paint(); + virtual void PaintBackground(); + virtual void OnTick(); + + private: + int m_nTextureId; + char *m_pszImageName; + + float m_flStartRadians; + float m_flEndRadians; + + float m_flLastAngle; + + float m_flTickDelay; + float m_flApproachSpeed; + + float m_flRotOriginX; + float m_flRotOriginY; + + float m_flRotatingX; + float m_flRotatingY; + float m_flRotatingWide; + float m_flRotatingTall; + + }; + +} // namespace vgui + +#endif // ROTATINGPROGRESSBAR_H \ No newline at end of file diff --git a/sp/src/public/vgui_controls/ScalableImagePanel.h b/sp/src/public/vgui_controls/ScalableImagePanel.h new file mode 100644 index 00000000..7c4f1b7a --- /dev/null +++ b/sp/src/public/vgui_controls/ScalableImagePanel.h @@ -0,0 +1,59 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SCALABLEIMAGEPANEL_H +#define SCALABLEIMAGEPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + //----------------------------------------------------------------------------- + // Purpose: 9-way Segmented background + //----------------------------------------------------------------------------- + class ScalableImagePanel : public Panel + { + DECLARE_CLASS_SIMPLE( ScalableImagePanel, Panel ); + public: + ScalableImagePanel(Panel *parent, const char *name); + ~ScalableImagePanel(); + + virtual void SetImage(const char *imageName); + void SetDrawColor( Color color ) { m_DrawColor = color; } + + protected: + virtual void PaintBackground(); + virtual void GetSettings(KeyValues *outResourceData); + virtual void ApplySettings(KeyValues *inResourceData); + virtual void PerformLayout( void ); + virtual const char *GetDescription(); + + private: + int m_iSrcCornerHeight; // in pixels, how tall is the corner inside the image + int m_iSrcCornerWidth; // same for width + int m_iCornerHeight; // output size of the corner height in pixels + int m_iCornerWidth; // same for width + + int m_iTextureID; + + float m_flCornerWidthPercent; // corner width as percentage of image width + float m_flCornerHeightPercent; // same for height + + char *m_pszImageName; + + char *m_pszDrawColorName; + Color m_DrawColor; + }; + +} // namespace vgui + +#endif // SCALABLEIMAGEPANEL_H diff --git a/sp/src/public/vgui_controls/ScrollBar.h b/sp/src/public/vgui_controls/ScrollBar.h new file mode 100644 index 00000000..c22e3a59 --- /dev/null +++ b/sp/src/public/vgui_controls/ScrollBar.h @@ -0,0 +1,133 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SCROLLBAR_H +#define SCROLLBAR_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class Button; +class ScrollBarSlider; + +//----------------------------------------------------------------------------- +// Purpose: Generic scrollbar +// Uses Buttons & SliderBars for the main functionality +//----------------------------------------------------------------------------- +class ScrollBar : public Panel +{ + DECLARE_CLASS_SIMPLE( ScrollBar, Panel ); + +public: + ScrollBar(Panel *parent, const char *panelName, bool vertical); + + // Set the value of the scroll bar slider. + virtual void SetValue(int value); + + // Get the value of the scroll bar slider. + virtual int GetValue(); + + // Set the rangeof numbers the slider can scroll through + virtual void SetRange(int min,int max); + + virtual void GetRange(int &min, int &max); + + // Set how many lines are displayed at one time + // in the window the scroll bar is attached to. + virtual void SetRangeWindow(int rangeWindow); + + // Get how many lines are displayed at one time + // in the window the scroll bar is attached to. + virtual int GetRangeWindow(); + + // Check if the scrollbar is vertical or horizontal + virtual bool IsVertical(); + + // Purpose: Check if the slider can move through one or more pixels per + // unit of its range. + virtual bool HasFullRange(); + + // Setup the indexed scroll bar button with the input params. + virtual void SetButton(Button* button,int index); + // Return the indexed scroll bar button + virtual Button *GetButton(int index); + // Set up the slider. + virtual void SetSlider(ScrollBarSlider* slider); + // Return a pointer to the slider. + virtual ScrollBarSlider *GetSlider(); + // Set how far the scroll bar slider moves + // when a scroll bar button is pressed + virtual void SetButtonPressedScrollValue(int value); + + virtual void Validate(); + + // Update and look for clicks when mouse is in the scroll bar window. + virtual void OnMouseFocusTicked(); + + // Set the slider's Paint border enabled. + virtual void SetPaintBorderEnabled(bool state); + // Set the slider's Paint background enabled. + virtual void SetPaintBackgroundEnabled(bool state); + // Set the slider's Paint enabled. + virtual void SetPaintEnabled(bool state); + + // Sets the scrollbar buttons visible or not + virtual void SetScrollbarButtonsVisible(bool visible); + + void SetAutohideButtons( bool bAutohide ) { m_bAutoHideButtons = bAutohide; } + + void UseImages( const char *pszUpArrow, const char *pszDownArrow, const char *pszLine, const char *pszBox ); + + /* MESSAGES SENT: + "ScrollBarSliderMoved" + "position" - new value of the slider + */ + + void SetOverriddenButtons( Button *pB1, Button *pB2 ) { m_pOverriddenButtons[0] = pB1; m_pOverriddenButtons[1] = pB2; } + + virtual void ApplySettings( KeyValues *pInResourceData ); + +protected: + + virtual void PerformLayout(); + virtual void SendSliderMoveMessage(int value); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void OnSizeChanged(int wide, int tall); + + MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position ); + virtual void RespondToScrollArrow(int const direction); + + virtual void UpdateButtonsForImages( void ); + virtual void UpdateSliderImages( void ); + Button *GetDepressedButton( int iIndex ); + +private: + Button* _button[2]; + ScrollBarSlider* _slider; + int _buttonPressedScrollValue; + int _scrollDelay; // used to control delays in scrolling + bool _respond; + bool m_bNoButtons; + CPanelAnimationVar( bool, m_bAutoHideButtons, "autohide_buttons", "0" ); + + vgui::ImagePanel *m_pUpArrow; + vgui::ImagePanel *m_pLine; + vgui::ImagePanel *m_pDownArrow; + vgui::ImagePanel *m_pBox; + Button *m_pOverriddenButtons[2]; +}; + +} + +#endif // SCROLLBAR_H diff --git a/sp/src/public/vgui_controls/ScrollBarSlider.h b/sp/src/public/vgui_controls/ScrollBarSlider.h new file mode 100644 index 00000000..8769222f --- /dev/null +++ b/sp/src/public/vgui_controls/ScrollBarSlider.h @@ -0,0 +1,94 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef SCROLLBARSLIDER_H +#define SCROLLBARSLIDER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class IBorder; + +//----------------------------------------------------------------------------- +// Purpose: ScrollBarSlider bar, as used in ScrollBar's +//----------------------------------------------------------------------------- +class ScrollBarSlider : public Panel +{ + DECLARE_CLASS_SIMPLE( ScrollBarSlider, Panel ); + +public: + ScrollBarSlider(Panel *parent, const char *panelName, bool vertical); + + // Set the ScrollBarSlider value of the nob. + virtual void SetValue(int value); + virtual int GetValue(); + + // Check whether the scroll bar is vertical or not + virtual bool IsVertical(); + + // Set max and min range of lines to display + virtual void SetRange(int min, int max); + + virtual void GetRange(int &min, int &max); + + // Set number of rows that can be displayed in window + virtual void SetRangeWindow(int rangeWindow); + + // Get number of rows that can be displayed in window + virtual int GetRangeWindow(); + + // Set the size of the ScrollBarSlider nob + virtual void SetSize(int wide, int tall); + + // Get current ScrollBarSlider bounds + virtual void GetNobPos(int &min, int &max); + + virtual bool HasFullRange(); + virtual void SetButtonOffset(int buttonOffset); + virtual void OnCursorMoved(int x, int y); + virtual void OnMousePressed(MouseCode code); + virtual void OnMouseDoublePressed(MouseCode code); + virtual void OnMouseReleased(MouseCode code); + + // Return true if this slider is actually drawing itself + virtual bool IsSliderVisible( void ); + + virtual void ApplySettings( KeyValues *pInResourceData ); + +protected: + virtual void Paint(); + virtual void PaintBackground(); + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme *pScheme); + +private: + virtual void RecomputeNobPosFromValue(); + virtual void RecomputeValueFromNobPos(); + virtual void SendScrollBarSliderMovedMessage(); + + bool _vertical; + bool _dragging; + int _nobPos[2]; + int _nobDragStartPos[2]; + int _dragStartPos[2]; + int _range[2]; + int _value; // the position of the ScrollBarSlider, in coordinates as specified by SetRange/SetRangeWindow + int _rangeWindow; + int _buttonOffset; + IBorder *_ScrollBarSliderBorder; +}; + +} // namespace vgui + +#endif // SCROLLBARSLIDER_H diff --git a/sp/src/public/vgui_controls/ScrollableEditablePanel.h b/sp/src/public/vgui_controls/ScrollableEditablePanel.h new file mode 100644 index 00000000..6796405d --- /dev/null +++ b/sp/src/public/vgui_controls/ScrollableEditablePanel.h @@ -0,0 +1,55 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#ifndef SCROLLABLEEDITABLEPANEL_H +#define SCROLLABLEEDITABLEPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/EditablePanel.h" + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +namespace vgui +{ + class ScrollBar; +} + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// An editable panel that has a scrollbar +//----------------------------------------------------------------------------- +class ScrollableEditablePanel : public vgui::EditablePanel +{ + DECLARE_CLASS_SIMPLE( ScrollableEditablePanel, vgui::EditablePanel ); + +public: + ScrollableEditablePanel( vgui::Panel *pParent, vgui::EditablePanel *pChild, const char *pName ); + virtual ~ScrollableEditablePanel() {} + + virtual void ApplySettings( KeyValues *pInResourceData ); + virtual void PerformLayout(); + + vgui::ScrollBar *GetScrollbar( void ) { return m_pScrollBar; } + + MESSAGE_FUNC( OnScrollBarSliderMoved, "ScrollBarSliderMoved" ); + virtual void OnMouseWheeled(int delta); // respond to mouse wheel events + +private: + vgui::ScrollBar *m_pScrollBar; + vgui::EditablePanel *m_pChild; +}; + + +} // end namespace vgui + +#endif // SCROLLABLEEDITABLEPANEL_H \ No newline at end of file diff --git a/sp/src/public/vgui_controls/SectionedListPanel.h b/sp/src/public/vgui_controls/SectionedListPanel.h new file mode 100644 index 00000000..c38f6c74 --- /dev/null +++ b/sp/src/public/vgui_controls/SectionedListPanel.h @@ -0,0 +1,317 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SECTIONEDLISTPANEL_H +#define SECTIONEDLISTPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include +#include +#include + +namespace vgui +{ + +class SectionedListPanel; +class SectionedListPanelHeader; +class CItemButton; + +// sorting function, should return true if itemID1 should be displayed before itemID2 +typedef bool (*SectionSortFunc_t)(SectionedListPanel *list, int itemID1, int itemID2); + +//----------------------------------------------------------------------------- +// Purpose: List panel control that is divided up into discrete sections +//----------------------------------------------------------------------------- +class SectionedListPanel : public Panel +{ + DECLARE_CLASS_SIMPLE( SectionedListPanel, Panel ); + +public: + SectionedListPanel(vgui::Panel *parent, const char *name); + ~SectionedListPanel(); + + // adds a new section; returns false if section already exists + virtual void AddSection(int sectionID, const char *name, SectionSortFunc_t sortFunc = NULL); + virtual void AddSection(int sectionID, const wchar_t *name, SectionSortFunc_t sortFunc = NULL); + virtual void AddSection(int sectionID, SectionedListPanelHeader *pHeader, SectionSortFunc_t sortFunc = NULL); + + // clears all the sections - leaves the items in place + virtual void RemoveAllSections(); + + // modifies section info + virtual void SetSectionFgColor(int sectionID, Color color); + virtual void SetSectionDividerColor( int sectionID, Color color); + // forces a section to always be visible + virtual void SetSectionAlwaysVisible(int sectionID, bool visible = true); + virtual void SetSectionMinimumHeight(int sectionID, int iMinimumHeight); + + // adds a new column to a section + enum ColumnFlags_e + { + HEADER_IMAGE = 0x01, // set if the header for the column is an image instead of text + COLUMN_IMAGE = 0x02, // set if the column contains an image instead of text (images are looked up by index from the ImageList) (see SetImageList below) + COLUMN_BRIGHT = 0x04, // set if the column text should be the bright color + COLUMN_CENTER = 0x08, // set to center the text/image in the column + COLUMN_RIGHT = 0x10, // set to right-align the text in the column + }; + virtual bool AddColumnToSection(int sectionID, const char *columnName, const char *columnText, int columnFlags, int width, HFont fallbackFont = INVALID_FONT ); + virtual bool AddColumnToSection(int sectionID, const char *columnName, const wchar_t *columnText, int columnFlags, int width, HFont fallbackFont = INVALID_FONT ); + + // modifies the text in an existing column + virtual bool ModifyColumn(int sectionID, const char *columnName, const wchar_t *columnText); + + // adds an item to the list; returns the itemID of the new item + virtual int AddItem(int sectionID, const KeyValues *data); + + // modifies an existing item; returns false if the item does not exist + virtual bool ModifyItem(int itemID, int sectionID, const KeyValues *data); + + // removes an item from the list; returns false if the item does not exist or is already removed + virtual bool RemoveItem(int itemID); + + // clears the list + virtual void RemoveAll() { DeleteAllItems(); } + // DeleteAllItems() is deprecated, use RemoveAll(); + virtual void DeleteAllItems(); + + // set the text color of an item + virtual void SetItemFgColor(int itemID, Color color); + //============================================================================= + // HPE_BEGIN: + // [menglish] Getters and setters for several item and section objects + //============================================================================= + virtual void SetItemBgColor( int itemID, Color color ); + virtual int GetColumnIndexByName(int sectionID, char* name); + virtual int GetLineSpacing() { return m_iLineSpacing; } + //============================================================================= + // HPE_END + //============================================================================= + virtual void SetItemFont( int itemID, HFont font ); + virtual void SetItemEnabled( int itemID, bool bEnabled ); + + /* MESSAGES SENT: + "RowSelected" + "itemID" - the selected item id, -1 if nothing selected + + // when an item has been clicked on + "RowContextMenu" "itemID" + "RowLeftClick" "itemID" + "RowDoubleLeftClick" "itemID" + */ + + // returns the number of columns in a section + virtual int GetColumnCountBySection(int sectionID); + + // returns the name of a column by section and column index; returns NULL if there are no more columns + // valid range of columnIndex is [0, GetColumnCountBySection) + virtual const char *GetColumnNameBySection(int sectionID, int columnIndex); + virtual const wchar_t *GetColumnTextBySection(int sectionID, int columnIndex); + virtual int GetColumnFlagsBySection(int sectionID, int columnIndex); + virtual int GetColumnWidthBySection(int sectionID, int columnIndex); + virtual HFont GetColumnFallbackFontBySection( int sectionID, int columnIndex ); + + // returns the id of the currently selected item, -1 if nothing is selected + virtual int GetSelectedItem(); + + // sets which item is currently selected + virtual void SetSelectedItem(int itemID); + + // remove selection + virtual void ClearSelection( void ); + + // returns the data of a selected item + // InvalidateItem(itemID) needs to be called if the KeyValues are modified + virtual KeyValues *GetItemData(int itemID); + + // returns what section an item is in + virtual int GetItemSection(int itemID); + + // forces an item to redraw (use when keyvalues have been modified) + virtual void InvalidateItem(int itemID); + + // returns true if the itemID is valid for use + virtual bool IsItemIDValid(int itemID); + virtual int GetHighestItemID(); + + // returns the number of items (ignoring section dividers) + virtual int GetItemCount(); + + // returns the item ID from the row, again ignoring section dividers - valid from [0, GetItemCount ) + virtual int GetItemIDFromRow(int row); + + // returns the row that this itemID occupies. -1 if the itemID is invalid + virtual int GetRowFromItemID(int itemID); + + // gets the local coordinates of a cell + virtual bool GetCellBounds(int itemID, int column, int &x, int &y, int &wide, int &tall); + + // Gets the coordinates of a section header + virtual bool GetSectionHeaderBounds(int sectionID, int &x, int &y, int &wide, int &tall); + + //============================================================================= + // HPE_BEGIN: + // [menglish] Get the bounds of an item or column. + //============================================================================= + + // gets the local coordinates of a cell using the max width for every column + virtual bool GetMaxCellBounds(int itemID, int column, int &x, int &y, int &wide, int &tall); + + // gets the local coordinates of an item + virtual bool GetItemBounds(int itemID, int &x, int &y, int &wide, int &tall); + + // [tj] Accessors for clickability + void SetClickable(bool clickable) { m_clickable = clickable; } + bool IsClickable() { return m_clickable; } + + // [tj] Accessors for header drawing + void SetDrawHeaders(bool drawHeaders) { m_bDrawSectionHeaders = drawHeaders; } + bool GetDrawHeaders() { return m_bDrawSectionHeaders; } + + //============================================================================= + // HPE_END + //============================================================================= + + // set up a field for editing + virtual void EnterEditMode(int itemID, int column, vgui::Panel *editPanel); + + // leaves editing mode + virtual void LeaveEditMode(); + + // returns true if we are currently in inline editing mode + virtual bool IsInEditMode(); + + // sets whether or not the vertical scrollbar should ever be displayed + virtual void SetVerticalScrollbar(bool state); + + // returns the size required to fully draw the contents of the panel + virtual void GetContentSize(int &wide, int &tall); + + // image handling + virtual void SetImageList(ImageList *imageList, bool deleteImageListWhenDone); + + virtual void ScrollToItem(int iItem); + + virtual void SetProportional(bool state); + + HFont GetHeaderFont( void ) const; + void SetHeaderFont( HFont hFont ); + HFont GetRowFont( void ) const; + void SetRowFont( HFont hFont ); + void MoveSelectionDown( void ); + void MoveSelectionUp( void ); + +protected: + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void ApplySettings(KeyValues *inResourceData); + virtual void OnSizeChanged(int wide, int tall); + virtual void OnMouseWheeled(int delta); + virtual void OnMousePressed( MouseCode code); + virtual void NavigateTo( void ); + virtual void OnKeyCodePressed( KeyCode code ); + virtual void OnSetFocus(); // called after the panel receives the keyboard focus + +public: + virtual void SetFontSection(int sectionID, HFont font); +private: + MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); + + int GetSectionTall(); + void LayoutPanels(int &contentTall); + + // Returns the index of a new item button, reusing an existing item button if possible + int GetNewItemButton(); + + friend class CItemButton; + void SetSelectedItem(CItemButton *item); + DHANDLE m_hSelectedItem; + + struct column_t + { + char m_szColumnName[32]; + wchar_t m_szColumnText[64]; + int m_iColumnFlags; + int m_iWidth; + HFont m_hFallbackFont; + }; + struct section_t + { + int m_iID; + bool m_bAlwaysVisible; + SectionedListPanelHeader *m_pHeader; + CUtlVector m_Columns; + SectionSortFunc_t m_pSortFunc; + int m_iMinimumHeight; + }; + + CUtlVector m_Sections; + CUtlLinkedList m_Items; + CUtlLinkedList m_FreeItems; + CUtlVector m_SortedItems; + + PHandle m_hEditModePanel; + int m_iEditModeItemID; + int m_iEditModeColumn; + int m_iContentHeight; + int m_iLineSpacing; + int m_iSectionGap; + + int FindSectionIndexByID(int sectionID); + void ReSortList(); + + ScrollBar *m_pScrollBar; + ImageList *m_pImageList; + bool m_bDeleteImageListWhenDone; + bool m_bSortNeeded; + bool m_bVerticalScrollbarEnabled; + + HFont m_hHeaderFont; + HFont m_hRowFont; + //============================================================================= + // HPE_BEGIN: + //============================================================================= + // [tj] Whether or not this list should respond to the mouse + bool m_clickable; + // [tj] Whether or not this list should draw the headers for the sections + bool m_bDrawSectionHeaders; + //============================================================================= + // HPE_END + //============================================================================= + + CPanelAnimationVar( bool, m_bShowColumns, "show_columns", "false" ); +}; + +class SectionedListPanelHeader : public Label +{ + DECLARE_CLASS_SIMPLE( SectionedListPanelHeader, Label ); + +public: + SectionedListPanelHeader(SectionedListPanel *parent, const char *name, int sectionID); + SectionedListPanelHeader(SectionedListPanel *parent, const wchar_t *name, int sectionID); + + virtual void ApplySchemeSettings(IScheme *pScheme) OVERRIDE; + virtual void Paint() OVERRIDE; + virtual void PerformLayout() OVERRIDE; + + void SetColor(Color col); + void SetDividerColor(Color col ); + +protected: + int m_iSectionID; + Color m_SectionDividerColor; + SectionedListPanel *m_pListPanel; +}; + +} // namespace vgui + +#endif // SECTIONEDLISTPANEL_H diff --git a/sp/src/public/vgui_controls/Slider.h b/sp/src/public/vgui_controls/Slider.h new file mode 100644 index 00000000..ce75aef0 --- /dev/null +++ b/sp/src/public/vgui_controls/Slider.h @@ -0,0 +1,123 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef SLIDER_H +#define SLIDER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Labeled horizontal slider +//----------------------------------------------------------------------------- +class Slider : public Panel +{ + DECLARE_CLASS_SIMPLE( Slider, Panel ); +public: + Slider(Panel *parent, const char *panelName); + + // interface + virtual void SetValue(int value, bool bTriggerChangeMessage = true); + virtual int GetValue(); + virtual void SetRange(int min, int max); // set to max and min range of rows to display + virtual void GetRange(int &min, int &max); + virtual void GetNobPos(int &min, int &max); // get current Slider position + virtual void SetButtonOffset(int buttonOffset); + virtual void OnCursorMoved(int x, int y); + virtual void OnMousePressed(MouseCode code); + virtual void OnMouseDoublePressed(MouseCode code); + virtual void OnMouseReleased(MouseCode code); + virtual void SetTickCaptions(const wchar_t *left, const wchar_t *right); + virtual void SetTickCaptions(const char *left, const char *right); + virtual void SetNumTicks(int ticks); + virtual void SetThumbWidth( int width ); + virtual int EstimateValueAtPos( int localMouseX, int localMouseY ); + virtual void SetInverted( bool bInverted ); + + // If you click on the slider outside of the nob, the nob jumps + // to the click position, and if this setting is enabled, the nob + // is then draggable from the new position until the mouse is released + virtual void SetDragOnRepositionNob( bool state ); + virtual bool IsDragOnRepositionNob() const; + + // Get if the slider nob is being dragged by user, usually the application + // should refuse from forcefully setting slider value if it is being dragged + // by user since the next frame the nob will pop back to mouse position + virtual bool IsDragged( void ) const; + + // This allows the slider to behave like it's larger than what's actually being drawn + virtual void SetSliderThumbSubRange( bool bEnable, int nMin = 0, int nMax = 100 ); + +protected: + virtual void OnSizeChanged(int wide, int tall); + virtual void Paint(); + virtual void PaintBackground(); + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void GetSettings(KeyValues *outResourceData); + virtual void ApplySettings(KeyValues *inResourceData); + virtual const char *GetDescription(); +#ifdef _X360 + virtual void OnKeyCodePressed(KeyCode code); +#endif + virtual void OnKeyCodeTyped(KeyCode code); + + virtual void DrawNob(); + virtual void DrawTicks(); + virtual void DrawTickLabels(); + + virtual void GetTrackRect( int &x, int &y, int &w, int &h ); + +protected: + virtual void RecomputeNobPosFromValue(); + virtual void RecomputeValueFromNobPos(); + + virtual void SendSliderMovedMessage(); + virtual void SendSliderDragStartMessage(); + virtual void SendSliderDragEndMessage(); + + void ClampRange(); + + bool _dragging; + int _nobPos[2]; + int _nobDragStartPos[2]; + int _dragStartPos[2]; + int _range[2]; + int _subrange[ 2 ]; + int _value; // the position of the Slider, in coordinates as specified by SetRange/SetRangeWindow + int _buttonOffset; + IBorder *_sliderBorder; + IBorder *_insetBorder; + float _nobSize; + + TextImage *_leftCaption; + TextImage *_rightCaption; + + Color m_TickColor; + Color m_TrackColor; + Color m_DisabledTextColor1; + Color m_DisabledTextColor2; +#ifdef _X360 + Color m_DepressedBgColor; +#endif + + int m_nNumTicks; + bool m_bIsDragOnRepositionNob : 1; + bool m_bUseSubRange : 1; + bool m_bInverted : 1; +}; + +} + +#endif // SLIDER_H diff --git a/sp/src/public/vgui_controls/Splitter.h b/sp/src/public/vgui_controls/Splitter.h new file mode 100644 index 00000000..f788ebcb --- /dev/null +++ b/sp/src/public/vgui_controls/Splitter.h @@ -0,0 +1,98 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef SPLITTER_H +#define SPLITTER_H + +#ifdef _WIN32 +#pragma once +#endif + +#include + +namespace vgui +{ + +enum SplitterMode_t +{ + SPLITTER_MODE_HORIZONTAL = 0, + SPLITTER_MODE_VERTICAL +}; + + +class SplitterHandle; +class SplitterChildPanel; + +//----------------------------------------------------------------------------- +// Purpose: Thin line used to divide sections, can be moved dragged! +//----------------------------------------------------------------------------- +class Splitter : public EditablePanel +{ + DECLARE_CLASS_SIMPLE( Splitter, EditablePanel ); + +public: + // nCount is the number of splitters to create. + // NOTE: The constructor here will create (nCount+1) EditablePanel children + // and name them child0...childN for .res file purposes. + Splitter( Panel *parent, const char *name, SplitterMode_t mode, int nCount ); + ~Splitter(); + + // Evenly respace all splitters + void EvenlyRespaceSplitters(); + + // respace splitters using given fractions (must sum to 1) + void RespaceSplitters( float *flFractions ); + + // Inherited from Panel + virtual void ApplySettings(KeyValues *inResourceData); + virtual void GetSettings( KeyValues *outResourceData ); + virtual void PerformLayout(); + virtual void OnSizeChanged(int newWide, int newTall); + virtual void ApplyUserConfigSettings(KeyValues *userConfig); + virtual void GetUserConfigSettings(KeyValues *userConfig); + virtual bool HasUserConfigSettings() { return true; } + + // Sets the splitter color + void SetSplitterColor( Color c ); + + // Enables borders on the splitters + void EnableBorders( bool bEnable ); + + // Locks the size of a particular child in pixels. + void LockChildSize( int nChildIndex, int nSize ); + void UnlockChildSize( int nChildIndex ); + +private: + void RecreateSplitters( int nCount ); + + struct SplitterInfo_t + { + SplitterChildPanel *m_pPanel; // This panel is to the left or above the handle + SplitterHandle *m_pHandle; + float m_flPos; + bool m_bLocked; + int m_nLockedSize; + }; + + int GetPosRange(); + int GetSplitterCount() const; + int GetSplitterPosition( int nIndex ); + void SetSplitterPosition( int nIndex, int nPos ); + int GetSubPanelCount() const; + int ComputeLockedSize( int nStartingIndex ); + + CUtlVector< SplitterInfo_t > m_Splitters; + SplitterMode_t m_Mode; + + friend class SplitterHandle; +}; + + +} // namespace vgui + + +#endif // SPLITTER_H diff --git a/sp/src/public/vgui_controls/TextEntry.h b/sp/src/public/vgui_controls/TextEntry.h new file mode 100644 index 00000000..7231acc4 --- /dev/null +++ b/sp/src/public/vgui_controls/TextEntry.h @@ -0,0 +1,390 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A Class to create a window that you can type and edit text in. +// Window can hold single line or multiline text. +// If it is single it can scroll horizontally in response to +// key input and mouse selection. +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TEXTENTRY_H +#define TEXTENTRY_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include +#include + +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Text-input handler +// Behaviour Specs: +// This class handles input from mouse and keyboard. +// TextEntry classes support several box styles, horizontal scrolling with no scrollbar +// vertical scrolling with or without a scrollbar, single line, multiline, +// editable and noneditable. +// +// Shared behaviour: +// URL's are a different text color and are clickable. Clicking them brings up a web browser. +// For vertical scroll bars, up and down arrows scroll one line at a time. +// Clicking and dragging the nob scrolls through text lines. +// Mouse wheel also moves the nob. +// User can select and highlight text in the window. +// Double clicking on a word selects it. +// +// Non editable: +// No blinking cursor in non editable windows. +// Right clicking mouse opens copy menu. Menu's top left corner is where mouse is. +// Ctrl-c will also copy the text. +// Editable: +// Blinking cursor is positioned where text will be inserted. +// Text keys type chars in the window. +// ctrl-c copy highlighted text +// ctrl-v paste highlighted text +// ctrl-x cut highlighted text +// ctrl-right arrow move cursor to the start of the next word +// ctrl-left arrow move cursor to the start of the prev word +// ctrl-enter delete the selected text (and inserts a newline if _catchEnterKey is true) +// insert delete selected text and pastes text from the clipboard +// delete delete the selected text +// ctrl-home move cursor to the start of the text +// ctrl-end move cursor to the end of the text. +// left arrow move cursor before prev char +// ctrl-shift left/right arrow selects text a word at a time +// right arrow move cursor before next char +// up arrow move cursor up one line. +// down arrow move cursor down one line. +// home move cursor to start of current line +// end move cursor to end of current line +// backspace delete prev char or selected text. +// Trying to move to the prev/next char/line/word when there is none moves the cursor to the +// start/end of the text. +// Horizontal scrolling: +// Trying to move to the prev/next char/line/word when there is none scrolls the text +// horizontally in the window so the new text displays at the correct side. +// When moving to prev chars scrolling is staggered. To next chars it is one char at a time. +// Cut/Copy/Paste Menu: +// Right clicking mouse brings up cut/copy/paste menu. +// If no text is highlighted the cut/copy options are dimmed. Cut is dimmed in non editable panels +// If there is no text in the clipboard or panel is not editable the paste option is dimmed. +// If the mouse is right clicked over selected text, the text stays selected. +// If the mouse is right clicked over unselected text, any selected text is deselected. +// +// +//----------------------------------------------------------------------------- +class TextEntry : public Panel +{ + DECLARE_CLASS_SIMPLE( TextEntry, Panel ); + +public: + TextEntry(Panel *parent, const char *panelName); + virtual ~TextEntry(); + + virtual void SetText(const wchar_t *wszText); + virtual void SetText(const char *text); + virtual void GetText(OUT_Z_BYTECAP(bufLenInBytes) char *buf, int bufLenInBytes); + virtual void GetText(OUT_Z_BYTECAP(bufLenInBytes) wchar_t *buf, int bufLenInBytes); + virtual int GetTextLength() const; + virtual bool IsTextFullySelected() const; + + // editing + virtual void GotoLeft(); // move cursor one char left + virtual void GotoRight(); // move cursor one char right + virtual void GotoUp(); // move cursor one line up + virtual void GotoDown(); // move cursor one line down + virtual void GotoWordRight(); // move cursor to Start of next word + virtual void GotoWordLeft(); // move cursor to Start of prev word + virtual void GotoFirstOfLine(); // go to Start of the current line + virtual void GotoEndOfLine(); // go to end of the current line + virtual void GotoTextStart(); // go to Start of text buffer + virtual void GotoTextEnd(); // go to end of text buffer + + virtual void InsertChar(wchar_t ch); + virtual void InsertString(const char *text); + virtual void InsertString(const wchar_t *wszText); + virtual void Backspace(); + virtual void Delete(); + virtual void SelectNone(); + virtual void OpenEditMenu(); + MESSAGE_FUNC( CutSelected, "DoCutSelected" ); + MESSAGE_FUNC( CopySelected, "DoCopySelected" ); + MESSAGE_FUNC( Paste, "DoPaste" ); + + MESSAGE_FUNC_INT( LanguageChanged, "DoLanguageChanged", handle ); + MESSAGE_FUNC_INT( ConversionModeChanged, "DoConversionModeChanged", handle ); + MESSAGE_FUNC_INT( SentenceModeChanged, "DoSentenceModeChanged", handle ); + + MESSAGE_FUNC_WCHARPTR( CompositionString, "DoCompositionString", string ); + + MESSAGE_FUNC( ShowIMECandidates, "DoShowIMECandidates" ); + MESSAGE_FUNC( HideIMECandidates, "DoHideIMECandidates" ); + MESSAGE_FUNC( UpdateIMECandidates, "DoUpdateIMECandidates" ); + + virtual void DeleteSelected(); + virtual void Undo(); + virtual void SaveUndoState(); + virtual void SetFont(HFont font); + virtual void SetTextHidden(bool bHideText); + virtual void SetEditable(bool state); + virtual bool IsEditable(); + virtual void SetEnabled(bool state); + // move the cursor to line 'line', given how many pixels are in a line + virtual void MoveCursor(int line, int pixelsAcross); + + // sets the color of the background when the control is disabled + virtual void SetDisabledBgColor(Color col); + + // set whether the box handles more than one line of entry + virtual void SetMultiline(bool state); + virtual bool IsMultiline(); + + // sets visibility of scrollbar + virtual void SetVerticalScrollbar(bool state); + + // sets whether or not the edit catches and stores ENTER key presses + virtual void SetCatchEnterKey(bool state); + + // sets whether or not to send "TextNewLine" msgs when ENTER key is pressed + virtual void SendNewLine(bool send); + + // sets limit of number of characters insertable into field; set to -1 to remove maximum + // only works with if rich-edit is NOT enabled + virtual void SetMaximumCharCount(int maxChars); + virtual int GetMaximumCharCount(); + virtual void SetAutoProgressOnHittingCharLimit(bool state); + + // sets whether to wrap text once maxChars is reached (on a line by line basis) + virtual void SetWrap(bool wrap); + + virtual void RecalculateLineBreaks(); + virtual void LayoutVerticalScrollBarSlider(); + + virtual bool RequestInfo(KeyValues *outputData); + + // sets the height of the window so all text is visible. + // used by tooltips + void SetToFullHeight(); + + // sets the width of the window so all text is visible. (will create one line) + // used by tooltips + void SetToFullWidth(); + + int GetNumLines(); + + /* INFO HANDLING + "GetText" + returns: + "text" - text contained in the text box + */ + + /* CUSTOM MESSAGE HANDLING + "SetText" + input: "text" - text is set to be this string + */ + + /* MESSAGE SENDING (to action signal targets) + "TextChanged" - sent when the text is edited by the user + + "TextNewLine" - sent when the end key is pressed in the text entry AND _sendNewLines is true + + "TextKillFocus" - sent when focus leaves textentry field + */ + + // Selects all the text in the text entry. + void SelectAllText(bool bResetCursorPos); + void SelectNoText(); + void SelectAllOnFirstFocus( bool status ); + void SetDrawWidth(int width); // width from right side of window we have to draw in + int GetDrawWidth(); + void SetHorizontalScrolling(bool status); // turn horizontal scrolling on or off. + + // sets whether non-asci characters (unicode chars > 127) are allowed in the control - defaults to OFF + void SetAllowNonAsciiCharacters(bool state); + + // sets whether or not number input only is allowed + void SetAllowNumericInputOnly(bool state); + + // By default, we draw the language shortname on the right hand side of the control + void SetDrawLanguageIDAtLeft( bool state ); + + virtual bool GetDropContextMenu( Menu *menu, CUtlVector< KeyValues * >& data ); + virtual bool IsDroppable( CUtlVector< KeyValues * >& data ); + virtual void OnPanelDropped( CUtlVector< KeyValues * >& data ); + virtual Panel *GetDragPanel(); + virtual void OnCreateDragData( KeyValues *msg ); + + void SelectAllOnFocusAlways( bool status ); + void SetSelectionTextColor( const Color& clr ); + void SetSelectionBgColor( const Color& clr ); + void SetSelectionUnfocusedBgColor( const Color& clr ); + + void SetUseFallbackFont( bool bState, HFont hFallback ); + +protected: + virtual void ResetCursorBlink(); + virtual void PerformLayout(); // layout the text in the window + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual void PaintBackground(); + virtual int DrawChar(wchar_t ch, HFont font, int index, int x, int y); + virtual bool DrawCursor(int x, int y); + + virtual void SetCharAt(wchar_t ch, int index); // set the value of a char in the text buffer + virtual void ApplySettings( KeyValues *inResourceData ); + virtual void GetSettings( KeyValues *outResourceData ); + virtual const char *GetDescription( void ); + virtual void FireActionSignal(); + virtual bool GetSelectedRange(int& cx0,int& cx1); + virtual void CursorToPixelSpace(int cursorPos, int &cx, int &cy); + virtual int PixelToCursorSpace(int cx, int cy); + virtual void AddAnotherLine(int &cx, int &cy); + virtual int GetYStart(); // works out ypixel position drawing started at + + virtual bool SelectCheck( bool fromMouse = false ); // check if we are in text selection mode + MESSAGE_FUNC_WCHARPTR( OnSetText, "SetText", text ); + MESSAGE_FUNC( OnSliderMoved, "ScrollBarSliderMoved" ); // respond to scroll bar events + virtual void OnKillFocus(); + virtual void OnMouseWheeled(int delta); // respond to mouse wheel events + virtual void OnKeyCodePressed(KeyCode code); //respond to keyboard events + virtual void OnKeyCodeTyped(KeyCode code); //respond to keyboard events + virtual void OnKeyTyped(wchar_t unichar); //respond to keyboard events + + virtual void OnCursorMoved(int x, int y); // respond to moving the cursor with mouse button down + virtual void OnMousePressed(MouseCode code); // respond to mouse down events + virtual void OnMouseDoublePressed( MouseCode code ); + virtual void OnMouseTriplePressed( MouseCode code ); + virtual void OnMouseReleased( MouseCode code ); // respond to mouse up events + + virtual void OnKeyFocusTicked(); // do while window has keyboard focus + virtual void OnMouseFocusTicked(); // do while window has mouse focus + virtual void OnCursorEntered(); // handle cursor entering window + virtual void OnCursorExited(); // handle cursor exiting window + + virtual void OnMouseCaptureLost(); + virtual void OnSizeChanged(int newWide, int newTall); + + // Returns the character index the drawing should Start at + virtual int GetStartDrawIndex(int &lineBreakIndexIndex); + +public: + // helper accessors for common gets + virtual float GetValueAsFloat(); + virtual int GetValueAsInt(); + +protected: + void ScrollRight(); // scroll to right until cursor is visible + void ScrollLeft(); // scroll to left + bool IsCursorOffRightSideOfWindow(int cursorPos); // check if cursor is off right side of window + bool IsCursorOffLeftSideOfWindow(int cursorPos); // check if cursor is off left side of window + void ScrollLeftForResize(); + + void OnSetFocus(); + // Change keyboard layout type + void OnChangeIME( bool forward ); + + bool NeedsEllipses( HFont font, int *pIndex ); + +private: + MESSAGE_FUNC_INT( OnSetState, "SetState", state ); + // get index in buffer of the Start of the current line we are on + int GetCurrentLineStart(); + // get index in buffer of the end of the current line we are on + int GetCurrentLineEnd(); + bool IsLineBreak(int index); + int GetCursorLine(); + void MoveScrollBar(int delta); + void CalcBreakIndex(); // calculate _recalculateLineBreaksIndex + void CreateEditMenu(); // create copy/cut/paste menu + +public: + Menu *GetEditMenu(); // retrieve copy/cut/paste menu + +private: + void FlipToLastIME(); + +public: + virtual void GetTextRange( wchar_t *buf, int from, int numchars ); // copy a portion of the text to the buffer and add zero-termination + virtual void GetTextRange( char *buf, int from, int numchars ); // copy a portion of the text to the buffer and add zero-termination + +private: + + CUtlVector m_TextStream; // the text in the text window is stored in this buffer + CUtlVector m_UndoTextStream; // a copy of the text buffer to revert changes + CUtlVector m_LineBreaks; // an array that holds the index in the buffer to wrap lines at + + int _cursorPos; // the position in the text buffer of the blinking cursor + bool _cursorIsAtEnd; + bool _putCursorAtEnd; + int _undoCursorPos; // a copy of the cursor position to revert changes + bool _cursorBlink; // whether cursor is blinking or not + bool _hideText; // whether text is visible on screen or not + bool _editable; // whether text is editable or not + bool _mouseSelection; // whether we are highlighting text or not (selecting text) + bool _mouseDragSelection; // tells weather mouse is outside window and button is down so we select text + int _mouseSelectCursorStart; // where mouse button was pressed down in text window + long _cursorNextBlinkTime; // time of next cursor blink + int _cursorBlinkRate; // speed of cursor blinking + int _select[2]; // select[1] is the offset in the text to where the cursor is currently + // select[0] is the offset to where the cursor was dragged to. or -1 if no drag. + int _pixelsIndent; + int _charCount; + int _maxCharCount; // max number of chars that can be in the text buffer + HFont _font; // font of chars in the text buffer + HFont _smallfont; + bool _dataChanged; // whether anything in the window has changed. + bool _multiline; // whether buffer is multiline or just a single line + bool _verticalScrollbar; // whether window has a vertical scroll bar + ScrollBar *_vertScrollBar; // the scroll bar used in the window + Color _cursorColor; // color of the text cursor + Color _disabledFgColor; + Color _disabledBgColor; + Color _selectionColor; + Color _selectionTextColor; // color of the highlighted text + Color _defaultSelectionBG2Color; + int _currentStartLine; // use for checking vertical text scrolling (multiline) + int _currentStartIndex; // use for horizontal text scrolling (!multiline) + bool _horizScrollingAllowed; // use to disable horizontal text scrolling period. + Color _focusEdgeColor; + bool _catchEnterKey; + bool _wrap; + bool _sendNewLines; + int _drawWidth; + + // selection data + Menu *m_pEditMenu; ///cut/copy/paste popup + + int _recalculateBreaksIndex; // tells next linebreakindex index to Start recalculating line breaks + bool _selectAllOnFirstFocus : 1; // highlights all text in window when focus is gained. + bool _selectAllOnFocusAlways : 1; + bool _firstFocusStatus; // keep track if we've had that first focus or not + bool m_bAllowNumericInputOnly; + bool m_bAllowNonAsciiCharacters; + bool m_bAutoProgressOnHittingCharLimit; + + enum + { + MAX_COMPOSITION_STRING = 256, + }; + + wchar_t m_szComposition[ MAX_COMPOSITION_STRING ]; + Menu *m_pIMECandidates; + int m_hPreviousIME; + bool m_bDrawLanguageIDAtLeft; + int m_nLangInset; + + bool m_bUseFallbackFont : 1; + HFont m_hFallbackFont; +}; + +} + +#endif // TEXTENTRY_H diff --git a/sp/src/public/vgui_controls/TextImage.h b/sp/src/public/vgui_controls/TextImage.h new file mode 100644 index 00000000..499785ff --- /dev/null +++ b/sp/src/public/vgui_controls/TextImage.h @@ -0,0 +1,143 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TEXTIMAGE_H +#define TEXTIMAGE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include + +#include +#include + +class KeyValues; + +namespace vgui +{ + +struct label_colorchange_t +{ + Color color; + int textStreamIndex; +}; + +// Used to sort the color changes into sequential order. +class CColorChangeListLess +{ +public: + bool Less( const label_colorchange_t &src1, const label_colorchange_t &src2, void *pCtx ) + { + if ( src1.textStreamIndex < src2.textStreamIndex ) + return true; + + return false; + } +}; + +//----------------------------------------------------------------------------- +// Purpose: Image that handles drawing of a text string +//----------------------------------------------------------------------------- +class TextImage : public Image +{ +public: + TextImage(const char *text); + TextImage(const wchar_t *wszText); + ~TextImage(); + +public: + // takes the string and looks it up in the localization file to convert it to unicode + virtual void SetText(const char *text); + // sets unicode text directly + virtual void SetText(const wchar_t *text, bool bClearUnlocalizedSymbol = false); + // get the full text in the image + virtual void GetText(char *buffer, int bufferSize); + virtual void GetText(wchar_t *buffer, int bufferLength); + // get the text in it's unlocalized form + virtual void GetUnlocalizedText(char *buffer, int bufferSize); + virtual StringIndex_t GetUnlocalizedTextSymbol(); + + // set the font of the text + virtual void SetFont(vgui::HFont font); + // get the font of the text + virtual vgui::HFont GetFont(); + + // set the width of the text to be drawn + // use this function if the textImage is in another window to cause + // the text to be truncated to the width of the window (elipsis added) + void SetDrawWidth(int width); + // get the width of the text to be drawn + void GetDrawWidth(int &width); + + void ResizeImageToContent(); + void ResizeImageToContentMaxWidth( int nMaxWidth ); + + // set the size of the image + virtual void SetSize(int wide,int tall); + + // get the full size of a text string + virtual void GetContentSize(int &wide, int &tall); + + // draws the text + virtual void Paint(); + + void SetWrap( bool bWrap ); + void RecalculateNewLinePositions(); + + void SetUseFallbackFont( bool bState, HFont hFallback ); + + void SetAllCaps( bool bAllCaps ); + + void SetCenterWrap( bool bWrap ); + void RecalculateCenterWrapIndents(); + + const wchar_t *GetUText( void ) { return _utext; } + + void AddColorChange( Color col, int iTextStreamIndex ); + void SetColorChangeStream( CUtlSortVector *pUtlVecStream ); + void ClearColorChangeStream( void ) { m_ColorChangeStream.Purge(); } + +protected: + // truncate the _text string to fit into the draw width + void SizeText(wchar_t *tempText, int stringLength); + // gets the size of a specified piece of text + virtual void GetTextSize(int &wide, int &tall); + +private: + void RecalculateEllipsesPosition(); + + wchar_t *_utext; // unicode version of the text + short _textBufferLen; // size of the text buffer + short _textLen; // length of the text string + vgui::HFont _font; // font of the text string + vgui::HFont _fallbackFont; + int _drawWidth; // this is the width of the window we are drawing into. + // if there is not enough room truncate the txt and add an elipsis + + StringIndex_t _unlocalizedTextSymbol; // store off the unlocalized text index for build mode + wchar_t *m_pwszEllipsesPosition; + + bool m_bRecalculateTruncation : 1; + bool m_bWrap : 1; + bool m_bUseFallbackFont : 1; + bool m_bRenderUsingFallbackFont : 1; + bool m_bAllCaps : 1; + CUtlVector m_LineBreaks; // an array that holds the index in the buffer to wrap lines at + + bool m_bWrapCenter; // Separate from m_bWrap to ensure it doesn't break legacy code. + CUtlVector m_LineXIndent; // For centered word wrap. The X indent for each line. + + CUtlSortVector m_ColorChangeStream; +}; + +} // namespace vgui + +#endif // TEXTIMAGE_H diff --git a/sp/src/public/vgui_controls/ToggleButton.h b/sp/src/public/vgui_controls/ToggleButton.h new file mode 100644 index 00000000..355e51a7 --- /dev/null +++ b/sp/src/public/vgui_controls/ToggleButton.h @@ -0,0 +1,54 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef TOGGLEBUTTON_H +#define TOGGLEBUTTON_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Type of button that when pressed stays selected & depressed until pressed again +//----------------------------------------------------------------------------- +class ToggleButton : public Button +{ + DECLARE_CLASS_SIMPLE( ToggleButton, Button ); + +public: + ToggleButton(Panel *parent, const char *panelName, const char *text); + + virtual void DoClick(); + + /* messages sent (get via AddActionSignalTarget()): + "ButtonToggled" + int "state" + */ + +protected: + // overrides + virtual void OnMouseDoublePressed(MouseCode code); + + virtual Color GetButtonFgColor(); + virtual void ApplySchemeSettings(IScheme *pScheme); + + virtual bool CanBeDefaultButton(void); + virtual void OnKeyCodePressed(KeyCode code); + +private: + Color _selectedColor; +}; + +} // namespace vgui + +#endif // TOGGLEBUTTON_H diff --git a/sp/src/public/vgui_controls/ToolWindow.h b/sp/src/public/vgui_controls/ToolWindow.h new file mode 100644 index 00000000..870f5339 --- /dev/null +++ b/sp/src/public/vgui_controls/ToolWindow.h @@ -0,0 +1,78 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef TOOLWINDOW_H +#define TOOLWINDOW_H +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class ToolWindow; + +// So that an app can have a "custom" tool window class created during window drag/drop operations on the property sheet +class IToolWindowFactory +{ +public: + virtual ToolWindow *InstanceToolWindow( Panel *parent, bool contextLabel, Panel *firstPage, char const *title, bool contextMenu ) = 0; +}; + +//----------------------------------------------------------------------------- +// Purpose: Simple frame that holds a property sheet +//----------------------------------------------------------------------------- +class ToolWindow : public Frame +{ + DECLARE_CLASS_SIMPLE( ToolWindow, Frame ); + +public: + ToolWindow(Panel *parent, bool contextLabel, IToolWindowFactory *factory = 0, Panel *page = NULL, char const *title = NULL, bool contextMenu = false, bool inGlobalList = true ); + + ~ToolWindow(); + + virtual bool IsDraggableTabContainer() const; + + // returns a pointer to the PropertySheet this dialog encapsulates + PropertySheet *GetPropertySheet(); + + // wrapper for PropertySheet interface + void AddPage(Panel *page, const char *title, bool contextMenu ); + void RemovePage( Panel *page ); + Panel *GetActivePage(); + void SetActivePage( Panel *page ); + + void SetToolWindowFactory( IToolWindowFactory *factory ); + IToolWindowFactory *GetToolWindowFactory(); + + static int GetToolWindowCount(); + static ToolWindow *GetToolWindow( int index ); + + static CUtlVector< ToolWindow * > s_ToolWindows; + + virtual void Grow( int edge = 0, int from_x = -1, int from_y = -1 ); + virtual void GrowFromClick(); + +protected: + // vgui overrides + virtual void PerformLayout(); + virtual void ActivateBuildMode(); + virtual void RequestFocus(int direction = 0); + virtual void OnMousePressed(MouseCode code); + virtual void OnMouseDoublePressed(MouseCode code); + +private: + PropertySheet *m_pPropertySheet; + IToolWindowFactory *m_pFactory; +}; + +}; // vgui + + +#endif // TOOLWINDOW_H diff --git a/sp/src/public/vgui_controls/Tooltip.h b/sp/src/public/vgui_controls/Tooltip.h new file mode 100644 index 00000000..2c7ec984 --- /dev/null +++ b/sp/src/public/vgui_controls/Tooltip.h @@ -0,0 +1,76 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Creates a Message box with a question in it and yes/no buttons +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TOOLTIP_H +#define TOOLTIP_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Tooltip for a panel - shows text when cursor hovers over a panel +//----------------------------------------------------------------------------- +class BaseTooltip +{ +public: + BaseTooltip(Panel *parent, const char *text = NULL); + + virtual void SetText(const char *text); + virtual const char *GetText(); + + virtual void ShowTooltip(Panel *currentPanel); + virtual void HideTooltip(); + + bool ShouldLayout( void ); + virtual void PerformLayout() { return; } + virtual void PositionWindow( Panel *pTipPanel ); + + void ResetDelay(); + void SetTooltipFormatToSingleLine(); + void SetTooltipFormatToMultiLine(); + void SetTooltipDelay(int tooltipDelayMilliseconds); + int GetTooltipDelay(); + void SetEnabled( bool bState ); + +private: + Panel *m_pParent; + virtual void ApplySchemeSettings(IScheme *pScheme) {}; +protected: + CUtlVector m_Text; + int _delay; // delay that counts down + int _tooltipDelay; // delay before tooltip comes up. + bool _makeVisible : 1; + bool _displayOnOneLine : 1; + bool _isDirty : 1; + bool _enabled : 1; +}; + +class TextTooltip : public BaseTooltip +{ +public: + TextTooltip(Panel *parent, const char *text = NULL); + ~TextTooltip(); + + virtual void SetText(const char *text); + virtual void ShowTooltip(Panel *currentPanel); + virtual void HideTooltip(); + virtual void SizeTextWindow(); + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme *pScheme); +}; + +}; + +#endif // TOOLTIP_H diff --git a/sp/src/public/vgui_controls/TreeView.h b/sp/src/public/vgui_controls/TreeView.h new file mode 100644 index 00000000..521d1691 --- /dev/null +++ b/sp/src/public/vgui_controls/TreeView.h @@ -0,0 +1,203 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TREEVIEW_H +#define TREEVIEW_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include +#include +#include + +class KeyValues; + +namespace vgui +{ + +class ExpandButton; +class TreeNode; +class TreeViewSubPanel; + +// sorting function, should return true if node1 should be displayed before node2 +typedef bool (*TreeViewSortFunc_t)(KeyValues *node1, KeyValues *node2); + +class TreeView : public Panel +{ + DECLARE_CLASS_SIMPLE( TreeView, Panel ); + +public: + TreeView(Panel *parent, const char *panelName); + ~TreeView(); + + void SetSortFunc(TreeViewSortFunc_t pSortFunc); + + virtual int AddItem(KeyValues *data, int parentItemIndex); + + virtual int GetRootItemIndex(); + virtual int GetNumChildren( int itemIndex ); + virtual int GetChild( int iParentItemIndex, int iChild ); // between 0 and GetNumChildren( iParentItemIndex ). + + virtual int GetItemCount(void); + virtual KeyValues *GetItemData(int itemIndex); + virtual void RemoveItem(int itemIndex, bool bPromoteChildren, bool bRecursivelyRemove = false ); + virtual void RemoveAll(); + virtual bool ModifyItem(int itemIndex, KeyValues *data); + virtual int GetItemParent(int itemIndex); + + virtual void SetFont(HFont font); + + virtual void SetImageList(ImageList *imageList, bool deleteImageListWhenDone); + + void SetAllowMultipleSelections( bool state ); + bool IsMultipleSelectionAllowed() const; + + virtual void ClearSelection(); + virtual void AddSelectedItem( int itemIndex, bool clearCurrentSelection, bool requestFocus = true, bool bMakeItemVisible = true ); + virtual void RemoveSelectedItem( int itemIndex ); + virtual void SelectAll(); + + virtual bool IsItemSelected( int itemIndex ); + virtual void RangeSelectItems( int clickedItem ); + virtual void FindNodesInRange( int startItem, int endItem, CUtlVector< int >& itemIndices ); + + // returns the id of the currently selected item, -1 if nothing is selected + virtual int GetSelectedItemCount() const; + virtual int GetFirstSelectedItem() const; + virtual void GetSelectedItems( CUtlVector< int >& list ); + virtual void GetSelectedItemData( CUtlVector< KeyValues * >& list ); + + // set colors for individual elments + virtual void SetItemFgColor(int itemIndex, const Color& color); + virtual void SetItemBgColor(int itemIndex, const Color& color); + virtual void SetItemSelectionTextColor( int itemIndex, const Color& clr ); + virtual void SetItemSelectionBgColor( int itemIndex, const Color& clr ); + virtual void SetItemSelectionUnfocusedBgColor( int itemIndex, const Color& clr ); + + // returns true if the itemID is valid for use + virtual bool IsItemIDValid(int itemIndex); + + // item iterators + // iterate from [0..GetHighestItemID()], + // and check each with IsItemIDValid() before using + virtual int GetHighestItemID(); + + virtual void ExpandItem(int itemIndex, bool bExpand); + virtual bool IsItemExpanded( int itemIndex ); + + virtual void MakeItemVisible(int itemIndex); + + // This tells which of the visible items is the top one. + virtual void GetVBarInfo( int &top, int &nItemsVisible, bool& hbarVisible ); + + virtual HFont GetFont(); + + virtual void GenerateDragDataForItem( int itemIndex, KeyValues *msg ); + virtual void SetDragEnabledItems( bool state ); + + virtual void OnLabelChanged( int itemIndex, char const *oldString, char const *newString ); + virtual bool IsLabelEditingAllowed() const; + virtual bool IsLabelBeingEdited() const; + virtual void SetAllowLabelEditing( bool state ); + + /* message sent + + "TreeViewItemSelected" int "itemIndex" + called when the selected item changes + "TreeViewItemDeselected" int "itemIndex" + called when item is deselected + */ + int GetRowHeight(); + int GetVisibleMaxWidth(); + virtual void OnMousePressed(MouseCode code); + + // By default, the tree view expands nodes on left-click. This enables/disables that feature + void EnableExpandTreeOnLeftClick( bool bEnable ); + + virtual void SetLabelEditingAllowed( int itemIndex, bool state ); + virtual void StartEditingLabel( int itemIndex ); + + virtual bool IsItemDroppable( int itemIndex, CUtlVector< KeyValues * >& msglist ); + virtual void OnItemDropped( int itemIndex, CUtlVector< KeyValues * >& msglist ); + virtual bool GetItemDropContextMenu( int itemIndex, Menu *menu, CUtlVector< KeyValues * >& msglist ); + virtual HCursor GetItemDropCursor( int itemIndex, CUtlVector< KeyValues * >& msglist ); + + virtual int GetPrevChildItemIndex( int itemIndex ); + virtual int GetNextChildItemIndex( int itemIndex ); + + virtual void PerformLayout(); + + // Makes the scrollbar parented to some other panel... + ScrollBar *SetScrollBarExternal( bool vertical, Panel *newParent ); + void GetScrollBarSize( bool vertical, int& w, int& h ); + + void SetMultipleItemDragEnabled( bool state ); // if this is set, then clicking on one row and dragging will select a run or items, etc. + bool IsMultipleItemDragEnabled() const; + + int FindItemUnderMouse( int mx, int my ); + +protected: + // functions to override + // called when a node, marked as "Expand", needs to generate it's child nodes when expanded + virtual void GenerateChildrenOfNode(int itemIndex) {} + + // override to open a custom context menu on a node being selected and right-clicked + virtual void GenerateContextMenu( int itemIndex, int x, int y ) {} + + // overrides + virtual void OnMouseWheeled(int delta); + virtual void OnSizeChanged(int wide, int tall); + virtual void ApplySchemeSettings(IScheme *pScheme); + MESSAGE_FUNC_INT( OnSliderMoved, "ScrollBarSliderMoved", position ); + virtual void SetBgColor( Color color ); + +private: + friend class TreeNode; + friend class TreeNodeText; + + TreeNode* GetItem( int itemIndex ); + virtual void RemoveChildrenOfNode( int itemIndex ); + void SetLabelBeingEdited( bool state ); + + // Clean up the image list + void CleanUpImageList( ); + + // to be accessed by TreeNodes + IImage* GetImage(int index); + + // bools + bool m_bAllowLabelEditing : 1; + bool m_bDragEnabledItems : 1; + bool m_bDeleteImageListWhenDone : 1; + bool m_bLeftClickExpandsTree : 1; + bool m_bLabelBeingEdited : 1; + bool m_bMultipleItemDragging : 1; + bool m_bAllowMultipleSelections : 1; + + // cross reference - no hierarchy ordering in this list + CUtlLinkedList m_NodeList; + ScrollBar *m_pHorzScrollBar, *m_pVertScrollBar; + int m_nRowHeight; + + ImageList *m_pImageList; + TreeNode *m_pRootNode; + TreeViewSortFunc_t m_pSortFunc; + HFont m_Font; + + CUtlVector< TreeNode * > m_SelectedItems; + TreeViewSubPanel *m_pSubPanel; + + int m_nMostRecentlySelectedItem; + bool m_bScrollbarExternal[ 2 ]; // 0 = vert, 1 = horz +}; + +} + +#endif // TREEVIEW_H diff --git a/sp/src/public/vgui_controls/TreeViewListControl.h b/sp/src/public/vgui_controls/TreeViewListControl.h new file mode 100644 index 00000000..8a034709 --- /dev/null +++ b/sp/src/public/vgui_controls/TreeViewListControl.h @@ -0,0 +1,130 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef TREEVIEWLISTCONTROL_H +#define TREEVIEWLISTCONTROL_H +#ifdef _WIN32 +#pragma once +#endif + + +#include +#include +#include +#include +#include "utlsymbol.h" + + +namespace vgui +{ + +// --------------------------------------------------------------------------------- // +// CTreeViewListControl +// +// This control has N columns, with a tree view in the leftmost column. +// --------------------------------------------------------------------------------- // + +class CTreeViewListControl : public vgui::Panel +{ + DECLARE_CLASS_SIMPLE( CTreeViewListControl, Panel ); + +public: + + CTreeViewListControl( vgui::Panel *pParent, const char *pName ); + + // Set the tree view to be displayed on the left. If this isn't set, then nothing displays in here. + virtual void SetTreeView( vgui::TreeView *pTree ); + + // Set the height of the title bar. + virtual void SetTitleBarInfo( vgui::HFont hFont, int titleBarHeight ); + + // Set the color to draw the border lines in. + virtual void SetBorderColor( Color clr ); + + // Initialize the column headers.. This info includes the tree view on the left, so this + virtual void SetNumColumns( int nColumns ); + virtual int GetNumColumns() const; + // ciFlags is a combination of CI_ flags. + virtual void SetColumnInfo( int iColumn, const char *pTitle, int width, int ciFlags=0 ); + + // Use this to render your stuff. Iterate over the rows in the tree view and + virtual int GetNumRows(); + virtual int GetTreeItemAtRow( int iRow ); // You can use m_pTree->GetItemData to get at the data for the row. + + // Use this to find out the client area to render in for each grid element. + // The returned box is inclusive. + // The rule is that the the top and left pixels in each grid element are reserved for lines. + virtual void GetGridElementBounds( int iColumn, int iRow, int &left, int &top, int &right, int &bottom ); + + virtual vgui::TreeView *GetTree(); + + virtual int GetTitleBarHeight(); + + virtual int GetScrollBarSize(); + +// Overrides. +public: + + // This is where it recalculates the row infos. + virtual void PerformLayout(); + + // Usually, you'll want to override paint. After calling the base, use GetNumRows() to + // iterate over the data in the tree control and fill in the other columns. + virtual void Paint(); + virtual void PostChildPaint(); + + // You can override this to change the way the title bars are drawn. + virtual void DrawTitleBars(); + + +public: + + enum + { + // By default, column header text is centered. + CI_HEADER_LEFTALIGN =0x0001 + }; + + +protected: + + void RecalculateRows(); + void RecalculateRows_R( int index ); + void RecalculateColumns(); + +private: + + vgui::TreeView *m_pTree; + + class CColumnInfo + { + public: + CColumnInfo() + { + m_Width = m_Left = m_Right = m_ciFlags = 0; + } + + CUtlSymbol m_Title; + int m_Width; + int m_Left; + int m_Right; + int m_ciFlags; // Combination of CI_ flags. + }; + CUtlVector m_Columns; + + vgui::HFont m_TitleBarFont; + int m_TitleBarHeight; + + // These are indices into the tree view. + CUtlVector m_Rows; + + Color m_BorderColor; +}; + +} // namespace + + +#endif // TREEVIEWLISTCONTROL_H diff --git a/sp/src/public/vgui_controls/URLLabel.h b/sp/src/public/vgui_controls/URLLabel.h new file mode 100644 index 00000000..66112513 --- /dev/null +++ b/sp/src/public/vgui_controls/URLLabel.h @@ -0,0 +1,49 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef URLLABEL_H +#define URLLABEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include +#include + +namespace vgui +{ + +class URLLabel : public Label +{ + DECLARE_CLASS_SIMPLE( URLLabel, Label ); + +public: + URLLabel(Panel *parent, const char *panelName, const char *text, const char *pszURL); + URLLabel(Panel *parent, const char *panelName, const wchar_t *wszText, const char *pszURL); + ~URLLabel(); + + void SetURL(const char *pszURL); + +protected: + virtual void OnMousePressed(MouseCode code); + virtual void ApplySettings( KeyValues *inResourceData ); + virtual void GetSettings( KeyValues *outResourceData ); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual const char *GetDescription( void ); + + const char *GetURL( void ) { return m_pszURL; } + +private: + char *m_pszURL; + int m_iURLSize; + bool m_bUnderline; +}; + +} + +#endif // URLLABEL_H diff --git a/sp/src/public/vgui_controls/WizardPanel.h b/sp/src/public/vgui_controls/WizardPanel.h new file mode 100644 index 00000000..c6e014e8 --- /dev/null +++ b/sp/src/public/vgui_controls/WizardPanel.h @@ -0,0 +1,127 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef WIZARDPANEL_H +#define WIZARDPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include + +namespace vgui +{ + +class WizardSubPanel; + +//----------------------------------------------------------------------------- +// Purpose: Type of dialog that supports moving back and forth through a series +// of sub-dialogs, WizardSubPanels +//----------------------------------------------------------------------------- +class WizardPanel : public Frame +{ + DECLARE_CLASS_SIMPLE( WizardPanel, Frame ); + +public: + WizardPanel(Panel *parent, const char *panelName); + ~WizardPanel(); + + // Start the wizard, starting with the startPanel + virtual void Run(WizardSubPanel *startPanel); + + // Called when the buttons are pressed + // WizardSubPanels can also call these functions to simulate a button being pressed + MESSAGE_FUNC( OnNextButton, "NextButton" ); + MESSAGE_FUNC( OnPrevButton, "PrevButton" ); + MESSAGE_FUNC( OnFinishButton, "FinishButton" ); + MESSAGE_FUNC( OnCancelButton, "CancelButton" ); + + // sets whether or not a button is enabled + // this state is managed, and will be reset whenever going to a new page + virtual void SetNextButtonEnabled(bool state); + virtual void SetPrevButtonEnabled(bool state); + virtual void SetFinishButtonEnabled(bool state); + virtual void SetCancelButtonEnabled(bool state); + + // sets whether or not a button is visible + // this state is unmanaged, the user needs to ensure that the buttons state + // is correct when going both back and prev through the wizard + virtual void SetNextButtonVisible(bool state); + virtual void SetPrevButtonVisible(bool state); + virtual void SetFinishButtonVisible(bool state); + virtual void SetCancelButtonVisible(bool state); + + // sets the text for a button + // setting the text to be NULL resets the text to it's default state + // this state is unmanaged, the user needs to ensure that the buttons state + // is correct when going both back and prev through the wizard + virtual void SetNextButtonText(const char *text); + virtual void SetPrevButtonText(const char *text); + virtual void SetFinishButtonText(const char *text); + virtual void SetCancelButtonText(const char *text); + + // general wizard state for all the subpanels to access + virtual KeyValues *GetWizardData(); + + // recalculates where the key focus should be in the wizard + virtual void ResetKeyFocus(); + virtual void ResetDefaultButton(); + + // resets the sub panel history for the control + virtual void ResetHistory(); + + // returns a page by name + virtual WizardSubPanel *GetSubPanelByName(const char *pageName); + + virtual void ShowButtons(bool state); + virtual void GetClientArea(int &x, int &y, int &wide, int &tall); + +protected: + MESSAGE_FUNC_PTR( InternalActivateNextSubPanel, "ActivateNextSubPanel", panel ) + { + ActivateNextSubPanel( (WizardSubPanel *)panel ); + } + + virtual void ActivateNextSubPanel(WizardSubPanel *subPanel); + virtual void ActivatePrevSubPanel(); + virtual void CreateButtons(); + virtual void RecalculateTabOrdering(); + virtual vgui::WizardSubPanel *GetCurrentSubPanel() { return _currentSubPanel; } + + // overrides + virtual void PerformLayout(); + virtual void ApplySchemeSettings(IScheme *pScheme); + + // reroute build messages to the currently active sub panel + virtual void ActivateBuildMode(); + + // close maps to the cancel button + virtual void OnClose(); + virtual void OnCommand(const char *command); + virtual void OnCloseFrameButtonPressed(); + +private: + WizardSubPanel *FindNextValidSubPanel(WizardSubPanel *currentPanel); + + Button *_prevButton; + Button *_nextButton; + Button *_cancelButton; + Button *_finishButton; + + WizardSubPanel *_currentSubPanel; + KeyValues *_currentData; + + Dar _subPanelStack; // contains a list of all the subpanels (not including the current one) + + bool _showButtons; +}; + +} // namespace vgui + + +#endif // WIZARDPANEL_H diff --git a/sp/src/public/vgui_controls/WizardSubPanel.h b/sp/src/public/vgui_controls/WizardSubPanel.h new file mode 100644 index 00000000..a7d71fb4 --- /dev/null +++ b/sp/src/public/vgui_controls/WizardSubPanel.h @@ -0,0 +1,91 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef WIZARDSUBPANEL_H +#define WIZARDSUBPANEL_H + +#ifdef _WIN32 +#pragma once +#endif + +#include + +namespace vgui +{ + +//----------------------------------------------------------------------------- +// Purpose: Base panel for use in Wizards and in property sheets +//----------------------------------------------------------------------------- +class WizardSubPanel : public EditablePanel +{ + DECLARE_CLASS_SIMPLE( WizardSubPanel, EditablePanel ); + +public: + // constructor + WizardSubPanel(Panel *parent, const char *panelName); + ~WizardSubPanel(); + + // called when the subpanel is displayed + // All controls & data should be reinitialized at this time + virtual void OnDisplayAsNext() {} + + // called anytime the panel is first displayed, whether the user is moving forward or back + // called immediately after OnDisplayAsNext/OnDisplayAsPrev + virtual void OnDisplay() {} + + // called when displayed as previous + virtual void OnDisplayAsPrev() {} + + // called when one of the wizard buttons are pressed + // returns true if the wizard should advance, false otherwise + virtual bool OnNextButton() { return true; } + virtual bool OnPrevButton() { return true; } + virtual bool OnFinishButton() { return true; } + virtual bool OnCancelButton() { return true; } + + // returns true if this panel should be displayed, or if we should just skip over it + virtual bool ShouldDisplayPanel() { return true; } + + // return true if this subpanel doesn't need the next/prev/finish/cancel buttons or will do it itself + virtual bool isNonWizardPanel() { return false; } + + // returns a pointer to the next subpanel that should be displayed + virtual WizardSubPanel *GetNextSubPanel() = 0; + + // returns a pointer to the panel to return to + // it must be a panel that is already in the wizards panel history + // returning NULL tells it to use the immediate previous panel in the history + virtual WizardSubPanel *GetPrevSubPanel() { return NULL; } + + virtual WizardPanel *GetWizardPanel() { return _wizardPanel; } + virtual void SetWizardPanel(WizardPanel *wizardPanel) { _wizardPanel = wizardPanel; } + + // returns a pointer to the wizard's doc + virtual KeyValues *GetWizardData(); + + // returns a pointer + virtual WizardSubPanel *GetSiblingSubPanelByName(const char *pageName); + + // gets the size this subpanel would like the wizard to be + // returns true if it has a desired size + virtual bool GetDesiredSize(int &wide, int &tall); + +protected: + virtual void ApplySettings(KeyValues *inResourceData); + virtual void GetSettings( KeyValues *outResourceData ); + virtual void ApplySchemeSettings(IScheme *pScheme); + virtual const char *GetDescription(); + +private: + WizardPanel *_wizardPanel; + int m_iDesiredWide, m_iDesiredTall; +}; + +} // namespace vgui + + +#endif // WIZARDSUBPANEL_H diff --git a/sp/src/public/vgui_controls/pch_vgui_controls.h b/sp/src/public/vgui_controls/pch_vgui_controls.h new file mode 100644 index 00000000..7b09eb5b --- /dev/null +++ b/sp/src/public/vgui_controls/pch_vgui_controls.h @@ -0,0 +1,115 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef PCH_VGUI_CONTROLS_H +#define PCH_VGUI_CONTROLS_H + +#ifdef _WIN32 +#pragma once +#endif + +// general includes +#include +#include +#include "tier0/dbg.h" +#include "tier0/valve_off.h" +#include "tier1/KeyValues.h" + +#include "tier0/valve_on.h" +#include "tier0/memdbgon.h" + +#include "filesystem.h" +#include "tier0/validator.h" + +// vgui includes +#include "vgui/IBorder.h" +#include "vgui/IInput.h" +#include "vgui/ILocalize.h" +#include "vgui/IPanel.h" +#include "vgui/IScheme.h" +#include "vgui/ISurface.h" +#include "vgui/ISystem.h" +#include "vgui/IVGui.h" +#include "vgui/KeyCode.h" +#include "vgui/Cursor.h" +#include "vgui/MouseCode.h" + +// vgui controls includes +#include "vgui_controls/Controls.h" + +#include "vgui_controls/AnimatingImagePanel.h" +#include "vgui_controls/AnimationController.h" +#include "vgui_controls/BitmapImagePanel.h" +#include "vgui_controls/BuildGroup.h" +#include "vgui_controls/BuildModeDialog.h" +#include "vgui_controls/Button.h" +#include "vgui_controls/CheckButton.h" +#include "vgui_controls/CheckButtonList.h" +#include "vgui_controls/ComboBox.h" +#include "vgui_controls/Controls.h" +#include "vgui_controls/DialogManager.h" +#include "vgui_controls/DirectorySelectDialog.h" +#include "vgui_controls/Divider.h" +#include "vgui_controls/EditablePanel.h" +#include "vgui_controls/FileOpenDialog.h" +#include "vgui_controls/FocusNavGroup.h" +#include "vgui_controls/Frame.h" +#include "vgui_controls/GraphPanel.h" +#include "vgui_controls/HTML.h" +#include "vgui_controls/Image.h" +#include "vgui_controls/ImageList.h" +#include "vgui_controls/ImagePanel.h" +#include "vgui_controls/Label.h" +#include "vgui_controls/ListPanel.h" +#include "vgui_controls/ListViewPanel.h" +#include "vgui_controls/Menu.h" +#include "vgui_controls/MenuBar.h" +#include "vgui_controls/MenuButton.h" +#include "vgui_controls/MenuItem.h" +#include "vgui_controls/MessageBox.h" +#include "vgui_controls/Panel.h" +#ifndef HL1 +#include "vgui_controls/PanelAnimationVar.h" +#endif +#include "vgui_controls/PanelListPanel.h" +#include "vgui_controls/PHandle.h" +#include "vgui_controls/ProgressBar.h" +#include "vgui_controls/ProgressBox.h" +#include "vgui_controls/PropertyDialog.h" +#include "vgui_controls/PropertyPage.h" +#include "vgui_controls/PropertySheet.h" +#include "vgui_controls/QueryBox.h" +#include "vgui_controls/RadioButton.h" +#include "vgui_controls/RichText.h" +#include "vgui_controls/ScrollBar.h" +#include "vgui_controls/ScrollBarSlider.h" +#include "vgui_controls/SectionedListPanel.h" +#include "vgui_controls/Slider.h" +#ifndef HL1 +#include "vgui_controls/Splitter.h" +#endif +#include "vgui_controls/TextEntry.h" +#include "vgui_controls/TextImage.h" +#include "vgui_controls/ToggleButton.h" +#include "vgui_controls/Tooltip.h" +#ifndef HL1 +#include "vgui_controls/ToolWindow.h" +#endif +#include "vgui_controls/TreeView.h" +#ifndef HL1 +#include "vgui_controls/TreeViewListControl.h" +#endif +#include "vgui_controls/URLLabel.h" +#include "vgui_controls/WizardPanel.h" +#include "vgui_controls/WizardSubPanel.h" + +#ifndef HL1 +#include "vgui_controls/KeyBoardEditorDialog.h" +#include "vgui_controls/InputDialog.h" +#endif + +#endif // PCH_VGUI_CONTROLS_H \ No newline at end of file diff --git a/sp/src/public/vgui_controls/perforcefilelistframe.h b/sp/src/public/vgui_controls/perforcefilelistframe.h new file mode 100644 index 00000000..7744bf23 --- /dev/null +++ b/sp/src/public/vgui_controls/perforcefilelistframe.h @@ -0,0 +1,151 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// List of perforce files and operations +// +//============================================================================= + +#ifndef PERFORCEFILELISTFRAME_H +#define PERFORCEFILELISTFRAME_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/Frame.h" +#include "tier1/utlvector.h" +#include "tier1/utlstring.h" +#include "p4lib/ip4.h" + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Enumeration of operation dialog ids +//----------------------------------------------------------------------------- +enum +{ + OPERATION_DIALOG_ID_PERFORCE = 0, + + OPERATION_DIALOG_STANDARD_ID_COUNT, + OPERATION_DIALOG_STANDARD_ID_MAX = OPERATION_DIALOG_STANDARD_ID_COUNT - 1, +}; + + +//----------------------------------------------------------------------------- +// Purpose: Modal dialog for a list of files + an operation to perform +//----------------------------------------------------------------------------- +class COperationFileListFrame : public vgui::Frame +{ + DECLARE_CLASS_SIMPLE( COperationFileListFrame, vgui::Frame ); + +public: + // NOTE: The dialog ID is used to allow dialogs to have different configurations saved + COperationFileListFrame( vgui::Panel *pParent, const char *pTitle, const char *pColumnHeader, bool bShowDescription, bool bShowOkOnly = false, int nDialogID = 1 ); + virtual ~COperationFileListFrame(); + + // Command handler + virtual void OnCommand( const char *pCommand ); + virtual void PerformLayout(); + + // Adds files to the frame + void ClearAllOperations(); + void AddOperation( const char *pOperation, const char *pFileName ); + void AddOperation( const char *pOperation, const char *pFileName, const Color& clr ); + + // Resizes the operation column to fit the operation text + void ResizeOperationColumnToContents(); + + // Sets the column header for the 'operation' column + void SetOperationColumnHeaderText( const char *pText ); + + // Shows the panel + void DoModal( KeyValues *pContextKeyValues = NULL, const char *pMessage = NULL ); + + // Retrieves the number of files, the file names, and operations + int GetOperationCount(); + const char *GetFileName( int i ); + const char *GetOperation( int i ); + + // Retreives the description (only if it was shown) + const char *GetDescription(); + +private: + virtual bool PerformOperation() { return true; } + const char *CompletionMessage(); + void CleanUpMessage(); + + vgui::ListPanel *m_pFileBrowser; + vgui::Splitter *m_pSplitter; + vgui::TextEntry *m_pDescription; + vgui::Button *m_pYesButton; + vgui::Button *m_pNoButton; + KeyValues *m_pContextKeyValues; + CUtlString m_MessageName; + char *m_pText; +}; + + +//----------------------------------------------------------------------------- +// Purpose: Modal dialog for picker +//----------------------------------------------------------------------------- +enum PerforceAction_t +{ + PERFORCE_ACTION_NONE = -1, + PERFORCE_ACTION_FILE_ADD = 0, + PERFORCE_ACTION_FILE_EDIT, + PERFORCE_ACTION_FILE_DELETE, + PERFORCE_ACTION_FILE_REVERT, + PERFORCE_ACTION_FILE_SUBMIT, +}; + + +//----------------------------------------------------------------------------- +// Purpose: Modal dialog for picker +//----------------------------------------------------------------------------- +class CPerforceFileListFrame : public COperationFileListFrame +{ + DECLARE_CLASS_SIMPLE( CPerforceFileListFrame, COperationFileListFrame ); + +public: + CPerforceFileListFrame( vgui::Panel *pParent, const char *pTitle, const char *pColumnHeader, PerforceAction_t action ); + virtual ~CPerforceFileListFrame(); + + // Adds files to the frame + void ClearAllFiles(); + void AddFile( const char *pFullPath ); + void AddFile( const char *pRelativePath, const char *pPathId ); + + void DoModal( KeyValues *pContextKeys = NULL, const char *pMessage = NULL ); + +private: + virtual bool PerformOperation(); + + // Adds files for open, submit + void AddFileForOpen( const char *pFullPath ); + void AddFileForSubmit( const char *pFullPath, P4FileState_t state ); + + // Does the perforce operation + void PerformPerforceAction( ); + + PerforceAction_t m_Action; + CUtlVector< P4File_t > m_OpenedFiles; + CUtlString m_LastOpenedFilePathId; +}; + + +//----------------------------------------------------------------------------- +// Show the perforce query dialog +// The specified keyvalues message will be sent either +// 1) If you open the file for add/edit +// 2) If you indicate to not add a file for add but don't hit cancel +// If a specific perforce action is specified, then the dialog will only +// be displayed if that action is appropriate +//----------------------------------------------------------------------------- +void ShowPerforceQuery( vgui::Panel *pParent, const char *pFileName, vgui::Panel *pActionSignalTarget, KeyValues *pKeyValues, PerforceAction_t actionFilter = PERFORCE_ACTION_NONE ); + + +#endif // PERFORCEFILELISTFRAME_H + diff --git a/sp/src/public/vgui_controls/savedocumentquery.h b/sp/src/public/vgui_controls/savedocumentquery.h new file mode 100644 index 00000000..fd738f46 --- /dev/null +++ b/sp/src/public/vgui_controls/savedocumentquery.h @@ -0,0 +1,37 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// This dialog asks if you want to save your work +// +//============================================================================= + +#ifndef SAVEDOCUMENTQUERY_H +#define SAVEDOCUMENTQUERY_H + +#ifdef _WIN32 +#pragma once +#endif + + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class KeyValues; +namespace vgui +{ +class Panel; +} + + +//----------------------------------------------------------------------------- +// Show the save document query dialog +// NOTE: The following commands will be posted to the action signal target: +// "OnExit" - when we want to quit +// "OnSave" - when we want to save the file +// "OnCloseNoSave" - when we want to close the file without saving it +// "commandname" - additional command send after saving (SAVEDOC_POSTCOMMAND_AFTER_SAVE) +// "OnMarkNotDirty" - when we want to mark the file not dirty +//----------------------------------------------------------------------------- +void ShowSaveDocumentQuery( vgui::Panel *pParent, const char *pFileName, const char *pFileType, int nContext, vgui::Panel *pActionSignalTarget, KeyValues *pPostSaveCommand ); + + +#endif // SAVEDOCUMENTQUERY_H diff --git a/sp/src/public/vgui_controls/subrectimage.h b/sp/src/public/vgui_controls/subrectimage.h new file mode 100644 index 00000000..b7738c4b --- /dev/null +++ b/sp/src/public/vgui_controls/subrectimage.h @@ -0,0 +1,51 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef SUBRECTIMAGE_H +#define SUBRECTIMAGE_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "vgui_controls/Image.h" +#include "vgui/VGUI.h" + + +//----------------------------------------------------------------------------- +// Purpose: Check box image +//----------------------------------------------------------------------------- +class CSubRectImage : public vgui::Image +{ +public: + CSubRectImage( const char *filename, bool hardwareFiltered, int subx, int suby, int subw, int subh ); + virtual ~CSubRectImage(); + + void GetSize( int &wide, int &tall ); + void GetContentSize( int &wide, int &tall ); + void SetSize( int x, int y ); + void SetPos( int x, int y ); + void SetColor( Color col ); + const char *GetName(); + void Paint(); + void ForceUpload(); + vgui::HTexture GetID(); + bool IsValid(); + +private: + vgui::HTexture _id; + int sub[ 4 ]; + char *_filename; + int _pos[2]; + int _wide,_tall; + Color _color; + bool _uploaded; + bool _valid; + bool _filtered; +}; + + +#endif // SUBRECTIMAGE_H \ No newline at end of file diff --git a/sp/src/public/vgui_controls/vgui_controls.cpp b/sp/src/public/vgui_controls/vgui_controls.cpp new file mode 100644 index 00000000..261ff983 --- /dev/null +++ b/sp/src/public/vgui_controls/vgui_controls.cpp @@ -0,0 +1,58 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= +#include "vgui/IVGui.h" +#include "vgui_controls/Controls.h" + +#include "vgui_controls/AnimatingImagePanel.h" +#include "vgui_controls/BitmapImagePanel.h" +#include "vgui_controls/ExpandButton.h" +#include "vgui_controls/TreeViewListControl.h" +#include "vgui_controls/HTML.h" + +// NOTE: This has to be the last file included! +#include "tier0/memdbgon.h" + + +using namespace vgui; + +USING_BUILD_FACTORY( Button ); +USING_BUILD_FACTORY( EditablePanel ); +USING_BUILD_FACTORY( ImagePanel ); +USING_BUILD_FACTORY( Label ); +USING_BUILD_FACTORY( Panel ); +USING_BUILD_FACTORY( ToggleButton ); +USING_BUILD_FACTORY( AnimatingImagePanel ); +USING_BUILD_FACTORY( CBitmapImagePanel ); +USING_BUILD_FACTORY( CheckButton ); +USING_BUILD_FACTORY( ComboBox ); +USING_BUILD_FACTORY_ALIAS( CvarToggleCheckButton, CvarToggleCheckButton ); +USING_BUILD_FACTORY( Divider ); +USING_BUILD_FACTORY( ExpandButton ); +USING_BUILD_FACTORY( GraphPanel ); +//USING_BUILD_FACTORY_ALIAS( HTML, HTML_NoJavascript ); +//USING_BUILD_FACTORY_ALIAS( HTML, HTML_Javascript ); +USING_BUILD_FACTORY( ListPanel ); +USING_BUILD_FACTORY( ListViewPanel ); +USING_BUILD_FACTORY( Menu ); +USING_BUILD_FACTORY( MenuBar ); +USING_BUILD_FACTORY( MenuButton ); +USING_BUILD_FACTORY( MenuItem ); +USING_BUILD_FACTORY( MessageBox ); +USING_BUILD_FACTORY( ProgressBar ); +USING_BUILD_FACTORY( CircularProgressBar ); +USING_BUILD_FACTORY( RadioButton ); +USING_BUILD_FACTORY( RichText ); +USING_BUILD_FACTORY( ScalableImagePanel ); +USING_BUILD_FACTORY_ALIAS( ScrollBar, ScrollBar_Vertical ); +USING_BUILD_FACTORY_ALIAS( ScrollBar, ScrollBar_Horizontal ); +USING_BUILD_FACTORY( ScrollBar ); +USING_BUILD_FACTORY( Slider ); +USING_BUILD_FACTORY( TextEntry ); +USING_BUILD_FACTORY( TreeView ); +USING_BUILD_FACTORY( CTreeViewListControl ); +USING_BUILD_FACTORY( URLLabel ); + +int g_nYou_Must_Add_Public_Vgui_Controls_Vgui_ControlsCpp_To_Your_Project = 0; diff --git a/sp/src/public/video/ivideoservices.h b/sp/src/public/video/ivideoservices.h new file mode 100644 index 00000000..8a2d2318 --- /dev/null +++ b/sp/src/public/video/ivideoservices.h @@ -0,0 +1,549 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +//============================================================================= + +#ifndef IVIDEOSERVICES_H +#define IVIDEOSERVICES_H + +#if defined ( WIN32 ) + #pragma once +#endif + +#include +#include "appframework/IAppSystem.h" +#include "tier0/platform.h" + +#include +#ifndef _STDINT_H +#define _STDINT_H +#endif +#ifndef _STDINT +#define _STDINT +#endif + + +#ifndef nullptr + #define nullptr ( 0 ) +#endif +#ifndef INT32_MAX +#define INT32_MAX (0x7FFFFFFF) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (0xFFFFFFFFu) +#endif + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class IMaterial; + + +//----------------------------------------------------------------------------- +// Types used when dealing with video services +//----------------------------------------------------------------------------- + +#define FILE_EXTENSION_ANY_MATCHING_VIDEO ".vid" + +//#define ENABLE_EXTERNAL_ENCODER_LOGGING + + +//----------------------------------------------------------------------------- +// enums used when dealing with video services +//----------------------------------------------------------------------------- + + // ============================================== + // various general video system enumerations + + +namespace VideoResult +{ + enum EVideoResult_t + { + SUCCESS = 0, + + SYSTEM_NOT_AVAILABLE, + CODEC_NOT_AVAILABLE, + FEATURE_NOT_AVAILABLE, + + UNKNOWN_OPERATION, + ILLEGAL_OPERATION, + OPERATION_NOT_SUPPORTED, + + BAD_INPUT_PARAMETERS, + OPERATION_ALREADY_PERFORMED, + OPERATION_OUT_OF_SEQUENCE, + + VIDEO_ERROR_OCCURED, + FILE_ERROR_OCCURED, + AUDIO_ERROR_OCCURED, + SYSTEM_ERROR_OCCURED, + INITIALIZATION_ERROR_OCCURED, + SHUTDOWN_ERROR_OCCURED, + + MATERIAL_NOT_FOUND, + RECORDER_NOT_FOUND, + VIDEO_FILE_NOT_FOUND, + VIDEO_SYSTEM_NOT_FOUND, + }; +}; +typedef VideoResult::EVideoResult_t VideoResult_t; + +namespace VideoSystem +{ + enum EVideoSystem_t + { + ALL_VIDEO_SYSTEMS = -2, + DETERMINE_FROM_FILE_EXTENSION = -1, + NONE = 0, + + BINK, + AVI, + WMV, + QUICKTIME, + WEBM, + + VIDEO_SYSTEM_COUNT, + VIDEO_SYSTEM_FIRST = 1, + }; +}; +typedef VideoSystem::EVideoSystem_t VideoSystem_t; + + +namespace VideoSystemStatus +{ + enum EVideoSystemStatus_t + { + OK = 0, + NOT_INSTALLED, + NOT_CURRENT_VERSION, + NOT_INITIALIZED, + INITIALIZATION_ERROR, + }; +}; +typedef VideoSystemStatus::EVideoSystemStatus_t VideoSystemStatus_t; + + +namespace VideoSystemFeature +{ + enum EVideoSystemFeature_t + { + NO_FEATURES = 0x00000000, + PLAY_VIDEO_FILE_FULL_SCREEN = 0x00000001, + PLAY_VIDEO_FILE_IN_MATERIAL = 0x00000002, + ENCODE_VIDEO_TO_FILE = 0x00000004, + ENCODE_AUDIO_TO_FILE = 0x00000008, + + + FULL_PLAYBACK = PLAY_VIDEO_FILE_FULL_SCREEN | PLAY_VIDEO_FILE_IN_MATERIAL, + FULL_ENCODE = ENCODE_VIDEO_TO_FILE | ENCODE_AUDIO_TO_FILE, + ALL_VALID_FEATURES = FULL_PLAYBACK | FULL_ENCODE, + + ESF_FORCE_UINT32 = UINT32_MAX, + }; + + DEFINE_ENUM_BITWISE_OPERATORS( EVideoSystemFeature_t ); +}; +typedef VideoSystemFeature::EVideoSystemFeature_t VideoSystemFeature_t; + + +namespace VideoSoundDeviceOperation +{ + enum EVideoSoundDeviceOperation_t + { + SET_DIRECT_SOUND_DEVICE = 0, // Windows option + SET_MILES_SOUND_DEVICE, // Supported by RAD + HOOK_X_AUDIO, // Xbox Option + SET_SOUND_MANAGER_DEVICE, // OSX Option + SET_LIB_AUDIO_DEVICE, // PS3 Option + SET_SDL_SOUND_DEVICE, // SDL Audio + SET_SDL_PARAMS, // SDL Audio params + SDLMIXER_CALLBACK, // SDLMixer callback + + OPERATION_COUNT + }; +}; +typedef VideoSoundDeviceOperation::EVideoSoundDeviceOperation_t VideoSoundDeviceOperation_t; + + + // ============================================== + // Video Encoding related settings + +namespace VideoEncodeCodec +{ + // + // NOTE: NEW CODECS SHOULD BE ADDED TO THE END OF THIS LIST. + // + enum EVideoEncodeCodec_t + { + MPEG2_CODEC, + MPEG4_CODEC, + H261_CODEC, + H263_CODEC, + H264_CODEC, + MJPEG_A_CODEC, + MJPEG_B_CODEC, + SORENSON3_CODEC, + CINEPACK_CODEC, + WEBM_CODEC, + + // + // NOTE: ADD NEW CODECS HERE. + // + + CODEC_COUNT, + + DEFAULT_CODEC = H264_CODEC, + }; +}; +typedef VideoEncodeCodec::EVideoEncodeCodec_t VideoEncodeCodec_t; + + +namespace VideoEncodeQuality +{ + enum EVideoEncodeQuality_t + { + MIN_QUALITY = 0, + MAX_QUALITY = 100 + }; +}; +typedef VideoEncodeQuality::EVideoEncodeQuality_t VideoEncodeQuality_t; + + +namespace VideoEncodeSourceFormat +{ + enum EVideoEncodeSourceFormat_t // Image source format for frames to encoded + { + BGRA_32BIT = 0, + BGR_24BIT, + RGB_24BIT, + RGBA_32BIT, + + VIDEO_FORMAT_COUNT, + VIDEO_FORMAT_FIRST = 0 + }; +}; +typedef VideoEncodeSourceFormat::EVideoEncodeSourceFormat_t VideoEncodeSourceFormat_t; + + +namespace VideoEncodeGamma +{ + enum EVideoEncodeGamma_t + { + NO_GAMMA_ADJUST = 0, + PLATFORM_STANDARD_GAMMA, + GAMMA_1_8, + GAMMA_2_2, + GAMMA_2_5, + + GAMMA_COUNT + }; +}; +typedef VideoEncodeGamma::EVideoEncodeGamma_t VideoEncodeGamma_t; + + +namespace VideoPlaybackGamma +{ + enum EVideoPlaybackGamma_t + { + USE_GAMMA_CONVAR = -1, + NO_GAMMA_ADJUST = 0, + PLATFORM_DEFAULT_GAMMMA, + GAMMA_1_8, + GAMMA_2_2, + GAMMA_2_5, + + GAMMA_COUNT + }; +}; +typedef VideoPlaybackGamma::EVideoPlaybackGamma_t VideoPlaybackGamma_t; + + + // ============================================== + // Video Playback related settings + +namespace VideoPlaybackFlags +{ + enum EVideoPlaybackFlags_t // Options when playing a video file + { + NO_PLAYBACK_OPTIONS = 0x00000000, + + // Full Screen Playback Options + FILL_WINDOW = 0x00000001, // force video fill entire window + LOCK_ASPECT_RATIO = 0x00000002, // preserve aspect ratio when scaling + INTEGRAL_SCALE = 0x00000004, // scale video only by integral amounts + CENTER_VIDEO_IN_WINDOW = 0x00000008, // center output video in window + + FORCE_MIN_PLAY_TIME = 0x00000010, // play for a minimum amount of time before allowing skip or abort + + ABORT_ON_SPACE = 0x00000100, // Keys to abort fullscreen playback on + ABORT_ON_ESC = 0x00000200, + ABORT_ON_RETURN = 0x00000400, + ABORT_ON_ANY_KEY = 0x00000700, + + PAUSE_ON_SPACE = 0x00001000, // Keys to pause fullscreen playback on + PAUSE_ON_ESC = 0x00002000, + PAUSE_ON_RETURN = 0x00004000, + PAUSE_ON_ANY_KEY = 0x00007000, + + LOOP_VIDEO = 0x00010000, // Full Screen and Video material + NO_AUDIO = 0x00020000, + PRELOAD_VIDEO = 0x00040000, + + DONT_AUTO_START_VIDEO = 0x00100000, // Don't begin playing until told to do so. + TEXTURES_ACTUAL_SIZE = 0x00200000, // Try and use textures the same size as the video frame + + VALID_FULLSCREEN_FLAGS = 0x0007771F, // Playback Flags that are valid for playing videos fullscreen + VALID_MATERIAL_FLAGS = 0x00370000, // Playback Flags that are valid for playing videos in a material + + DEFAULT_MATERIAL_OPTIONS = NO_PLAYBACK_OPTIONS, + DEFAULT_FULLSCREEN_OPTIONS = CENTER_VIDEO_IN_WINDOW | LOCK_ASPECT_RATIO | ABORT_ON_ANY_KEY, + + EVPF_FORCE_UINT32 = UINT32_MAX, + }; + + DEFINE_ENUM_BITWISE_OPERATORS( EVideoPlaybackFlags_t ); +} +typedef VideoPlaybackFlags::EVideoPlaybackFlags_t VideoPlaybackFlags_t; + + +namespace AudioEncodeSourceFormat +{ + enum EAudioEncodeSourceFormat_t // Audio source format to encode + { + AUDIO_NONE = 0, + AUDIO_16BIT_PCMStereo, + + AUDIO_FORMAT_COUNT + }; +}; +typedef AudioEncodeSourceFormat::EAudioEncodeSourceFormat_t AudioEncodeSourceFormat_t; + + +namespace AudioEncodeOptions +{ + enum EAudioEncodeOptions_t // Options to control audio encoding + { + NO_AUDIO_OPTIONS = 0x00000000, + + USE_AUDIO_ENCODE_GROUP_SIZE = 0x00000001, // When adding to the video media, use fixed size sample groups + GROUP_SIZE_IS_VIDEO_FRAME = 0x00000002, // use a group size equal to one video frame in duration + LIMIT_AUDIO_TRACK_TO_VIDEO_DURATION = 0x00000004, // Don't let the Audio Track exceed the video track in duration + PAD_AUDIO_WITH_SILENCE = 0x00000008, // If Audio track duration is less than video track's, pad with silence + + AEO_FORCE_UINT32 = UINT32_MAX, + }; + DEFINE_ENUM_BITWISE_OPERATORS( EAudioEncodeOptions_t ); +} +typedef AudioEncodeOptions::EAudioEncodeOptions_t AudioEncodeOptions_t; + + +//----------------------------------------------------------------------------- +// Frame Rate Class +//----------------------------------------------------------------------------- +class VideoFrameRate_t +{ + public: + inline VideoFrameRate_t() : m_TimeUnitsPerSecond( 0 ), m_TimeUnitsPerFrame( 1000 ) {}; + + inline VideoFrameRate_t( int FPS, bool NTSC ) { SetFPS( FPS, NTSC); } + inline explicit VideoFrameRate_t( float FPS ) { SetFPS( FPS); }; + + inline VideoFrameRate_t& operator=( const VideoFrameRate_t& rhs ) { m_TimeUnitsPerSecond = rhs.m_TimeUnitsPerSecond; m_TimeUnitsPerFrame = rhs.m_TimeUnitsPerFrame; return *this; } + inline VideoFrameRate_t( const VideoFrameRate_t &rhs ) { *this = rhs; }; + + inline void SetRaw( int timeUnitsPerSecond, int TimeUnitsPerFrame ) { m_TimeUnitsPerSecond = timeUnitsPerSecond; m_TimeUnitsPerFrame = TimeUnitsPerFrame; } + + inline float GetFPS() const { return (float) m_TimeUnitsPerSecond / (float) m_TimeUnitsPerFrame; } + inline int GetIntFPS() const { return (int) ( (float) m_TimeUnitsPerSecond / (float) m_TimeUnitsPerFrame + 0.5f ); } + inline bool IsNTSCRate() const { return ( m_TimeUnitsPerFrame == 1001 ); } + inline int GetUnitsPerSecond() const { return m_TimeUnitsPerSecond; } + inline int GetUnitsPerFrame() const { return m_TimeUnitsPerFrame; } + + inline void SetFPS( int FPS, bool NTSC ) { m_TimeUnitsPerSecond = FPS * 1000; m_TimeUnitsPerFrame = 1000 + (uint) NTSC; } + inline void SetFPS( float FPS ) { m_TimeUnitsPerSecond = (uint) ( FPS * 1000.0f ); m_TimeUnitsPerFrame = 1000; } + + static inline bool IsNTSC( float FPS ) { float diff = ceil(FPS) - FPS; return ( diff > 0.02f && diff < 0.05f); } + + inline void Clear() { m_TimeUnitsPerSecond = 0; m_TimeUnitsPerFrame = 1000; } + inline bool IsValid() { return ( m_TimeUnitsPerSecond != 0); } + + private: + uint32 m_TimeUnitsPerSecond; + uint32 m_TimeUnitsPerFrame; +}; + + + +//----------------------------------------------------------------------------- +// specific interfaces returned and managed by video services +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +// Video Material interface - manages the playing back of a video to a +// a material / texture combo +//----------------------------------------------------------------------------- +class IVideoMaterial : public IBaseInterface +{ + public: + // Video information functions + virtual const char *GetVideoFileName() = 0; // Gets the file name of the video this material is playing + virtual VideoResult_t GetLastResult() = 0; // Gets detailed info on the last operation + + virtual VideoFrameRate_t &GetVideoFrameRate() = 0; // Returns the frame rate of the associated video in FPS + + // Audio Functions + virtual bool HasAudio() = 0; // Query if the video has an audio track + + virtual bool SetVolume( float fVolume ) = 0; // Adjust the playback volume + virtual float GetVolume() = 0; // Query the current volume + + virtual void SetMuted( bool bMuteState ) = 0; // Mute/UnMutes the audio playback + virtual bool IsMuted() = 0; // Query muted status + + virtual VideoResult_t SoundDeviceCommand( VideoSoundDeviceOperation_t operation, void *pDevice = nullptr, void *pData = nullptr ) = 0; // Assign Sound Device for this Video Material + + // Video playback state functions + virtual bool IsVideoReadyToPlay() = 0; // Queries if the video material was initialized successfully and is ready for playback, but not playing or finished + virtual bool IsVideoPlaying() = 0; // Is the video currently playing (and needs update calls, etc), or paused while playing? + virtual bool IsNewFrameReady() = 0; // Do we have a new frame to get & display? + virtual bool IsFinishedPlaying() = 0; // Have we reached the end of the movie + + virtual bool StartVideo() = 0; // Starts the video playing + virtual bool StopVideo() = 0; // Terminates the video playing + + virtual void SetLooping( bool bLoopVideo ) = 0; // Sets the video to loop (or not) + virtual bool IsLooping() = 0; // Queries if the video is looping + + virtual void SetPaused( bool bPauseState ) = 0; // Pauses or Unpauses video playback + virtual bool IsPaused() = 0; // Queries if the video is paused + + // Position in playback functions + virtual float GetVideoDuration() = 0; // Returns the duration of the associated video in seconds + virtual int GetFrameCount() = 0; // Returns the total number of (unique) frames in the video + + virtual bool SetFrame( int FrameNum ) = 0; // Sets the current frame # in the video to play next + virtual int GetCurrentFrame() = 0; // Gets the current frame # for the video playback, 0 based + + virtual bool SetTime( float flTime ) = 0; // Sets the video playback to specified time (in seconds) + virtual float GetCurrentVideoTime() = 0; // Gets the current time in the video playback + + // Update function + virtual bool Update() = 0; // Updates the video frame to reflect the time passed, true = new frame available + + // Material / Texture Info functions + virtual IMaterial *GetMaterial() = 0; // Gets the IMaterial associated with an video material + + virtual void GetVideoTexCoordRange( float *pMaxU, float *pMaxV ) = 0; // Returns the max texture coordinate of the video portion of the material surface ( 0.0, 0.0 to U, V ) + virtual void GetVideoImageSize( int *pWidth, int *pHeight ) = 0; // Returns the frame size of the Video Image Frame in pixels ( the stored in a subrect of the material itself) + +}; + + +//----------------------------------------------------------------------------- +// Video Recorder interface - manages the creation of a new video file +//----------------------------------------------------------------------------- +class IVideoRecorder : public IBaseInterface +{ + public: + virtual bool EstimateMovieFileSize( size_t *pEstSize, int movieWidth, int movieHeight, VideoFrameRate_t movieFps, float movieDuration, VideoEncodeCodec_t theCodec, int videoQuality, AudioEncodeSourceFormat_t srcAudioFormat = AudioEncodeSourceFormat::AUDIO_NONE, int audioSampleRate = 0 ) = 0; + + virtual bool CreateNewMovieFile( const char *pFilename, bool hasAudioTrack = false ) = 0; + + virtual bool SetMovieVideoParameters( VideoEncodeCodec_t theCodec, int videoQuality, int movieFrameWidth, int movieFrameHeight, VideoFrameRate_t movieFPS, VideoEncodeGamma_t gamma = VideoEncodeGamma::NO_GAMMA_ADJUST ) = 0; + virtual bool SetMovieSourceImageParameters( VideoEncodeSourceFormat_t srcImageFormat, int imgWidth, int imgHeight ) = 0; + virtual bool SetMovieSourceAudioParameters( AudioEncodeSourceFormat_t srcAudioFormat = AudioEncodeSourceFormat::AUDIO_NONE, int audioSampleRate = 0, AudioEncodeOptions_t audioOptions = AudioEncodeOptions::NO_AUDIO_OPTIONS, int audioSampleGroupSize = 0) = 0; + + virtual bool IsReadyToRecord() = 0; + virtual VideoResult_t GetLastResult() = 0; + + virtual bool AppendVideoFrame( void *pFrameBuffer, int nStrideAdjustBytes = 0 ) = 0; + virtual bool AppendAudioSamples( void *pSampleBuffer, size_t sampleSize ) = 0; + + virtual int GetFrameCount() = 0; + virtual int GetSampleCount() = 0; + + virtual VideoFrameRate_t GetFPS() = 0; + virtual int GetSampleRate() = 0; + + virtual bool AbortMovie() = 0; + virtual bool FinishMovie( bool SaveMovieToDisk = true ) = 0; + +#ifdef ENABLE_EXTERNAL_ENCODER_LOGGING + virtual bool LogMessage( const char *msg ) = 0; +#endif + +}; + + + + +//----------------------------------------------------------------------------- +// Main VIDEO_SERVICES interface +//----------------------------------------------------------------------------- +#define VIDEO_SERVICES_INTERFACE_VERSION "IVideoServices002" + + +class IVideoServices : public IAppSystem +{ + public: + // Query the available video systems + virtual int GetAvailableVideoSystemCount() = 0; + virtual VideoSystem_t GetAvailableVideoSystem( int n ) = 0; + + virtual bool IsVideoSystemAvailable( VideoSystem_t videoSystem ) = 0; + virtual VideoSystemStatus_t GetVideoSystemStatus( VideoSystem_t videoSystem ) = 0; + virtual VideoSystemFeature_t GetVideoSystemFeatures( VideoSystem_t videoSystem ) = 0; + virtual const char *GetVideoSystemName( VideoSystem_t videoSystem ) = 0; + + virtual VideoSystem_t FindNextSystemWithFeature( VideoSystemFeature_t features, VideoSystem_t startAfter = VideoSystem::NONE ) = 0; + + virtual VideoResult_t GetLastResult() = 0; + + // deal with video file extensions and video system mappings + virtual int GetSupportedFileExtensionCount( VideoSystem_t videoSystem ) = 0; + virtual const char *GetSupportedFileExtension( VideoSystem_t videoSystem, int extNum = 0 ) = 0; + virtual VideoSystemFeature_t GetSupportedFileExtensionFeatures( VideoSystem_t videoSystem, int extNum = 0 ) = 0; + + virtual VideoSystem_t LocateVideoSystemForPlayingFile( const char *pFileName, VideoSystemFeature_t playMode = VideoSystemFeature::PLAY_VIDEO_FILE_IN_MATERIAL ) = 0; + virtual VideoResult_t LocatePlayableVideoFile( const char *pSearchFileName, const char *pPathID, VideoSystem_t *pPlaybackSystem, char *pPlaybackFileName, int fileNameMaxLen, VideoSystemFeature_t playMode = VideoSystemFeature::FULL_PLAYBACK ) = 0; + + // Create/destroy a video material + virtual IVideoMaterial *CreateVideoMaterial( const char *pMaterialName, const char *pVideoFileName, const char *pPathID = nullptr, + VideoPlaybackFlags_t playbackFlags = VideoPlaybackFlags::DEFAULT_MATERIAL_OPTIONS, + VideoSystem_t videoSystem = VideoSystem::DETERMINE_FROM_FILE_EXTENSION, bool PlayAlternateIfNotAvailable = true ) = 0; + + virtual VideoResult_t DestroyVideoMaterial( IVideoMaterial* pVideoMaterial ) = 0; + virtual int GetUniqueMaterialID() = 0; + + // Create/destroy a video encoder + virtual VideoResult_t IsRecordCodecAvailable( VideoSystem_t videoSystem, VideoEncodeCodec_t codec ) = 0; + + virtual IVideoRecorder *CreateVideoRecorder( VideoSystem_t videoSystem ) = 0; + virtual VideoResult_t DestroyVideoRecorder( IVideoRecorder *pVideoRecorder ) = 0; + + // Plays a given video file until it completes or the user presses ESC, SPACE, or ENTER + virtual VideoResult_t PlayVideoFileFullScreen( const char *pFileName, const char *pPathID, void *mainWindow, int windowWidth, int windowHeight, int desktopWidth, int desktopHeight, bool windowed, float forcedMinTime, + VideoPlaybackFlags_t playbackFlags = VideoPlaybackFlags::DEFAULT_FULLSCREEN_OPTIONS, + VideoSystem_t videoSystem = VideoSystem::DETERMINE_FROM_FILE_EXTENSION, bool PlayAlternateIfNotAvailable = true ) = 0; + + // Sets the sound devices that the video will decode to + virtual VideoResult_t SoundDeviceCommand( VideoSoundDeviceOperation_t operation, void *pDevice = nullptr, void *pData = nullptr, VideoSystem_t videoSystem = VideoSystem::ALL_VIDEO_SYSTEMS ) = 0; + + // Get the (localized) name of a codec as a string + virtual const wchar_t *GetCodecName( VideoEncodeCodec_t nCodec ) = 0; + +}; + + + + + + + + +#endif // IVIDEOSERVICES_H diff --git a/sp/src/public/vphysics/collision_set.h b/sp/src/public/vphysics/collision_set.h new file mode 100644 index 00000000..66aaeb83 --- /dev/null +++ b/sp/src/public/vphysics/collision_set.h @@ -0,0 +1,20 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +// A set of collision rules +// NOTE: Defaults to all indices disabled +class IPhysicsCollisionSet +{ +public: + ~IPhysicsCollisionSet() {} + + virtual void EnableCollisions( int index0, int index1 ) = 0; + virtual void DisableCollisions( int index0, int index1 ) = 0; + + virtual bool ShouldCollide( int index0, int index1 ) = 0; +}; \ No newline at end of file diff --git a/sp/src/public/vphysics/constraints.h b/sp/src/public/vphysics/constraints.h new file mode 100644 index 00000000..afea7606 --- /dev/null +++ b/sp/src/public/vphysics/constraints.h @@ -0,0 +1,345 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef CONSTRAINTS_H +#define CONSTRAINTS_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vphysics_interface.h" +#include "mathlib/mathlib.h" + +// constraint groups +struct constraint_groupparams_t +{ + int additionalIterations; // additional solver iterations make the constraint system more stable + int minErrorTicks; // minimum number of ticks with an error before it's reported + float errorTolerance; // error tolerance in HL units + + inline void Defaults() + { + additionalIterations = 0; + minErrorTicks = 15; + errorTolerance = 3.0f; + } +}; + +// Breakable constraints; +// +// forceLimit - kg * in / s limit (N * conversion(in/m)) +// torqueLimit - kg * in^2 / s (Nm * conversion(in^2/m^2)) + +// +// strength 0 - 1 +struct constraint_breakableparams_t +{ + float strength; // strength of the constraint 0.0 - 1.0 + float forceLimit; // constraint force limit to break (0 means never break) + float torqueLimit; // constraint torque limit to break (0 means never break) + float bodyMassScale[2]; // scale applied to mass of reference/attached object before solving constriant + bool isActive; + + inline void Defaults() + { + forceLimit = 0.0f; + torqueLimit = 0.0f; + strength = 1.0f; + bodyMassScale[0] = 1.0f; + bodyMassScale[1] = 1.0f; + isActive = true; + } +}; + +//----------------------------------------------------------------------------- +// Purpose: constraint limit on a single rotation axis +//----------------------------------------------------------------------------- +struct constraint_axislimit_t +{ + float minRotation; + float maxRotation; + float angularVelocity; // desired angular velocity around hinge + float torque; // torque to achieve angular velocity (use 0, torque for "friction") + + inline void SetAxisFriction( float rmin, float rmax, float friction ) + { + minRotation = rmin; + maxRotation = rmax; + angularVelocity = 0; + torque = friction; + } + inline void Defaults() + { + SetAxisFriction(0,0,0); + } +}; + +// Builds a transform which maps points in the input object's local space +// to the output object's local space +inline void BuildObjectRelativeXform( IPhysicsObject *pOutputSpace, IPhysicsObject *pInputSpace, matrix3x4_t &xformInToOut ) +{ + matrix3x4_t outInv, tmp, input; + pOutputSpace->GetPositionMatrix( &tmp ); + MatrixInvert( tmp, outInv ); + pInputSpace->GetPositionMatrix( &input ); + ConcatTransforms( outInv, input, xformInToOut ); +} + + +//----------------------------------------------------------------------------- +// Purpose: special limited ballsocket constraint for ragdolls. +// Has axis limits for all 3 axes. +//----------------------------------------------------------------------------- +struct constraint_ragdollparams_t +{ + constraint_breakableparams_t constraint; + matrix3x4_t constraintToReference;// xform constraint space to refobject space + matrix3x4_t constraintToAttached; // xform constraint space to attached object space + int parentIndex; // NOTE: only used for parsing. NEED NOT BE SET for create + int childIndex; // NOTE: only used for parsing. NEED NOT BE SET for create + + constraint_axislimit_t axes[3]; + bool onlyAngularLimits; // only angular limits (not translation as well?) + bool isActive; + bool useClockwiseRotations; // HACKHACK: Did this wrong in version one. Fix in the future. + + inline void Defaults() + { + constraint.Defaults(); + isActive = true; + SetIdentityMatrix( constraintToReference ); + SetIdentityMatrix( constraintToAttached ); + parentIndex = -1; + childIndex = -1; + axes[0].Defaults(); + axes[1].Defaults(); + axes[2].Defaults(); + onlyAngularLimits = false; + useClockwiseRotations = false; + } +}; + +//----------------------------------------------------------------------------- +// Purpose: Used to init a hinge restricting the relative position and orientation +// of two objects to rotation around a single axis +//----------------------------------------------------------------------------- +struct constraint_hingeparams_t +{ + Vector worldPosition; // position in world space on the hinge axis + Vector worldAxisDirection; // unit direction vector of the hinge axis in world space + constraint_axislimit_t hingeAxis; + constraint_breakableparams_t constraint; + + inline void Defaults() + { + worldPosition.Init(); + worldAxisDirection.Init(); + hingeAxis.Defaults(); + constraint.Defaults(); + } +}; + +struct constraint_limitedhingeparams_t : public constraint_hingeparams_t +{ + Vector referencePerpAxisDirection; // unit direction vector vector perpendicular to the hinge axis in world space + Vector attachedPerpAxisDirection; // unit direction vector vector perpendicular to the hinge axis in world space + + constraint_limitedhingeparams_t() {} + constraint_limitedhingeparams_t( const constraint_hingeparams_t &hinge ) + { + static_cast(*this) = hinge; + referencePerpAxisDirection.Init(); + attachedPerpAxisDirection.Init(); + } + + inline void Defaults() + { + this->constraint_hingeparams_t::Defaults(); + referencePerpAxisDirection.Init(); + attachedPerpAxisDirection.Init(); + } +}; + +//----------------------------------------------------------------------------- +// Purpose: Used to init a constraint that fixes the position and orientation +// of two objects relative to each other (like glue) +//----------------------------------------------------------------------------- +struct constraint_fixedparams_t +{ + matrix3x4_t attachedRefXform; // xform attached object space to ref object space + constraint_breakableparams_t constraint; + + inline void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached ) + { + BuildObjectRelativeXform( pRef, pAttached, attachedRefXform ); + } + + inline void Defaults() + { + SetIdentityMatrix( attachedRefXform ); + constraint.Defaults(); + } +}; + + +//----------------------------------------------------------------------------- +// Purpose: Same parameters as fixed constraint, but torqueLimit has no effect +//----------------------------------------------------------------------------- +struct constraint_ballsocketparams_t +{ + Vector constraintPosition[2]; // position of the constraint in each object's space + constraint_breakableparams_t constraint; + inline void Defaults() + { + constraint.Defaults(); + constraintPosition[0].Init(); + constraintPosition[1].Init(); + } + + void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &ballsocketOrigin ) + { + pRef->WorldToLocal( &constraintPosition[0], ballsocketOrigin ); + pAttached->WorldToLocal( &constraintPosition[1], ballsocketOrigin ); + } +}; + +struct constraint_slidingparams_t +{ + matrix3x4_t attachedRefXform; // xform attached object space to ref object space + Vector slideAxisRef; // unit direction vector of the slide axis in ref object space + constraint_breakableparams_t constraint; + // NOTE: if limitMin == limitMax there is NO limit set! + float limitMin; // minimum limit coordinate refAxisDirection space + float limitMax; // maximum limit coordinate refAxisDirection space + float friction; // friction on sliding + float velocity; // desired velocity + + inline void Defaults() + { + SetIdentityMatrix( attachedRefXform ); + slideAxisRef.Init(); + limitMin = limitMax = 0; + friction = 0; + velocity = 0; + constraint.Defaults(); + } + + inline void SetFriction( float inputFriction ) + { + friction = inputFriction; + velocity = 0; + } + + inline void SetLinearMotor( float inputVelocity, float maxForce ) + { + friction = maxForce; + velocity = inputVelocity; + } + + inline void InitWithCurrentObjectState( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &slideDirWorldspace ) + { + BuildObjectRelativeXform( pRef, pAttached, attachedRefXform ); + matrix3x4_t tmp; + pRef->GetPositionMatrix( &tmp ); + VectorIRotate( slideDirWorldspace, tmp, slideAxisRef ); + } +}; + +struct constraint_pulleyparams_t +{ + constraint_breakableparams_t constraint; + Vector pulleyPosition[2]; // These are the pulley positions for the reference and attached objects in world space + Vector objectPosition[2]; // local positions of attachments to the ref,att objects + float totalLength; // total rope length (include gearing!) + float gearRatio; // gearing affects attached object ALWAYS + bool isRigid; + + inline void Defaults() + { + constraint.Defaults(); + totalLength = 1.0; + gearRatio = 1.0; + pulleyPosition[0].Init(); + pulleyPosition[1].Init(); + objectPosition[0].Init(); + objectPosition[1].Init(); + isRigid = false; + } +}; + + +struct constraint_lengthparams_t +{ + constraint_breakableparams_t constraint; + Vector objectPosition[2]; // These are the positions for the reference and attached objects in local space + float totalLength; // Length of rope/spring/constraint. Distance to maintain + float minLength; // if rigid, objects are not allowed to move closer than totalLength either + + void InitWorldspace( IPhysicsObject *pRef, IPhysicsObject *pAttached, const Vector &refPosition, const Vector &attachedPosition, bool rigid = false ) + { + pRef->WorldToLocal( &objectPosition[0], refPosition ); + pAttached->WorldToLocal( &objectPosition[1], attachedPosition ); + totalLength = (refPosition - attachedPosition).Length(); + minLength = rigid ? totalLength : 0; + } + + inline void Defaults() + { + constraint.Defaults(); + objectPosition[0].Init(); + objectPosition[1].Init(); + totalLength = 1; + minLength = 0; + } +}; + +class IPhysicsConstraint +{ +public: + virtual ~IPhysicsConstraint( void ) {} + + // NOTE: Constraints are active when created. You can temporarily enable/disable them with these functions + virtual void Activate( void ) = 0; + virtual void Deactivate( void ) = 0; + + // set a pointer to the game object + virtual void SetGameData( void *gameData ) = 0; + + // get a pointer to the game object + virtual void *GetGameData( void ) const = 0; + + // Get the parent/referenced object + virtual IPhysicsObject *GetReferenceObject( void ) const = 0; + + // Get the attached object + virtual IPhysicsObject *GetAttachedObject( void ) const = 0; + + virtual void SetLinearMotor( float speed, float maxLinearImpulse ) = 0; + virtual void SetAngularMotor( float rotSpeed, float maxAngularImpulse ) = 0; + + virtual void UpdateRagdollTransforms( const matrix3x4_t &constraintToReference, const matrix3x4_t &constraintToAttached ) = 0; + virtual bool GetConstraintTransform( matrix3x4_t *pConstraintToReference, matrix3x4_t *pConstraintToAttached ) const = 0; + virtual bool GetConstraintParams( constraint_breakableparams_t *pParams ) const = 0; + + virtual void OutputDebugInfo() = 0; +}; + + +class IPhysicsConstraintGroup +{ +public: + virtual ~IPhysicsConstraintGroup( void ) {} + virtual void Activate() = 0; + virtual bool IsInErrorState() = 0; + virtual void ClearErrorState() = 0; + virtual void GetErrorParams( constraint_groupparams_t *pParams ) = 0; + virtual void SetErrorParams( const constraint_groupparams_t ¶ms ) = 0; + virtual void SolvePenetration( IPhysicsObject *pObj0, IPhysicsObject *pObj1 ) = 0; +}; + + +#endif // CONSTRAINTS_H diff --git a/sp/src/public/vphysics/friction.h b/sp/src/public/vphysics/friction.h new file mode 100644 index 00000000..f8d6bd63 --- /dev/null +++ b/sp/src/public/vphysics/friction.h @@ -0,0 +1,51 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef FRICTION_H +#define FRICTION_H +#ifdef _WIN32 +#pragma once +#endif + +// NOTE: This is an iterator for the contact points on an object +// NOTE: This should only be used temporarily. Holding one of these +// NOTE: across collision callbacks or calls into simulation will cause errors! +// NOTE: VPHYSICS may choose to make the data contained within this object invalid +// NOTE: any time simulation is run. +class IPhysicsFrictionSnapshot +{ +public: + virtual ~IPhysicsFrictionSnapshot() {} + + virtual bool IsValid() = 0; + + // Object 0 is this object, Object 1 is the other object + virtual IPhysicsObject *GetObject( int index ) = 0; + virtual int GetMaterial( int index ) = 0; + + virtual void GetContactPoint( Vector &out ) = 0; + + // points away from source object + virtual void GetSurfaceNormal( Vector &out ) = 0; + virtual float GetNormalForce() = 0; + virtual float GetEnergyAbsorbed() = 0; + + // recompute friction (useful if dynamically altering materials/mass) + virtual void RecomputeFriction() = 0; + // clear all friction force at this contact point + virtual void ClearFrictionForce() = 0; + + virtual void MarkContactForDelete() = 0; + virtual void DeleteAllMarkedContacts( bool wakeObjects ) = 0; + + // Move to the next friction data for this object + virtual void NextFrictionData() = 0; + virtual float GetFrictionCoefficient() = 0; +}; + + + +#endif // FRICTION_H diff --git a/sp/src/public/vphysics/object_hash.h b/sp/src/public/vphysics/object_hash.h new file mode 100644 index 00000000..bfdef84c --- /dev/null +++ b/sp/src/public/vphysics/object_hash.h @@ -0,0 +1,29 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef OBJECT_HASH_H +#define OBJECT_HASH_H +#ifdef _WIN32 +#pragma once +#endif + +class IPhysicsObjectPairHash +{ +public: + virtual ~IPhysicsObjectPairHash() {} + virtual void AddObjectPair( void *pObject0, void *pObject1 ) = 0; + virtual void RemoveObjectPair( void *pObject0, void *pObject1 ) = 0; + virtual bool IsObjectPairInHash( void *pObject0, void *pObject1 ) = 0; + virtual void RemoveAllPairsForObject( void *pObject0 ) = 0; + virtual bool IsObjectInHash( void *pObject0 ) = 0; + + // Used to iterate over all pairs an object is part of + virtual int GetPairCountForObject( void *pObject0 ) = 0; + virtual int GetPairListForObject( void *pObject0, int nMaxCount, void **ppObjectList ) = 0; +}; + + +#endif // OBJECT_HASH_H diff --git a/sp/src/public/vphysics/performance.h b/sp/src/public/vphysics/performance.h new file mode 100644 index 00000000..fa1cf47e --- /dev/null +++ b/sp/src/public/vphysics/performance.h @@ -0,0 +1,44 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef PERFORMANCE_H +#define PERFORMANCE_H +#ifdef _WIN32 +#pragma once +#endif + +// Don't ever change these values, or face all kinds of subtle gameplay changes +const float k_flMaxVelocity = 2000.0f; +const float k_flMaxAngularVelocity = 360.0f * 10.0f; + +const float DEFAULT_MIN_FRICTION_MASS = 10.0f; +const float DEFAULT_MAX_FRICTION_MASS = 2500.0f; +struct physics_performanceparams_t +{ + int maxCollisionsPerObjectPerTimestep; // object will be frozen after this many collisions (visual hitching vs. CPU cost) + int maxCollisionChecksPerTimestep; // objects may penetrate after this many collision checks (can be extended in AdditionalCollisionChecksThisTick) + float maxVelocity; // limit world space linear velocity to this (in / s) + float maxAngularVelocity; // limit world space angular velocity to this (degrees / s) + float lookAheadTimeObjectsVsWorld; // predict collisions this far (seconds) into the future + float lookAheadTimeObjectsVsObject; // predict collisions this far (seconds) into the future + float minFrictionMass; // min mass for friction solves (constrains dynamic range of mass to improve stability) + float maxFrictionMass; // mas mass for friction solves + + void Defaults() + { + maxCollisionsPerObjectPerTimestep = 6; + maxCollisionChecksPerTimestep = 250; + maxVelocity = k_flMaxVelocity; + maxAngularVelocity = k_flMaxAngularVelocity; + lookAheadTimeObjectsVsWorld = 1.0f; + lookAheadTimeObjectsVsObject = 0.5f; + minFrictionMass = DEFAULT_MIN_FRICTION_MASS; + maxFrictionMass = DEFAULT_MAX_FRICTION_MASS; + } +}; + + +#endif // PERFORMANCE_H diff --git a/sp/src/public/vphysics/player_controller.h b/sp/src/public/vphysics/player_controller.h new file mode 100644 index 00000000..6fbe1b07 --- /dev/null +++ b/sp/src/public/vphysics/player_controller.h @@ -0,0 +1,47 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef PLAYER_CONTROLLER_H +#define PLAYER_CONTROLLER_H +#ifdef _WIN32 +#pragma once +#endif + +class IPhysicsPlayerControllerEvent +{ +public: + virtual int ShouldMoveTo( IPhysicsObject *pObject, const Vector &position ) = 0; +}; + +class IPhysicsPlayerController +{ +public: + virtual ~IPhysicsPlayerController( void ) {} + + virtual void Update( const Vector &position, const Vector &velocity, float secondsToArrival, bool onground, IPhysicsObject *ground ) = 0; + virtual void SetEventHandler( IPhysicsPlayerControllerEvent *handler ) = 0; + virtual bool IsInContact( void ) = 0; + virtual void MaxSpeed( const Vector &maxVelocity ) = 0; + + // allows game code to change collision models + virtual void SetObject( IPhysicsObject *pObject ) = 0; + // UNDONE: Refactor this and shadow controllers into a single class/interface through IPhysicsObject + virtual int GetShadowPosition( Vector *position, QAngle *angles ) = 0; + virtual void StepUp( float height ) = 0; + virtual void Jump() = 0; + virtual void GetShadowVelocity( Vector *velocity ) = 0; + virtual IPhysicsObject *GetObject() = 0; + virtual void GetLastImpulse( Vector *pOut ) = 0; + + virtual void SetPushMassLimit( float maxPushMass ) = 0; + virtual void SetPushSpeedLimit( float maxPushSpeed ) = 0; + + virtual float GetPushMassLimit() = 0; + virtual float GetPushSpeedLimit() = 0; + virtual bool WasFrozen() = 0; +}; + +#endif // PLAYER_CONTROLLER_H diff --git a/sp/src/public/vphysics/stats.h b/sp/src/public/vphysics/stats.h new file mode 100644 index 00000000..21d81199 --- /dev/null +++ b/sp/src/public/vphysics/stats.h @@ -0,0 +1,40 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#ifndef STATS_H +#define STATS_H +#ifdef _WIN32 +#pragma once +#endif + +// internal counters to measure cost of physics simulation +struct physics_stats_t +{ + float maxRescueSpeed; + float maxSpeedGain; + + int impactSysNum; + int impactCounter; + int impactSumSys; + int impactHardRescueCount; + int impactRescueAfterCount; + int impactDelayedCount; + int impactCollisionChecks; + int impactStaticCount; + + double totalEnergyDestroyed; + int collisionPairsTotal; + int collisionPairsCreated; + int collisionPairsDestroyed; + + int potentialCollisionsObjectVsObject; + int potentialCollisionsObjectVsWorld; + + int frictionEventsProcessed; +}; + + +#endif // STATS_H diff --git a/sp/src/public/vphysics/vehicles.h b/sp/src/public/vphysics/vehicles.h new file mode 100644 index 00000000..0125aa93 --- /dev/null +++ b/sp/src/public/vphysics/vehicles.h @@ -0,0 +1,250 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef VEHICLES_H +#define VEHICLES_H +#ifdef _WIN32 +#pragma once +#endif + +#include "datamap.h" + + +#define VEHICLE_TYPE_CAR_WHEELS (1<<0) +#define VEHICLE_TYPE_CAR_RAYCAST (1<<1) +#define VEHICLE_TYPE_JETSKI_RAYCAST (1<<2) +#define VEHICLE_TYPE_AIRBOAT_RAYCAST (1<<3) + +#define VEHICLE_MAX_AXLE_COUNT 4 +#define VEHICLE_MAX_GEAR_COUNT 6 +#define VEHICLE_MAX_WHEEL_COUNT (2*VEHICLE_MAX_AXLE_COUNT) + +#define VEHICLE_TIRE_NORMAL 0 +#define VEHICLE_TIRE_BRAKING 1 +#define VEHICLE_TIRE_POWERSLIDE 2 + +struct vehicle_controlparams_t +{ + float throttle; + float steering; + float brake; + float boost; + bool handbrake; + bool handbrakeLeft; + bool handbrakeRight; + bool brakepedal; + bool bHasBrakePedal; + bool bAnalogSteering; +}; + +struct vehicle_operatingparams_t +{ + DECLARE_SIMPLE_DATADESC(); + + float speed; + float engineRPM; + int gear; + float boostDelay; + int boostTimeLeft; + float skidSpeed; + int skidMaterial; + float steeringAngle; + int wheelsNotInContact; + int wheelsInContact; + bool isTorqueBoosting; +}; + +// Debug! +#define VEHICLE_DEBUGRENDERDATA_MAX_WHEELS 10 +#define VEHICLE_DEBUGRENDERDATA_MAX_AXLES 3 + +struct vehicle_debugcarsystem_t +{ + Vector vecAxlePos[VEHICLE_DEBUGRENDERDATA_MAX_AXLES]; + + Vector vecWheelPos[VEHICLE_DEBUGRENDERDATA_MAX_WHEELS]; + Vector vecWheelRaycasts[VEHICLE_DEBUGRENDERDATA_MAX_WHEELS][2]; + Vector vecWheelRaycastImpacts[VEHICLE_DEBUGRENDERDATA_MAX_WHEELS]; +}; + +struct vehicleparams_t; + +class IPhysicsVehicleController +{ +public: + virtual ~IPhysicsVehicleController() {} + // call this from the game code with the control parameters + virtual void Update( float dt, vehicle_controlparams_t &controls ) = 0; + virtual const vehicle_operatingparams_t &GetOperatingParams() = 0; + virtual const vehicleparams_t &GetVehicleParams() = 0; + virtual vehicleparams_t &GetVehicleParamsForChange() = 0; + virtual float UpdateBooster(float dt) = 0; + virtual int GetWheelCount(void) = 0; + virtual IPhysicsObject *GetWheel(int index) = 0; + virtual bool GetWheelContactPoint( int index, Vector *pContactPoint, int *pSurfaceProps ) = 0; + virtual void SetSpringLength(int wheelIndex, float length) = 0; + virtual void SetWheelFriction(int wheelIndex, float friction) = 0; + + virtual void OnVehicleEnter( void ) = 0; + virtual void OnVehicleExit( void ) = 0; + + virtual void SetEngineDisabled( bool bDisable ) = 0; + virtual bool IsEngineDisabled( void ) = 0; + + // Debug + virtual void GetCarSystemDebugData( vehicle_debugcarsystem_t &debugCarSystem ) = 0; + virtual void VehicleDataReload() = 0; +}; + + +// parameters for the body object control of the vehicle +struct vehicle_bodyparams_t +{ + DECLARE_SIMPLE_DATADESC(); + + Vector massCenterOverride; // leave at vec3_origin for no override + float massOverride; // leave at 0 for no override + float addGravity; // keeps car down + float tiltForce; // keeps car down when not on flat ground + float tiltForceHeight; // where the tilt force pulls relative to center of mass + float counterTorqueFactor; + float keepUprightTorque; + float maxAngularVelocity; // clamp the car angular velocity separately from other objects to keep stable +}; + +// wheel objects are created by vphysics, these are the parameters for those objects +// NOTE: They are paired, so only one set of parameters is necessary per axle +struct vehicle_wheelparams_t +{ + DECLARE_SIMPLE_DATADESC(); + + float radius; + float mass; + float inertia; + float damping; // usually 0 + float rotdamping; // usually 0 + float frictionScale; // 1.5 front, 1.8 rear + int materialIndex; + int brakeMaterialIndex; + int skidMaterialIndex; + float springAdditionalLength; // 0 means the spring is at it's rest length +}; + +struct vehicle_suspensionparams_t +{ + DECLARE_SIMPLE_DATADESC(); + + float springConstant; + float springDamping; + float stabilizerConstant; + float springDampingCompression; + float maxBodyForce; +}; + +// NOTE: both raytrace and wheel data here because jetski uses both. +struct vehicle_axleparams_t +{ + DECLARE_SIMPLE_DATADESC(); + + Vector offset; // center of this axle in vehicle object space + Vector wheelOffset; // offset to wheel (assume other wheel is symmetric at -wheelOffset) from axle center + Vector raytraceCenterOffset; // offset to center of axle for the raytrace data. + Vector raytraceOffset; // offset to raytrace for non-wheel (some wheeled) vehicles + vehicle_wheelparams_t wheels; + vehicle_suspensionparams_t suspension; + float torqueFactor; // normalized to 1 across all axles + // e.g. 0,1 for rear wheel drive - 0.5,0.5 for 4 wheel drive + float brakeFactor; // normalized to 1 across all axles +}; + +struct vehicle_steeringparams_t +{ + DECLARE_SIMPLE_DATADESC(); + + float degreesSlow; // angle in degrees of steering at slow speed + float degreesFast; // angle in degrees of steering at fast speed + float degreesBoost; // angle in degrees of steering at fast speed + float steeringRateSlow; // this is the speed the wheels are steered when the vehicle is slow + float steeringRateFast; // this is the speed the wheels are steered when the vehicle is "fast" + float steeringRestRateSlow; // this is the speed at which the wheels move toward their resting state (straight ahead) at slow speed + float steeringRestRateFast; // this is the speed at which the wheels move toward their resting state (straight ahead) at fast speed + float speedSlow; // this is the max speed of "slow" + float speedFast; // this is the min speed of "fast" + float turnThrottleReduceSlow; // this is the amount of throttle reduction to apply at the maximum steering angle + float turnThrottleReduceFast; // this is the amount of throttle reduction to apply at the maximum steering angle + float brakeSteeringRateFactor; // this scales the steering rate when the brake/handbrake is down + float throttleSteeringRestRateFactor; // this scales the steering rest rate when the throttle is down + float powerSlideAccel; // scale of speed to acceleration + float boostSteeringRestRateFactor; // this scales the steering rest rate when boosting + float boostSteeringRateFactor; // this scales the steering rest rate when boosting + float steeringExponent; // this makes the steering response non-linear. The steering function is linear, then raised to this power + + bool isSkidAllowed; // true/false skid flag + bool dustCloud; // flag for creating a dustcloud behind vehicle +}; + +struct vehicle_engineparams_t +{ + DECLARE_SIMPLE_DATADESC(); + + float horsepower; + float maxSpeed; + float maxRevSpeed; + float maxRPM; // redline RPM limit + float axleRatio; // ratio of engine rev to axle rev + float throttleTime; // time to reach full throttle in seconds + + // transmission + int gearCount; // gear count - max 10 + float gearRatio[VEHICLE_MAX_GEAR_COUNT]; // ratio for each gear + + // automatic transmission (simple auto-shifter - switches at fixed RPM limits) + float shiftUpRPM; // max RPMs to switch to a higher gear + float shiftDownRPM; // min RPMs to switch to a lower gear + float boostForce; + float boostDuration; + float boostDelay; + float boostMaxSpeed; + float autobrakeSpeedGain; + float autobrakeSpeedFactor; + bool torqueBoost; + bool isAutoTransmission; // true for auto, false for manual +}; + +struct vehicleparams_t +{ + DECLARE_SIMPLE_DATADESC(); + + int axleCount; + int wheelsPerAxle; + vehicle_bodyparams_t body; + vehicle_axleparams_t axles[VEHICLE_MAX_AXLE_COUNT]; + vehicle_engineparams_t engine; + vehicle_steeringparams_t steering; +}; + +// Iterator for queries +class CPassengerSeatTransition; +typedef CUtlVector< CPassengerSeatTransition> PassengerSeatAnims_t; + +// Seat query types +enum VehicleSeatQuery_e +{ + VEHICLE_SEAT_ANY, // Any available seat for our role + VEHICLE_SEAT_NEAREST, // Seat closest to our starting point +}; + +// Seat anim types for return +enum PassengerSeatAnimType_t +{ + PASSENGER_SEAT_ENTRY, + PASSENGER_SEAT_EXIT +}; + +#define VEHICLE_SEAT_INVALID -1 // An invalid seat + +#endif // VEHICLES_H diff --git a/sp/src/public/vphysics/virtualmesh.h b/sp/src/public/vphysics/virtualmesh.h new file mode 100644 index 00000000..41da4ea6 --- /dev/null +++ b/sp/src/public/vphysics/virtualmesh.h @@ -0,0 +1,46 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#ifndef VIRTUALMESH_H +#define VIRTUALMESH_H +#ifdef _WIN32 +#pragma once +#endif + +// NOTE: These are fixed length to make it easy to fill these out without memory allocation or storage +const int MAX_VIRTUAL_TRIANGLES = 1024; +struct virtualmeshlist_t +{ + Vector *pVerts; + int indexCount; + int triangleCount; + int vertexCount; + int surfacePropsIndex; + byte *pHull; + unsigned short indices[MAX_VIRTUAL_TRIANGLES*3]; +}; + +struct virtualmeshtrianglelist_t +{ + int triangleCount; + unsigned short triangleIndices[MAX_VIRTUAL_TRIANGLES*3]; +}; + +class IVirtualMeshEvent +{ +public: + virtual void GetVirtualMesh( void *userData, virtualmeshlist_t *pList ) = 0; + virtual void GetWorldspaceBounds( void *userData, Vector *pMins, Vector *pMaxs ) = 0; + virtual void GetTrianglesInSphere( void *userData, const Vector ¢er, float radius, virtualmeshtrianglelist_t *pList ) = 0; +}; +struct virtualmeshparams_t +{ + IVirtualMeshEvent *pMeshEventHandler; + void *userData; + bool buildOuterHull; +}; + +#endif // VIRTUALMESH_H diff --git a/sp/src/public/vscript/ivscript.h b/sp/src/public/vscript/ivscript.h new file mode 100644 index 00000000..4b3388df --- /dev/null +++ b/sp/src/public/vscript/ivscript.h @@ -0,0 +1,1750 @@ +//========== Copyright © 2008, Valve Corporation, All rights reserved. ======== +// +// Purpose: VScript +// +// Overview +// -------- +// VScript is an abstract binding layer that allows code to expose itself to +// multiple scripting languages in a uniform format. Code can expose +// functions, classes, and data to the scripting languages, and can also +// call functions that reside in scripts. +// +// Initializing +// ------------ +// +// To create a script virtual machine (VM), grab the global instance of +// IScriptManager, call CreateVM, then call Init on the returned VM. Right +// now you can have multiple VMs, but only VMs for a specific language. +// +// Exposing functions and classes +// ------------------------------ +// +// To expose a C++ function to the scripting system, you just need to fill out a +// description block. Using templates, the system will automatically deduce +// all of the binding requirements (parameters and return values). Functions +// are limited as to what the types of the parameters can be. See ScriptVariant_t. +// +// extern IScriptVM *pScriptVM; +// bool Foo( int ); +// void Bar(); +// float FooBar( int, const char * ); +// float OverlyTechnicalName( bool ); +// +// void RegisterFuncs() +// { +// ScriptRegisterFunction( pScriptVM, Foo ); +// ScriptRegisterFunction( pScriptVM, Bar ); +// ScriptRegisterFunction( pScriptVM, FooBar ); +// ScriptRegisterFunctionNamed( pScriptVM, OverlyTechnicalName, "SimpleName" ); +// } +// +// class CMyClass +// { +// public: +// bool Foo( int ); +// void Bar(); +// float FooBar( int, const char * ); +// float OverlyTechnicalName( bool ); +// }; +// +// BEGIN_SCRIPTDESC_ROOT( CMyClass ) +// DEFINE_SCRIPTFUNC( Foo ) +// DEFINE_SCRIPTFUNC( Bar ) +// DEFINE_SCRIPTFUNC( FooBar ) +// DEFINE_SCRIPTFUNC_NAMED( OverlyTechnicalName, "SimpleMemberName" ) +// END_SCRIPTDESC(); +// +// class CMyDerivedClass : public CMyClass +// { +// public: +// float DerivedFunc() const; +// }; +// +// BEGIN_SCRIPTDESC( CMyDerivedClass, CMyClass ) +// DEFINE_SCRIPTFUNC( DerivedFunc ) +// END_SCRIPTDESC(); +// +// CMyDerivedClass derivedInstance; +// +// void AnotherFunction() +// { +// // Manual class exposure +// pScriptVM->RegisterClass( GetScriptDescForClass( CMyClass ) ); +// +// // Auto registration by instance +// pScriptVM->RegisterInstance( &derivedInstance, "theInstance" ); +// } +// +// Classes with "DEFINE_SCRIPT_CONSTRUCTOR()" in their description can be instanced within scripts +// +// Scopes +// ------ +// Scripts can either be run at the global scope, or in a user defined scope. In the latter case, +// all "globals" within the script are actually in the scope. This can be used to bind private +// data spaces with C++ objects. +// +// Calling a function on a script +// ------------------------------ +// Generally, use the "Call" functions. This example is the equivalent of DoIt("Har", 6.0, 99). +// +// hFunction = pScriptVM->LookupFunction( "DoIt", hScope ); +// pScriptVM->Call( hFunction, hScope, true, NULL, "Har", 6.0, 99 ); +// +//============================================================================= + +#ifndef IVSCRIPT_H +#define IVSCRIPT_H + +#include "platform.h" +#include "datamap.h" +#include "appframework/IAppSystem.h" +#include "tier1/functors.h" +#include "tier0/memdbgon.h" + +#if defined( _WIN32 ) +#pragma once +#endif + +#ifdef VSCRIPT_DLL_EXPORT +#define VSCRIPT_INTERFACE DLL_EXPORT +#define VSCRIPT_OVERLOAD DLL_GLOBAL_EXPORT +#define VSCRIPT_CLASS DLL_CLASS_EXPORT +#else +#define VSCRIPT_INTERFACE DLL_IMPORT +#define VSCRIPT_OVERLOAD DLL_GLOBAL_IMPORT +#define VSCRIPT_CLASS DLL_CLASS_IMPORT +#endif + +class CUtlBuffer; + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define VSCRIPT_INTERFACE_VERSION "VScriptManager009" + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +class IScriptVM; +#ifdef MAPBASE_VSCRIPT +class KeyValues; + +// This has been moved up a bit for IScriptManager +DECLARE_POINTER_HANDLE( HSCRIPT ); +#define INVALID_HSCRIPT ((HSCRIPT)-1) +#endif + +enum ScriptLanguage_t +{ + SL_NONE, + SL_GAMEMONKEY, + SL_SQUIRREL, + SL_LUA, + SL_PYTHON, + + SL_DEFAULT = SL_SQUIRREL +}; + +class IScriptManager : public IAppSystem +{ +public: + virtual IScriptVM *CreateVM( ScriptLanguage_t language = SL_DEFAULT ) = 0; + virtual void DestroyVM( IScriptVM * ) = 0; + +#ifdef MAPBASE_VSCRIPT + virtual HSCRIPT CreateScriptKeyValues( IScriptVM *pVM, KeyValues *pKV, bool bAllowDestruct ) = 0; + virtual KeyValues *GetKeyValuesFromScriptKV( IScriptVM *pVM, HSCRIPT hSKV ) = 0; +#endif +}; + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#ifdef MAPBASE_VSCRIPT +template T *HScriptToClass( HSCRIPT hObj ) +{ + return (hObj) ? (T*)g_pScriptVM->GetInstanceValue( hObj, GetScriptDesc( (T*)NULL ) ) : NULL; +} +#else +DECLARE_POINTER_HANDLE( HSCRIPT ); +#define INVALID_HSCRIPT ((HSCRIPT)-1) +#endif + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +enum ExtendedFieldType +{ + FIELD_TYPEUNKNOWN = FIELD_TYPECOUNT, + FIELD_CSTRING, + FIELD_HSCRIPT, + FIELD_VARIANT, +}; + +typedef int ScriptDataType_t; +struct ScriptVariant_t; + +template struct ScriptDeducer { /*enum { FIELD_TYPE = FIELD_TYPEUNKNOWN };*/ }; +#define DECLARE_DEDUCE_FIELDTYPE( fieldType, type ) template<> struct ScriptDeducer { enum { FIELD_TYPE = fieldType }; }; + +DECLARE_DEDUCE_FIELDTYPE( FIELD_VOID, void ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_FLOAT, float ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_CSTRING, const char * ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_CSTRING, char * ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, Vector ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, const Vector &); +DECLARE_DEDUCE_FIELDTYPE( FIELD_INTEGER, int ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_BOOLEAN, bool ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_CHARACTER, char ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_HSCRIPT, HSCRIPT ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_VARIANT, ScriptVariant_t ); +#ifdef MAPBASE_VSCRIPT +DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, QAngle ); +DECLARE_DEDUCE_FIELDTYPE( FIELD_VECTOR, const QAngle& ); +#endif + +#define ScriptDeduceType( T ) ScriptDeducer::FIELD_TYPE + +template +inline const char * ScriptFieldTypeName() +{ + return T::using_unknown_script_type(); +} + +#define DECLARE_NAMED_FIELDTYPE( fieldType, strName ) template <> inline const char * ScriptFieldTypeName() { return strName; } +DECLARE_NAMED_FIELDTYPE( void, "void" ); +DECLARE_NAMED_FIELDTYPE( float, "float" ); +DECLARE_NAMED_FIELDTYPE( const char *, "cstring" ); +DECLARE_NAMED_FIELDTYPE( char *, "cstring" ); +DECLARE_NAMED_FIELDTYPE( Vector, "vector" ); +DECLARE_NAMED_FIELDTYPE( const Vector&, "vector" ); +DECLARE_NAMED_FIELDTYPE( int, "integer" ); +DECLARE_NAMED_FIELDTYPE( bool, "boolean" ); +DECLARE_NAMED_FIELDTYPE( char, "character" ); +DECLARE_NAMED_FIELDTYPE( HSCRIPT, "hscript" ); +DECLARE_NAMED_FIELDTYPE( ScriptVariant_t, "variant" ); +#ifdef MAPBASE_VSCRIPT +DECLARE_NAMED_FIELDTYPE( QAngle, "vector" ); +DECLARE_NAMED_FIELDTYPE( const QAngle&, "vector" ); +#endif + +inline const char * ScriptFieldTypeName( int16 eType) +{ + switch( eType ) + { + case FIELD_VOID: return "void"; + case FIELD_FLOAT: return "float"; + case FIELD_CSTRING: return "cstring"; + case FIELD_VECTOR: return "vector"; + case FIELD_INTEGER: return "integer"; + case FIELD_BOOLEAN: return "boolean"; + case FIELD_CHARACTER: return "character"; + case FIELD_HSCRIPT: return "hscript"; + case FIELD_VARIANT: return "variant"; + default: return "unknown_script_type"; + } +} + +//--------------------------------------------------------- + +struct ScriptFuncDescriptor_t +{ + ScriptFuncDescriptor_t() + { + m_pszFunction = NULL; + m_ReturnType = FIELD_TYPEUNKNOWN; + m_pszDescription = NULL; + } + + const char *m_pszScriptName; + const char *m_pszFunction; + const char *m_pszDescription; + ScriptDataType_t m_ReturnType; + CUtlVector m_Parameters; +}; + +#ifdef MAPBASE_VSCRIPT +//--------------------------------------------------------- +// VScript Member Variables +// +// An odd concept. Because IScriptInstanceHelper now supports +// get/set metamethods, classes are capable of pretending they +// have member variables which VScript can get and set. +// +// There's no default way of documenting these variables, so even though +// these are not actually binding anything, this is here to allow VScript +// to describe these fake member variables in its documentation. +//--------------------------------------------------------- +struct ScriptMemberDesc_t +{ + const char *m_pszScriptName; + const char *m_pszDescription; + ScriptDataType_t m_ReturnType; +}; +#endif + + +//--------------------------------------------------------- + +// Prefix a script description with this in order to not show the function or class in help +#define SCRIPT_HIDE "@" + +// Prefix a script description of a class to indicate it is a singleton and the single instance should be in the help +#define SCRIPT_SINGLETON "!" + +// Prefix a script description with this to indicate it should be represented using an alternate name +#define SCRIPT_ALIAS( alias, description ) "#" alias ":" description + +//--------------------------------------------------------- + +enum ScriptFuncBindingFlags_t +{ + SF_MEMBER_FUNC = 0x01, +}; + +typedef bool (*ScriptBindingFunc_t)( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ); + +struct ScriptFunctionBinding_t +{ + ScriptFuncDescriptor_t m_desc; + ScriptBindingFunc_t m_pfnBinding; + void * m_pFunction; + unsigned m_flags; +}; + +//--------------------------------------------------------- +class IScriptInstanceHelper +{ +public: + virtual void *GetProxied( void *p ) { return p; } + virtual bool ToString( void *p, char *pBuf, int bufSize ) { return false; } + virtual void *BindOnRead( HSCRIPT hInstance, void *pOld, const char *pszId ) { return NULL; } + +#ifdef MAPBASE_VSCRIPT + virtual bool Get( void *p, const char *pszKey, ScriptVariant_t &variant ) { return false; } + virtual bool Set( void *p, const char *pszKey, ScriptVariant_t &variant ) { return false; } + + virtual ScriptVariant_t *Add( void *p, ScriptVariant_t &variant ) { return NULL; } + virtual ScriptVariant_t *Subtract( void *p, ScriptVariant_t &variant ) { return NULL; } + virtual ScriptVariant_t *Multiply( void *p, ScriptVariant_t &variant ) { return NULL; } + virtual ScriptVariant_t *Divide( void *p, ScriptVariant_t &variant ) { return NULL; } +#endif +}; + +//--------------------------------------------------------- + +#ifdef MAPBASE_VSCRIPT +struct ScriptHook_t; +#endif + +struct ScriptClassDesc_t +{ + ScriptClassDesc_t() : m_pszScriptName( 0 ), m_pszClassname( 0 ), m_pszDescription( 0 ), m_pBaseDesc( 0 ), m_pfnConstruct( 0 ), m_pfnDestruct( 0 ), pHelper(NULL) + { +#ifdef MAPBASE_VSCRIPT + AllClassesDesc().AddToTail(this); +#endif + } + + const char * m_pszScriptName; + const char * m_pszClassname; + const char * m_pszDescription; + ScriptClassDesc_t * m_pBaseDesc; + CUtlVector m_FunctionBindings; + +#ifdef MAPBASE_VSCRIPT + CUtlVector m_Hooks; + CUtlVector m_Members; +#endif + + void *(*m_pfnConstruct)(); + void (*m_pfnDestruct)( void *); + IScriptInstanceHelper * pHelper; // optional helper + +#ifdef MAPBASE_VSCRIPT + static CUtlVector& AllClassesDesc() + { + static CUtlVector classes; + return classes; + } +#endif +}; + +//--------------------------------------------------------- +// A simple variant type. Intentionally not full featured (no implicit conversion, no memory management) +//--------------------------------------------------------- + +enum SVFlags_t +{ + SV_FREE = 0x01, +}; + +#pragma warning(push) +#pragma warning(disable:4800) +struct ScriptVariant_t +{ + ScriptVariant_t() : m_flags( 0 ), m_type( FIELD_VOID ) { m_pVector = 0; } + ScriptVariant_t( int val ) : m_flags( 0 ), m_type( FIELD_INTEGER ) { m_int = val;} + ScriptVariant_t( float val ) : m_flags( 0 ), m_type( FIELD_FLOAT ) { m_float = val; } + ScriptVariant_t( double val ) : m_flags( 0 ), m_type( FIELD_FLOAT ) { m_float = (float)val; } + ScriptVariant_t( char val ) : m_flags( 0 ), m_type( FIELD_CHARACTER ) { m_char = val; } + ScriptVariant_t( bool val ) : m_flags( 0 ), m_type( FIELD_BOOLEAN ) { m_bool = val; } + ScriptVariant_t( HSCRIPT val ) : m_flags( 0 ), m_type( FIELD_HSCRIPT ) { m_hScript = val; } + + ScriptVariant_t( const Vector &val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pVector = &val; } else { m_pVector = new Vector( val ); m_flags |= SV_FREE; } } + ScriptVariant_t( const Vector *val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pVector = val; } else { m_pVector = new Vector( *val ); m_flags |= SV_FREE; } } + ScriptVariant_t( const char *val , bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_CSTRING ) { if ( !bCopy ) { m_pszString = val; } else { m_pszString = strdup( val ); m_flags |= SV_FREE; } } + +#ifdef MAPBASE_VSCRIPT + ScriptVariant_t( const QAngle &val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pAngle = &val; } else { m_pAngle = new QAngle( val ); m_flags |= SV_FREE; } } + ScriptVariant_t( const QAngle *val, bool bCopy = false ) : m_flags( 0 ), m_type( FIELD_VECTOR ) { if ( !bCopy ) { m_pAngle = val; } else { m_pAngle = new QAngle( *val ); m_flags |= SV_FREE; } } +#endif + + bool IsNull() const { return (m_type == FIELD_VOID ); } + + operator int() const { Assert( m_type == FIELD_INTEGER ); return m_int; } + operator float() const { Assert( m_type == FIELD_FLOAT ); return m_float; } + operator const char *() const { Assert( m_type == FIELD_CSTRING ); return ( m_pszString ) ? m_pszString : ""; } + operator const Vector &() const { Assert( m_type == FIELD_VECTOR ); static Vector vecNull(0, 0, 0); return (m_pVector) ? *m_pVector : vecNull; } + operator char() const { Assert( m_type == FIELD_CHARACTER ); return m_char; } + operator bool() const { Assert( m_type == FIELD_BOOLEAN ); return m_bool; } + operator HSCRIPT() const { Assert( m_type == FIELD_HSCRIPT ); return m_hScript; } +#ifdef MAPBASE_VSCRIPT + operator const QAngle &() const { Assert( m_type == FIELD_VECTOR ); static QAngle vecNull(0, 0, 0); return (m_pAngle) ? *m_pAngle : vecNull; } +#endif + + void operator=( int i ) { m_type = FIELD_INTEGER; m_int = i; } + void operator=( float f ) { m_type = FIELD_FLOAT; m_float = f; } + void operator=( double f ) { m_type = FIELD_FLOAT; m_float = (float)f; } + void operator=( const Vector &vec ) { m_type = FIELD_VECTOR; m_pVector = &vec; } + void operator=( const Vector *vec ) { m_type = FIELD_VECTOR; m_pVector = vec; } + void operator=( const char *psz ) { m_type = FIELD_CSTRING; m_pszString = psz; } + void operator=( char c ) { m_type = FIELD_CHARACTER; m_char = c; } + void operator=( bool b ) { m_type = FIELD_BOOLEAN; m_bool = b; } + void operator=( HSCRIPT h ) { m_type = FIELD_HSCRIPT; m_hScript = h; } +#ifdef MAPBASE_VSCRIPT + void operator=( const QAngle &vec ) { m_type = FIELD_VECTOR; m_pAngle = &vec; } + void operator=( const QAngle *vec ) { m_type = FIELD_VECTOR; m_pAngle = vec; } +#endif + + void Free() { if ( ( m_flags & SV_FREE ) && ( m_type == FIELD_HSCRIPT || m_type == FIELD_VECTOR || m_type == FIELD_CSTRING ) ) delete m_pszString; } // Generally only needed for return results + + template + T Get() + { + T value; + AssignTo( &value ); + return value; + } + + template + bool AssignTo( T *pDest ) + { + ScriptDataType_t destType = ScriptDeduceType( T ); + if ( destType == FIELD_TYPEUNKNOWN ) + { + DevWarning( "Unable to convert script variant to unknown type\n" ); + } + if ( destType == m_type ) + { + *pDest = *this; + return true; + } + + if ( m_type != FIELD_VECTOR && m_type != FIELD_CSTRING && destType != FIELD_VECTOR && destType != FIELD_CSTRING ) + { + switch ( m_type ) + { + case FIELD_VOID: *pDest = 0; break; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_CHARACTER: *pDest = m_char; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + case FIELD_HSCRIPT: *pDest = m_hScript; return true; + } + } + else + { + DevWarning( "No free conversion of %s script variant to %s right now\n", + ScriptFieldTypeName( m_type ), ScriptFieldTypeName() ); + if ( destType != FIELD_VECTOR ) + { + *pDest = 0; + } + } + return false; + } + + bool AssignTo( float *pDest ) + { + switch( m_type ) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + default: + DevWarning( "No conversion from %s to float now\n", ScriptFieldTypeName( m_type ) ); + return false; + } + } + + bool AssignTo( int *pDest ) + { + switch( m_type ) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + default: + DevWarning( "No conversion from %s to int now\n", ScriptFieldTypeName( m_type ) ); + return false; + } + } + + bool AssignTo( bool *pDest ) + { + switch( m_type ) + { + case FIELD_VOID: *pDest = 0; return false; + case FIELD_INTEGER: *pDest = m_int; return true; + case FIELD_FLOAT: *pDest = m_float; return true; + case FIELD_BOOLEAN: *pDest = m_bool; return true; + default: + DevWarning( "No conversion from %s to bool now\n", ScriptFieldTypeName( m_type ) ); + return false; + } + } + + bool AssignTo( char **pDest ) + { + DevWarning( "No free conversion of string or vector script variant right now\n" ); + // If want to support this, probably need to malloc string and require free on other side [3/24/2008 tom] + *pDest = ""; + return false; + } + + bool AssignTo( ScriptVariant_t *pDest ) + { + pDest->m_type = m_type; + if ( m_type == FIELD_VECTOR ) + { + pDest->m_pVector = new Vector; + ((Vector *)(pDest->m_pVector))->Init( m_pVector->x, m_pVector->y, m_pVector->z ); + pDest->m_flags |= SV_FREE; + } + else if ( m_type == FIELD_CSTRING ) + { + pDest->m_pszString = strdup( m_pszString ); + pDest->m_flags |= SV_FREE; + } + else + { + pDest->m_int = m_int; + } + return false; + } + + union + { + int m_int; + float m_float; + const char * m_pszString; + const Vector * m_pVector; + char m_char; + bool m_bool; + HSCRIPT m_hScript; +#ifdef MAPBASE_VSCRIPT + // This uses FIELD_VECTOR, so it's considered a Vector in the VM (just like save/restore) + const QAngle * m_pAngle; +#endif + }; + + int16 m_type; + int16 m_flags; + +private: +}; + +#define SCRIPT_VARIANT_NULL ScriptVariant_t() + +#ifdef MAPBASE_VSCRIPT +//--------------------------------------------------------- +struct ScriptConstantBinding_t +{ + const char *m_pszScriptName; + const char *m_pszDescription; + ScriptVariant_t m_data; + unsigned m_flags; +}; + +//--------------------------------------------------------- +struct ScriptEnumDesc_t +{ + ScriptEnumDesc_t() : m_pszScriptName( 0 ), m_pszDescription( 0 ), m_flags( 0 ) + { + AllEnumsDesc().AddToTail(this); + } + + virtual void RegisterDesc() = 0; + + const char *m_pszScriptName; + const char *m_pszDescription; + CUtlVector m_ConstantBindings; + unsigned m_flags; + + static CUtlVector& AllEnumsDesc() + { + static CUtlVector enums; + return enums; + } +}; +#endif + +#pragma warning(pop) + + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#include "vscript_templates.h" + +// Lower level macro primitives +#define ScriptInitFunctionBinding( pScriptFunction, func ) ScriptInitFunctionBindingNamed( pScriptFunction, func, #func ) +#define ScriptInitFunctionBindingNamed( pScriptFunction, func, scriptName ) do { ScriptInitFuncDescriptorNamed( (&(pScriptFunction)->m_desc), func, scriptName ); (pScriptFunction)->m_pfnBinding = ScriptCreateBinding( &func ); (pScriptFunction)->m_pFunction = (void *)&func; } while (0) + +#define ScriptInitMemberFunctionBinding( pScriptFunction, class, func ) ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, #func ) +#define ScriptInitMemberFunctionBindingNamed( pScriptFunction, class, func, scriptName ) ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, scriptName ) +#define ScriptInitMemberFunctionBinding_( pScriptFunction, class, func, scriptName ) do { ScriptInitMemberFuncDescriptor_( (&(pScriptFunction)->m_desc), class, func, scriptName ); (pScriptFunction)->m_pfnBinding = ScriptCreateBinding( ((class *)0), &class::func ); (pScriptFunction)->m_pFunction = ScriptConvertFuncPtrToVoid( &class::func ); (pScriptFunction)->m_flags = SF_MEMBER_FUNC; } while (0) + +#define ScriptInitClassDesc( pClassDesc, class, pBaseClassDesc ) ScriptInitClassDescNamed( pClassDesc, class, pBaseClassDesc, #class ) +#define ScriptInitClassDescNamed( pClassDesc, class, pBaseClassDesc, scriptName ) ScriptInitClassDescNamed_( pClassDesc, class, pBaseClassDesc, scriptName ) +#define ScriptInitClassDescNoBase( pClassDesc, class ) ScriptInitClassDescNoBaseNamed( pClassDesc, class, #class ) +#define ScriptInitClassDescNoBaseNamed( pClassDesc, class, scriptName ) ScriptInitClassDescNamed_( pClassDesc, class, NULL, scriptName ) +#define ScriptInitClassDescNamed_( pClassDesc, class, pBaseClassDesc, scriptName ) do { (pClassDesc)->m_pszScriptName = scriptName; (pClassDesc)->m_pszClassname = #class; (pClassDesc)->m_pBaseDesc = pBaseClassDesc; } while ( 0 ) + +#define ScriptAddFunctionToClassDesc( pClassDesc, class, func, description ) ScriptAddFunctionToClassDescNamed( pClassDesc, class, func, #func, description ) +#define ScriptAddFunctionToClassDescNamed( pClassDesc, class, func, scriptName, description ) do { ScriptFunctionBinding_t *pBinding = &((pClassDesc)->m_FunctionBindings[(pClassDesc)->m_FunctionBindings.AddToTail()]); pBinding->m_desc.m_pszDescription = description; ScriptInitMemberFunctionBindingNamed( pBinding, class, func, scriptName ); } while (0) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define ScriptRegisterFunction( pVM, func, description ) ScriptRegisterFunctionNamed( pVM, func, #func, description ) +#define ScriptRegisterFunctionNamed( pVM, func, scriptName, description ) do { static ScriptFunctionBinding_t binding; binding.m_desc.m_pszDescription = description; binding.m_desc.m_Parameters.RemoveAll(); ScriptInitFunctionBindingNamed( &binding, func, scriptName ); pVM->RegisterFunction( &binding ); } while (0) + +#ifdef MAPBASE_VSCRIPT +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define ScriptRegisterConstant( pVM, constant, description ) ScriptRegisterConstantNamed( pVM, constant, #constant, description ) +#define ScriptRegisterConstantNamed( pVM, constant, scriptName, description ) do { static ScriptConstantBinding_t binding; binding.m_pszScriptName = scriptName; binding.m_pszDescription = description; binding.m_data = constant; pVM->RegisterConstant( &binding ); } while (0) + +// Could probably use a better name. +// This is used for registering variants (particularly vectors) not tied to existing variables. +// The principal difference is that m_data is initted with bCopy set to true. +#define ScriptRegisterConstantFromTemp( pVM, constant, description ) ScriptRegisterConstantFromTempNamed( pVM, constant, #constant, description ) +#define ScriptRegisterConstantFromTempNamed( pVM, constant, scriptName, description ) do { static ScriptConstantBinding_t binding; binding.m_pszScriptName = scriptName; binding.m_pszDescription = description; binding.m_data = ScriptVariant_t( constant, true ); pVM->RegisterConstant( &binding ); } while (0) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define BEGIN_SCRIPTENUM( enumName, description ) \ + struct ScriptEnum##enumName##Desc_t : public ScriptEnumDesc_t \ + { \ + void RegisterDesc(); \ + }; \ + ScriptEnum##enumName##Desc_t g_##enumName##_EnumDesc; \ + \ + void ScriptEnum##enumName##Desc_t::RegisterDesc() \ + { \ + static bool bInitialized; \ + if ( bInitialized ) \ + return; \ + \ + bInitialized = true; \ + \ + m_pszScriptName = #enumName; \ + m_pszDescription = description; \ + +#define DEFINE_ENUMCONST( constant, description ) DEFINE_ENUMCONST_NAMED( constant, #constant, description ) +#define DEFINE_ENUMCONST_NAMED( constant, scriptName, description ) do { ScriptConstantBinding_t *pBinding = &(m_ConstantBindings[m_ConstantBindings.AddToTail()]); pBinding->m_pszScriptName = scriptName; pBinding->m_pszDescription = description; pBinding->m_data = constant; pBinding->m_flags = SF_MEMBER_FUNC; } while (0); + +#define END_SCRIPTENUM() \ + } \ + + +#define GetScriptDescForEnum( enumName ) GetScriptDesc( ( className *)NULL ) +#endif + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define ALLOW_SCRIPT_ACCESS() template friend ScriptClassDesc_t *GetScriptDesc(T *); + +#define BEGIN_SCRIPTDESC( className, baseClass, description ) BEGIN_SCRIPTDESC_NAMED( className, baseClass, #className, description ) +#define BEGIN_SCRIPTDESC_ROOT( className, description ) BEGIN_SCRIPTDESC_ROOT_NAMED( className, #className, description ) + +#define BEGIN_SCRIPTDESC_NAMED( className, baseClass, scriptName, description ) \ + template <> ScriptClassDesc_t* GetScriptDesc(baseClass*); \ + template <> ScriptClassDesc_t* GetScriptDesc(className*); \ + ScriptClassDesc_t & g_##className##_ScriptDesc = *GetScriptDesc(nullptr); \ + template <> ScriptClassDesc_t* GetScriptDesc(className*) \ + { \ + static ScriptClassDesc_t g_##className##_ScriptDesc; \ + typedef className _className; \ + ScriptClassDesc_t *pDesc = &g_##className##_ScriptDesc; \ + if (pDesc->m_pszClassname) return pDesc; \ + pDesc->m_pszDescription = description; \ + ScriptInitClassDescNamed( pDesc, className, GetScriptDescForClass( baseClass ), scriptName ); \ + ScriptClassDesc_t *pInstanceHelperBase = pDesc->m_pBaseDesc; \ + while ( pInstanceHelperBase ) \ + { \ + if ( pInstanceHelperBase->pHelper ) \ + { \ + pDesc->pHelper = pInstanceHelperBase->pHelper; \ + break; \ + } \ + pInstanceHelperBase = pInstanceHelperBase->m_pBaseDesc; \ + } + + +#define BEGIN_SCRIPTDESC_ROOT_NAMED( className, scriptName, description ) \ + BEGIN_SCRIPTDESC_NAMED( className, ScriptNoBase_t, scriptName, description ) + +#define END_SCRIPTDESC() \ + return pDesc; \ + } + +#define DEFINE_SCRIPTFUNC( func, description ) DEFINE_SCRIPTFUNC_NAMED( func, #func, description ) +#define DEFINE_SCRIPTFUNC_NAMED( func, scriptName, description ) ScriptAddFunctionToClassDescNamed( pDesc, _className, func, scriptName, description ); +#define DEFINE_SCRIPT_CONSTRUCTOR() ScriptAddConstructorToClassDesc( pDesc, _className ); +#define DEFINE_SCRIPT_INSTANCE_HELPER( p ) pDesc->pHelper = (p); + +#ifdef MAPBASE_VSCRIPT +// Use this for hooks which have no parameters +#define DEFINE_SIMPLE_SCRIPTHOOK( hook, hookName, returnType, description ) \ + if (!hook.m_bDefined) \ + { \ + ScriptHook_t *pHook = &hook; \ + pHook->m_desc.m_pszScriptName = hookName; pHook->m_desc.m_pszFunction = #hook; pHook->m_desc.m_ReturnType = returnType; pHook->m_desc.m_pszDescription = description; \ + pDesc->m_Hooks.AddToTail(pHook); \ + } + +#define BEGIN_SCRIPTHOOK( hook, hookName, returnType, description ) \ + if (!hook.m_bDefined) \ + { \ + ScriptHook_t *pHook = &hook; \ + pHook->m_desc.m_pszScriptName = hookName; pHook->m_desc.m_pszFunction = #hook; pHook->m_desc.m_ReturnType = returnType; pHook->m_desc.m_pszDescription = description; + +#define DEFINE_SCRIPTHOOK_PARAM( paramName, type ) pHook->AddParameter( paramName, type ); + +#define END_SCRIPTHOOK() \ + pDesc->m_Hooks.AddToTail(pHook); \ + } + +#define DEFINE_MEMBERVAR( varName, returnType, description ) \ + do { ScriptMemberDesc_t *pBinding = &((pDesc)->m_Members[(pDesc)->m_Members.AddToTail()]); pBinding->m_pszScriptName = varName; pBinding->m_pszDescription = description; pBinding->m_ReturnType = returnType; } while (0); +#endif + +template ScriptClassDesc_t *GetScriptDesc(T *); + +struct ScriptNoBase_t; +template <> inline ScriptClassDesc_t *GetScriptDesc( ScriptNoBase_t *) { return NULL; } + +#define GetScriptDescForClass( className ) GetScriptDesc( ( className *)NULL ) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +template +class CScriptConstructor +{ +public: + static void *Construct() { return new T; } + static void Destruct( void *p ) { delete (T *)p; } +}; + +#define ScriptAddConstructorToClassDesc( pClassDesc, class ) do { (pClassDesc)->m_pfnConstruct = &CScriptConstructor::Construct; (pClassDesc)->m_pfnDestruct = &CScriptConstructor::Destruct; } while (0) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +enum ScriptErrorLevel_t +{ + SCRIPT_LEVEL_WARNING = 0, + SCRIPT_LEVEL_ERROR, +}; + +typedef void ( *ScriptOutputFunc_t )( const char *pszText ); +typedef bool ( *ScriptErrorFunc_t )( ScriptErrorLevel_t eLevel, const char *pszText ); + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#ifdef RegisterClass +#undef RegisterClass +#endif + +enum ScriptStatus_t +{ + SCRIPT_ERROR = -1, + SCRIPT_DONE, + SCRIPT_RUNNING, +}; + +class IScriptVM +{ +public: + virtual bool Init() = 0; + virtual void Shutdown() = 0; + + virtual bool ConnectDebugger() = 0; + virtual void DisconnectDebugger() = 0; + + virtual ScriptLanguage_t GetLanguage() = 0; + virtual const char *GetLanguageName() = 0; + + virtual void AddSearchPath( const char *pszSearchPath ) = 0; + + //-------------------------------------------------------- + + virtual bool Frame( float simTime ) = 0; + + //-------------------------------------------------------- + // Simple script usage + //-------------------------------------------------------- + virtual ScriptStatus_t Run( const char *pszScript, bool bWait = true ) = 0; + inline ScriptStatus_t Run( const unsigned char *pszScript, bool bWait = true ) { return Run( (char *)pszScript, bWait ); } + + //-------------------------------------------------------- + // Compilation + //-------------------------------------------------------- + virtual HSCRIPT CompileScript( const char *pszScript, const char *pszId = NULL ) = 0; + inline HSCRIPT CompileScript( const unsigned char *pszScript, const char *pszId = NULL ) { return CompileScript( (char *)pszScript, pszId ); } + virtual void ReleaseScript( HSCRIPT ) = 0; + + //-------------------------------------------------------- + // Execution of compiled + //-------------------------------------------------------- + virtual ScriptStatus_t Run( HSCRIPT hScript, HSCRIPT hScope = NULL, bool bWait = true ) = 0; + virtual ScriptStatus_t Run( HSCRIPT hScript, bool bWait ) = 0; + + //-------------------------------------------------------- + // Scope + //-------------------------------------------------------- + virtual HSCRIPT CreateScope( const char *pszScope, HSCRIPT hParent = NULL ) = 0; + virtual void ReleaseScope( HSCRIPT hScript ) = 0; + + //-------------------------------------------------------- + // Script functions + //-------------------------------------------------------- + virtual HSCRIPT LookupFunction( const char *pszFunction, HSCRIPT hScope = NULL ) = 0; + virtual void ReleaseFunction( HSCRIPT hScript ) = 0; + + //-------------------------------------------------------- + // Script functions (raw, use Call()) + //-------------------------------------------------------- + virtual ScriptStatus_t ExecuteFunction( HSCRIPT hFunction, ScriptVariant_t *pArgs, int nArgs, ScriptVariant_t *pReturn, HSCRIPT hScope, bool bWait ) = 0; + + //-------------------------------------------------------- + // External functions + //-------------------------------------------------------- + virtual void RegisterFunction( ScriptFunctionBinding_t *pScriptFunction ) = 0; + + //-------------------------------------------------------- + // External classes + //-------------------------------------------------------- + virtual bool RegisterClass( ScriptClassDesc_t *pClassDesc ) = 0; + +#ifdef MAPBASE_VSCRIPT + //-------------------------------------------------------- + // External constants + //-------------------------------------------------------- + virtual void RegisterConstant( ScriptConstantBinding_t *pScriptConstant ) = 0; + + //-------------------------------------------------------- + // External enums + //-------------------------------------------------------- + virtual void RegisterEnum( ScriptEnumDesc_t *pEnumDesc ) = 0; +#endif + + //-------------------------------------------------------- + // External instances. Note class will be auto-registered. + //-------------------------------------------------------- + +#ifdef MAPBASE_VSCRIPT + // When a RegisterInstance instance is deleted, VScript normally treats it as a strong reference and only deregisters the instance itself, preserving the registered data + // it points to so the game can continue to use it. + // bAllowDestruct is supposed to allow VScript to treat it as a weak reference created by the script, destructing the registered data automatically like any other type. + // This is useful for classes pretending to be primitive types. + virtual HSCRIPT RegisterInstance( ScriptClassDesc_t *pDesc, void *pInstance, bool bAllowDestruct = false ) = 0; + virtual void SetInstanceUniqeId( HSCRIPT hInstance, const char *pszId ) = 0; + template HSCRIPT RegisterInstance( T *pInstance, bool bAllowDestruct = false ) { return RegisterInstance( GetScriptDesc( pInstance ), pInstance, bAllowDestruct ); } + template HSCRIPT RegisterInstance( T *pInstance, const char *pszInstance, HSCRIPT hScope = NULL, bool bAllowDestruct = false) { HSCRIPT hInstance = RegisterInstance( GetScriptDesc( pInstance ), pInstance, bAllowDestruct ); SetValue( hScope, pszInstance, hInstance ); return hInstance; } +#else + virtual HSCRIPT RegisterInstance( ScriptClassDesc_t *pDesc, void *pInstance ) = 0; + virtual void SetInstanceUniqeId( HSCRIPT hInstance, const char *pszId ) = 0; + template HSCRIPT RegisterInstance( T *pInstance ) { return RegisterInstance( GetScriptDesc( pInstance ), pInstance ); } + template HSCRIPT RegisterInstance( T *pInstance, const char *pszInstance, HSCRIPT hScope = NULL) { HSCRIPT hInstance = RegisterInstance( GetScriptDesc( pInstance ), pInstance ); SetValue( hScope, pszInstance, hInstance ); return hInstance; } +#endif + virtual void RemoveInstance( HSCRIPT ) = 0; + void RemoveInstance( HSCRIPT hInstance, const char *pszInstance, HSCRIPT hScope = NULL ) { ClearValue( hScope, pszInstance ); RemoveInstance( hInstance ); } + void RemoveInstance( const char *pszInstance, HSCRIPT hScope = NULL ) { ScriptVariant_t val; if ( GetValue( hScope, pszInstance, &val ) ) { if ( val.m_type == FIELD_HSCRIPT ) { RemoveInstance( val, pszInstance, hScope ); } ReleaseValue( val ); } } + + virtual void *GetInstanceValue( HSCRIPT hInstance, ScriptClassDesc_t *pExpectedType = NULL ) = 0; + + //---------------------------------------------------------------------------- + + virtual bool GenerateUniqueKey( const char *pszRoot, char *pBuf, int nBufSize ) = 0; + + //---------------------------------------------------------------------------- + + virtual bool ValueExists( HSCRIPT hScope, const char *pszKey ) = 0; + bool ValueExists( const char *pszKey ) { return ValueExists( NULL, pszKey ); } + + virtual bool SetValue( HSCRIPT hScope, const char *pszKey, const char *pszValue ) = 0; + virtual bool SetValue( HSCRIPT hScope, const char *pszKey, const ScriptVariant_t &value ) = 0; + bool SetValue( const char *pszKey, const ScriptVariant_t &value ) { return SetValue(NULL, pszKey, value ); } +#ifdef MAPBASE_VSCRIPT + virtual bool SetValue( HSCRIPT hScope, const ScriptVariant_t& key, const ScriptVariant_t& val ) = 0; +#endif + + virtual void CreateTable( ScriptVariant_t &Table ) = 0; + virtual int GetNumTableEntries( HSCRIPT hScope ) = 0; + virtual int GetKeyValue( HSCRIPT hScope, int nIterator, ScriptVariant_t *pKey, ScriptVariant_t *pValue ) = 0; + + virtual bool GetValue( HSCRIPT hScope, const char *pszKey, ScriptVariant_t *pValue ) = 0; + bool GetValue( const char *pszKey, ScriptVariant_t *pValue ) { return GetValue(NULL, pszKey, pValue ); } +#ifdef MAPBASE_VSCRIPT + virtual bool GetValue( HSCRIPT hScope, ScriptVariant_t key, ScriptVariant_t* pValue ) = 0; +#endif + virtual void ReleaseValue( ScriptVariant_t &value ) = 0; + + virtual bool ClearValue( HSCRIPT hScope, const char *pszKey ) = 0; + bool ClearValue( const char *pszKey) { return ClearValue( NULL, pszKey ); } +#ifdef MAPBASE_VSCRIPT + virtual bool ClearValue( HSCRIPT hScope, ScriptVariant_t pKey ) = 0; +#endif + +#ifdef MAPBASE_VSCRIPT + virtual void CreateArray(ScriptVariant_t &arr, int size = 0) = 0; + virtual bool ArrayAppend(HSCRIPT hArray, const ScriptVariant_t &val) = 0; +#endif + + //---------------------------------------------------------------------------- + + virtual void WriteState( CUtlBuffer *pBuffer ) = 0; + virtual void ReadState( CUtlBuffer *pBuffer ) = 0; + virtual void RemoveOrphanInstances() = 0; + + virtual void DumpState() = 0; + + virtual void SetOutputCallback( ScriptOutputFunc_t pFunc ) = 0; + virtual void SetErrorCallback( ScriptErrorFunc_t pFunc ) = 0; + + //---------------------------------------------------------------------------- + + virtual bool RaiseException( const char *pszExceptionText ) = 0; + + //---------------------------------------------------------------------------- + // Call API + // + // Note for string and vector return types, the caller must delete the pointed to memory + //---------------------------------------------------------------------------- + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope = NULL, bool bWait = true, ScriptVariant_t *pReturn = NULL ) + { + return ExecuteFunction( hFunction, NULL, 0, pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1 ) + { + ScriptVariant_t args[1]; args[0] = arg1; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2 ) + { + ScriptVariant_t args[2]; args[0] = arg1; args[1] = arg2; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3 ) + { + ScriptVariant_t args[3]; args[0] = arg1; args[1] = arg2; args[2] = arg3; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4 ) + { + ScriptVariant_t args[4]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5 ) + { + ScriptVariant_t args[5]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6 ) + { + ScriptVariant_t args[6]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7 ) + { + ScriptVariant_t args[7]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8 ) + { + ScriptVariant_t args[8]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9 ) + { + ScriptVariant_t args[9]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10 ) + { + ScriptVariant_t args[10]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11 ) + { + ScriptVariant_t args[11]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12 ) + { + ScriptVariant_t args[12]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13 ) + { + ScriptVariant_t args[13]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, HSCRIPT hScope, bool bWait, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13, ARG_TYPE_14 arg14 ) + { + ScriptVariant_t args[14]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; args[13] = arg14; + return ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, hScope, bWait ); + } + +#ifdef MAPBASE_VSCRIPT + void RegisterAllClasses() + { + CUtlVector& classDescs = ScriptClassDesc_t::AllClassesDesc(); + FOR_EACH_VEC(classDescs, i) + { + RegisterClass(classDescs[i]); + } + } + + void RegisterAllEnums() + { + CUtlVector& enumDescs = ScriptEnumDesc_t::AllEnumsDesc(); + FOR_EACH_VEC(enumDescs, i) + { + enumDescs[i]->RegisterDesc(); + RegisterEnum(enumDescs[i]); + } + } +#endif +}; + + +//----------------------------------------------------------------------------- +// Script scope helper class +//----------------------------------------------------------------------------- + +class CDefScriptScopeBase +{ +public: + static IScriptVM *GetVM() + { + extern IScriptVM *g_pScriptVM; + return g_pScriptVM; + } +}; + +template +class CScriptScopeT : public CDefScriptScopeBase +{ +public: + CScriptScopeT() : + m_hScope( INVALID_HSCRIPT ), + m_flags( 0 ) + { + } + + ~CScriptScopeT() + { + Term(); + } + + bool IsInitialized() + { + return m_hScope != INVALID_HSCRIPT; + } + + bool Init( const char *pszName ) + { + m_hScope = GetVM()->CreateScope( pszName ); + return ( m_hScope != NULL ); + } + + bool Init( HSCRIPT hScope, bool bExternal = true ) + { + if ( bExternal ) + { + m_flags |= EXTERNAL; + } + m_hScope = hScope; + return ( m_hScope != NULL ); + } + + bool InitGlobal() + { + Assert( 0 ); // todo [3/24/2008 tom] + m_hScope = GetVM()->CreateScope( "" ); + return ( m_hScope != NULL ); + } + + void Term() + { + if ( m_hScope != INVALID_HSCRIPT ) + { + IScriptVM *pVM = GetVM(); + if ( pVM ) + { + for ( int i = 0; i < m_FuncHandles.Count(); i++ ) + { + pVM->ReleaseFunction( *m_FuncHandles[i] ); + } + } + m_FuncHandles.Purge(); + if ( m_hScope && pVM && !(m_flags & EXTERNAL) ) + { + pVM->ReleaseScope( m_hScope ); + } + m_hScope = INVALID_HSCRIPT; + } + m_flags = 0; + } + + void InvalidateCachedValues() + { + IScriptVM *pVM = GetVM(); + for ( int i = 0; i < m_FuncHandles.Count(); i++ ) + { + if ( *m_FuncHandles[i] ) + pVM->ReleaseFunction( *m_FuncHandles[i] ); + *m_FuncHandles[i] = INVALID_HSCRIPT; + } + m_FuncHandles.RemoveAll(); + } + + operator HSCRIPT() + { + return ( m_hScope != INVALID_HSCRIPT ) ? m_hScope : NULL; + } + + bool ValueExists( const char *pszKey ) { return GetVM()->ValueExists( m_hScope, pszKey ); } + bool SetValue( const char *pszKey, const ScriptVariant_t &value ) { return GetVM()->SetValue(m_hScope, pszKey, value ); } + bool GetValue( const char *pszKey, ScriptVariant_t *pValue ) { return GetVM()->GetValue(m_hScope, pszKey, pValue ); } + void ReleaseValue( ScriptVariant_t &value ) { GetVM()->ReleaseValue( value ); } + bool ClearValue( const char *pszKey) { return GetVM()->ClearValue( m_hScope, pszKey ); } + + ScriptStatus_t Run( HSCRIPT hScript ) + { + InvalidateCachedValues(); + return GetVM()->Run( hScript, m_hScope ); + } + + ScriptStatus_t Run( const char *pszScriptText, const char *pszScriptName = NULL ) + { + InvalidateCachedValues(); + HSCRIPT hScript = GetVM()->CompileScript( pszScriptText, pszScriptName ); + if ( hScript ) + { + ScriptStatus_t result = GetVM()->Run( hScript, m_hScope ); + GetVM()->ReleaseScript( hScript ); + return result; + } + return SCRIPT_ERROR; + } + + ScriptStatus_t Run( const unsigned char *pszScriptText, const char *pszScriptName = NULL ) + { + return Run( (const char *)pszScriptText, pszScriptName); + } + + HSCRIPT LookupFunction( const char *pszFunction ) + { + return GetVM()->LookupFunction( pszFunction, m_hScope ); + } + + void ReleaseFunction( HSCRIPT hScript ) + { + GetVM()->ReleaseFunction( hScript ); + } + + bool FunctionExists( const char *pszFunction ) + { + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + GetVM()->ReleaseFunction( hFunction ); + return ( hFunction != NULL ) ; + } + + //----------------------------------------------------- + + enum Flags_t + { + EXTERNAL = 0x01, + }; + + //----------------------------------------------------- + + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn = NULL ) + { + return GetVM()->ExecuteFunction( hFunction, NULL, 0, pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1 ) + { + ScriptVariant_t args[1]; args[0] = arg1; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2 ) + { + ScriptVariant_t args[2]; args[0] = arg1; args[1] = arg2; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3 ) + { + ScriptVariant_t args[3]; args[0] = arg1; args[1] = arg2; args[2] = arg3; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4 ) + { + ScriptVariant_t args[4]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5 ) + { + ScriptVariant_t args[5]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6 ) + { + ScriptVariant_t args[6]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7 ) + { + ScriptVariant_t args[7]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8 ) + { + ScriptVariant_t args[8]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9 ) + { + ScriptVariant_t args[9]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10 ) + { + ScriptVariant_t args[10]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11 ) + { + ScriptVariant_t args[11]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12 ) + { + ScriptVariant_t args[12]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13 ) + { + ScriptVariant_t args[13]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + template + ScriptStatus_t Call( HSCRIPT hFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13, ARG_TYPE_14 arg14 ) + { + ScriptVariant_t args[14]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; args[13] = arg14; + return GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + } + + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn = NULL ) + { + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, NULL, 0, pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1 ) + { + ScriptVariant_t args[1]; args[0] = arg1; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2 ) + { + ScriptVariant_t args[2]; args[0] = arg1; args[1] = arg2; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3 ) + { + ScriptVariant_t args[3]; args[0] = arg1; args[1] = arg2; args[2] = arg3; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4 ) + { + ScriptVariant_t args[4]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5 ) + { + ScriptVariant_t args[5]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6 ) + { + ScriptVariant_t args[6]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7 ) + { + ScriptVariant_t args[7]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8 ) + { + ScriptVariant_t args[8]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9 ) + { + ScriptVariant_t args[9]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10 ) + { + ScriptVariant_t args[10]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11 ) + { + ScriptVariant_t args[11]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12 ) + { + ScriptVariant_t args[12]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13 ) + { + ScriptVariant_t args[13]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + + template + ScriptStatus_t Call( const char *pszFunction, ScriptVariant_t *pReturn, ARG_TYPE_1 arg1, ARG_TYPE_2 arg2, ARG_TYPE_3 arg3, ARG_TYPE_4 arg4, ARG_TYPE_5 arg5, ARG_TYPE_6 arg6, ARG_TYPE_7 arg7, ARG_TYPE_8 arg8, ARG_TYPE_9 arg9, ARG_TYPE_10 arg10, ARG_TYPE_11 arg11, ARG_TYPE_12 arg12, ARG_TYPE_13 arg13, ARG_TYPE_14 arg14 ) + { + ScriptVariant_t args[14]; args[0] = arg1; args[1] = arg2; args[2] = arg3; args[3] = arg4; args[4] = arg5; args[5] = arg6; args[6] = arg7; args[7] = arg8; args[8] = arg9; args[9] = arg10; args[10] = arg11; args[11] = arg12; args[12] = arg13; args[13] = arg14; + HSCRIPT hFunction = GetVM()->LookupFunction( pszFunction, m_hScope ); + if ( !hFunction ) + return SCRIPT_ERROR; + ScriptStatus_t status = GetVM()->ExecuteFunction( hFunction, args, ARRAYSIZE(args), pReturn, m_hScope, true ); + GetVM()->ReleaseFunction( hFunction ); + return status; + } + +protected: + HSCRIPT m_hScope; + int m_flags; + CUtlVectorConservative m_FuncHandles; +}; + +typedef CScriptScopeT<> CScriptScope; + +#define VScriptAddEnumToScope_( scope, enumVal, scriptName ) (scope).SetValue( scriptName, (int)enumVal ) +#define VScriptAddEnumToScope( scope, enumVal ) VScriptAddEnumToScope_( scope, enumVal, #enumVal ) + +#define VScriptAddEnumToRoot( enumVal ) g_pScriptVM->SetValue( #enumVal, (int)enumVal ) + +#ifdef MAPBASE_VSCRIPT +//----------------------------------------------------------------------------- +// Function bindings allow script functions to run C++ functions. +// Hooks allow C++ functions to run script functions. +// +// This was previously done with raw function lookups, but Mapbase adds more and +// it's hard to keep track of them without proper standards or documentation. +// +// At the moment, this simply plugs hook documentation into VScript and maintains +// the same function lookup method on the inside, but it's intended to be open for +// more complex hook mechanisms with proper parameters in the future. +// +// For example: +// +// if (m_hFunc) +// { +// g_pScriptVM->ExecuteFunction( m_Func, pArgs, m_desc.m_Parameters.Count(), pReturn, m_ScriptScope, true ); +// } +//----------------------------------------------------------------------------- +struct ScriptHook_t +{ + ScriptFuncDescriptor_t m_desc; + CUtlVector m_pszParameterNames; + bool m_bDefined; + + void AddParameter( const char *pszName, ScriptDataType_t type ) + { + int iCur = m_desc.m_Parameters.Count(); + m_desc.m_Parameters.SetGrowSize( 1 ); m_desc.m_Parameters.EnsureCapacity( iCur + 1 ); m_desc.m_Parameters.AddToTail( type ); + m_pszParameterNames.SetGrowSize( 1 ); m_pszParameterNames.EnsureCapacity( iCur + 1 ); m_pszParameterNames.AddToTail( pszName ); + } + + // ----------------------------------------------------------------- + + // Cached for when CanRunInScope() is called before Call() + HSCRIPT m_hFunc; + + // Checks if there's a function of this name which would run in this scope + HSCRIPT CanRunInScope( HSCRIPT hScope ) + { + extern IScriptVM *g_pScriptVM; + m_hFunc = g_pScriptVM->LookupFunction( m_desc.m_pszScriptName, hScope ); + return m_hFunc; + } + + // Checks if an existing func can be used + bool CheckFuncValid( HSCRIPT hFunc ) + { + // TODO: Better crtieria for this? + if (hFunc) + { + m_hFunc = hFunc; + return true; + } + return false; + } + + // Call the function + bool Call( HSCRIPT hScope, ScriptVariant_t *pReturn, ScriptVariant_t *pArgs, bool bRelease = true ) + { + extern IScriptVM *g_pScriptVM; + + // Make sure we have a function in this scope + if (!m_hFunc && !CanRunInScope(hScope)) + return false; + else + { + for (int i = 0; i < m_desc.m_Parameters.Count(); i++) + { + g_pScriptVM->SetValue( m_pszParameterNames[i], pArgs[i] ); + } + + g_pScriptVM->ExecuteFunction( m_hFunc, NULL, 0, pReturn, hScope, true ); + + if (bRelease) + g_pScriptVM->ReleaseFunction( m_hFunc ); + + m_hFunc = NULL; + + for (int i = 0; i < m_desc.m_Parameters.Count(); i++) + { + g_pScriptVM->ClearValue( m_pszParameterNames[i] ); + } + + return true; + } + + return false; + } +}; +#endif + +//----------------------------------------------------------------------------- +// Script function proxy support +//----------------------------------------------------------------------------- + +class CScriptFuncHolder +{ +public: + CScriptFuncHolder() : hFunction( INVALID_HSCRIPT ) {} + bool IsValid() { return ( hFunction != INVALID_HSCRIPT ); } + bool IsNull() { return ( !hFunction ); } + HSCRIPT hFunction; +}; + +#define DEFINE_SCRIPT_PROXY_GUTS( FuncName, N ) \ + CScriptFuncHolder m_hScriptFunc_##FuncName; \ + template < typename RET_TYPE FUNC_TEMPLATE_ARG_PARAMS_##N> \ + bool FuncName( RET_TYPE *pRetVal FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + if ( !m_hScriptFunc_##FuncName.IsValid() ) \ + { \ + m_hScriptFunc_##FuncName.hFunction = LookupFunction( #FuncName ); \ + m_FuncHandles.AddToTail( &m_hScriptFunc_##FuncName.hFunction ); \ + } \ + \ + if ( !m_hScriptFunc_##FuncName.IsNull() ) \ + { \ + ScriptVariant_t returnVal; \ + Assert( N == m_desc.m_Parameters.Count() ); \ + ScriptStatus_t result = Call( m_hScriptFunc_##FuncName.hFunction, &returnVal, FUNC_CALL_ARGS_##N ); \ + if ( result != SCRIPT_ERROR ) \ + { \ + returnVal.AssignTo( pRetVal ); \ + returnVal.Free(); \ + return true; \ + } \ + } \ + return false; \ + } + +#define DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, N ) \ + CScriptFuncHolder m_hScriptFunc_##FuncName; \ + template < FUNC_SOLO_TEMPLATE_ARG_PARAMS_##N> \ + bool FuncName( FUNC_PROXY_ARG_FORMAL_PARAMS_##N ) \ + { \ + if ( !m_hScriptFunc_##FuncName.IsValid() ) \ + { \ + m_hScriptFunc_##FuncName.hFunction = LookupFunction( #FuncName ); \ + m_FuncHandles.AddToTail( &m_hScriptFunc_##FuncName.hFunction ); \ + } \ + \ + if ( !m_hScriptFunc_##FuncName.IsNull() ) \ + { \ + Assert( N == m_desc.m_Parameters.Count() ); \ + ScriptStatus_t result = Call( m_hScriptFunc_##FuncName.hFunction, NULL, FUNC_CALL_ARGS_##N ); \ + if ( result != SCRIPT_ERROR ) \ + { \ + return true; \ + } \ + } \ + return false; \ + } + +#define DEFINE_SCRIPT_PROXY_0V( FuncName ) \ + CScriptFuncHolder m_hScriptFunc_##FuncName; \ + bool FuncName() \ + { \ + if ( !m_hScriptFunc_##FuncName.IsValid() ) \ + { \ + m_hScriptFunc_##FuncName.hFunction = LookupFunction( #FuncName ); \ + m_FuncHandles.AddToTail( &m_hScriptFunc_##FuncName.hFunction ); \ + } \ + \ + if ( !m_hScriptFunc_##FuncName.IsNull() ) \ + { \ + ScriptStatus_t result = Call( m_hScriptFunc_##FuncName.hFunction, NULL ); \ + if ( result != SCRIPT_ERROR ) \ + { \ + return true; \ + } \ + } \ + return false; \ + } + +#define DEFINE_SCRIPT_PROXY_0( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 0 ) +#define DEFINE_SCRIPT_PROXY_1( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 1 ) +#define DEFINE_SCRIPT_PROXY_2( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 2 ) +#define DEFINE_SCRIPT_PROXY_3( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 3 ) +#define DEFINE_SCRIPT_PROXY_4( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 4 ) +#define DEFINE_SCRIPT_PROXY_5( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 5 ) +#define DEFINE_SCRIPT_PROXY_6( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 6 ) +#define DEFINE_SCRIPT_PROXY_7( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 7 ) +#define DEFINE_SCRIPT_PROXY_8( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 8 ) +#define DEFINE_SCRIPT_PROXY_9( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 9 ) +#define DEFINE_SCRIPT_PROXY_10( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 10 ) +#define DEFINE_SCRIPT_PROXY_11( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 11 ) +#define DEFINE_SCRIPT_PROXY_12( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 12 ) +#define DEFINE_SCRIPT_PROXY_13( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 13 ) +#define DEFINE_SCRIPT_PROXY_14( FuncName ) DEFINE_SCRIPT_PROXY_GUTS( FuncName, 14 ) + +#define DEFINE_SCRIPT_PROXY_1V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 1 ) +#define DEFINE_SCRIPT_PROXY_2V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 2 ) +#define DEFINE_SCRIPT_PROXY_3V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 3 ) +#define DEFINE_SCRIPT_PROXY_4V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 4 ) +#define DEFINE_SCRIPT_PROXY_5V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 5 ) +#define DEFINE_SCRIPT_PROXY_6V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 6 ) +#define DEFINE_SCRIPT_PROXY_7V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 7 ) +#define DEFINE_SCRIPT_PROXY_8V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 8 ) +#define DEFINE_SCRIPT_PROXY_9V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 9 ) +#define DEFINE_SCRIPT_PROXY_10V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 10 ) +#define DEFINE_SCRIPT_PROXY_11V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 11 ) +#define DEFINE_SCRIPT_PROXY_12V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 12 ) +#define DEFINE_SCRIPT_PROXY_13V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 13 ) +#define DEFINE_SCRIPT_PROXY_14V( FuncName ) DEFINE_SCRIPT_PROXY_GUTS_NO_RETVAL( FuncName, 14 ) + +//----------------------------------------------------------------------------- + +#include "tier0/memdbgoff.h" + +#endif // IVSCRIPT_H diff --git a/sp/src/public/vscript/vscript_templates.h b/sp/src/public/vscript/vscript_templates.h new file mode 100644 index 00000000..e23a9fe9 --- /dev/null +++ b/sp/src/public/vscript/vscript_templates.h @@ -0,0 +1,414 @@ +//========== Copyright © 2008, Valve Corporation, All rights reserved. ======== +// +// Purpose: +// +//============================================================================= + +#ifndef VSCRIPT_TEMPLATES_H +#define VSCRIPT_TEMPLATES_H + +#include "tier0/basetypes.h" + +#if defined( _WIN32 ) +#pragma once +#endif + +#define FUNC_APPEND_PARAMS_0 +#define FUNC_APPEND_PARAMS_1 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 1 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); +#define FUNC_APPEND_PARAMS_2 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 2 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); +#define FUNC_APPEND_PARAMS_3 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 3 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); +#define FUNC_APPEND_PARAMS_4 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 4 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); +#define FUNC_APPEND_PARAMS_5 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 5 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); +#define FUNC_APPEND_PARAMS_6 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 6 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); +#define FUNC_APPEND_PARAMS_7 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 7 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); +#define FUNC_APPEND_PARAMS_8 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 8 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); +#define FUNC_APPEND_PARAMS_9 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 9 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); +#define FUNC_APPEND_PARAMS_10 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 10 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); +#define FUNC_APPEND_PARAMS_11 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 11 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); +#define FUNC_APPEND_PARAMS_12 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 12 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); +#define FUNC_APPEND_PARAMS_13 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 13 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_13 ) ); +#define FUNC_APPEND_PARAMS_14 pDesc->m_Parameters.SetGrowSize( 1 ); pDesc->m_Parameters.EnsureCapacity( 14 ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_1 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_2 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_3 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_4 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_5 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_6 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_7 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_8 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_9 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_10 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_11 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_12 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_13 ) ); pDesc->m_Parameters.AddToTail( ScriptDeduceType( FUNC_ARG_TYPE_14 ) ); + +#define DEFINE_NONMEMBER_FUNC_TYPE_DEDUCER(N) \ + template \ + inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \ + { \ + pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \ + FUNC_APPEND_PARAMS_##N \ + } + +FUNC_GENERATE_ALL( DEFINE_NONMEMBER_FUNC_TYPE_DEDUCER ); + +#define DEFINE_MEMBER_FUNC_TYPE_DEDUCER(N) \ + template \ + inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \ + { \ + pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \ + FUNC_APPEND_PARAMS_##N \ + } + +FUNC_GENERATE_ALL( DEFINE_MEMBER_FUNC_TYPE_DEDUCER ); + +//------------------------------------- + +#define DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER(N) \ + template \ + inline void ScriptDeduceFunctionSignature(ScriptFuncDescriptor_t *pDesc, OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const ) \ + { \ + pDesc->m_ReturnType = ScriptDeduceType(FUNCTION_RETTYPE); \ + FUNC_APPEND_PARAMS_##N \ + } + +FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_FUNC_TYPE_DEDUCER ); + +#define ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, (class *)(0), &class::func ); } + +#define ScriptInitFuncDescriptorNamed( pDesc, func, scriptName ) if ( 0 ) {} else { (pDesc)->m_pszScriptName = scriptName; (pDesc)->m_pszFunction = #func; ScriptDeduceFunctionSignature( pDesc, &func ); } +#define ScriptInitFuncDescriptor( pDesc, func ) ScriptInitFuncDescriptorNamed( pDesc, func, #func ) +#define ScriptInitMemberFuncDescriptorNamed( pDesc, class, func, scriptName ) ScriptInitMemberFuncDescriptor_( pDesc, class, func, scriptName ) +#define ScriptInitMemberFuncDescriptor( pDesc, class, func ) ScriptInitMemberFuncDescriptorNamed( pDesc, class, func, #func ) + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +template +inline void *ScriptConvertFuncPtrToVoid( FUNCPTR_TYPE pFunc ) +{ + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) ) + { + union FuncPtrConvert + { + void *p; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvert convert; + convert.pFunc = pFunc; + return convert.p; + } +#if defined( _MSC_VER ) + else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) + { + struct MicrosoftUnknownMFP + { + void *p; + int m_delta; + }; + + union FuncPtrConvertMI + { + MicrosoftUnknownMFP mfp; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvertMI convert; + convert.pFunc = pFunc; + if ( convert.mfp.m_delta == 0 ) + { + return convert.mfp.p; + } + AssertMsg( 0, "Function pointer must be from primary vtable" ); + } + else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) ) + { + struct MicrosoftUnknownMFP + { + void *p; + int m_delta; + int m_vtordisp; + int m_vtable_index; + }; + + union FuncPtrConvertMI + { + MicrosoftUnknownMFP mfp; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvertMI convert; + convert.pFunc = pFunc; + if ( convert.mfp.m_delta == 0 ) + { + return convert.mfp.p; + } + AssertMsg( 0, "Function pointer must be from primary vtable" ); + } +#elif defined( GNUC ) + else if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) + { + AssertMsg( 0, "Note: This path has not been verified yet. See comments below in #else case." ); + + struct GnuMFP + { + union + { + void *funcadr; // If vtable_index_2 is even, then this is the function pointer. + int vtable_index_2; // If vtable_index_2 is odd, then this = vindex*2+1. + }; + int delta; + }; + + GnuMFP *p = (GnuMFP*)&pFunc; + if ( p->vtable_index_2 & 1 ) + { + char **delta = (char**)p->delta; + char *pCur = *delta + (p->vtable_index_2+1)/2; + return (void*)( pCur + 4 ); + } + else + { + return p->funcadr; + } + } +#else +#error "Need to implement code to crack non-offset member function pointer case" + // For gcc, see: http://www.codeproject.com/KB/cpp/FastDelegate.aspx + // + // Current versions of the GNU compiler use a strange and tricky + // optimization. It observes that, for virtual inheritance, you have to look + // up the vtable in order to get the voffset required to calculate the this + // pointer. While you're doing that, you might as well store the function + // pointer in the vtable. By doing this, they combine the m_func_address and + // m_vtable_index fields into one, and they distinguish between them by + // ensuring that function pointers always point to even addresses but vtable + // indices are always odd: + // + // // GNU g++ uses a tricky space optimisation, also adopted by IBM's VisualAge and XLC. + // struct GnuMFP { + // union { + // CODEPTR funcadr; // always even + // int vtable_index_2; // = vindex*2+1, always odd + // }; + // int delta; + // }; + // adjustedthis = this + delta + // if (funcadr & 1) CALL (* ( *delta + (vindex+1)/2) + 4) + // else CALL funcadr + // + // The G++ method is well documented, so it has been adopted by many other + // vendors, including IBM's VisualAge and XLC compilers, recent versions of + // Open64, Pathscale EKO, and Metrowerks' 64-bit compilers. A simpler scheme + // used by earlier versions of GCC is also very common. SGI's now + // discontinued MIPSPro and Pro64 compilers, and Apple's ancient MrCpp + // compiler used this method. (Note that the Pro64 compiler has become the + // open source Open64 compiler). + +#endif + else + AssertMsg( 0, "Member function pointer not supported. Why on earth are you using virtual inheritance!?" ); + return NULL; +} + +template +inline FUNCPTR_TYPE ScriptConvertFuncPtrFromVoid( void *p ) +{ + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) ) ) + { + union FuncPtrConvert + { + void *p; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvert convert; + convert.p = p; + return convert.pFunc; + } + +#if defined( _MSC_VER ) + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + sizeof( int ) ) ) + { + struct MicrosoftUnknownMFP + { + void *p; + int m_delta; + }; + + union FuncPtrConvertMI + { + MicrosoftUnknownMFP mfp; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvertMI convert; + convert.mfp.p = p; + convert.mfp.m_delta = 0; + return convert.pFunc; + } + if ( ( sizeof( FUNCPTR_TYPE ) == sizeof( void * ) + ( sizeof( int ) * 3 ) ) ) + { + struct MicrosoftUnknownMFP + { + void *p; + int m_delta; + int m_vtordisp; + int m_vtable_index; + }; + + union FuncPtrConvertMI + { + MicrosoftUnknownMFP mfp; + FUNCPTR_TYPE pFunc; + }; + + FuncPtrConvertMI convert; + convert.mfp.p = p; + convert.mfp.m_delta = 0; + return convert.pFunc; + } +#elif defined( POSIX ) + AssertMsg( 0, "Note: This path has not been implemented yet." ); +#else +#error "Need to implement code to crack non-offset member function pointer case" +#endif + Assert( 0 ); + return NULL; +} + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_0 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_1 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_1 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_2 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_2 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_3 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_3 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_4 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_4 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_5 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_5 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_6 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_6 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_7 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_7 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_8 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_8 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_9 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_9 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_10 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_10 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_11 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_11 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_12 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_12 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_13 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_13 +#define FUNC_BASE_TEMPLATE_FUNC_PARAMS_PASSTHRU_14 , FUNC_BASE_TEMPLATE_FUNC_PARAMS_14 + +#define SCRIPT_BINDING_ARGS_0 +#define SCRIPT_BINDING_ARGS_1 pArguments[0] +#define SCRIPT_BINDING_ARGS_2 pArguments[0], pArguments[1] +#define SCRIPT_BINDING_ARGS_3 pArguments[0], pArguments[1], pArguments[2] +#define SCRIPT_BINDING_ARGS_4 pArguments[0], pArguments[1], pArguments[2], pArguments[3] +#define SCRIPT_BINDING_ARGS_5 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4] +#define SCRIPT_BINDING_ARGS_6 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5] +#define SCRIPT_BINDING_ARGS_7 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6] +#define SCRIPT_BINDING_ARGS_8 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7] +#define SCRIPT_BINDING_ARGS_9 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8] +#define SCRIPT_BINDING_ARGS_10 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9] +#define SCRIPT_BINDING_ARGS_11 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10] +#define SCRIPT_BINDING_ARGS_12 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11] +#define SCRIPT_BINDING_ARGS_13 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11], pArguments[12] +#define SCRIPT_BINDING_ARGS_14 pArguments[0], pArguments[1], pArguments[2], pArguments[3], pArguments[4], pArguments[5], pArguments[6], pArguments[7], pArguments[8], pArguments[9], pArguments[10], pArguments[11], pArguments[12], pArguments[13] + + +#define DEFINE_SCRIPT_BINDINGS(N) \ + template \ + class CNonMemberScriptBinding##N \ + { \ + public: \ + static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + { \ + Assert( nArguments == N ); \ + Assert( pReturn ); \ + Assert( !pContext ); \ + \ + if ( nArguments != N || !pReturn || pContext ) \ + { \ + return false; \ + } \ + *pReturn = ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \ + if ( pReturn->m_type == FIELD_VECTOR ) \ + pReturn->m_pVector = new Vector(*pReturn->m_pVector); \ + return true; \ + } \ + }; \ + \ + template \ + class CNonMemberScriptBinding##N \ + { \ + public: \ + static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + { \ + Assert( nArguments == N ); \ + Assert( !pReturn ); \ + Assert( !pContext ); \ + \ + if ( nArguments != N || pReturn || pContext ) \ + { \ + return false; \ + } \ + ((FUNC_TYPE)pFunction)( SCRIPT_BINDING_ARGS_##N ); \ + return true; \ + } \ + }; \ + \ + template \ + class CMemberScriptBinding##N \ + { \ + public: \ + static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + { \ + Assert( nArguments == N ); \ + Assert( pReturn ); \ + Assert( pContext ); \ + \ + if ( nArguments != N || !pReturn || !pContext ) \ + { \ + return false; \ + } \ + *pReturn = (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid(pFunction))( SCRIPT_BINDING_ARGS_##N ); \ + if ( pReturn->m_type == FIELD_VECTOR ) \ + pReturn->m_pVector = new Vector(*pReturn->m_pVector); \ + return true; \ + } \ + }; \ + \ + template \ + class CMemberScriptBinding##N \ + { \ + public: \ + static bool Call( void *pFunction, void *pContext, ScriptVariant_t *pArguments, int nArguments, ScriptVariant_t *pReturn ) \ + { \ + Assert( nArguments == N ); \ + Assert( !pReturn ); \ + Assert( pContext ); \ + \ + if ( nArguments != N || pReturn || !pContext ) \ + { \ + return false; \ + } \ + (((OBJECT_TYPE_PTR)(pContext))->*ScriptConvertFuncPtrFromVoid(pFunction))( SCRIPT_BINDING_ARGS_##N ); \ + return true; \ + } \ + }; \ + \ + template \ + inline ScriptBindingFunc_t ScriptCreateBinding(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \ + { \ + typedef FUNCTION_RETTYPE (*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \ + return &CNonMemberScriptBinding##N::Call; \ + } \ + \ + template \ + inline ScriptBindingFunc_t ScriptCreateBinding(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE (FUNCTION_CLASS::*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) ) \ + { \ + typedef FUNCTION_RETTYPE (FUNCTION_CLASS::*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \ + return &CMemberScriptBinding##N::Call; \ + } \ + \ + template \ + inline ScriptBindingFunc_t ScriptCreateBinding(OBJECT_TYPE_PTR pObject, FUNCTION_RETTYPE (FUNCTION_CLASS::*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const ) \ + { \ + typedef FUNCTION_RETTYPE (FUNCTION_CLASS::*Func_t)(FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N); \ + return &CMemberScriptBinding##N::Call; \ + } + +FUNC_GENERATE_ALL( DEFINE_SCRIPT_BINDINGS ); + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +#endif // VSCRIPT_TEMPLATES_H diff --git a/sp/src/public/vstdlib/IKeyValuesSystem.h b/sp/src/public/vstdlib/IKeyValuesSystem.h new file mode 100644 index 00000000..1bd5a8ab --- /dev/null +++ b/sp/src/public/vstdlib/IKeyValuesSystem.h @@ -0,0 +1,48 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// +#ifndef VSTDLIB_IKEYVALUESSYSTEM_H +#define VSTDLIB_IKEYVALUESSYSTEM_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vstdlib/vstdlib.h" + +// handle to a KeyValues key name symbol +typedef int HKeySymbol; +#define INVALID_KEY_SYMBOL (-1) + +//----------------------------------------------------------------------------- +// Purpose: Interface to shared data repository for KeyValues (included in vgui_controls.lib) +// allows for central data storage point of KeyValues symbol table +//----------------------------------------------------------------------------- +class IKeyValuesSystem +{ +public: + // registers the size of the KeyValues in the specified instance + // so it can build a properly sized memory pool for the KeyValues objects + // the sizes will usually never differ but this is for versioning safety + virtual void RegisterSizeofKeyValues(int size) = 0; + + // allocates/frees a KeyValues object from the shared mempool + virtual void *AllocKeyValuesMemory(int size) = 0; + virtual void FreeKeyValuesMemory(void *pMem) = 0; + + // symbol table access (used for key names) + virtual HKeySymbol GetSymbolForString( const char *name, bool bCreate = true ) = 0; + virtual const char *GetStringForSymbol(HKeySymbol symbol) = 0; + + // for debugging, adds KeyValues record into global list so we can track memory leaks + virtual void AddKeyValuesToMemoryLeakList(void *pMem, HKeySymbol name) = 0; + virtual void RemoveKeyValuesFromMemoryLeakList(void *pMem) = 0; +}; + +VSTDLIB_INTERFACE IKeyValuesSystem *KeyValuesSystem(); + +// #define KEYVALUESSYSTEM_INTERFACE_VERSION "KeyValuesSystem002" + +#endif // VSTDLIB_IKEYVALUESSYSTEM_H diff --git a/sp/src/public/vstdlib/coroutine.h b/sp/src/public/vstdlib/coroutine.h new file mode 100644 index 00000000..797324df --- /dev/null +++ b/sp/src/public/vstdlib/coroutine.h @@ -0,0 +1,69 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: setjmp/longjmp based cooperative multitasking system +// +//============================================================================= + +#ifndef COROUTINE_H +#define COROUTINE_H +#pragma once + +#include "vstdlib/vstdlib.h" + +// enable this to do coroutine tracing +// this will tell coroutine API users to set coroutine names +// #define COROUTINE_TRACE + +//----------------------------------------------------------------------------- +// Purpose: handles running coroutines +// setjmp/longjmp based cooperative multitasking system +//----------------------------------------------------------------------------- + +// coroutine callback +typedef void (__cdecl *CoroutineFunc_t )(void *); + +// handle to a coroutine +typedef int32 HCoroutine; + +// creates a new coroutine +// no coroutine code is executed until Coroutine_Continue() is called +VSTDLIB_INTERFACE HCoroutine Coroutine_Create( CoroutineFunc_t pFunc, void *pvParam ); + +// continues the specified coroutine +// returns true if the coroutine is still running, false otherwise +VSTDLIB_INTERFACE bool Coroutine_Continue( HCoroutine hCoroutine, const char *pchName = NULL ); + +// cancels a currently running coroutine +VSTDLIB_INTERFACE void Coroutine_Cancel( HCoroutine hCoroutine ); + +// 'load' a coroutine only to debug it - immediately breaks into debugger +// when continued, pops back to the prior coroutine +VSTDLIB_INTERFACE void Coroutine_DebugBreak( HCoroutine hCoroutine ); + +// Load a coroutine and generate an assert. Used to get a minidump of a job +VSTDLIB_INTERFACE void Coroutine_DebugAssert( HCoroutine hCoroutine, const char *pchMsg ); + +// called from the coroutine to return control to the main thread +VSTDLIB_INTERFACE void Coroutine_YieldToMain(); + +// returns true if the code is currently running inside of a coroutine +VSTDLIB_INTERFACE bool Coroutine_IsActive(); + +// returns a handle the currently active coroutine +VSTDLIB_INTERFACE HCoroutine Coroutine_GetCurrentlyActive(); + +// call when a thread is quiting to release any per-thread memory +VSTDLIB_INTERFACE void Coroutine_ReleaseThreadMemory(); + +// runs a self-test of the coroutine system +VSTDLIB_INTERFACE bool Coroutine_Test(); + +// memory validation +VSTDLIB_INTERFACE void Coroutine_ValidateGlobals( class CValidator &validator ); + +// for debugging purposes - returns stack depth of current coroutine +VSTDLIB_INTERFACE size_t Coroutine_GetStackDepth(); + + + +#endif // COROUTINE_H diff --git a/sp/src/public/vstdlib/cvar.h b/sp/src/public/vstdlib/cvar.h new file mode 100644 index 00000000..63734411 --- /dev/null +++ b/sp/src/public/vstdlib/cvar.h @@ -0,0 +1,25 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#if !defined( CVAR_H ) +#define CVAR_H +#ifdef _WIN32 +#pragma once +#endif + +#include "vstdlib/vstdlib.h" +#include "icvar.h" + + +//----------------------------------------------------------------------------- +// Returns a CVar dictionary for tool usage +//----------------------------------------------------------------------------- +VSTDLIB_INTERFACE CreateInterfaceFn VStdLib_GetICVarFactory(); + + +#endif // CVAR_H diff --git a/sp/src/public/vstdlib/iprocessutils.h b/sp/src/public/vstdlib/iprocessutils.h new file mode 100644 index 00000000..8e4d37f8 --- /dev/null +++ b/sp/src/public/vstdlib/iprocessutils.h @@ -0,0 +1,64 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//===========================================================================// + +#ifndef IPROCESSUTILS_H +#define IPROCESSUTILS_H + +#ifdef _WIN32 +#pragma once +#endif + + +#include "appframework/IAppSystem.h" + + +//----------------------------------------------------------------------------- +// Handle to a process +//----------------------------------------------------------------------------- +typedef int ProcessHandle_t; +enum +{ + PROCESS_HANDLE_INVALID = 0, +}; + + +//----------------------------------------------------------------------------- +// Interface version +//----------------------------------------------------------------------------- +#define PROCESS_UTILS_INTERFACE_VERSION "VProcessUtils001" + + +//----------------------------------------------------------------------------- +// Interface for makefiles to build differently depending on where they are run from +//----------------------------------------------------------------------------- +abstract_class IProcessUtils : public IAppSystem +{ +public: + // Starts, stops a process + virtual ProcessHandle_t StartProcess( const char *pCommandLine, bool bConnectStdPipes ) = 0; + virtual ProcessHandle_t StartProcess( int argc, const char **argv, bool bConnectStdPipes ) = 0; + virtual void CloseProcess( ProcessHandle_t hProcess ) = 0; + virtual void AbortProcess( ProcessHandle_t hProcess ) = 0; + + // Returns true if a process is complete + virtual bool IsProcessComplete( ProcessHandle_t hProcess ) = 0; + + // Waits until a process is complete + virtual void WaitUntilProcessCompletes( ProcessHandle_t hProcess ) = 0; + + // Methods used to write input into a process + virtual int SendProcessInput( ProcessHandle_t hProcess, char *pBuf, int nBufLen ) = 0; + + // Methods used to read output back from a process + virtual int GetProcessOutputSize( ProcessHandle_t hProcess ) = 0; + virtual int GetProcessOutput( ProcessHandle_t hProcess, char *pBuf, int nBufLen ) = 0; + + // Returns the exit code for the process. Doesn't work unless the process is complete + virtual int GetProcessExitCode( ProcessHandle_t hProcess ) = 0; +}; + + +#endif // IPROCESSUTILS_H diff --git a/sp/src/public/vstdlib/jobthread.h b/sp/src/public/vstdlib/jobthread.h new file mode 100644 index 00000000..559937b3 --- /dev/null +++ b/sp/src/public/vstdlib/jobthread.h @@ -0,0 +1,1344 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A utility for a discrete job-oriented worker thread. +// +// The class CThreadPool is both the job queue, and the +// worker thread. Except when the main thread attempts to +// synchronously execute a job, most of the inter-thread locking +// on the queue. +// +// The queue threading model uses a manual reset event for optimal +// throughput. Adding to the queue is guarded by a semaphore that +// will block the inserting thread if the queue has overflown. +// This prevents the worker thread from being starved out even if +// not running at a higher priority than the master thread. +// +// The thread function waits for jobs, services jobs, and manages +// communication between the worker and master threads. The nature +// of the work is opaque to the Executer. +// +// CJob instances actually do the work. The base class +// calls virtual methods for job primitives, so derivations don't +// need to worry about threading models. All of the variants of +// job and OS can be expressed in this hierarchy. Instances of +// CJob are the items placed in the queue, and by +// overriding the job primitives they are the manner by which +// users of the Executer control the state of the job. +// +//============================================================================= + +#include +#include "tier0/threadtools.h" +#include "tier1/refcount.h" +#include "tier1/utllinkedlist.h" +#include "tier1/utlvector.h" +#include "tier1/functors.h" +#include "tier0/vprof_telemetry.h" + +#include "vstdlib/vstdlib.h" + +#ifndef JOBTHREAD_H +#define JOBTHREAD_H + +#ifdef AddJob // windows.h print function collisions +#undef AddJob +#undef GetJob +#endif + +#ifdef VSTDLIB_DLL_EXPORT +#define JOB_INTERFACE DLL_EXPORT +#define JOB_OVERLOAD DLL_GLOBAL_EXPORT +#define JOB_CLASS DLL_CLASS_EXPORT +#else +#define JOB_INTERFACE DLL_IMPORT +#define JOB_OVERLOAD DLL_GLOBAL_IMPORT +#define JOB_CLASS DLL_CLASS_IMPORT +#endif + +#if defined( _WIN32 ) +#pragma once +#endif + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- + +class CJob; + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +enum JobStatusEnum_t +{ + // Use negative for errors + JOB_OK, // operation is successful + JOB_STATUS_PENDING, // file is properly queued, waiting for service + JOB_STATUS_INPROGRESS, // file is being accessed + JOB_STATUS_ABORTED, // file was aborted by caller + JOB_STATUS_UNSERVICED, // file is not yet queued +}; + +typedef int JobStatus_t; + +enum JobFlags_t +{ + JF_IO = ( 1 << 0 ), // The job primarily blocks on IO or hardware + JF_BOOST_THREAD = ( 1 << 1 ), // Up the thread priority to max allowed while processing task + JF_SERIAL = ( 1 << 2 ), // Job cannot be executed out of order relative to other "strict" jobs + JF_QUEUE = ( 1 << 3 ), // Queue it, even if not an IO job +}; + +enum JobPriority_t +{ + JP_LOW, + JP_NORMAL, + JP_HIGH +}; + +#define TP_MAX_POOL_THREADS 64 +struct ThreadPoolStartParams_t +{ + ThreadPoolStartParams_t( bool bIOThreads = false, unsigned nThreads = -1, int *pAffinities = NULL, ThreeState_t fDistribute = TRS_NONE, unsigned nStackSize = -1, int iThreadPriority = SHRT_MIN ) + : bIOThreads( bIOThreads ), nThreads( nThreads ), fDistribute( fDistribute ), nStackSize( nStackSize ), iThreadPriority( iThreadPriority ), nThreadsMax( -1 ) + { + bExecOnThreadPoolThreadsOnly = false; + + bUseAffinityTable = ( pAffinities != NULL ) && ( fDistribute == TRS_TRUE ) && ( nThreads != -1 ); + if ( bUseAffinityTable ) + { + // user supplied an optional 1:1 affinity mapping to override normal distribute behavior + nThreads = MIN( TP_MAX_POOL_THREADS, nThreads ); + for ( unsigned int i = 0; i < nThreads; i++ ) + { + iAffinityTable[i] = pAffinities[i]; + } + } + } + + int nThreads; + int nThreadsMax; + ThreeState_t fDistribute; + int nStackSize; + int iThreadPriority; + int iAffinityTable[TP_MAX_POOL_THREADS]; + + bool bIOThreads : 1; + bool bUseAffinityTable : 1; + bool bExecOnThreadPoolThreadsOnly : 1; +}; + +//----------------------------------------------------------------------------- +// +// IThreadPool +// +//----------------------------------------------------------------------------- + +typedef bool (*JobFilter_t)( CJob * ); + +//--------------------------------------------------------- +// Messages supported through the CallWorker() method +//--------------------------------------------------------- +enum ThreadPoolMessages_t +{ + TPM_EXIT, // Exit the thread + TPM_SUSPEND, // Suspend after next operation + TPM_RUNFUNCTOR, // Run functor, reply when done. +}; + +//--------------------------------------------------------- + +abstract_class IThreadPool : public IRefCounted +{ +public: + virtual ~IThreadPool() {}; + + //----------------------------------------------------- + // Thread functions + //----------------------------------------------------- + virtual bool Start( const ThreadPoolStartParams_t &startParams = ThreadPoolStartParams_t() ) = 0; + virtual bool Stop( int timeout = TT_INFINITE ) = 0; + + //----------------------------------------------------- + // Functions for any thread + //----------------------------------------------------- + virtual unsigned GetJobCount() = 0; + virtual int NumThreads() = 0; + virtual int NumIdleThreads() = 0; + + //----------------------------------------------------- + // Pause/resume processing jobs + //----------------------------------------------------- + virtual int SuspendExecution() = 0; + virtual int ResumeExecution() = 0; + + //----------------------------------------------------- + // Offer the current thread to the pool + //----------------------------------------------------- + virtual int YieldWait( CThreadEvent **pEvents, int nEvents, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) = 0; + virtual int YieldWait( CJob **, int nJobs, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) = 0; + virtual void Yield( unsigned timeout ) = 0; + + bool YieldWait( CThreadEvent &event, unsigned timeout = TT_INFINITE ); + bool YieldWait( CJob *, unsigned timeout = TT_INFINITE ); + + //----------------------------------------------------- + // Add a native job to the queue (master thread) + //----------------------------------------------------- + virtual void AddJob( CJob * ) = 0; + + //----------------------------------------------------- + // All threads execute pFunctor asap. Thread will either wake up + // and execute or execute pFunctor right after completing current job and + // before looking for another job. + //----------------------------------------------------- + virtual void ExecuteHighPriorityFunctor( CFunctor *pFunctor ) = 0; + + //----------------------------------------------------- + // Add an function object to the queue (master thread) + //----------------------------------------------------- + virtual void AddFunctor( CFunctor *pFunctor, CJob **ppJob = NULL, const char *pszDescription = NULL, unsigned flags = 0 ) { AddFunctorInternal( RetAddRef( pFunctor ), ppJob, pszDescription, flags ); } + + //----------------------------------------------------- + // Change the priority of an active job + //----------------------------------------------------- + virtual void ChangePriority( CJob *p, JobPriority_t priority ) = 0; + + //----------------------------------------------------- + // Bulk job manipulation (blocking) + //----------------------------------------------------- + int ExecuteAll( JobFilter_t pfnFilter = NULL ) { return ExecuteToPriority( JP_LOW, pfnFilter ); } + virtual int ExecuteToPriority( JobPriority_t toPriority, JobFilter_t pfnFilter = NULL ) = 0; + virtual int AbortAll() = 0; + + //----------------------------------------------------- + virtual void Reserved1() = 0; + + //----------------------------------------------------- + // Add an arbitrary call to the queue (master thread) + // + // Avert thy eyes! Imagine rather: + // + // CJob *AddCall( , [args1, [arg2,]...] + // CJob *AddCall( , , [args1, [arg2,]...] + // CJob *AddRefCall( , , [args1, [arg2,]...] + // CJob *QueueCall( , [args1, [arg2,]...] + // CJob *QueueCall( , , [args1, [arg2,]...] + //----------------------------------------------------- + + #define DEFINE_NONMEMBER_ADD_CALL(N) \ + template \ + CJob *AddCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + //------------------------------------- + + #define DEFINE_MEMBER_ADD_CALL(N) \ + template \ + CJob *AddCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + //------------------------------------- + + #define DEFINE_CONST_MEMBER_ADD_CALL(N) \ + template \ + CJob *AddCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + //------------------------------------- + + #define DEFINE_REF_COUNTING_MEMBER_ADD_CALL(N) \ + template \ + CJob *AddRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + //------------------------------------- + + #define DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL(N) \ + template \ + CJob *AddRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + if ( !NumIdleThreads() ) \ + { \ + pJob = GetDummyJob(); \ + FunctorDirectCall( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob ); \ + } \ + \ + return pJob; \ + } + + //----------------------------------------------------------------------------- + + #define DEFINE_NONMEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueCall(FUNCTION_RETTYPE (*pfnProxied)( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateFunctor( pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + return pJob; \ + } + + //------------------------------------- + + #define DEFINE_MEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + return pJob; \ + } + + //------------------------------------- + + #define DEFINE_CONST_MEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + return pJob; \ + } + + //------------------------------------- + + #define DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + return pJob; \ + } + + //------------------------------------- + + #define DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL(N) \ + template \ + CJob *QueueRefCall(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( FUNC_BASE_TEMPLATE_FUNC_PARAMS_##N ) const FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + CJob *pJob; \ + AddFunctorInternal( CreateRefCountingFunctor( pObject, pfnProxied FUNC_FUNCTOR_CALL_ARGS_##N ), &pJob, NULL, JF_QUEUE ); \ + \ + return pJob; \ + } + + FUNC_GENERATE_ALL( DEFINE_NONMEMBER_ADD_CALL ); + FUNC_GENERATE_ALL( DEFINE_MEMBER_ADD_CALL ); + FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_ADD_CALL ); + FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_ADD_CALL ); + FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL ); + FUNC_GENERATE_ALL( DEFINE_NONMEMBER_QUEUE_CALL ); + FUNC_GENERATE_ALL( DEFINE_MEMBER_QUEUE_CALL ); + FUNC_GENERATE_ALL( DEFINE_CONST_MEMBER_QUEUE_CALL ); + FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL ); + FUNC_GENERATE_ALL( DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL ); + + #undef DEFINE_NONMEMBER_ADD_CALL + #undef DEFINE_MEMBER_ADD_CALL + #undef DEFINE_CONST_MEMBER_ADD_CALL + #undef DEFINE_REF_COUNTING_MEMBER_ADD_CALL + #undef DEFINE_REF_COUNTING_CONST_MEMBER_ADD_CALL + #undef DEFINE_NONMEMBER_QUEUE_CALL + #undef DEFINE_MEMBER_QUEUE_CALL + #undef DEFINE_CONST_MEMBER_QUEUE_CALL + #undef DEFINE_REF_COUNTING_MEMBER_QUEUE_CALL + #undef DEFINE_REF_COUNTING_CONST_MEMBER_QUEUE_CALL + +private: + virtual void AddFunctorInternal( CFunctor *, CJob ** = NULL, const char *pszDescription = NULL, unsigned flags = 0 ) = 0; + + //----------------------------------------------------- + // Services for internal use by job instances + //----------------------------------------------------- + friend class CJob; + + virtual CJob *GetDummyJob() = 0; + +public: + virtual void Distribute( bool bDistribute = true, int *pAffinityTable = NULL ) = 0; + + virtual bool Start( const ThreadPoolStartParams_t &startParams, const char *pszNameOverride ) = 0; +}; + +//----------------------------------------------------------------------------- + +JOB_INTERFACE IThreadPool *CreateThreadPool(); +JOB_INTERFACE void DestroyThreadPool( IThreadPool *pPool ); + +//------------------------------------- + +JOB_INTERFACE void RunThreadPoolTests(); + +//----------------------------------------------------------------------------- + +JOB_INTERFACE IThreadPool *g_pThreadPool; + +//----------------------------------------------------------------------------- +// Class to combine the metadata for an operation and the ability to perform +// the operation. Meant for inheritance. All functions inline, defers to executor +//----------------------------------------------------------------------------- +DECLARE_POINTER_HANDLE( ThreadPoolData_t ); +#define JOB_NO_DATA ((ThreadPoolData_t)-1) + +class CJob : public CRefCounted1 +{ +public: + CJob( JobPriority_t priority = JP_NORMAL ) + : m_status( JOB_STATUS_UNSERVICED ), + m_ThreadPoolData( JOB_NO_DATA ), + m_priority( priority ), + m_flags( 0 ), + m_pThreadPool( NULL ), + m_CompleteEvent( true ), + m_iServicingThread( -1 ) + { + m_szDescription[ 0 ] = 0; + } + + //----------------------------------------------------- + // Priority (not thread safe) + //----------------------------------------------------- + void SetPriority( JobPriority_t priority ) { m_priority = priority; } + JobPriority_t GetPriority() const { return m_priority; } + + //----------------------------------------------------- + + void SetFlags( unsigned flags ) { m_flags = flags; } + unsigned GetFlags() const { return m_flags; } + + //----------------------------------------------------- + + void SetServiceThread( int iServicingThread ) { m_iServicingThread = (char)iServicingThread; } + int GetServiceThread() const { return m_iServicingThread; } + void ClearServiceThread() { m_iServicingThread = -1; } + + //----------------------------------------------------- + // Fast queries + //----------------------------------------------------- + bool Executed() const { return ( m_status == JOB_OK ); } + bool CanExecute() const { return ( m_status == JOB_STATUS_PENDING || m_status == JOB_STATUS_UNSERVICED ); } + bool IsFinished() const { return ( m_status != JOB_STATUS_PENDING && m_status != JOB_STATUS_INPROGRESS && m_status != JOB_STATUS_UNSERVICED ); } + JobStatus_t GetStatus() const { return m_status; } + + /// Slam the status to a particular value. This is named "slam" instead of "set," + /// to warn you that it should only be used in unusual situations. Otherwise, the + /// job manager really should manage the status for you, and you should not manhandle it. + void SlamStatus(JobStatus_t s) { m_status = s; } + + //----------------------------------------------------- + // Try to acquire ownership (to satisfy). If you take the lock, you must either execute or abort. + //----------------------------------------------------- + bool TryLock() { return m_mutex.TryLock(); } + void Lock() { m_mutex.Lock(); } + void Unlock() { m_mutex.Unlock(); } + + //----------------------------------------------------- + // Thread event support (safe for NULL this to simplify code ) + //----------------------------------------------------- + bool WaitForFinish( uint32 dwTimeout = TT_INFINITE ) { if (!this) return true; return ( !IsFinished() ) ? g_pThreadPool->YieldWait( this, dwTimeout ) : true; } + bool WaitForFinishAndRelease( uint32 dwTimeout = TT_INFINITE ) { if (!this) return true; bool bResult = WaitForFinish( dwTimeout); Release(); return bResult; } + CThreadEvent *AccessEvent() { return &m_CompleteEvent; } + + //----------------------------------------------------- + // Perform the job + //----------------------------------------------------- + JobStatus_t Execute(); + JobStatus_t TryExecute(); + JobStatus_t ExecuteAndRelease() { JobStatus_t status = Execute(); Release(); return status; } + JobStatus_t TryExecuteAndRelease() { JobStatus_t status = TryExecute(); Release(); return status; } + + //----------------------------------------------------- + // Terminate the job, discard if partially or wholly fulfilled + //----------------------------------------------------- + JobStatus_t Abort( bool bDiscard = true ); + + virtual char const *Describe() { return m_szDescription[ 0 ] ? m_szDescription : "Job"; } + virtual void SetDescription( const char *pszDescription ) + { + if( pszDescription ) + { + Q_strncpy( m_szDescription, pszDescription, sizeof( m_szDescription ) ); + } + else + { + m_szDescription[ 0 ] = 0; + } + } + +private: + //----------------------------------------------------- + friend class CThreadPool; + + JobStatus_t m_status; + JobPriority_t m_priority; + CThreadMutex m_mutex; + unsigned char m_flags; + char m_iServicingThread; + short m_reserved; + ThreadPoolData_t m_ThreadPoolData; + IThreadPool * m_pThreadPool; + CThreadEvent m_CompleteEvent; + char m_szDescription[ 32 ]; + +private: + //----------------------------------------------------- + CJob( const CJob &fromRequest ); + void operator=(const CJob &fromRequest ); + + virtual JobStatus_t DoExecute() = 0; + virtual JobStatus_t DoAbort( bool bDiscard ) { return JOB_STATUS_ABORTED; } + virtual void DoCleanup() {} +}; + +//----------------------------------------------------------------------------- + +class CFunctorJob : public CJob +{ +public: + CFunctorJob( CFunctor *pFunctor, const char *pszDescription = NULL ) + : m_pFunctor( pFunctor ) + { + if ( pszDescription ) + { + Q_strncpy( m_szDescription, pszDescription, sizeof(m_szDescription) ); + } + else + { + m_szDescription[0] = 0; + } + } + + virtual JobStatus_t DoExecute() + { + (*m_pFunctor)(); + return JOB_OK; + } + + const char *Describe() + { + return m_szDescription; + } + +private: + CRefPtr m_pFunctor; + char m_szDescription[16]; +}; + +//----------------------------------------------------------------------------- +// Utility for managing multiple jobs +//----------------------------------------------------------------------------- + +class CJobSet +{ +public: + CJobSet( CJob *pJob = NULL ) + { + if ( pJob ) + { + m_jobs.AddToTail( pJob ); + } + } + + CJobSet( CJob **ppJobs, int nJobs ) + { + if ( ppJobs ) + { + m_jobs.AddMultipleToTail( nJobs, ppJobs ); + } + } + + ~CJobSet() + { + for ( int i = 0; i < m_jobs.Count(); i++ ) + { + m_jobs[i]->Release(); + } + } + + void operator+=( CJob *pJob ) + { + m_jobs.AddToTail( pJob ); + } + + void operator-=( CJob *pJob ) + { + m_jobs.FindAndRemove( pJob ); + } + + void Execute( bool bRelease = true ) + { + for ( int i = 0; i < m_jobs.Count(); i++ ) + { + m_jobs[i]->Execute(); + if ( bRelease ) + { + m_jobs[i]->Release(); + } + } + + if ( bRelease ) + { + m_jobs.RemoveAll(); + } + } + + void Abort( bool bRelease = true ) + { + for ( int i = 0; i < m_jobs.Count(); i++ ) + { + m_jobs[i]->Abort(); + if ( bRelease ) + { + m_jobs[i]->Release(); + } + } + + if ( bRelease ) + { + m_jobs.RemoveAll(); + } + } + + void WaitForFinish( bool bRelease = true ) + { + for ( int i = 0; i < m_jobs.Count(); i++ ) + { + m_jobs[i]->WaitForFinish(); + if ( bRelease ) + { + m_jobs[i]->Release(); + } + } + + if ( bRelease ) + { + m_jobs.RemoveAll(); + } + } + + void WaitForFinish( IThreadPool *pPool, bool bRelease = true ) + { + pPool->YieldWait( m_jobs.Base(), m_jobs.Count() ); + + if ( bRelease ) + { + for ( int i = 0; i < m_jobs.Count(); i++ ) + { + m_jobs[i]->Release(); + } + + m_jobs.RemoveAll(); + } + } + +private: + CUtlVectorFixed m_jobs; +}; + +//----------------------------------------------------------------------------- +// Job helpers +//----------------------------------------------------------------------------- + +#define ThreadExecute g_pThreadPool->QueueCall +#define ThreadExecuteRef g_pThreadPool->QueueRefCall + +#define BeginExecuteParallel() do { CJobSet jobSet +#define EndExecuteParallel() jobSet.WaitForFinish( g_pThreadPool ); } while (0) + +#define ExecuteParallel jobSet += g_pThreadPool->QueueCall +#define ExecuteRefParallel jobSet += g_pThreadPool->QueueCallRef + + +//----------------------------------------------------------------------------- +// Work splitting: array split, best when cost per item is roughly equal +//----------------------------------------------------------------------------- + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4389) +#pragma warning(disable:4018) +#pragma warning(disable:4701) +#endif + +#define DEFINE_NON_MEMBER_ITER_RANGE_PARALLEL(N) \ + template \ + void IterRangeParallel(FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( ITERTYPE1, ITERTYPE2 FUNC_ADDL_TEMPLATE_FUNC_PARAMS_##N ), ITERTYPE1 from, ITERTYPE2 to FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + const int MAX_THREADS = 16; \ + int nIdle = g_pThreadPool->NumIdleThreads(); \ + ITERTYPE1 range = to - from; \ + int nThreads = MIN( nIdle + 1, range ); \ + if ( nThreads > MAX_THREADS ) \ + { \ + nThreads = MAX_THREADS; \ + } \ + if ( nThreads < 2 ) \ + { \ + FunctorDirectCall( pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + ITERTYPE1 nIncrement = range / nThreads; \ + \ + CJobSet jobSet; \ + while ( --nThreads ) \ + { \ + ITERTYPE2 thisTo = from + nIncrement; \ + jobSet += g_pThreadPool->AddCall( pfnProxied, from, thisTo FUNC_FUNCTOR_CALL_ARGS_##N ); \ + from = thisTo; \ + } \ + FunctorDirectCall( pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ + jobSet.WaitForFinish( g_pThreadPool ); \ + } \ + \ + } + +FUNC_GENERATE_ALL( DEFINE_NON_MEMBER_ITER_RANGE_PARALLEL ); + +#define DEFINE_MEMBER_ITER_RANGE_PARALLEL(N) \ + template \ + void IterRangeParallel(OBJECT_TYPE *pObject, FUNCTION_RETTYPE ( FUNCTION_CLASS::*pfnProxied )( ITERTYPE1, ITERTYPE2 FUNC_ADDL_TEMPLATE_FUNC_PARAMS_##N ), ITERTYPE1 from, ITERTYPE2 to FUNC_ARG_FORMAL_PARAMS_##N ) \ + { \ + const int MAX_THREADS = 16; \ + int nIdle = g_pThreadPool->NumIdleThreads(); \ + ITERTYPE1 range = to - from; \ + int nThreads = MIN( nIdle + 1, range ); \ + if ( nThreads > MAX_THREADS ) \ + { \ + nThreads = MAX_THREADS; \ + } \ + if ( nThreads < 2 ) \ + { \ + FunctorDirectCall( pObject, pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ + } \ + else \ + { \ + ITERTYPE1 nIncrement = range / nThreads; \ + \ + CJobSet jobSet; \ + while ( --nThreads ) \ + { \ + ITERTYPE2 thisTo = from + nIncrement; \ + jobSet += g_pThreadPool->AddCall( pObject, pfnProxied, from, thisTo FUNC_FUNCTOR_CALL_ARGS_##N ); \ + from = thisTo; \ + } \ + FunctorDirectCall( pObject, pfnProxied, from, to FUNC_FUNCTOR_CALL_ARGS_##N ); \ + jobSet.WaitForFinish( g_pThreadPool ); \ + } \ + \ + } + +FUNC_GENERATE_ALL( DEFINE_MEMBER_ITER_RANGE_PARALLEL ); + +//----------------------------------------------------------------------------- +// Work splitting: competitive, best when cost per item varies a lot +//----------------------------------------------------------------------------- + +template +class CJobItemProcessor +{ +public: + typedef T ItemType_t; + void Begin() {} + // void Process( ItemType_t & ) {} + void End() {} +}; + +template +class CFuncJobItemProcessor : public CJobItemProcessor +{ +public: + void Init(void (*pfnProcess)( T & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL ) + { + m_pfnProcess = pfnProcess; + m_pfnBegin = pfnBegin; + m_pfnEnd = pfnEnd; + } + + //CFuncJobItemProcessor(OBJECT_TYPE_PTR pObject, void (FUNCTION_CLASS::*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL ); + void Begin() { if ( m_pfnBegin ) (*m_pfnBegin)(); } + void Process( T &item ) { (*m_pfnProcess)( item ); } + void End() { if ( m_pfnEnd ) (*m_pfnEnd)(); } + +protected: + void (*m_pfnProcess)( T & ); + void (*m_pfnBegin)(); + void (*m_pfnEnd)(); +}; + +template +class CMemberFuncJobItemProcessor : public CJobItemProcessor +{ +public: + void Init( OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( T & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL ) + { + m_pObject = pObject; + m_pfnProcess = pfnProcess; + m_pfnBegin = pfnBegin; + m_pfnEnd = pfnEnd; + } + + void Begin() { if ( m_pfnBegin ) ((*m_pObject).*m_pfnBegin)(); } + void Process( T &item ) { ((*m_pObject).*m_pfnProcess)( item ); } + void End() { if ( m_pfnEnd ) ((*m_pObject).*m_pfnEnd)(); } + +protected: + OBJECT_TYPE *m_pObject; + void (FUNCTION_CLASS::*m_pfnProcess)( T & ); + void (FUNCTION_CLASS::*m_pfnBegin)(); + void (FUNCTION_CLASS::*m_pfnEnd)(); +}; + +template +class CParallelProcessor +{ +public: + CParallelProcessor( const char *pszDescription ) + { + m_pItems = m_pLimit= 0; + m_szDescription = pszDescription; + } + + void Run( ITEM_TYPE *pItems, unsigned nItems, int nMaxParallel = INT_MAX, IThreadPool *pThreadPool = NULL ) + { + tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "Run %s %d", m_szDescription, nItems ); + + if ( nItems == 0 ) + return; + + if ( !pThreadPool ) + { + pThreadPool = g_pThreadPool; + } + + m_pItems = pItems; + m_pLimit = pItems + nItems; + + int nJobs = nItems - 1; + + if ( nJobs > nMaxParallel ) + { + nJobs = nMaxParallel; + } + + if (! pThreadPool ) // only possible on linux + { + DoExecute( ); + return; + } + + int nThreads = pThreadPool->NumThreads(); + if ( nJobs > nThreads ) + { + nJobs = nThreads; + } + + if ( nJobs > 1 ) + { + CJob **jobs = (CJob **)stackalloc( nJobs * sizeof(CJob **) ); + int i = nJobs; + + while( i-- ) + { + jobs[i] = pThreadPool->QueueCall( this, &CParallelProcessor::DoExecute ); + jobs[i]->SetDescription( m_szDescription ); + } + + DoExecute(); + + for ( i = 0; i < nJobs; i++ ) + { + jobs[i]->Abort(); // will either abort ones that never got a thread, or noop on ones that did + jobs[i]->Release(); + } + } + else + { + DoExecute(); + } + } + + ITEM_PROCESSOR_TYPE m_ItemProcessor; + +private: + void DoExecute() + { + tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "DoExecute %s", m_szDescription ); + + if ( m_pItems < m_pLimit ) + { + m_ItemProcessor.Begin(); + + ITEM_TYPE *pLimit = m_pLimit; + + for (;;) + { + ITEM_TYPE *pCurrent = m_pItems++; + if ( pCurrent < pLimit ) + { + m_ItemProcessor.Process( *pCurrent ); + } + else + { + break; + } + } + + m_ItemProcessor.End(); + } + } + CInterlockedPtr m_pItems; + ITEM_TYPE * m_pLimit; + const char * m_szDescription; +}; + +template +inline void ParallelProcess( const char *pszDescription, ITEM_TYPE *pItems, unsigned nItems, void (*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) +{ + CParallelProcessor > processor( pszDescription ); + processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd ); + processor.Run( pItems, nItems, nMaxParallel ); + +} + +template +inline void ParallelProcess( const char *pszDescription, ITEM_TYPE *pItems, unsigned nItems, OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( ITEM_TYPE & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) +{ + CParallelProcessor > processor( pszDescription ); + processor.m_ItemProcessor.Init( pObject, pfnProcess, pfnBegin, pfnEnd ); + processor.Run( pItems, nItems, nMaxParallel ); +} + +// Parallel Process that lets you specify threadpool +template +inline void ParallelProcess( const char *pszDescription, IThreadPool *pPool, ITEM_TYPE *pItems, unsigned nItems, void (*pfnProcess)( ITEM_TYPE & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) +{ + CParallelProcessor > processor( pszDescription ); + processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd ); + processor.Run( pItems, nItems, nMaxParallel, pPool ); +} + + +template +class CParallelLoopProcessor +{ +public: + CParallelLoopProcessor( const char *pszDescription ) + { + m_lIndex = m_lLimit= 0; + m_nActive = 0; + m_szDescription = pszDescription; + } + + void Run( long lBegin, long nItems, int nMaxParallel = INT_MAX ) + { + if ( nItems ) + { + m_lIndex = lBegin; + m_lLimit = lBegin + nItems; + int i = g_pThreadPool->NumIdleThreads(); + + if ( nMaxParallel < i) + { + i = nMaxParallel; + } + + while( i-- ) + { + ++m_nActive; + ThreadExecute( this, &CParallelLoopProcessor::DoExecute )->Release(); + } + + ++m_nActive; + DoExecute(); + + while ( m_nActive ) + { + ThreadPause(); + } + } + } + + ITEM_PROCESSOR_TYPE m_ItemProcessor; + +private: + void DoExecute() + { + tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "DoExecute %s", m_szDescription ); + + m_ItemProcessor.Begin(); + + long lLimit = m_lLimit; + + for (;;) + { + long lIndex = m_lIndex ++; + if ( lIndex < lLimit ) + { + m_ItemProcessor.Process( lIndex ); + } + else + { + break; + } + } + + m_ItemProcessor.End(); + + --m_nActive; + } + CInterlockedInt m_lIndex; + long m_lLimit; + CInterlockedInt m_nActive; + const char * m_szDescription; +}; + +inline void ParallelLoopProcess( const char *szDescription, long lBegin, unsigned nItems, void (*pfnProcess)( long const & ), void (*pfnBegin)() = NULL, void (*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) +{ + CParallelLoopProcessor< CFuncJobItemProcessor< long const > > processor( szDescription ); + processor.m_ItemProcessor.Init( pfnProcess, pfnBegin, pfnEnd ); + processor.Run( lBegin, nItems, nMaxParallel ); + +} + +template < typename OBJECT_TYPE, typename FUNCTION_CLASS > +inline void ParallelLoopProcess( const char *szDescription, long lBegin, unsigned nItems, OBJECT_TYPE *pObject, void (FUNCTION_CLASS::*pfnProcess)( long const & ), void (FUNCTION_CLASS::*pfnBegin)() = NULL, void (FUNCTION_CLASS::*pfnEnd)() = NULL, int nMaxParallel = INT_MAX ) +{ + CParallelLoopProcessor< CMemberFuncJobItemProcessor > processor( szDescription ); + processor.m_ItemProcessor.Init( pObject, pfnProcess, pfnBegin, pfnEnd ); + processor.Run( lBegin, nItems, nMaxParallel ); +} + + +template +class CParallelProcessorBase +{ +protected: + typedef CParallelProcessorBase ThisParallelProcessorBase_t; + typedef Derived ThisParallelProcessorDerived_t; + +public: + CParallelProcessorBase() + { + m_nActive = 0; + m_szDescription = NULL; + } + void SetDescription( const char *pszDescription ) + { + m_szDescription = pszDescription; + } + +protected: + void Run( int nMaxParallel = INT_MAX, int threadOverride = -1 ) + { + int i = g_pThreadPool->NumIdleThreads(); + + if ( nMaxParallel < i) + { + i = nMaxParallel; + } + + while( i -- > 0 ) + { + if ( threadOverride == -1 || i == threadOverride - 1 ) + { + ++ m_nActive; + ThreadExecute( this, &ThisParallelProcessorBase_t::DoExecute )->Release(); + } + } + + if ( threadOverride == -1 || threadOverride == 0 ) + { + ++ m_nActive; + DoExecute(); + } + + while ( m_nActive ) + { + ThreadPause(); + } + } + +protected: + void OnBegin() {} + bool OnProcess() { return false; } + void OnEnd() {} + +private: + void DoExecute() + { + tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "DoExecute %s", m_szDescription ); + + static_cast( this )->OnBegin(); + + while ( static_cast( this )->OnProcess() ) + continue; + + static_cast(this)->OnEnd(); + + -- m_nActive; + } + + CInterlockedInt m_nActive; + const char * m_szDescription; +}; + + + + +//----------------------------------------------------------------------------- +// Raw thread launching +//----------------------------------------------------------------------------- + +inline unsigned FunctorExecuteThread( void *pParam ) +{ + CFunctor *pFunctor = (CFunctor *)pParam; + (*pFunctor)(); + pFunctor->Release(); + return 0; +} + +inline ThreadHandle_t ThreadExecuteSoloImpl( CFunctor *pFunctor, const char *pszName = NULL ) +{ + ThreadHandle_t hThread; + ThreadId_t threadId; + hThread = CreateSimpleThread( FunctorExecuteThread, pFunctor, &threadId ); + if ( pszName ) + { + ThreadSetDebugName( threadId, pszName ); + } + return hThread; +} + +inline ThreadHandle_t ThreadExecuteSolo( CJob *pJob ) { return ThreadExecuteSoloImpl( CreateFunctor( pJob, &CJob::Execute ), pJob->Describe() ); } + +template +inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6, a7 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSolo( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8 ) { return ThreadExecuteSoloImpl( CreateFunctor( a1, a2, a3, a4, a5, a6, a7, a8 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6, a7 ), pszName ); } + +template +inline ThreadHandle_t ThreadExecuteSoloRef( const char *pszName, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7, T8 a8 ) { return ThreadExecuteSoloImpl( CreateRefCountingFunctor(a1, a2, a3, a4, a5, a6, a7, a8 ), pszName ); } + +//----------------------------------------------------------------------------- + +inline bool IThreadPool::YieldWait( CThreadEvent &event, unsigned timeout ) +{ + CThreadEvent *pEvent = &event; + return ( YieldWait( &pEvent, 1, true, timeout ) != TW_TIMEOUT ); +} + +inline bool IThreadPool::YieldWait( CJob *pJob, unsigned timeout ) +{ + return ( YieldWait( &pJob, 1, true, timeout ) != TW_TIMEOUT ); +} + +//----------------------------------------------------------------------------- + +inline JobStatus_t CJob::Execute() +{ + if ( IsFinished() ) + { + return m_status; + } + + tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %s %d", __FUNCTION__, Describe(), m_status ); + + AUTO_LOCK( m_mutex ); + AddRef(); + + JobStatus_t result; + + switch ( m_status ) + { + case JOB_STATUS_UNSERVICED: + case JOB_STATUS_PENDING: + { + // Service it + m_status = JOB_STATUS_INPROGRESS; + result = m_status = DoExecute(); + DoCleanup(); + m_CompleteEvent.Set(); + break; + } + + case JOB_STATUS_INPROGRESS: + AssertMsg(0, "Mutex Should have protected use while processing"); + // fall through... + + case JOB_OK: + case JOB_STATUS_ABORTED: + result = m_status; + break; + + default: + AssertMsg( m_status < JOB_OK, "Unknown job state"); + result = m_status; + } + + Release(); + + return result; +} + + +//--------------------------------------------------------- + +inline JobStatus_t CJob::TryExecute() +{ + tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %s %d", __FUNCTION__, Describe(), m_status ); + + // TryLock() would only fail if another thread has entered + // Execute() or Abort() + if ( !IsFinished() && TryLock() ) + { + // ...service the request + Execute(); + Unlock(); + } + return m_status; +} + +//--------------------------------------------------------- + +inline JobStatus_t CJob::Abort( bool bDiscard ) +{ + if ( IsFinished() ) + { + return m_status; + } + + tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s %s %d", __FUNCTION__, Describe(), m_status ); + + AUTO_LOCK( m_mutex ); + AddRef(); + + JobStatus_t result; + + switch ( m_status ) + { + case JOB_STATUS_UNSERVICED: + case JOB_STATUS_PENDING: + { + tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "CJob::DoAbort" ); + + result = m_status = DoAbort( bDiscard ); + if ( bDiscard ) + DoCleanup(); + m_CompleteEvent.Set(); + } + break; + + case JOB_STATUS_ABORTED: + case JOB_STATUS_INPROGRESS: + case JOB_OK: + result = m_status; + break; + + default: + AssertMsg( m_status < JOB_OK, "Unknown job state"); + result = m_status; + } + + Release(); + + return result; +} + +//----------------------------------------------------------------------------- + +#endif // JOBTHREAD_H diff --git a/sp/src/public/vstdlib/osversion.h b/sp/src/public/vstdlib/osversion.h new file mode 100644 index 00000000..ecc68ae5 --- /dev/null +++ b/sp/src/public/vstdlib/osversion.h @@ -0,0 +1,60 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $Workfile: $ +// $Date: $ +// +//----------------------------------------------------------------------------- +// $Log: $ +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef OSVERSION_H +#define OSVERSION_H +#pragma once + +#include "vstdlib/vstdlib.h" + +// OS types we know about +// Must be in ascending capability order, we use this for min OS requirements +enum EOSType +{ + k_eOSUnknown = -1, + k_eMacOSUnknown = -102, + k_eMacOS104 = -101, + k_eMacOS105 = -100, + k_eMacOS1058 = -99, + k_eMacOS106 = -95, + k_eMacOS1063 = -94, + k_eMacOS107 = -90, + // k_eMacOSMax = -1 + k_eLinuxUnknown = -203, + k_eLinux22 = -202, + k_eLinux24 = -201, + k_eLinux26 = -200, + // k_eLinuxMax = -103 + k_eWinUnknown = 0, + k_eWin311 = 1, + k_eWin95, + k_eWin98, + k_eWinME, + k_eWinNT, + k_eWin2000, + k_eWinXP, + k_eWin2003, + k_eWinVista, + k_eWindows7, + k_eWin2008, + k_eWinMAX, + k_eOSTypeMax = k_eWinMAX + 11 // win types + other ifdef'd types +}; + +VSTDLIB_INTERFACE const char *GetNameFromOSType( EOSType eOSType ); +VSTDLIB_INTERFACE const char *GetOSDetailString( char *pchOutBuf, int cchOutBuf ); +VSTDLIB_INTERFACE EOSType GetOSType(); +VSTDLIB_INTERFACE bool OSTypesAreCompatible( EOSType eOSTypeDetected, EOSType eOSTypeRequired ); +VSTDLIB_INTERFACE const char *GetPlatformName( bool *pbIs64Bit ); + +#endif // OSVERSION_H diff --git a/sp/src/public/vstdlib/pch_vstdlib.h b/sp/src/public/vstdlib/pch_vstdlib.h new file mode 100644 index 00000000..57242c41 --- /dev/null +++ b/sp/src/public/vstdlib/pch_vstdlib.h @@ -0,0 +1,51 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// The copyright to the contents herein is the property of Valve, L.L.C. +// The contents may be used and/or copied only with the written permission of +// Valve, L.L.C., or in accordance with the terms and conditions stipulated in +// the agreement/contract under which the contents have been supplied. +// +// Purpose: +// +// $Workfile: $ +// $NoKeywords: $ +//============================================================================= + + +#pragma warning(disable: 4514) + +// First include standard libraries +#include +#include +#include +#include +#include +#include + +// Next, include public +#include "tier0/basetypes.h" +#include "tier0/dbg.h" +#include "tier0/valobject.h" + +// Next, include vstdlib +#include "vstdlib/vstdlib.h" +#include "tier1/strtools.h" +#include "vstdlib/random.h" +#include "tier1/KeyValues.h" +#include "tier1/utlmemory.h" +#include "tier1/utlrbtree.h" +#include "tier1/utlvector.h" +#include "tier1/utllinkedlist.h" +#include "tier1/utlmultilist.h" +#include "tier1/utlsymbol.h" +#include "tier0/icommandline.h" +#include "tier1/netadr.h" +#include "tier1/mempool.h" +#include "tier1/utlbuffer.h" +#include "tier1/utlstring.h" +#include "tier1/utlmap.h" + +#include "tier0/memdbgon.h" + + + diff --git a/sp/src/public/vstdlib/random.h b/sp/src/public/vstdlib/random.h new file mode 100644 index 00000000..88188031 --- /dev/null +++ b/sp/src/public/vstdlib/random.h @@ -0,0 +1,111 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Random number generator +// +// $Workfile: $ +// $NoKeywords: $ +//===========================================================================// + +#ifndef VSTDLIB_RANDOM_H +#define VSTDLIB_RANDOM_H + +#include "vstdlib/vstdlib.h" +#include "tier0/basetypes.h" +#include "tier0/threadtools.h" +#include "tier1/interface.h" + +#define NTAB 32 + +#pragma warning(push) +#pragma warning( disable:4251 ) + +//----------------------------------------------------------------------------- +// A generator of uniformly distributed random numbers +//----------------------------------------------------------------------------- +class IUniformRandomStream +{ +public: + // Sets the seed of the random number generator + virtual void SetSeed( int iSeed ) = 0; + + // Generates random numbers + virtual float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ) = 0; + virtual int RandomInt( int iMinVal, int iMaxVal ) = 0; + virtual float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ) = 0; +}; + + +//----------------------------------------------------------------------------- +// The standard generator of uniformly distributed random numbers +//----------------------------------------------------------------------------- +class VSTDLIB_CLASS CUniformRandomStream : public IUniformRandomStream +{ +public: + CUniformRandomStream(); + + // Sets the seed of the random number generator + virtual void SetSeed( int iSeed ); + + // Generates random numbers + virtual float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ); + virtual int RandomInt( int iMinVal, int iMaxVal ); + virtual float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ); + +private: + int GenerateRandomNumber(); + + int m_idum; + int m_iy; + int m_iv[NTAB]; + + CThreadFastMutex m_mutex; +}; + + +//----------------------------------------------------------------------------- +// A generator of gaussian distributed random numbers +//----------------------------------------------------------------------------- +class VSTDLIB_CLASS CGaussianRandomStream +{ +public: + // Passing in NULL will cause the gaussian stream to use the + // installed global random number generator + CGaussianRandomStream( IUniformRandomStream *pUniformStream = NULL ); + + // Attaches to a random uniform stream + void AttachToStream( IUniformRandomStream *pUniformStream = NULL ); + + // Generates random numbers + float RandomFloat( float flMean = 0.0f, float flStdDev = 1.0f ); + +private: + IUniformRandomStream *m_pUniformStream; + bool m_bHaveValue; + float m_flRandomValue; + + CThreadFastMutex m_mutex; +}; + + +//----------------------------------------------------------------------------- +// A couple of convenience functions to access the library's global uniform stream +//----------------------------------------------------------------------------- +VSTDLIB_INTERFACE void RandomSeed( int iSeed ); +VSTDLIB_INTERFACE float RandomFloat( float flMinVal = 0.0f, float flMaxVal = 1.0f ); +VSTDLIB_INTERFACE float RandomFloatExp( float flMinVal = 0.0f, float flMaxVal = 1.0f, float flExponent = 1.0f ); +VSTDLIB_INTERFACE int RandomInt( int iMinVal, int iMaxVal ); +VSTDLIB_INTERFACE float RandomGaussianFloat( float flMean = 0.0f, float flStdDev = 1.0f ); + + +//----------------------------------------------------------------------------- +// Installs a global random number generator, which will affect the Random functions above +//----------------------------------------------------------------------------- +VSTDLIB_INTERFACE void InstallUniformRandomStream( IUniformRandomStream *pStream ); + + +#pragma warning(pop) + +#endif // VSTDLIB_RANDOM_H + + + diff --git a/sp/src/public/vstdlib/vcover.h b/sp/src/public/vstdlib/vcover.h new file mode 100644 index 00000000..156534c0 --- /dev/null +++ b/sp/src/public/vstdlib/vcover.h @@ -0,0 +1,125 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: A simple tool for coverage tests +// +//============================================================================= + +#ifndef VCOVER_H +#define VCOVER_H + +#include "tier1/utlrbtree.h" +#include "vstdlib.h" + +#if defined( _WIN32 ) +#pragma once +#endif + +class CVCoverage +{ +public: + CVCoverage() : + m_bActive( false ), + m_depth( 0 ), + m_token( 1 ) + { + } + + bool IsActive() const + { + return m_bActive; + } + + void SetActive( bool bActive ) + { + Assert( bActive != m_bActive ); + m_bActive = bActive; + if ( bActive ) + ++m_token; + } + + void Begin() + { + ++m_depth; + } + + void End() + { + --m_depth; + } + + void Reset() + { + m_locations.RemoveAll(); + } + + bool ShouldCover( unsigned token ) const + { + return ( m_bActive && m_depth > 0 && token != m_token ); + } + + unsigned Cover( const char *pszFile, int line ) + { + Location_t location = { pszFile, line }; + + m_locations.Insert( location ); + + return m_token; + } + + void Report() + { + for ( int i = m_locations.FirstInorder(); i != m_locations.InvalidIndex(); i = m_locations.NextInorder( i ) ) + { + Msg( "%s(%d) :\n", m_locations[i].pszFile, m_locations[i].line ); + } + } + +private: + struct Location_t + { + const char *pszFile; + int line; + + }; + + class CLocationLess + { + public: + CLocationLess( int ignored ) {} + bool operator!() { return false; } + + bool operator()( const Location_t &lhs, const Location_t &rhs ) const + { + if ( lhs.line < rhs.line ) + { + return true; + } + + return CaselessStringLessThan( lhs.pszFile, rhs.pszFile ); + } + }; + + bool m_bActive; + int m_depth; + unsigned m_token; + + CUtlRBTree< Location_t, unsigned short, CLocationLess > m_locations; +}; + +VSTDLIB_INTERFACE CVCoverage g_VCoverage; + +#ifdef VCOVER_ENABLED +#define VCOVER() \ + do \ + { \ + static token; \ + if ( g_VCoverage.ShouldCover( token ) ) \ + { \ + token = g_VCoverage.Cover( __FILE__, __LINE__ ); \ + } \ + } while( 0 ) +#else +#define VCOVER() ((void)0) +#endif + +#endif // VCOVER_H diff --git a/sp/src/public/vstdlib/vstdlib.h b/sp/src/public/vstdlib/vstdlib.h new file mode 100644 index 00000000..4e3a7f89 --- /dev/null +++ b/sp/src/public/vstdlib/vstdlib.h @@ -0,0 +1,33 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +// +//=============================================================================// + +#ifndef VSTDLIB_H +#define VSTDLIB_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "tier0/platform.h" + +//----------------------------------------------------------------------------- +// dll export stuff +//----------------------------------------------------------------------------- +#ifdef VSTDLIB_DLL_EXPORT +#define VSTDLIB_INTERFACE DLL_EXPORT +#define VSTDLIB_OVERLOAD DLL_GLOBAL_EXPORT +#define VSTDLIB_CLASS DLL_CLASS_EXPORT +#define VSTDLIB_GLOBAL DLL_GLOBAL_EXPORT +#else +#define VSTDLIB_INTERFACE DLL_IMPORT +#define VSTDLIB_OVERLOAD DLL_GLOBAL_IMPORT +#define VSTDLIB_CLASS DLL_CLASS_IMPORT +#define VSTDLIB_GLOBAL DLL_GLOBAL_IMPORT +#endif + +#endif // VSTDLIB_H diff --git a/sp/src/public/vtf/vtf.h b/sp/src/public/vtf/vtf.h new file mode 100644 index 00000000..ecf10c88 --- /dev/null +++ b/sp/src/public/vtf/vtf.h @@ -0,0 +1,608 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//===========================================================================// + +#ifndef VTF_H +#define VTF_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "bitmap/imageformat.h" +#include "tier0/platform.h" + +// #define VTF_FILE_FORMAT_ONLY to just include the vtf header and none of the code declaration +#ifndef VTF_FILE_FORMAT_ONLY + +//----------------------------------------------------------------------------- +// Forward declarations +//----------------------------------------------------------------------------- +class CUtlBuffer; +class Vector; +struct Rect_t; +class IFileSystem; + +//----------------------------------------------------------------------------- +// Texture flags +//----------------------------------------------------------------------------- +enum CompiledVtfFlags +{ + // flags from the *.txt config file + TEXTUREFLAGS_POINTSAMPLE = 0x00000001, + TEXTUREFLAGS_TRILINEAR = 0x00000002, + TEXTUREFLAGS_CLAMPS = 0x00000004, + TEXTUREFLAGS_CLAMPT = 0x00000008, + TEXTUREFLAGS_ANISOTROPIC = 0x00000010, + TEXTUREFLAGS_HINT_DXT5 = 0x00000020, + TEXTUREFLAGS_SRGB = 0x00000040, + TEXTUREFLAGS_NORMAL = 0x00000080, + TEXTUREFLAGS_NOMIP = 0x00000100, + TEXTUREFLAGS_NOLOD = 0x00000200, + TEXTUREFLAGS_ALL_MIPS = 0x00000400, + TEXTUREFLAGS_PROCEDURAL = 0x00000800, + + // These are automatically generated by vtex from the texture data. + TEXTUREFLAGS_ONEBITALPHA = 0x00001000, + TEXTUREFLAGS_EIGHTBITALPHA = 0x00002000, + + // newer flags from the *.txt config file + TEXTUREFLAGS_ENVMAP = 0x00004000, + TEXTUREFLAGS_RENDERTARGET = 0x00008000, + TEXTUREFLAGS_DEPTHRENDERTARGET = 0x00010000, + TEXTUREFLAGS_NODEBUGOVERRIDE = 0x00020000, + TEXTUREFLAGS_SINGLECOPY = 0x00040000, + + TEXTUREFLAGS_UNUSED_00080000 = 0x00080000, + TEXTUREFLAGS_UNUSED_00100000 = 0x00100000, + TEXTUREFLAGS_UNUSED_00200000 = 0x00200000, + TEXTUREFLAGS_UNUSED_00400000 = 0x00400000, + + TEXTUREFLAGS_NODEPTHBUFFER = 0x00800000, + + TEXTUREFLAGS_UNUSED_01000000 = 0x01000000, + + TEXTUREFLAGS_CLAMPU = 0x02000000, + + TEXTUREFLAGS_VERTEXTEXTURE = 0x04000000, // Useable as a vertex texture + + TEXTUREFLAGS_SSBUMP = 0x08000000, + + TEXTUREFLAGS_UNUSED_10000000 = 0x10000000, + + // Clamp to border color on all texture coordinates + TEXTUREFLAGS_BORDER = 0x20000000, + + TEXTUREFLAGS_UNUSED_40000000 = 0x40000000, + TEXTUREFLAGS_UNUSED_80000000 = 0x80000000, +}; + +enum VersionedVtfFlags +{ + VERSIONED_VTF_FLAGS_MASK_7_3 = ~0xD1780400, // For a ver 7.3 or earlier only these flags are valid +}; + + +struct VtfProcessingOptions +{ + uint32 cbSize; // Set to sizeof( VtfProcessingOptions ) + + // + // Flags0 + // + enum Flags0 + { + // Have a channel decaying to a given decay goal for the given last number of mips + OPT_DECAY_R = 0x00000001, // Red decays + OPT_DECAY_G = 0x00000002, // Green decays + OPT_DECAY_B = 0x00000004, // Blue decays + OPT_DECAY_A = 0x00000008, // Alpha decays + + OPT_DECAY_EXP_R = 0x00000010, // Channel R decays exponentially (otherwise linearly) + OPT_DECAY_EXP_G = 0x00000020, // Channel G decays exponentially (otherwise linearly) + OPT_DECAY_EXP_B = 0x00000040, // Channel B decays exponentially (otherwise linearly) + OPT_DECAY_EXP_A = 0x00000080, // Channel A decays exponentially (otherwise linearly) + + OPT_NOCOMPRESS = 0x00000100, // Use uncompressed image format + OPT_NORMAL_DUDV = 0x00000200, // dU dV normal map + OPT_FILTER_NICE = 0x00000400, // Use nice filtering + + OPT_SET_ALPHA_ONEOVERMIP = 0x00001000, // Alpha = 1/miplevel + OPT_PREMULT_COLOR_ONEOVERMIP = 0x00002000, // Color *= 1/miplevel + OPT_MIP_ALPHATEST = 0x00004000, // Alpha-tested mip generation + }; + + uint32 flags0; // A combination of "Flags0" + + // + // Decay settings + // + uint8 clrDecayGoal[4]; // Goal colors for R G B A + uint8 numNotDecayMips[4]; // Number of first mips unaffected by decay (0 means all below mip0) + float fDecayExponentBase[4]; // For exponential decay the base number (e.g. 0.75) +}; + + +//----------------------------------------------------------------------------- +// Cubemap face indices +//----------------------------------------------------------------------------- +enum CubeMapFaceIndex_t +{ + CUBEMAP_FACE_RIGHT = 0, + CUBEMAP_FACE_LEFT, + CUBEMAP_FACE_BACK, // NOTE: This face is in the +y direction?!?!? + CUBEMAP_FACE_FRONT, // NOTE: This face is in the -y direction!?!? + CUBEMAP_FACE_UP, + CUBEMAP_FACE_DOWN, + + // This is the fallback for low-end + CUBEMAP_FACE_SPHEREMAP, + + // NOTE: Cubemaps have *7* faces; the 7th is the fallback spheremap + CUBEMAP_FACE_COUNT +}; + + +//----------------------------------------------------------------------------- +// Enumeration used for spheremap generation +//----------------------------------------------------------------------------- +enum LookDir_t +{ + LOOK_DOWN_X = 0, + LOOK_DOWN_NEGX, + LOOK_DOWN_Y, + LOOK_DOWN_NEGY, + LOOK_DOWN_Z, + LOOK_DOWN_NEGZ, +}; + + +//----------------------------------------------------------------------------- +// Use this image format if you want to perform tool operations on the texture +//----------------------------------------------------------------------------- +#define IMAGE_FORMAT_DEFAULT ((ImageFormat)-2) + +//----------------------------------------------------------------------------- +// Interface to get at various bits of a VTF texture +//----------------------------------------------------------------------------- +class IVTFTexture +{ +public: + virtual ~IVTFTexture() {} + + // Initializes the texture and allocates space for the bits + // In most cases, you shouldn't force the mip count. + virtual bool Init( int nWidth, int nHeight, int nDepth, ImageFormat fmt, int nFlags, int iFrameCount, int nForceMipCount = -1 ) = 0; + + // Methods to set other texture fields + virtual void SetBumpScale( float flScale ) = 0; + virtual void SetReflectivity( const Vector &vecReflectivity ) = 0; + + // Methods to initialize the low-res image + virtual void InitLowResImage( int nWidth, int nHeight, ImageFormat fmt ) = 0; + + // set the resource data (for writers). pass size=0 to delete data. if pdata is not null, + // the resource data will be copied from *pData + virtual void *SetResourceData( uint32 eType, void const *pData, size_t nDataSize ) = 0; + + // find the resource data and return a pointer to it. The data pointed to by this pointer will + // go away when the ivtftexture does. retruns null if resource not present + virtual void *GetResourceData( uint32 eType, size_t *pDataSize ) const = 0; + + // Locates the resource entry info if it's present, easier than crawling array types + virtual bool HasResourceEntry( uint32 eType ) const = 0; + + // Retrieve available resource types of this IVTFTextures + // arrTypesBuffer buffer to be filled with resource types available. + // numTypesBufferElems how many resource types the buffer can accomodate. + // Returns: + // number of resource types available (can be greater than "numTypesBufferElems" + // in which case only first "numTypesBufferElems" are copied to "arrTypesBuffer") + virtual unsigned int GetResourceTypes( uint32 *arrTypesBuffer, int numTypesBufferElems ) const = 0; + + // When unserializing, we can skip a certain number of mip levels, + // and we also can just load everything but the image data + // NOTE: If you load only the buffer header, you'll need to use the + // VTFBufferHeaderSize() method below to only read that much from the file + // NOTE: If you skip mip levels, the height + width of the texture will + // change to reflect the size of the largest read in mip level + virtual bool Unserialize( CUtlBuffer &buf, bool bHeaderOnly = false, int nSkipMipLevels = 0 ) = 0; + virtual bool Serialize( CUtlBuffer &buf ) = 0; + + // These are methods to help with optimization: + // Once the header is read in, they indicate where to start reading + // other data (measured from file start), and how many bytes to read.... + virtual void LowResFileInfo( int *pStartLocation, int *pSizeInBytes) const = 0; + virtual void ImageFileInfo( int nFrame, int nFace, int nMip, int *pStartLocation, int *pSizeInBytes) const = 0; + virtual int FileSize( int nMipSkipCount = 0 ) const = 0; + + // Attributes... + virtual int Width() const = 0; + virtual int Height() const = 0; + virtual int Depth() const = 0; + virtual int MipCount() const = 0; + + // returns the size of one row of a particular mip level + virtual int RowSizeInBytes( int nMipLevel ) const = 0; + + // returns the size of one face of a particular mip level + virtual int FaceSizeInBytes( int nMipLevel ) const = 0; + + virtual ImageFormat Format() const = 0; + virtual int FaceCount() const = 0; + virtual int FrameCount() const = 0; + virtual int Flags() const = 0; + + virtual float BumpScale() const = 0; + + virtual int LowResWidth() const = 0; + virtual int LowResHeight() const = 0; + virtual ImageFormat LowResFormat() const = 0; + + // NOTE: reflectivity[0] = blue, [1] = greem, [2] = red + virtual const Vector &Reflectivity() const = 0; + + virtual bool IsCubeMap() const = 0; + virtual bool IsNormalMap() const = 0; + virtual bool IsVolumeTexture() const = 0; + + // Computes the dimensions of a particular mip level + virtual void ComputeMipLevelDimensions( int iMipLevel, int *pMipWidth, int *pMipHeight, int *pMipDepth ) const = 0; + + // Computes the size (in bytes) of a single mipmap of a single face of a single frame + virtual int ComputeMipSize( int iMipLevel ) const = 0; + + // Computes the size of a subrect (specified at the top mip level) at a particular lower mip level + virtual void ComputeMipLevelSubRect( Rect_t* pSrcRect, int nMipLevel, Rect_t *pSubRect ) const = 0; + + // Computes the size (in bytes) of a single face of a single frame + // All mip levels starting at the specified mip level are included + virtual int ComputeFaceSize( int iStartingMipLevel = 0 ) const = 0; + + // Computes the total size (in bytes) of all faces, all frames + virtual int ComputeTotalSize() const = 0; + + // Returns the base address of the image data + virtual unsigned char *ImageData() = 0; + + // Returns a pointer to the data associated with a particular frame, face, and mip level + virtual unsigned char *ImageData( int iFrame, int iFace, int iMipLevel ) = 0; + + // Returns a pointer to the data associated with a particular frame, face, mip level, and offset + virtual unsigned char *ImageData( int iFrame, int iFace, int iMipLevel, int x, int y, int z = 0 ) = 0; + + // Returns the base address of the low-res image data + virtual unsigned char *LowResImageData() = 0; + + // Converts the textures image format. Use IMAGE_FORMAT_DEFAULT + // if you want to be able to use various tool functions below + virtual void ConvertImageFormat( ImageFormat fmt, bool bNormalToDUDV ) = 0; + + // NOTE: The following methods only work on textures using the + // IMAGE_FORMAT_DEFAULT! + + // Generate spheremap based on the current cube faces (only works for cubemaps) + // The look dir indicates the direction of the center of the sphere + // NOTE: Only call this *after* cube faces have been correctly + // oriented (using FixCubemapFaceOrientation) + virtual void GenerateSpheremap( LookDir_t lookDir = LOOK_DOWN_Z ) = 0; + + // Generate spheremap based on the current cube faces (only works for cubemaps) + // The look dir indicates the direction of the center of the sphere + // NOTE: Only call this *after* cube faces have been correctly + // oriented (using FixCubemapFaceOrientation) + virtual void GenerateHemisphereMap( unsigned char *pSphereMapBitsRGBA, int targetWidth, + int targetHeight, LookDir_t lookDir, int iFrame ) = 0; + + // Fixes the cubemap faces orientation from our standard to the + // standard the material system needs. + virtual void FixCubemapFaceOrientation( ) = 0; + + // Generates mipmaps from the base mip levels + virtual void GenerateMipmaps() = 0; + + // Put 1/miplevel (1..n) into alpha. + virtual void PutOneOverMipLevelInAlpha() = 0; + + // Computes the reflectivity + virtual void ComputeReflectivity( ) = 0; + + // Computes the alpha flags + virtual void ComputeAlphaFlags() = 0; + + // Generate the low-res image bits + virtual bool ConstructLowResImage() = 0; + + // Gets the texture all internally consistent assuming you've loaded + // mip 0 of all faces of all frames + virtual void PostProcess(bool bGenerateSpheremap, LookDir_t lookDir = LOOK_DOWN_Z, bool bAllowFixCubemapOrientation = true) = 0; + + // Blends adjacent pixels on cubemap borders, since the card doesn't do it. If the texture + // is S3TC compressed, then it has to do it AFTER the texture has been compressed to prevent + // artifacts along the edges. + // + // If bSkybox is true, it assumes the faces are oriented in the way the engine draws the skybox + // (which happens to be different from the way cubemaps have their faces). + virtual void MatchCubeMapBorders( int iStage, ImageFormat finalFormat, bool bSkybox ) = 0; + + // Sets threshhold values for alphatest mipmapping + virtual void SetAlphaTestThreshholds( float flBase, float flHighFreq ) = 0; + +#if defined( _X360 ) + virtual int UpdateOrCreate( const char *pFilename, const char *pPathID = NULL, bool bForce = false ) = 0; + virtual bool UnserializeFromBuffer( CUtlBuffer &buf, bool bBufferIsVolatile, bool bHeaderOnly, bool bPreloadOnly, int nMipSkipCount ) = 0; + virtual int FileSize( bool bPreloadOnly, int nMipSkipCount ) const = 0; + virtual int MappingWidth() const = 0; + virtual int MappingHeight() const = 0; + virtual int MappingDepth() const = 0; + virtual int MipSkipCount() const = 0; + virtual bool IsPreTiled() const = 0; + virtual unsigned char *LowResImageSample() = 0; + virtual void ReleaseImageMemory() = 0; +#endif + + // Sets post-processing flags (settings are copied, pointer passed to distinguish between structure versions) + virtual void SetPostProcessingSettings( VtfProcessingOptions const *pOptions ) = 0; +}; + +//----------------------------------------------------------------------------- +// Class factory +//----------------------------------------------------------------------------- +IVTFTexture *CreateVTFTexture(); +void DestroyVTFTexture( IVTFTexture *pTexture ); + +//----------------------------------------------------------------------------- +// Allows us to only load in the first little bit of the VTF file to get info +// Clients should read this much into a UtlBuffer and then pass it in to +// Unserialize +//----------------------------------------------------------------------------- +int VTFFileHeaderSize( int nMajorVersion = -1, int nMinorVersion = -1 ); + +//----------------------------------------------------------------------------- +// 360 Conversion +//----------------------------------------------------------------------------- +typedef bool (*CompressFunc_t)( CUtlBuffer &inputBuffer, CUtlBuffer &outputBuffer ); +bool ConvertVTFTo360Format( const char *pDebugName, CUtlBuffer &sourceBuf, CUtlBuffer &targetBuf, CompressFunc_t pCompressFunc ); + +//----------------------------------------------------------------------------- +// 360 Preload +//----------------------------------------------------------------------------- +bool GetVTFPreload360Data( const char *pDebugName, CUtlBuffer &fileBufferIn, CUtlBuffer &preloadBufferOut ); + +#include "mathlib/vector.h" + +#endif // VTF_FILE_FORMAT_ONLY + +//----------------------------------------------------------------------------- +// Disk format for VTF files ver. 7.2 and earlier +// +// NOTE: After the header is the low-res image data +// Then follows image data, which is sorted in the following manner +// +// for each mip level (starting with 1x1, and getting larger) +// for each animation frame +// for each face +// store the image data for the face +// +// NOTE: In memory, we store the data in the following manner: +// for each animation frame +// for each face +// for each mip level (starting with the largest, and getting smaller) +// store the image data for the face +// +// This is done because the various image manipulation function we have +// expect this format +//----------------------------------------------------------------------------- +// Disk format for VTF files ver. 7.3 +// +// NOTE: After the header is the array of ResourceEntryInfo structures, +// number of elements in the array is defined by "numResources". +// there are entries for: +// eRsrcLowResImage = low-res image data +// eRsrcSheet = sheet data +// eRsrcImage = image data +// { +// for each mip level (starting with 1x1, and getting larger) +// for each animation frame +// for each face +// store the image data for the face +// +// NOTE: In memory, we store the data in the following manner: +// for each animation frame +// for each face +// for each mip level (starting with the largest, and getting smaller) +// store the image data for the face +// } +// +//----------------------------------------------------------------------------- + + +#include "datamap.h" + +#pragma pack(1) + +// version number for the disk texture cache +#define VTF_MAJOR_VERSION 7 +#define VTF_MINOR_VERSION 4 + +//----------------------------------------------------------------------------- +// !!!!CRITICAL!!!! BEFORE YOU CHANGE THE FORMAT +// +// The structure sizes ARE NOT what they appear, regardless of Pack(1). +// The "VectorAligned" causes invisible padding in the FINAL derived structure. +// +// Each VTF format has been silently plagued by this. +// +// LOOK AT A 7.3 FILE. The 7.3 structure ends at 0x48 as you would expect by +// counting structure bytes. But, the "Infos" start at 0x50! because the PC +// compiler pads, the 360 compiler does NOT. +//----------------------------------------------------------------------------- + +struct VTFFileBaseHeader_t +{ + DECLARE_BYTESWAP_DATADESC(); + char fileTypeString[4]; // "VTF" Valve texture file + int version[2]; // version[0].version[1] + int headerSize; +}; + +struct VTFFileHeaderV7_1_t : public VTFFileBaseHeader_t +{ + DECLARE_BYTESWAP_DATADESC(); + unsigned short width; + unsigned short height; + unsigned int flags; + unsigned short numFrames; + unsigned short startFrame; +#if !defined( POSIX ) && !defined( _X360 ) + VectorAligned reflectivity; +#else + // must manually align in order to maintain pack(1) expected layout with existing binaries + char pad1[4]; + Vector reflectivity; + char pad2[4]; +#endif + float bumpScale; + ImageFormat imageFormat; + unsigned char numMipLevels; + ImageFormat lowResImageFormat; + unsigned char lowResImageWidth; + unsigned char lowResImageHeight; +}; + +struct VTFFileHeaderV7_2_t : public VTFFileHeaderV7_1_t +{ + DECLARE_BYTESWAP_DATADESC(); + + unsigned short depth; +}; + +#define BYTE_POS( byteVal, shft ) uint32( uint32(uint8(byteVal)) << uint8(shft * 8) ) +#if !defined( _X360 ) +#define MK_VTF_RSRC_ID(a, b, c) uint32( BYTE_POS(a, 0) | BYTE_POS(b, 1) | BYTE_POS(c, 2) ) +#define MK_VTF_RSRCF(d) BYTE_POS(d, 3) +#else +#define MK_VTF_RSRC_ID(a, b, c) uint32( BYTE_POS(a, 3) | BYTE_POS(b, 2) | BYTE_POS(c, 1) ) +#define MK_VTF_RSRCF(d) BYTE_POS(d, 0) +#endif + +// Special section for stock resources types +enum ResourceEntryType +{ + // Legacy stock resources, readin/writing are handled differently (i.e. they do not have the length tag word!) + VTF_LEGACY_RSRC_LOW_RES_IMAGE = MK_VTF_RSRC_ID( 0x01, 0, 0 ), // Low-res image data + VTF_LEGACY_RSRC_IMAGE = MK_VTF_RSRC_ID( 0x30, 0, 0 ), // Image data + + // New extended resource + VTF_RSRC_SHEET = MK_VTF_RSRC_ID( 0x10, 0, 0 ), // Sheet data +}; + +// Bytes with special meaning when set in a resource type +enum ResourceEntryTypeFlag +{ + RSRCF_HAS_NO_DATA_CHUNK = MK_VTF_RSRCF( 0x02 ), // Resource doesn't have a corresponding data chunk + RSRCF_MASK = MK_VTF_RSRCF( 0xFF ) // Mask for all the flags +}; + +// Header details constants +enum HeaderDetails +{ + MAX_RSRC_DICTIONARY_ENTRIES = 32, // Max number of resources in dictionary + MAX_X360_RSRC_DICTIONARY_ENTRIES = 4, // 360 needs this to be slim, otherwise preload size suffers +}; + +struct ResourceEntryInfo +{ + union + { + unsigned int eType; // Use MK_VTF_??? macros to be endian compliant with the type + unsigned char chTypeBytes[4]; + }; + unsigned int resData; // Resource data or offset from the beginning of the file +}; + +struct VTFFileHeaderV7_3_t : public VTFFileHeaderV7_2_t +{ + DECLARE_BYTESWAP_DATADESC(); + + char pad4[3]; + unsigned int numResources; + +#if defined( _X360 ) || defined( POSIX ) + // must manually align in order to maintain pack(1) expected layout with existing binaries + char pad5[8]; +#endif + + // AFTER THE IMPLICIT PADDING CAUSED BY THE COMPILER.... + // *** followed by *** ResourceEntryInfo resources[0]; + // Array of resource entry infos sorted ascending by type +}; + +struct VTFFileHeader_t : public VTFFileHeaderV7_3_t +{ + DECLARE_BYTESWAP_DATADESC(); +}; + +#define VTF_X360_MAJOR_VERSION 0x0360 +#define VTF_X360_MINOR_VERSION 8 +struct VTFFileHeaderX360_t : public VTFFileBaseHeader_t +{ + DECLARE_BYTESWAP_DATADESC(); + unsigned int flags; + unsigned short width; // actual width of data in file + unsigned short height; // actual height of data in file + unsigned short depth; // actual depth of data in file + unsigned short numFrames; + unsigned short preloadDataSize; // exact size of preload data (may extend into image!) + unsigned char mipSkipCount; // used to resconstruct mapping dimensions + unsigned char numResources; + Vector reflectivity; // Resides on 16 byte boundary! + float bumpScale; + ImageFormat imageFormat; + unsigned char lowResImageSample[4]; + unsigned int compressedSize; + + // *** followed by *** ResourceEntryInfo resources[0]; +}; + +/////////////////////////// +// Resource Extensions // +/////////////////////////// + +// extended texture lod control: +#define VTF_RSRC_TEXTURE_LOD_SETTINGS ( MK_VTF_RSRC_ID( 'L','O','D' ) ) +struct TextureLODControlSettings_t +{ + // What to clamp the dimenstions to, mip-map wise, when at picmip 0. keeps texture from + // exceeding (1< +#define MAX_PATH PATH_MAX +typedef bool BOOL; +#endif + +#ifndef XZIP_H +#if !defined(DECLARE_HANDLE) +#if !defined(HANDLE) +typedef void *HANDLE; +#endif +#define DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name +#endif +DECLARE_HANDLE(HZIP); // An HZIP identifies a zip file that is being created +#endif + +#if defined(_WIN32) && !defined(_WINBASE_) && !defined(_FILETIME_) +#define _FILETIME_ +typedef struct _FILETIME +{ + DWORD dwLowDateTime; + DWORD dwHighDateTime; +} FILETIME, * LPFILETIME, *PFILETIME; +#endif + +#if defined(POSIX) +typedef time_t FILETIME; +#endif + +typedef DWORD ZRESULT; +// return codes from any of the zip functions. Listed later. + +#define ZIP_HANDLE 1 +#define ZIP_FILENAME 2 +#define ZIP_MEMORY 3 + +typedef struct +{ int index; // index of this file within the zip + char name[MAX_PATH]; // filename within the zip + DWORD attr; // attributes, as in GetFileAttributes. + FILETIME atime,ctime,mtime;// access, create, modify filetimes + long comp_size; // sizes of item, compressed and uncompressed. These + long unc_size; // may be -1 if not yet known (e.g. being streamed in) +} ZIPENTRY; + +typedef struct +{ int index; // index of this file within the zip + TCHAR name[MAX_PATH]; // filename within the zip + DWORD attr; // attributes, as in GetFileAttributes. + FILETIME atime,ctime,mtime;// access, create, modify filetimes + long comp_size; // sizes of item, compressed and uncompressed. These + long unc_size; // may be -1 if not yet known (e.g. being streamed in) +} ZIPENTRYW; + + +/////////////////////////////////////////////////////////////////////////////// +// +// OpenZip() +// +// Purpose: Open an existing zip archive file +// +// Parameters: z - archive file name if flags is ZIP_FILENAME; for other +// uses see below +// len - for memory (ZIP_MEMORY) should be the buffer size; +// for other uses, should be 0 +// flags - indicates usage, see below; for files, this will be +// ZIP_FILENAME +// +// Returns: HZIP - non-zero if zip archive opened ok, otherwise 0 +// +HZIP OpenZip(void *z, unsigned int len, DWORD flags); +// OpenZip - opens a zip file and returns a handle with which you can +// subsequently examine its contents. You can open a zip file from: +// from a pipe: OpenZip(hpipe_read,0, ZIP_HANDLE); +// from a file (by handle): OpenZip(hfile,0, ZIP_HANDLE); +// from a file (by name): OpenZip("c:\\test.zip",0, ZIP_FILENAME); +// from a memory block: OpenZip(bufstart, buflen, ZIP_MEMORY); +// If the file is opened through a pipe, then items may only be +// accessed in increasing order, and an item may only be unzipped once, +// although GetZipItem can be called immediately before and after unzipping +// it. If it's opened i n any other way, then full random access is possible. +// Note: pipe input is not yet implemented. + + +/////////////////////////////////////////////////////////////////////////////// +// +// GetZipItem() +// +// Purpose: Get information about an item in an open zip archive +// +// Parameters: hz - handle of open zip archive +// index - index number (0 based) of item in zip +// ze - pointer to a ZIPENTRY (if ANSI) or ZIPENTRYW struct +// (if Unicode) +// +// Returns: ZRESULT - ZR_OK if success, otherwise some other value +// + +#ifdef _UNICODE +#define GetZipItem GetZipItemW +#else +#define GetZipItem GetZipItemA +#endif + +ZRESULT GetZipItemA(HZIP hz, int index, ZIPENTRY *ze); +ZRESULT GetZipItemW(HZIP hz, int index, ZIPENTRYW *ze); +// GetZipItem - call this to get information about an item in the zip. +// If index is -1 and the file wasn't opened through a pipe, +// then it returns information about the whole zipfile +// (and in particular ze.index returns the number of index items). +// Note: the item might be a directory (ze.attr & FILE_ATTRIBUTE_DIRECTORY) +// See below for notes on what happens when you unzip such an item. +// Note: if you are opening the zip through a pipe, then random access +// is not possible and GetZipItem(-1) fails and you can't discover the number +// of items except by calling GetZipItem on each one of them in turn, +// starting at 0, until eventually the call fails. Also, in the event that +// you are opening through a pipe and the zip was itself created into a pipe, +// then then comp_size and sometimes unc_size as well may not be known until +// after the item has been unzipped. + + +/////////////////////////////////////////////////////////////////////////////// +// +// FindZipItem() +// +// Purpose: Find item by name and return information about it +// +// Parameters: hz - handle of open zip archive +// name - name of file to look for inside zip archive +// ic - TRUE = case insensitive +// index - pointer to index number returned, or -1 +// ze - pointer to a ZIPENTRY (if ANSI) or ZIPENTRYW struct +// (if Unicode) +// +// Returns: ZRESULT - ZR_OK if success, otherwise some other value +// + +#ifdef _UNICODE +#define FindZipItem FindZipItemW +#else +#define FindZipItem FindZipItemA +#endif + +ZRESULT FindZipItemA(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRY *ze); +ZRESULT FindZipItemW(HZIP hz, const TCHAR *name, bool ic, int *index, ZIPENTRYW *ze); +// FindZipItem - finds an item by name. ic means 'insensitive to case'. +// It returns the index of the item, and returns information about it. +// If nothing was found, then index is set to -1 and the function returns +// an error code. + + +/////////////////////////////////////////////////////////////////////////////// +// +// UnzipItem() +// +// Purpose: Find item by index and unzip it +// +// Parameters: hz - handle of open zip archive +// index - index number of file to unzip +// dst - target file name of unzipped file +// len - for memory (ZIP_MEMORY. length of buffer; +// otherwise 0 +// flags - indicates usage, see below; for files, this will be +// ZIP_FILENAME +// +// Returns: ZRESULT - ZR_OK if success, otherwise some other value +// + +ZRESULT UnzipItem(HZIP hz, int index, void *dst, unsigned int len, DWORD flags); +// UnzipItem - given an index to an item, unzips it. You can unzip to: +// to a pipe: UnzipItem(hz,i, hpipe_write,0,ZIP_HANDLE); +// to a file (by handle): UnzipItem(hz,i, hfile,0,ZIP_HANDLE); +// to a file (by name): UnzipItem(hz,i, ze.name,0,ZIP_FILENAME); +// to a memory block: UnzipItem(hz,i, buf,buflen,ZIP_MEMORY); +// In the final case, if the buffer isn't large enough to hold it all, +// then the return code indicates that more is yet to come. If it was +// large enough, and you want to know precisely how big, GetZipItem. +// Note: zip files are normally stored with relative pathnames. If you +// unzip with ZIP_FILENAME a relative pathname then the item gets created +// relative to the current directory - it first ensures that all necessary +// subdirectories have been created. Also, the item may itself be a directory. +// If you unzip a directory with ZIP_FILENAME, then the directory gets created. +// If you unzip it to a handle or a memory block, then nothing gets created +// and it emits 0 bytes. + + +/////////////////////////////////////////////////////////////////////////////// +// +// CloseZip() +// +// Purpose: Close an open zip archive +// +// Parameters: hz - handle to an open zip archive +// +// Returns: ZRESULT - ZR_OK if success, otherwise some other value +// +ZRESULT CloseZip(HZIP hz); +// CloseZip - the zip handle must be closed with this function. + +unsigned int FormatZipMessage(ZRESULT code, char *buf,unsigned int len); +// FormatZipMessage - given an error code, formats it as a string. +// It returns the length of the error message. If buf/len points +// to a real buffer, then it also writes as much as possible into there. + + +// These are the result codes: +#define ZR_OK 0x00000000 // nb. the pseudo-code zr-recent is never returned, +#define ZR_RECENT 0x00000001 // but can be passed to FormatZipMessage. +// The following come from general system stuff (e.g. files not openable) +#define ZR_GENMASK 0x0000FF00 +#define ZR_NODUPH 0x00000100 // couldn't duplicate the handle +#define ZR_NOFILE 0x00000200 // couldn't create/open the file +#define ZR_NOALLOC 0x00000300 // failed to allocate some resource +#define ZR_WRITE 0x00000400 // a general error writing to the file +#define ZR_NOTFOUND 0x00000500 // couldn't find that file in the zip +#define ZR_MORE 0x00000600 // there's still more data to be unzipped +#define ZR_CORRUPT 0x00000700 // the zipfile is corrupt or not a zipfile +#define ZR_READ 0x00000800 // a general error reading the file +// The following come from mistakes on the part of the caller +#define ZR_CALLERMASK 0x00FF0000 +#define ZR_ARGS 0x00010000 // general mistake with the arguments +#define ZR_NOTMMAP 0x00020000 // tried to ZipGetMemory, but that only works on mmap zipfiles, which yours wasn't +#define ZR_MEMSIZE 0x00030000 // the memory size is too small +#define ZR_FAILED 0x00040000 // the thing was already failed when you called this function +#define ZR_ENDED 0x00050000 // the zip creation has already been closed +#define ZR_MISSIZE 0x00060000 // the indicated input file size turned out mistaken +#define ZR_PARTIALUNZ 0x00070000 // the file had already been partially unzipped +#define ZR_ZMODE 0x00080000 // tried to mix creating/opening a zip +// The following come from bugs within the zip library itself +#define ZR_BUGMASK 0xFF000000 +#define ZR_NOTINITED 0x01000000 // initialisation didn't work +#define ZR_SEEK 0x02000000 // trying to seek in an unseekable file +#define ZR_NOCHANGE 0x04000000 // changed its mind on storage, but not allowed +#define ZR_FLATE 0x05000000 // an internal error in the de/inflation code + + + + + +// e.g. +// +// SetCurrentDirectory("c:\\docs\\stuff"); +// HZIP hz = OpenZip("c:\\stuff.zip",0,ZIP_FILENAME); +// ZIPENTRY ze; GetZipItem(hz,-1,&ze); int numitems=ze.index; +// for (int i=0; i +#include +#include + +static bool SameSign(float a, float b) +{ + int32 aa=*((int *) &a); + int32 bb=*((int *) &b); + return ((aa^bb)&0x80000000)==0; +} + +int FourRays::CalculateDirectionSignMask(void) const +{ + // this code treats the floats as integers since all it cares about is the sign bit and + // floating point compares suck. + + int ret; + int ormask; + int andmask; + int32 const *treat_as_int=((int32 const *) (&direction)); + + ormask=andmask=*(treat_as_int++); + ormask|=*treat_as_int; + andmask&=*(treat_as_int++); + ormask|=*(treat_as_int); + andmask&=*(treat_as_int++); + ormask|=*(treat_as_int); + andmask&=*(treat_as_int++); + if (ormask>=0) + ret=0; + else + { + if (andmask<0) + ret=1; + else return -1; + } + ormask=andmask=*(treat_as_int++); + ormask|=*treat_as_int; + andmask&=*(treat_as_int++); + ormask|=*(treat_as_int); + andmask&=*(treat_as_int++); + ormask|=*(treat_as_int); + andmask&=*(treat_as_int++); + if (ormask<0) + { + if (andmask<0) + ret|=2; + else return -1; + } + ormask=andmask=*(treat_as_int++); + ormask|=*treat_as_int; + andmask&=*(treat_as_int++); + ormask|=*(treat_as_int); + andmask&=*(treat_as_int++); + ormask|=*(treat_as_int); + andmask&=*(treat_as_int++); + if (ormask<0) + { + if (andmask<0) + ret|=4; + else return -1; + } + return ret; +} + + + + +void RayTracingEnvironment::MakeRoomForTriangles( int ntris ) +{ + //OptimizedTriangleList.EnsureCapacity( ntris ); + if (! (Flags & RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS)) + TriangleColors.EnsureCapacity( ntris ); +} + + +void RayTracingEnvironment::AddTriangle(int32 id, const Vector &v1, + const Vector &v2, const Vector &v3, + const Vector &color) +{ + AddTriangle( id, v1, v2, v3, color, 0, 0 ); +} + +void RayTracingEnvironment::AddTriangle(int32 id, const Vector &v1, + const Vector &v2, const Vector &v3, + const Vector &color, uint16 flags, int32 materialIndex) +{ + CacheOptimizedTriangle tmptri; + tmptri.m_Data.m_GeometryData.m_nTriangleID = id; + tmptri.Vertex( 0 ) = v1; + tmptri.Vertex( 1 ) = v2; + tmptri.Vertex( 2 ) = v3; + tmptri.m_Data.m_GeometryData.m_nFlags = flags; + OptimizedTriangleList.AddToTail(tmptri); + if (! ( Flags & RTE_FLAGS_DONT_STORE_TRIANGLE_COLORS) ) + TriangleColors.AddToTail(color); + if ( !( Flags & RTE_FLAGS_DONT_STORE_TRIANGLE_MATERIALS) ) + TriangleMaterials.AddToTail(materialIndex); +// printf("add triange from (%f %f %f),(%f %f %f),(%f %f %f) id %d\n", +// XYZ(v1),XYZ(v2),XYZ(v3),id); +} + +void RayTracingEnvironment::AddQuad( + int32 id, const Vector &v1, const Vector &v2, const Vector &v3, + const Vector &v4, // specify vertices in cw or ccw order + const Vector &color) +{ + AddTriangle(id,v1,v2,v3,color); + AddTriangle(id+1,v1,v3,v4,color); +} + + +void RayTracingEnvironment::AddAxisAlignedRectangularSolid(int id,Vector minc, Vector maxc, + const Vector &color) +{ + + // "far" face + AddQuad(id, + Vector(minc.x,maxc.y,maxc.z), + Vector(maxc.x,maxc.y,maxc.z),Vector(maxc.x,minc.y,maxc.z), + Vector(minc.x,minc.y,maxc.z),color); + // "near" face + AddQuad(id, + Vector(minc.x,maxc.y,minc.z), + Vector(maxc.x,maxc.y,minc.z),Vector(maxc.x,minc.y,minc.z), + Vector(minc.x,minc.y,minc.z),color); + + // "left" face + AddQuad(id, + Vector(minc.x,maxc.y,maxc.z), + Vector(minc.x,maxc.y,minc.z), + Vector(minc.x,minc.y,minc.z), + Vector(minc.x,minc.y,maxc.z),color); + // "right" face + AddQuad(id, + Vector(maxc.x,maxc.y,maxc.z), + Vector(maxc.x,maxc.y,minc.z), + Vector(maxc.x,minc.y,minc.z), + Vector(maxc.x,minc.y,maxc.z),color); + + // "top" face + AddQuad(id, + Vector(minc.x,maxc.y,maxc.z), + Vector(maxc.x,maxc.y,maxc.z), + Vector(maxc.x,maxc.y,minc.z), + Vector(minc.x,maxc.y,minc.z),color); + // "bot" face + AddQuad(id, + Vector(minc.x,minc.y,maxc.z), + Vector(maxc.x,minc.y,maxc.z), + Vector(maxc.x,minc.y,minc.z), + Vector(minc.x,minc.y,minc.z),color); +} + + + +static Vector GetEdgeEquation(Vector p1, Vector p2, int c1, int c2, Vector InsidePoint) +{ + float nx=p1[c2]-p2[c2]; + float ny=p2[c1]-p1[c1]; + float d=-(nx*p1[c1]+ny*p1[c2]); +// assert(fabs(nx*p1[c1]+ny*p1[c2]+d)<0.01); +// assert(fabs(nx*p2[c1]+ny*p2[c2]+d)<0.01); + + // use the convention that negative is "outside" + float trial_dist=InsidePoint[c1]*nx+InsidePoint[c2]*ny+d; + if (trial_dist<0) + { + nx = -nx; + ny = -ny; + d = -d; + trial_dist = -trial_dist; + } + nx /= trial_dist; // scale so that it will be =1.0 at the oppositve vertex + ny /= trial_dist; + d /= trial_dist; + + return Vector(nx,ny,d); +} + +void CacheOptimizedTriangle::ChangeIntoIntersectionFormat(void) +{ + // lose the vertices and use edge equations instead + + // grab the whole original triangle to we don't overwrite it + TriGeometryData_t srcTri = m_Data.m_GeometryData; + + m_Data.m_IntersectData.m_nFlags = srcTri.m_nFlags; + m_Data.m_IntersectData.m_nTriangleID = srcTri.m_nTriangleID; + + Vector p1 = srcTri.Vertex( 0 ); + Vector p2 = srcTri.Vertex( 1 ); + Vector p3 = srcTri.Vertex( 2 ); + + Vector e1 = p2 - p1; + Vector e2 = p3 - p1; + + Vector N = e1.Cross( e2 ); + N.NormalizeInPlace(); + // now, determine which axis to drop + int drop_axis = 0; + for(int c=1 ; c<3 ; c++) + if ( fabs(N[c]) > fabs( N[drop_axis] ) ) + drop_axis = c; + + m_Data.m_IntersectData.m_flD = N.Dot( p1 ); + m_Data.m_IntersectData.m_flNx = N.x; + m_Data.m_IntersectData.m_flNy = N.y; + m_Data.m_IntersectData.m_flNz = N.z; + + // decide which axes to keep + int nCoordSelect0 = ( drop_axis + 1 ) % 3; + int nCoordSelect1 = ( drop_axis + 2 ) % 3; + + m_Data.m_IntersectData.m_nCoordSelect0 = nCoordSelect0; + m_Data.m_IntersectData.m_nCoordSelect1 = nCoordSelect1; + + + Vector edge1 = GetEdgeEquation( p1, p2, nCoordSelect0, nCoordSelect1, p3 ); + m_Data.m_IntersectData.m_ProjectedEdgeEquations[0] = edge1.x; + m_Data.m_IntersectData.m_ProjectedEdgeEquations[1] = edge1.y; + m_Data.m_IntersectData.m_ProjectedEdgeEquations[2] = edge1.z; + + Vector edge2 = GetEdgeEquation( p2, p3, nCoordSelect0, nCoordSelect1, p1 ); + m_Data.m_IntersectData.m_ProjectedEdgeEquations[3] = edge2.x; + m_Data.m_IntersectData.m_ProjectedEdgeEquations[4] = edge2.y; + m_Data.m_IntersectData.m_ProjectedEdgeEquations[5] = edge2.z; + + +} + +#ifndef MAPBASE +int n_intersection_calculations=0; +#endif + +int CacheOptimizedTriangle::ClassifyAgainstAxisSplit(int split_plane, float split_value) +{ + // classify a triangle against an axis-aligned plane + float minc=Vertex(0)[split_plane]; + float maxc=minc; + for(int v=1;v<3;v++) + { + minc=min(minc,Vertex(v)[split_plane]); + maxc=max(maxc,Vertex(v)[split_plane]); + } + + if (minc>=split_value) + return PLANECHECK_POSITIVE; + if (maxc<=split_value) + return PLANECHECK_NEGATIVE; + if (minc==maxc) + return PLANECHECK_POSITIVE; + return PLANECHECK_STRADDLING; +} + +#define MAILBOX_HASH_SIZE 256 +#define MAX_TREE_DEPTH 21 +#define MAX_NODE_STACK_LEN (40*MAX_TREE_DEPTH) + +struct NodeToVisit { + CacheOptimizedKDNode const *node; + fltx4 TMin; + fltx4 TMax; +}; + + +static fltx4 FourEpsilons={1.0e-10,1.0e-10,1.0e-10,1.0e-10}; +static fltx4 FourZeros={1.0e-10,1.0e-10,1.0e-10,1.0e-10}; +static fltx4 FourNegativeEpsilons={-1.0e-10,-1.0e-10,-1.0e-10,-1.0e-10}; + +static float BoxSurfaceArea(Vector const &boxmin, Vector const &boxmax) +{ + Vector boxdim=boxmax-boxmin; + return 2.0*((boxdim[0]*boxdim[2])+(boxdim[0]*boxdim[1])+(boxdim[1]*boxdim[2])); +} + +void RayTracingEnvironment::Trace4Rays(const FourRays &rays, fltx4 TMin, fltx4 TMax, + RayTracingResult *rslt_out, + int32 skip_id, ITransparentTriangleCallback *pCallback) +{ + int msk=rays.CalculateDirectionSignMask(); + if (msk!=-1) + Trace4Rays(rays,TMin,TMax,msk,rslt_out,skip_id, pCallback); + else + { + // sucky case - can't trace 4 rays at once. in the worst case, need to trace all 4 + // separately, but usually we will still get 2x, Since our tracer only does 4 at a + // time, we will have to cover up the undesired rays with the desired ray + + //!! speed!! there is room for some sse-ization here + FourRays tmprays; + tmprays.origin=rays.origin; + + uint8 need_trace[4]={1,1,1,1}; + for(int try_trace=0;try_trace<4;try_trace++) + { + if (need_trace[try_trace]) + { + need_trace[try_trace]=2; // going to trace it + // replicate the ray being traced into all 4 rays + tmprays.direction.x=ReplicateX4(rays.direction.X(try_trace)); + tmprays.direction.y=ReplicateX4(rays.direction.Y(try_trace)); + tmprays.direction.z=ReplicateX4(rays.direction.Z(try_trace)); + // now, see if any of the other remaining rays can be handled at the same time. + for(int try2=try_trace+1;try2<4;try2++) + if (need_trace[try2]) + { + if ( + SameSign(rays.direction.X(try2), + rays.direction.X(try_trace)) && + SameSign(rays.direction.Y(try2), + rays.direction.Y(try_trace)) && + SameSign(rays.direction.Z(try2), + rays.direction.Z(try_trace))) + { + need_trace[try2]=2; + tmprays.direction.X(try2) = rays.direction.X(try2); + tmprays.direction.Y(try2) = rays.direction.Y(try2); + tmprays.direction.Z(try2) = rays.direction.Z(try2); + } + } + // ok, now trace between 1 and 3 rays, and output the results + RayTracingResult tmpresults; + msk=tmprays.CalculateDirectionSignMask(); + assert(msk!=-1); + Trace4Rays(tmprays,TMin,TMax,msk,&tmpresults,skip_id, pCallback); + // now, move results to proper place + for(int i=0;i<4;i++) + if (need_trace[i]==2) + { + need_trace[i]=0; + rslt_out->HitIds[i]=tmpresults.HitIds[i]; + SubFloat(rslt_out->HitDistance, i) = SubFloat(tmpresults.HitDistance, i); + rslt_out->surface_normal.X(i) = tmpresults.surface_normal.X(i); + rslt_out->surface_normal.Y(i) = tmpresults.surface_normal.Y(i); + rslt_out->surface_normal.Z(i) = tmpresults.surface_normal.Z(i); + } + + } + } + } +} + + +void RayTracingEnvironment::Trace4Rays(const FourRays &rays, fltx4 TMin, fltx4 TMax, + int DirectionSignMask, RayTracingResult *rslt_out, + int32 skip_id, ITransparentTriangleCallback *pCallback) +{ + rays.Check(); + + memset(rslt_out->HitIds,0xff,sizeof(rslt_out->HitIds)); + + rslt_out->HitDistance=ReplicateX4(1.0e23); + + rslt_out->surface_normal.DuplicateVector(Vector(0.,0.,0.)); + FourVectors OneOverRayDir=rays.direction; + OneOverRayDir.MakeReciprocalSaturate(); + + // now, clip rays against bounding box + for(int c=0;c<3;c++) + { + fltx4 isect_min_t= + MulSIMD(SubSIMD(ReplicateX4(m_MinBound[c]),rays.origin[c]),OneOverRayDir[c]); + fltx4 isect_max_t= + MulSIMD(SubSIMD(ReplicateX4(m_MaxBound[c]),rays.origin[c]),OneOverRayDir[c]); + TMin=MaxSIMD(TMin,MinSIMD(isect_min_t,isect_max_t)); + TMax=MinSIMD(TMax,MaxSIMD(isect_min_t,isect_max_t)); + } + fltx4 active=CmpLeSIMD(TMin,TMax); // mask of which rays are active + if (! IsAnyNegative(active) ) + return; // missed bounding box + + int32 mailboxids[MAILBOX_HASH_SIZE]; // used to avoid redundant triangle tests + memset(mailboxids,0xff,sizeof(mailboxids)); // !!speed!! keep around? + + int front_idx[3],back_idx[3]; // based on ray direction, whether to + // visit left or right node first + + if (DirectionSignMask & 1) + { + back_idx[0]=0; + front_idx[0]=1; + } + else + { + back_idx[0]=1; + front_idx[0]=0; + } + if (DirectionSignMask & 2) + { + back_idx[1]=0; + front_idx[1]=1; + } + else + { + back_idx[1]=1; + front_idx[1]=0; + } + if (DirectionSignMask & 4) + { + back_idx[2]=0; + front_idx[2]=1; + } + else + { + back_idx[2]=1; + front_idx[2]=0; + } + + NodeToVisit NodeQueue[MAX_NODE_STACK_LEN]; + CacheOptimizedKDNode const *CurNode=&(OptimizedKDTree[0]); + NodeToVisit *stack_ptr=&NodeQueue[MAX_NODE_STACK_LEN]; + while(1) + { + while (CurNode->NodeType() != KDNODE_STATE_LEAF) // traverse until next leaf + { + int split_plane_number=CurNode->NodeType(); + CacheOptimizedKDNode const *FrontChild=&(OptimizedKDTree[CurNode->LeftChild()]); + + fltx4 dist_to_sep_plane= // dist=(split-org)/dir + MulSIMD( + SubSIMD(ReplicateX4(CurNode->SplittingPlaneValue), + rays.origin[split_plane_number]),OneOverRayDir[split_plane_number]); + fltx4 active=CmpLeSIMD(TMin,TMax); // mask of which rays are active + + // now, decide how to traverse children. can either do front,back, or do front and push + // back. + fltx4 hits_front=AndSIMD(active,CmpGeSIMD(dist_to_sep_plane,TMin)); + if (! IsAnyNegative(hits_front)) + { + // missed the front. only traverse back + //printf("only visit back %d\n",CurNode->LeftChild()+back_idx[split_plane_number]); + CurNode=FrontChild+back_idx[split_plane_number]; + TMin=MaxSIMD(TMin, dist_to_sep_plane); + + } + else + { + fltx4 hits_back=AndSIMD(active,CmpLeSIMD(dist_to_sep_plane,TMax)); + if (! IsAnyNegative(hits_back) ) + { + // missed the back - only need to traverse front node + //printf("only visit front %d\n",CurNode->LeftChild()+front_idx[split_plane_number]); + CurNode=FrontChild+front_idx[split_plane_number]; + TMax=MinSIMD(TMax, dist_to_sep_plane); + } + else + { + // at least some rays hit both nodes. + // must push far, traverse near + //printf("visit %d,%d\n",CurNode->LeftChild()+front_idx[split_plane_number], + // CurNode->LeftChild()+back_idx[split_plane_number]); + assert(stack_ptr>NodeQueue); + --stack_ptr; + stack_ptr->node=FrontChild+back_idx[split_plane_number]; + stack_ptr->TMin=MaxSIMD(TMin,dist_to_sep_plane); + stack_ptr->TMax=TMax; + CurNode=FrontChild+front_idx[split_plane_number]; + TMax=MinSIMD(TMax,dist_to_sep_plane); + } + } + } + // hit a leaf! must do intersection check + int ntris=CurNode->NumberOfTrianglesInLeaf(); + if (ntris) + { + int32 const *tlist=&(TriangleIndexList[CurNode->TriangleIndexStart()]); + do + { + int tnum=*(tlist++); + //printf("try tri %d\n",tnum); + // check mailbox + int mbox_slot=tnum & (MAILBOX_HASH_SIZE-1); + TriIntersectData_t const *tri = &( OptimizedTriangleList[tnum].m_Data.m_IntersectData ); + if ( ( mailboxids[mbox_slot] != tnum ) && ( tri->m_nTriangleID != skip_id ) ) + { +#ifndef MAPBASE + n_intersection_calculations++; +#endif + mailboxids[mbox_slot] = tnum; + // compute plane intersection + + + FourVectors N; + N.x = ReplicateX4( tri->m_flNx ); + N.y = ReplicateX4( tri->m_flNy ); + N.z = ReplicateX4( tri->m_flNz ); + + fltx4 DDotN = rays.direction * N; + // mask off zero or near zero (ray parallel to surface) + fltx4 did_hit = OrSIMD( CmpGtSIMD( DDotN,FourEpsilons ), + CmpLtSIMD( DDotN, FourNegativeEpsilons ) ); + + fltx4 numerator=SubSIMD( ReplicateX4( tri->m_flD ), rays.origin * N ); + + fltx4 isect_t=DivSIMD( numerator,DDotN ); + // now, we have the distance to the plane. lets update our mask + did_hit = AndSIMD( did_hit, CmpGtSIMD( isect_t, FourZeros ) ); + //did_hit=AndSIMD(did_hit,CmpLtSIMD(isect_t,TMax)); + did_hit = AndSIMD( did_hit, CmpLtSIMD( isect_t, rslt_out->HitDistance ) ); + + if ( ! IsAnyNegative( did_hit ) ) + continue; + + // now, check 3 edges + fltx4 hitc1 = AddSIMD( rays.origin[tri->m_nCoordSelect0], + MulSIMD( isect_t, rays.direction[ tri->m_nCoordSelect0] ) ); + fltx4 hitc2 = AddSIMD( rays.origin[tri->m_nCoordSelect1], + MulSIMD( isect_t, rays.direction[tri->m_nCoordSelect1] ) ); + + // do barycentric coordinate check + fltx4 B0 = MulSIMD( ReplicateX4( tri->m_ProjectedEdgeEquations[0] ), hitc1 ); + + B0 = AddSIMD( + B0, + MulSIMD( ReplicateX4( tri->m_ProjectedEdgeEquations[1] ), hitc2 ) ); + B0 = AddSIMD( + B0, ReplicateX4( tri->m_ProjectedEdgeEquations[2] ) ); + + did_hit = AndSIMD( did_hit, CmpGeSIMD( B0, FourZeros ) ); + + fltx4 B1 = MulSIMD( ReplicateX4( tri->m_ProjectedEdgeEquations[3] ), hitc1 ); + B1 = AddSIMD( + B1, + MulSIMD( ReplicateX4( tri->m_ProjectedEdgeEquations[4]), hitc2 ) ); + + B1 = AddSIMD( + B1, ReplicateX4( tri->m_ProjectedEdgeEquations[5] ) ); + + did_hit = AndSIMD( did_hit, CmpGeSIMD( B1, FourZeros ) ); + + fltx4 B2 = AddSIMD( B1, B0 ); + did_hit = AndSIMD( did_hit, CmpLeSIMD( B2, Four_Ones ) ); + + if ( ! IsAnyNegative( did_hit ) ) + continue; + + // if the triangle is transparent + if ( tri->m_nFlags & FCACHETRI_TRANSPARENT ) + { + if ( pCallback ) + { + // assuming a triangle indexed as v0, v1, v2 + // the projected edge equations are set up such that the vert opposite the first + // equation is v2, and the vert opposite the second equation is v0 + // Therefore we pass them back in 1, 2, 0 order + // Also B2 is currently B1 + B0 and needs to be 1 - (B1+B0) in order to be a real + // barycentric coordinate. Compute that now and pass it to the callback + fltx4 b2 = SubSIMD( Four_Ones, B2 ); + if ( pCallback->VisitTriangle_ShouldContinue( *tri, rays, &did_hit, &B1, &b2, &B0, tnum ) ) + { + did_hit = Four_Zeros; + } + } + } + // now, set the hit_id and closest_hit fields for any enabled rays + fltx4 replicated_n = ReplicateIX4(tnum); + StoreAlignedSIMD((float *) rslt_out->HitIds, + OrSIMD(AndSIMD(replicated_n,did_hit), + AndNotSIMD(did_hit,LoadAlignedSIMD( + (float *) rslt_out->HitIds)))); + rslt_out->HitDistance=OrSIMD(AndSIMD(isect_t,did_hit), + AndNotSIMD(did_hit,rslt_out->HitDistance)); + + rslt_out->surface_normal.x=OrSIMD( + AndSIMD(N.x,did_hit), + AndNotSIMD(did_hit,rslt_out->surface_normal.x)); + rslt_out->surface_normal.y=OrSIMD( + AndSIMD(N.y,did_hit), + AndNotSIMD(did_hit,rslt_out->surface_normal.y)); + rslt_out->surface_normal.z=OrSIMD( + AndSIMD(N.z,did_hit), + AndNotSIMD(did_hit,rslt_out->surface_normal.z)); + + } + } while (--ntris); + // now, check if all rays have terminated + fltx4 raydone=CmpLeSIMD(TMax,rslt_out->HitDistance); + if (! IsAnyNegative(raydone)) + { + return; + } + } + + if (stack_ptr==&NodeQueue[MAX_NODE_STACK_LEN]) + { + return; + } + // pop stack! + CurNode=stack_ptr->node; + TMin=stack_ptr->TMin; + TMax=stack_ptr->TMax; + stack_ptr++; + } +} + + +int RayTracingEnvironment::MakeLeafNode(int first_tri, int last_tri) +{ + CacheOptimizedKDNode ret; + ret.Children=KDNODE_STATE_LEAF+(TriangleIndexList.Count()<<2); + ret.SetNumberOfTrianglesInLeafNode(1+(last_tri-first_tri)); + for(int tnum=first_tri;tnum<=last_tri;tnum++) + TriangleIndexList.AddToTail(tnum); + OptimizedKDTree.AddToTail(ret); + return OptimizedKDTree.Count()-1; +} + + +void RayTracingEnvironment::CalculateTriangleListBounds(int32 const *tris,int ntris, + Vector &minout, Vector &maxout) +{ + minout = Vector( 1.0e23, 1.0e23, 1.0e23); + maxout = Vector( -1.0e23, -1.0e23, -1.0e23); + for(int i=0; iMaxBound[axis]) || (trial_splitvalueMAX_TREE_DEPTH)) + { + // no benefit to splitting. just make this a leaf node + OptimizedKDTree[node_number].Children=KDNODE_STATE_LEAF+(TriangleIndexList.Count()<<2); + OptimizedKDTree[node_number].SetNumberOfTrianglesInLeafNode(ntris); +#ifdef DEBUG_RAYTRACE + OptimizedKDTree[node_number].vecMins = MinBound; + OptimizedKDTree[node_number].vecMaxs = MaxBound; +#endif + for(int t=0;t + +static uint32 MapDistanceToPixel(float t) +{ + if (t<0) return 0xffff0000; + if (t>100) return 0xff000000; + int a=t*1000; a&=0xff; + int b=t*10; b &=0xff; + int c=t*.01; c &=0xff; + return 0xff000000+(a<<16)+(b<<8)+c; +} + +#define IGAMMA (1.0/2.2) + +#define MAGIC_NUMBER (1<<23) + +static fltx4 Four_MagicNumbers={ MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER, MAGIC_NUMBER }; +static ALIGN16 int32 Four_255s[4]= {0xff,0xff,0xff,0xff}; +#define PIXMASK ( * ( reinterpret_cast< fltx4 *>( &Four_255s ) ) ) + +void MapLinearIntensities(FourVectors const &intens,uint32 *p1, uint32 *p2, uint32 *p3, uint32 *p4) +{ + // convert four pixels worth of sse-style rgb into argb lwords + // NOTE the _mm_empty macro is voodoo. do not mess with this routine casually - simply throwing + // anything that ends up generating a fpu stack references in here would be bad news. + static fltx4 pixscale={255.0,255.0,255.0,255.0}; + fltx4 r,g,b; + r=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.x,IGAMMA))); + g=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.y,IGAMMA))); + b=MinSIMD(pixscale,MulSIMD(pixscale,PowSIMD(intens.z,IGAMMA))); + // now, convert to integer + r=AndSIMD( AddSIMD( r, Four_MagicNumbers ), PIXMASK ); + g=AndSIMD( AddSIMD( g, Four_MagicNumbers ), PIXMASK ); + b=AndSIMD( AddSIMD( b, Four_MagicNumbers ), PIXMASK ); + + *(p1)=(SubInt(r, 0))|(SubInt(g, 0)<<8)|(SubInt(b, 0)<<16); + *(p2)=(SubInt(r, 1))|(SubInt(g, 1)<<8)|(SubInt(b, 1)<<16); + *(p3)=(SubInt(r, 2))|(SubInt(g, 2)<<8)|(SubInt(b, 2)<<16); + *(p4)=(SubInt(r, 3))|(SubInt(g, 3)<<8)|(SubInt(b, 3)<<16); +} + +static ALIGN16 int32 signmask[4]={0x80000000,0x80000000,0x80000000,0x80000000}; +static ALIGN16 int32 all_ones[4]={-1,-1,-1,-1}; +static fltx4 all_zeros={0,0,0,0}; +static fltx4 TraceLimit={1.0e20,1.0e20,1.0e20,1.0e20}; + +void RayTracingEnvironment::RenderScene( + int width, int height, // width and height of desired rendering + int stride, // actual width in pixels of target buffer + uint32 *output_buffer, // pointer to destination + Vector CameraOrigin, // eye position + Vector ULCorner, // word space coordinates of upper left + // monitor corner + Vector URCorner, // top right corner + Vector LLCorner, // lower left + Vector LRCorner, // lower right + RayTraceLightingMode_t lmode) +{ + // first, compute deltas + Vector dxvector=URCorner; + dxvector-=ULCorner; + dxvector*=(1.0/width); + Vector dxvectortimes2=dxvector; + dxvectortimes2+=dxvector; + + Vector dyvector=LLCorner; + dyvector-=ULCorner; + dyvector*=(1.0/height); + + + // block_offsets-relative offsets for eahc of the 4 pixels in the block, in sse format + FourVectors block_offsets; + block_offsets.LoadAndSwizzle(Vector(0,0,0),dxvector,dyvector,dxvector+dyvector); + + FourRays myrays; + myrays.origin.DuplicateVector(CameraOrigin); + + // tmprays is used fo rthe case when we cannot trace 4 rays at once. + FourRays tmprays; + tmprays.origin.DuplicateVector(CameraOrigin); + + // now, we will ray trace pixels. we will do the rays in a 2x2 pattern + for(int y=0;y=0) + { + surf_colors.X(i)=TriangleColors[rslt.HitIds[i]].x; + surf_colors.Y(i)=TriangleColors[rslt.HitIds[i]].y; + surf_colors.Z(i)=TriangleColors[rslt.HitIds[i]].z; + } + + } + FourVectors surface_pos=myrays.direction; + surface_pos*=rslt.HitDistance; + surface_pos+=myrays.origin; + + switch(lmode) + { + case DIRECT_LIGHTING: + { + // light all points + for(int l=0;l0) + { + l1.m_Color*=area_of_virtual_light/M_PI; + l1.m_Range=0.0; + l1.m_Falloff=1.0; + l1.m_Attenuation0=1.0; + l1.m_Attenuation1=0.0; + l1.m_Attenuation2=1.0; // intens falls off as 1/r^2 + l1.m_Theta=0; + l1.m_Phi=M_PI; + l1.RecalculateDerivedValues(); + LightList.AddToTail(l1); + } + } + } + } + } + } +} + + + +static unsigned int GetSignMask(Vector const &v) +{ + unsigned int ret=0; + if (v.x<0.0) + ret++; + if (v.y<0) + ret+=2; + if (v.z<0) + ret+=4; + return ret; +} + + +inline void RayTracingEnvironment::FlushStreamEntry(RayStream &s,int msk) +{ + assert(msk>=0); + assert(msk<8); + fltx4 tmax=s.PendingRays[msk].direction.length(); + fltx4 scl=ReciprocalSaturateSIMD(tmax); + s.PendingRays[msk].direction*=scl; // normalize + RayTracingResult tmpresult; + Trace4Rays(s.PendingRays[msk],Four_Zeros,tmax,msk,&tmpresult); + // now, write out results + for(int r=0;r<4;r++) + { + RayTracingSingleResult *out=s.PendingStreamOutputs[msk][r]; + out->ray_length=SubFloat( tmax, r ); + out->surface_normal.x=tmpresult.surface_normal.X(r); + out->surface_normal.y=tmpresult.surface_normal.Y(r); + out->surface_normal.z=tmpresult.surface_normal.Z(r); + out->HitID=tmpresult.HitIds[r]; + out->HitDistance=SubFloat( tmpresult.HitDistance, r ); + } + s.n_in_stream[msk]=0; +} + +void RayTracingEnvironment::AddToRayStream(RayStream &s, + Vector const &start,Vector const &end, + RayTracingSingleResult *rslt_out) +{ + Vector delta=end; + delta-=start; + int msk=GetSignMask(delta); + assert(msk>=0); + assert(msk<8); + int pos=s.n_in_stream[msk]; + assert(pos<4); + s.PendingRays[msk].origin.X(pos)=start.x; + s.PendingRays[msk].origin.Y(pos)=start.y; + s.PendingRays[msk].origin.Z(pos)=start.z; + s.PendingRays[msk].direction.X(pos)=delta.x; + s.PendingRays[msk].direction.Y(pos)=delta.y; + s.PendingRays[msk].direction.Z(pos)=delta.z; + s.PendingStreamOutputs[msk][pos]=rslt_out; + if (pos==3) + { + FlushStreamEntry(s,msk); + } + else + s.n_in_stream[msk]++; +} + +void RayTracingEnvironment::FinishRayStream(RayStream &s) +{ + for(int msk=0;msk<8;msk++) + { + int cnt=s.n_in_stream[msk]; + if (cnt) + { + // fill in unfilled entries with dups of first + for(int c=cnt;c<4;c++) + { + s.PendingRays[msk].origin.X(c) = s.PendingRays[msk].origin.X(0); + s.PendingRays[msk].origin.Y(c) = s.PendingRays[msk].origin.Y(0); + s.PendingRays[msk].origin.Z(c) = s.PendingRays[msk].origin.Z(0); + s.PendingRays[msk].direction.X(c) = s.PendingRays[msk].direction.X(0); + s.PendingRays[msk].direction.Y(c) = s.PendingRays[msk].direction.Y(0); + s.PendingRays[msk].direction.Z(c) = s.PendingRays[msk].direction.Z(0); + s.PendingStreamOutputs[msk][c]=s.PendingStreamOutputs[msk][0]; + } + FlushStreamEntry(s,msk); + } + } +} diff --git a/sp/src/raytrace/trace3.cpp b/sp/src/raytrace/trace3.cpp new file mode 100644 index 00000000..b582347e --- /dev/null +++ b/sp/src/raytrace/trace3.cpp @@ -0,0 +1,127 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// + +#include "raytrace.h" +#include +#include "bsplib.h" + +static Vector VertCoord(dface_t const &f, int vnum) +{ + int eIndex = dsurfedges[f.firstedge+vnum]; + int point; + if( eIndex < 0 ) + { + point = dedges[-eIndex].v[1]; + } + else + { + point = dedges[eIndex].v[0]; + } + dvertex_t *v=dvertexes+point; + return Vector(v->point[0],v->point[1],v->point[2]); + +} + +Vector colors[]={ + Vector(0.5,0.5,1), + Vector(0.5,1,0.5), + Vector(0.5,1,1), + Vector(1,0.5,0.5), + Vector(1,0.5,1), + Vector(1,1,1)}; + +void RayTracingEnvironment::AddBSPFace(int id,dface_t const &face) +{ + if (face.dispinfo!=-1) // displacements must be dealt with elsewhere + return; + texinfo_t *tx =(face.texinfo>=0)?&(texinfo[face.texinfo]):0; +// if (tx && (tx->flags & (SURF_SKY|SURF_NODRAW))) +// return; + if (tx) + { + printf("id %d flags=%x\n",id,tx->flags); + } + printf("side: "); + for(int v=0;v PlanesToSkip; +// SidesToSkip.EnsureCapacity(numplanes); +// for(int s=0;s OrigFaceVisited; +// OrigFaceVisited.EnsureCapacity(numorigfaces); +// int n_added=0; + +// for(int i=0;i +inline void swap( T& x, T& y ) +{ + T temp = x; + x = y; + y = temp; +} +#endif + +#include +#include + +#include +#include + +#include +#include +#include + +#include + +#include "string_t.h" +#include "globalvars_base.h" + +#include + +#include "interface/dll_init.h" + +#include "engine/ivmodelinfo.h" +#include "engine/ivmodelrender.h" + +#include "util/igamesystem.h" + +#include "editorCommon.h" + +#endif // CBASE_H diff --git a/sp/src/shadereditor/chlsl_image.cpp b/sp/src/shadereditor/chlsl_image.cpp new file mode 100644 index 00000000..66bb16ef --- /dev/null +++ b/sp/src/shadereditor/chlsl_image.cpp @@ -0,0 +1,303 @@ + +#include "cbase.h" +#include "editorCommon.h" +#include "view_shared.h" + +#include "vtf/vtf.h" +//#include "magick++.h" +#ifdef SHADER_EDITOR_DLL_2006 +#include "setjmp.h" +#endif + +#include "jpeglib/jpeglib.h" + +CHLSL_Image::CHLSL_Image() +{ + pVtf = NULL; + bEnvmap = false; + pKVM = NULL; +} + +CHLSL_Image::~CHLSL_Image() +{ + DestroyImage(); +} + +void CHLSL_Image::DestroyImage() +{ + if ( pVtf ) + DestroyVTFTexture( pVtf ); + pVtf = NULL; +} + + +bool CHLSL_Image::LoadFromVTF( const char *path ) +{ + pVtf = CreateVTFTexture(); + if ( !pVtf ) + return false; + + CUtlBuffer vtf; + bool bSuccess = g_pFullFileSystem->ReadFile( path, 0, vtf ) && pVtf->Unserialize( vtf ); + vtf.Purge(); + + if ( !bSuccess ) + { + DestroyImage(); + return false; + } + + pVtf->ConvertImageFormat( IMAGE_FORMAT_DEFAULT, false ); + bEnvmap = ( pVtf->Flags() & TEXTUREFLAGS_ENVMAP ) != 0; + return true; +} + +void CHLSL_Image::InitProceduralMaterial() +{ +} + +void CHLSL_Image::DestroyProceduralMaterial() +{ +} + +#include "bitmap/tgawriter.h" + + +struct ValveJpegErrorHandler_t +{ + struct jpeg_error_mgr m_Base; + jmp_buf m_ErrorContext; +}; + +static void ValveJpegErrorHandler( j_common_ptr cinfo ) +{ + ValveJpegErrorHandler_t *pError = reinterpret_cast< ValveJpegErrorHandler_t * >( cinfo->err ); + char buffer[ JMSG_LENGTH_MAX ]; + ( *cinfo->err->format_message )( cinfo, buffer ); + Warning( "%s\n", buffer ); + longjmp( pError->m_ErrorContext, 1 ); +} + +CUtlVector jOut; +#define BLOCK_SIZE 16384 + +void jInit_destination(j_compress_ptr cinfo) +{ + jOut.Purge(); + jOut.SetSize(BLOCK_SIZE); + cinfo->dest->next_output_byte = &jOut[0]; + cinfo->dest->free_in_buffer = jOut.Count(); +} + +boolean jEmpty_output_buffer(j_compress_ptr cinfo) +{ + size_t oldsize = jOut.Count(); + jOut.SetCountNonDestructively(oldsize + BLOCK_SIZE); + + cinfo->dest->next_output_byte = &jOut[oldsize]; + cinfo->dest->free_in_buffer = jOut.Count() - oldsize; + return true; +} + +void jTerm_destination(j_compress_ptr cinfo) +{ + jOut.SetCountNonDestructively(jOut.Count() - cinfo->dest->free_in_buffer); +} + +void CHLSL_Image::CreateScreenshot( CNodeView *n, const char *filepath ) +{ + Vector4D graphBounds; + n->GetGraphBoundaries( graphBounds ); + + int vsize_x, vsize_y; + n->GetSize( vsize_x, vsize_y ); + const float zoomFactor = 1.0f / clamp( sedit_screenshot_zoom.GetFloat(), 0.01f, 100.0f ); + + float nodespace_width = graphBounds.z - graphBounds.x; + float nodespace_height = graphBounds.w - graphBounds.y; + float nodespace_width_pershot = vsize_x * zoomFactor; + float nodespace_height_pershot = vsize_y * zoomFactor; + + int numshots_x = ceil( nodespace_width / nodespace_width_pershot ); + int numshots_y = ceil( nodespace_height / nodespace_height_pershot ); + + Vector2D extraSpace; + extraSpace.x = (nodespace_width_pershot*numshots_x) - nodespace_width; + extraSpace.y = (nodespace_height_pershot*numshots_y) - nodespace_height; + extraSpace *= 0.5f; + + n->vecScreenshotBounds.Init( graphBounds.x - extraSpace.x, + graphBounds.y - extraSpace.y, + graphBounds.z + extraSpace.x, + graphBounds.w + extraSpace.y ); + + int tgapixels_x = numshots_x * vsize_x - numshots_x; + int tgapixels_y = numshots_y * vsize_y - numshots_y; + + unsigned int targetSize = tgapixels_x * 3 * tgapixels_y; + unsigned char *pTGA = ( unsigned char * )malloc( targetSize ); + if ( !pTGA ) + { + Warning( "Not enough memory available (failed to malloc %u bytes).\n", targetSize ); + } + + Vector2D pos_old = n->AccessViewPos(); + float zoom_old = n->AccessViewZoom(); + n->bRenderingScreenShot = true; + + n->AccessViewZoom() = zoomFactor; + + int vp_x, vp_y; + vp_x = vp_y = 0; + n->LocalToScreen( vp_x, vp_y ); + int screen_sx, screen_sy; + engine->GetScreenSize( screen_sx, screen_sy ); + + vp_x++; + vp_y++; + vsize_x--; + vsize_y--; + + n->AccessViewPos().Init(); + + CViewSetup view2D; + view2D.x = 0; + view2D.y = 0; + view2D.width = screen_sx; + view2D.height = screen_sy; + view2D.m_bRenderToSubrectOfLargerScreen = false; + Frustum _fplanes; + + CMatRenderContextPtr pRenderContext( materials ); + +#ifdef SHADER_EDITOR_DLL_2006 + render->Push2DView( view2D, 0, false, NULL, _fplanes ); +#else + render->Push2DView( view2D, 0, NULL, _fplanes ); +#endif + pRenderContext->PushRenderTargetAndViewport( NULL, view2D.x, view2D.y, view2D.width, view2D.height ); + +// bool bSuccess = TGAWriter::WriteDummyFileNoAlloc( filepath, tgapixels_x, tgapixels_y, IMAGE_FORMAT_RGBA8888 ); +// Assert( bSuccess ); + + if ( pTGA ) + { + for ( int sX = 0; sX < numshots_x; sX ++ ) + { + for ( int sY = 0; sY < numshots_y; sY ++ ) + { + Vector2D basepos( graphBounds.x + nodespace_width_pershot * 0.5f, graphBounds.w - nodespace_height_pershot * 0.5f ); + basepos.x += sX * nodespace_width_pershot; + basepos.y -= sY * nodespace_height_pershot; + basepos.x *= -1.0f; + basepos += extraSpace; + n->AccessViewPos() = basepos; + + pRenderContext->ClearColor4ub( 0, 0, 0, 0 ); + pRenderContext->ClearBuffers( true, true ); + vgui::ipanel()->PaintTraverse( n->GetVPanel(), true ); + + unsigned int sizeimg = vsize_x * 3 * vsize_y; + unsigned char *pImage = ( unsigned char * )malloc( sizeimg ); + if ( pImage ) + { + pRenderContext->ReadPixels( vp_x, vp_y, vsize_x, vsize_y, pImage, IMAGE_FORMAT_RGB888 ); + + for ( int pX = 0; pX < vsize_x; pX ++ ) + { + for ( int pY = 0; pY < vsize_y; pY ++ ) + { + int targetpixel = (sX * vsize_x + pX) * 3 + + ( sY * vsize_y + pY ) * tgapixels_x * 3; + int srcpixel = pX * 3 + pY * vsize_x * 3; + + Q_memcpy( &pTGA[targetpixel], &pImage[srcpixel], 3 ); + } + } +#if 0 +#if DEBUG + bool bSuccess = +#endif + TGAWriter::WriteRectNoAlloc( pImage, filepath, sX * vsize_x, sY * vsize_y, vsize_x, vsize_y, 0, IMAGE_FORMAT_RGB888 ); +#if DEBUG + Assert( bSuccess ); +#endif +#endif + + free( pImage ); + } + else + Warning( "Tiling error (failed to malloc %u bytes).\n", sizeimg ); + + } + } + } + + + if ( pTGA ) + { + //unsigned int iMaxTGASize = 1024 + (tgapixels_x * tgapixels_y * 3); + //void *pTGA_BUFFER = malloc( iMaxTGASize ); + //if ( pTGA_BUFFER ) + //{ + // CUtlBuffer buffer( pTGA_BUFFER, iMaxTGASize ); + + // TGAWriter::WriteToBuffer( pTGA, buffer, tgapixels_x, tgapixels_y, IMAGE_FORMAT_RGB888, IMAGE_FORMAT_RGB888 ); + // filesystem->AsyncWrite( filepath, buffer.Base(), buffer.TellPut(), true ); + //} + //else + //{ + // Warning( "Not enough memory available (failed to malloc %u bytes).\n", iMaxTGASize ); + //} + + jpeg_compress_struct jInfo; + ValveJpegErrorHandler_t jErr; + jpeg_destination_mgr jDest; + + jInfo.err = jpeg_std_error( &jErr.m_Base ); + jInfo.err->error_exit = &ValveJpegErrorHandler; + + jpeg_create_compress( &jInfo ); + + jInfo.dest = &jDest; + jInfo.dest->init_destination = &jInit_destination; + jInfo.dest->empty_output_buffer = &jEmpty_output_buffer; + jInfo.dest->term_destination = &jTerm_destination; + + jInfo.image_width = tgapixels_x; + jInfo.image_height = tgapixels_y; + jInfo.input_components = 3; + jInfo.in_color_space = JCS_RGB; + jpeg_set_defaults( &jInfo ); + jpeg_set_quality( &jInfo, clamp( sedit_screenshot_quali.GetInt(), 1, 100 ), FALSE ); + + jpeg_start_compress(&jInfo, TRUE); + + JSAMPROW row_pointer[1]; + int row_stride; + row_stride = jInfo.image_width * 3; + while (jInfo.next_scanline < jInfo.image_height) + { + row_pointer[0] = &pTGA[jInfo.next_scanline * row_stride]; + jpeg_write_scanlines(&jInfo, row_pointer, 1); + } + + jpeg_finish_compress(&jInfo); + + jpeg_destroy_compress(&jInfo); + + void *pBUFFER = malloc( jOut.Count() ); + Q_memcpy( pBUFFER, jOut.Base(), jOut.Count() ); + filesystem->AsyncWrite( filepath, pBUFFER, jOut.Count(), true ); + + jOut.Purge(); + free( pTGA ); + } + + pRenderContext->PopRenderTargetAndViewport(); + render->PopView( _fplanes ); + + n->bRenderingScreenShot = false; + n->AccessViewPos() = pos_old; + n->AccessViewZoom() = zoom_old; +} diff --git a/sp/src/shadereditor/chlsl_image.h b/sp/src/shadereditor/chlsl_image.h new file mode 100644 index 00000000..06bce653 --- /dev/null +++ b/sp/src/shadereditor/chlsl_image.h @@ -0,0 +1,35 @@ +#ifndef CHLSL_IMAGE_H +#define CHLSL_IMAGE_H + +#include "vtf/vtf.h" +#include "editorCommon.h" + +class CHLSL_Image +{ +public: + + CHLSL_Image(); + ~CHLSL_Image(); + + void DestroyImage(); + bool LoadFromVTF( const char *path ); + + bool IsEnvmap(){ return bEnvmap; }; + IVTFTexture *GetVTF(){return pVtf;}; + + void InitProceduralMaterial(); + void DestroyProceduralMaterial(); + + static void CreateScreenshot( CNodeView *n, const char *filepath ); + +private: + IVTFTexture *pVtf; + bool bEnvmap; + + IMaterial *pProcMat; + KeyValues *pKVM; +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/chlsl_mesh.cpp b/sp/src/shadereditor/chlsl_mesh.cpp new file mode 100644 index 00000000..9d936800 --- /dev/null +++ b/sp/src/shadereditor/chlsl_mesh.cpp @@ -0,0 +1,829 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CHLSL_Vertex::CHLSL_Vertex() +{ + Q_memset( this, 0, sizeof(CHLSL_Vertex) ); +} +CHLSL_Vertex::~CHLSL_Vertex() +{ +} +//CHLSL_Vertex::CHLSL_Vertex( const CHLSL_Vertex &o ) +//{ +//} + + + +CHLSL_Triangle::CHLSL_Triangle() +{ + vertices[ 0 ] = NULL; + vertices[ 1 ] = NULL; + vertices[ 2 ] = NULL; +} +CHLSL_Triangle::~CHLSL_Triangle() +{ +} +//CHLSL_Triangle::CHLSL_Triangle( const CHLSL_Triangle &o ) +//{ +//} + + + +CHLSL_Mesh::CHLSL_Mesh() +{ + m_Vertices = NULL; + m_iNumVertices = 0; + + m_Triangles = NULL; + m_iNumTriangles = 0; +} +CHLSL_Mesh::~CHLSL_Mesh() +{ + delete [] m_Vertices; + delete [] m_Triangles; +} +CHLSL_Mesh::CHLSL_Mesh( const CHLSL_Mesh &o ) +{ + m_iNumVertices = o.m_iNumVertices; + m_iNumTriangles = o.m_iNumTriangles; + + m_Vertices = new CHLSL_Vertex[m_iNumVertices]; + Q_memcpy(m_Vertices,o.m_Vertices,sizeof(CHLSL_Vertex)*m_iNumVertices); + + m_Triangles = new CHLSL_Triangle[m_iNumTriangles]; + Q_memcpy(m_Triangles,o.m_Triangles,sizeof(CHLSL_Triangle)*m_iNumTriangles); + + int vertexOffset = m_Vertices - o.m_Vertices; + for ( int i = 0; i < m_iNumTriangles; i++ ) + { + m_Triangles[i].vertices[0] += vertexOffset; + m_Triangles[i].vertices[1] += vertexOffset; + m_Triangles[i].vertices[2] += vertexOffset; + } +} + +void CHLSL_Mesh::CreateCylinder( float size, int subdiv ) +{ + subdiv /= 2; + + delete [] m_Vertices; + delete [] m_Triangles; + + int num_verts_u = subdiv + 1; + int num_verts_v = subdiv + 1; + int num_verts_side = num_verts_u * num_verts_v; + int num_verts_top = 1 + num_verts_u - 1; + m_iNumVertices = num_verts_side + num_verts_top * 2; + + int num_tris_u = (num_verts_u-1); + int num_tris_v = (num_verts_v-1); + int num_tris_side = num_tris_u * num_tris_v * 2; + int num_tris_top = num_tris_u; + m_iNumTriangles = num_tris_side + num_tris_top * 2; + + m_Vertices = new CHLSL_Vertex[ m_iNumVertices ]; + m_Triangles = new CHLSL_Triangle[ m_iNumTriangles ]; + + QAngle rotate( 0, 0, 0 ); + + float yaw_step = 360.0f / (num_verts_u-1); + float up_step = size * 2.0f / (num_verts_v-1); + float size_radius = size * 0.5f; + + Vector fwd, right, up, pos; + +/// verts for side + for ( int vert_u = 0; vert_u < num_verts_u; vert_u++ ) + { + AngleVectors( rotate, &fwd, &right, &up ); + + pos = up * size + fwd * size_radius; + + for ( int vert_v = 0; vert_v < num_verts_v; vert_v++ ) + { + int vindex = vert_u * num_verts_v + + vert_v; + + Assert( vindex < m_iNumVertices ); + + CHLSL_Vertex &vert = m_Vertices[ vindex ]; + + Q_memcpy( vert.normal, fwd.Base(), sizeof( float ) * 3 ); + Q_memcpy( vert.pos, pos.Base(), sizeof( float ) * 3 ); + + vert.uv[0][0] = vert_u / (float)( num_verts_u - 1 ); + vert.uv[0][1] = vert_v / (float)( num_verts_v - 1 ); + + pos -= up * up_step; + } + + rotate.y += yaw_step; + } + +/// verts for top/bottom + for ( int v_side = 0; v_side < 2; v_side++ ) + { + rotate.y = 0; + float sign = (v_side==1) ? -1.0f : 1.0f; + + up.Init( 0, 0, sign ); + Vector height = up * size; + + for ( int v_u = 0; v_u < num_verts_top; v_u++ ) + { + int vindex = num_verts_side + + v_side * num_verts_top + + v_u; + + Assert( vindex < m_iNumVertices ); + + CHLSL_Vertex &vert = m_Vertices[ vindex ]; + + Vector2D uv; + Vector pos = height; + + if ( v_u > 0 ) + { + AngleVectors( rotate, &fwd, NULL, NULL ); + pos += fwd * size_radius; + uv.x = -sign * fwd.x * 0.5f + 0.5f; + uv.y = fwd.y * 0.5f + 0.5f; + rotate.y += yaw_step * sign; + } + else + uv.Init( 0.5f, 0.5f ); + + Q_memcpy( vert.pos, pos.Base(), sizeof( float ) * 3 ); + Q_memcpy( vert.normal, up.Base(), sizeof( float ) * 3 ); + Q_memcpy( vert.uv, uv.Base(), sizeof( float ) * 2 ); + } + } + +/// tris for side + for ( int tri_u = 0; tri_u < num_tris_u; tri_u++ ) + { + for ( int tri_v = 0; tri_v < num_tris_v; tri_v++ ) + { + int tri_0 = tri_u * num_tris_v + + tri_v; + int tri_1 = tri_0 + num_tris_side / 2; + + Assert( tri_0 < m_iNumTriangles ); + Assert( tri_1 < m_iNumTriangles ); + + CHLSL_Triangle &t0 = m_Triangles[ tri_0 ]; + CHLSL_Triangle &t1 = m_Triangles[ tri_1 ]; + + int v00 = tri_u * num_verts_v + + tri_v; + int v01 = v00 + 1; + int v10 = (tri_u+1) * num_verts_v + + tri_v; + int v11 = v10 + 1; + + Assert( v00 < m_iNumVertices ); + Assert( v01 < m_iNumVertices ); + Assert( v10 < m_iNumVertices ); + Assert( v11 < m_iNumVertices ); + + t0.vertices[ 0 ] = &m_Vertices[ v00 ]; + t0.vertices[ 1 ] = &m_Vertices[ v10 ]; + t0.vertices[ 2 ] = &m_Vertices[ v01 ]; + + t1.vertices[ 0 ] = &m_Vertices[ v10 ]; + t1.vertices[ 1 ] = &m_Vertices[ v11 ]; + t1.vertices[ 2 ] = &m_Vertices[ v01 ]; + } + } + +/// tris for top + for ( int dir = 0; dir < 2; dir++ ) + { + int v_mid = num_verts_side + + dir * num_verts_top; + + Assert( v_mid < m_iNumVertices ); + + for ( int tri_n = 0; tri_n < num_tris_top; tri_n++ ) + { + int tIndex = num_tris_side + + dir * num_tris_top + + tri_n; + + Assert( tIndex < m_iNumTriangles ); + + CHLSL_Triangle &t = m_Triangles[ tIndex ]; + + int v00 = v_mid + tri_n + 1; + int v10 = (tri_n < (num_tris_top-1)) ? v00 + 1 : v_mid + 1; + + Assert( v00 < m_iNumVertices ); + Assert( v10 < m_iNumVertices ); + + t.vertices[ 0 ] = &m_Vertices[ v00 ]; + t.vertices[ 1 ] = &m_Vertices[ v_mid ]; + t.vertices[ 2 ] = &m_Vertices[ v10 ]; + } + } + + + GenerateTangentSpace(); +} + +void CHLSL_Mesh::CreatePlane( float size, int subdiv ) +{ + delete [] m_Vertices; + delete [] m_Triangles; + + float dist_per_vert = size / subdiv * 2; + + int num_verts_side = ( subdiv + 1 ); + m_iNumVertices = num_verts_side * num_verts_side; + + int num_tris_side = subdiv; + m_iNumTriangles = num_tris_side * num_tris_side * 2; + + m_Vertices = new CHLSL_Vertex[ m_iNumVertices ]; + m_Triangles = new CHLSL_Triangle[ m_iNumTriangles ]; + + Vector fwd( 0, 0, 1 ); + Vector right( 0, -1, 0 ); + Vector up( -1, 0, 0 ); + + for ( int vert_right = 0; vert_right < num_verts_side; vert_right++ ) + { + for ( int vert_up = 0; vert_up < num_verts_side; vert_up++ ) + { + int vertindex = vert_up * num_verts_side + + vert_right; + + CHLSL_Vertex &vert = m_Vertices[ vertindex ]; + + Vector pos = right * -size + up * -size; + pos += right * vert_right * dist_per_vert; + pos += up * vert_up * dist_per_vert; + + Vector2D uv( vert_right / (float)(num_verts_side - 1), + vert_up / (float)(num_verts_side - 1) ); + + Vector n = fwd; + + Q_memcpy( vert.normal, n.Base(), sizeof( float ) * 3 ); + Q_memcpy( vert.pos, pos.Base(), sizeof( float ) * 3 ); + Q_memcpy( vert.uv, uv.Base(), sizeof( float ) * 2 ); + } + } + + for ( int tri_right = 0; tri_right < num_tris_side; tri_right++ ) + { + for ( int tri_up = 0; tri_up < num_tris_side; tri_up++ ) + { + int tri_index_0 = tri_up * num_tris_side + + tri_right; + int tri_index_1 = tri_index_0 + m_iNumTriangles / 2; + + Assert( tri_index_0 < m_iNumTriangles ); + Assert( tri_index_1 < m_iNumTriangles ); + + int v00_index = tri_up * num_verts_side + + tri_right; + int v10_index = v00_index + 1; + int v01_index = (tri_up+1) * num_verts_side + + tri_right; + int v11_index = v01_index + 1; + + Assert( v00_index < m_iNumVertices ); + Assert( v01_index < m_iNumVertices ); + Assert( v10_index < m_iNumVertices ); + Assert( v11_index < m_iNumVertices ); + + CHLSL_Triangle &t0 = m_Triangles[ tri_index_0 ]; + CHLSL_Triangle &t1 = m_Triangles[ tri_index_1 ]; + + t0.vertices[ 0 ] = &m_Vertices[ v00_index ]; + t0.vertices[ 1 ] = &m_Vertices[ v10_index ]; + t0.vertices[ 2 ] = &m_Vertices[ v01_index ]; + + t1.vertices[ 0 ] = &m_Vertices[ v10_index ]; + t1.vertices[ 1 ] = &m_Vertices[ v11_index ]; + t1.vertices[ 2 ] = &m_Vertices[ v01_index ]; + } + } + + GenerateTangentSpace(); +} + +void CHLSL_Mesh::CreateCube( float size, int subdiv ) +{ + subdiv /= 3; + subdiv = max( subdiv, 1 ); + + delete [] m_Vertices; + delete [] m_Triangles; + + float dist_per_vert = size / subdiv * 2; + + int num_verts_side = ( subdiv + 1 ); + int num_verts_plane = num_verts_side * num_verts_side; + + int num_tris_side = subdiv; + int num_tris_plane = num_tris_side * num_tris_side * 2; + + m_iNumVertices = num_verts_plane * 6; + m_iNumTriangles = num_tris_plane * 6; + + m_Vertices = new CHLSL_Vertex[ m_iNumVertices ]; + m_Triangles = new CHLSL_Triangle[ m_iNumTriangles ]; + + const Vector orient[6][3] = + { + Vector( 1, 0, 0 ),Vector( 0, 1, 0 ),Vector( 0, 0, -1 ), + Vector( 0, 1, 0 ),Vector( -1, 0, 0 ),Vector( 0, 0, -1 ), + Vector( -1, 0, 0 ),Vector( 0, -1, 0 ),Vector( 0, 0, -1 ), + Vector( 0, -1, 0 ),Vector( 1, 0, 0 ),Vector( 0, 0, -1 ), + Vector( 0, 0, 1 ),Vector( -1, 0, 0 ),Vector( 0, 1, 0 ), + Vector( 0, 0, -1 ),Vector( -1, 0, 0 ),Vector( 0, -1, 0 ), + }; + + for ( int plane = 0; plane < 6; plane++ ) + { + int orientIndex = plane; + + Vector fwd = orient[ orientIndex ][0]; + Vector right = orient[ orientIndex ][1]; + Vector up = orient[ orientIndex ][2]; + + for ( int vert_right = 0; vert_right < num_verts_side; vert_right++ ) + { + for ( int vert_up = 0; vert_up < num_verts_side; vert_up++ ) + { + int vertindex = plane * num_verts_plane + + vert_up * num_verts_side + + vert_right; + + Assert( vertindex < m_iNumVertices ); + + CHLSL_Vertex &vert = m_Vertices[ vertindex ]; + + Vector pos = fwd * size; + pos -= right * size + up * size; + pos += right * vert_right * dist_per_vert; + pos += up * vert_up * dist_per_vert; + + Vector2D uv( vert_right / (float)(num_verts_side - 1), + vert_up / (float)(num_verts_side - 1) ); + + Vector n = fwd; + + Q_memcpy( vert.normal, n.Base(), sizeof( float ) * 3 ); + Q_memcpy( vert.pos, pos.Base(), sizeof( float ) * 3 ); + Q_memcpy( vert.uv, uv.Base(), sizeof( float ) * 2 ); + } + } + } + + for ( int plane = 0; plane < 6; plane++ ) + { + bool bFlip = true; //plane > 2; + + for ( int tri_right = 0; tri_right < num_tris_side; tri_right++ ) + { + for ( int tri_up = 0; tri_up < num_tris_side; tri_up++ ) + { + int tri_index_0 = plane * num_tris_plane + + tri_up * num_tris_side + + tri_right; + int tri_index_1 = tri_index_0 + num_tris_plane / 2; + + Assert( tri_index_0 < m_iNumTriangles ); + Assert( tri_index_1 < m_iNumTriangles ); + + int v00_index = plane * num_verts_plane + + tri_up * num_verts_side + + tri_right; + int v10_index = v00_index + 1; + int v01_index = plane * num_verts_plane + + (tri_up+1) * num_verts_side + + tri_right; + int v11_index = v01_index + 1; + + Assert( v00_index < m_iNumVertices ); + Assert( v01_index < m_iNumVertices ); + Assert( v10_index < m_iNumVertices ); + Assert( v11_index < m_iNumVertices ); + + CHLSL_Triangle &t0 = m_Triangles[ tri_index_0 ]; + CHLSL_Triangle &t1 = m_Triangles[ tri_index_1 ]; + + int idx_1 = bFlip ? 1 : 2; + int idx_2 = bFlip ? 2 : 1; + + t0.vertices[ 0 ] = &m_Vertices[ v00_index ]; + t0.vertices[ idx_1 ] = &m_Vertices[ v10_index ]; + t0.vertices[ idx_2 ] = &m_Vertices[ v01_index ]; + + t1.vertices[ 0 ] = &m_Vertices[ v10_index ]; + t1.vertices[ idx_1 ] = &m_Vertices[ v11_index ]; + t1.vertices[ idx_2 ] = &m_Vertices[ v01_index ]; + } + } + } + + GenerateTangentSpace(); +} + +void CHLSL_Mesh::CreateSphere( float radius, int subdiv ) +{ + subdiv = max( subdiv, 1 ); + + delete [] m_Vertices; + delete [] m_Triangles; + int subdivs_u = subdiv; + // two halfs + int subdivs_v = subdivs_u / 2; + + float yaw_change = 360.0f / subdivs_u; + float pitch_change = 90.0f / subdivs_v; + + int iverts_onehalf = (subdivs_v + 1) * subdivs_u; + m_iNumVertices = iverts_onehalf * 2; + m_Vertices = new CHLSL_Vertex[m_iNumVertices]; + + int itris_onehalf = (subdivs_v - 1) * subdivs_u * 2 + subdivs_u; + m_iNumTriangles = itris_onehalf * 2; + m_Triangles = new CHLSL_Triangle[m_iNumTriangles]; + +/// SETUP VERTICES + for ( int goUp = 0; goUp <= subdivs_v; goUp++ ) + { + for ( int goRound = 0; goRound < subdivs_u; goRound++ ) + { + QAngle center_d( 90, 0, 0 ); + center_d.x -= goUp * pitch_change; + center_d.y += goRound * yaw_change; + if ( goUp == subdivs_v ) + center_d.x = 0; + + Vector dir; + AngleVectors( center_d, &dir ); + + int VertexSlot = goUp + (1+subdivs_v) * goRound; + //Msg("writing vert: %i\n", VertexSlot); + + Vector normal = dir; + normal.NormalizeInPlace(); + Vector pos = dir * radius; + + if ( !goUp && goRound ) + m_Vertices[ VertexSlot ] = m_Vertices[ 0 ]; + else + { + //CHLSL_Vertex *pV = new CHLSL_Vertex(); + //VectorCopy( pos.Base(), pV->pos ); + //VectorCopy( normal.Base(), pV->normal ); + //m_Vertices[ VertexSlot ] = *pV; + CHLSL_Vertex pV; + VectorCopy( pos.Base(), pV.pos ); + VectorCopy( normal.Base(), pV.normal ); + m_Vertices[ VertexSlot ] = pV; + } + } + } + for ( int goUp = 0; goUp <= subdivs_v; goUp++ ) + { + for ( int goRound = 0; goRound < subdivs_u; goRound++ ) + { + QAngle center_d( -90, 0, 0 ); + center_d.x += goUp * pitch_change; + center_d.y += goRound * yaw_change; + if ( goUp == subdivs_v ) + center_d.x = 0; + + Vector dir; + AngleVectors( center_d, &dir ); + + int VertexSlot = goUp + (1+subdivs_v) * goRound + iverts_onehalf; + //Msg("2- writing vert: %i\n", VertexSlot); + + Vector normal = dir; + normal.NormalizeInPlace(); + Vector pos = dir * radius; + + if ( !goUp && goRound ) + m_Vertices[ VertexSlot ] = m_Vertices[ iverts_onehalf ]; + else + { + //CHLSL_Vertex *pV = new CHLSL_Vertex(); + //VectorCopy( pos.Base(), pV->pos ); + //VectorCopy( normal.Base(), pV->normal ); + //m_Vertices[ VertexSlot ] = *pV; + CHLSL_Vertex pV; + VectorCopy( pos.Base(), pV.pos ); + VectorCopy( normal.Base(), pV.normal ); + m_Vertices[ VertexSlot ] = pV; + } + } + } + +/// SETUP TRIANGLE LINKS + int TriSlot_A = 0; + for ( int goUp = 1; goUp < subdivs_v; goUp++ ) + { + for ( int goRound = 0; goRound < subdivs_u; goRound++ ) + { + int VertexSlot = goUp + (1+subdivs_v) * goRound; + TriSlot_A = (goUp-1) * 2 + (subdivs_v-1) * goRound * 2; + //Msg("writing triangle: %i and %i\n", TriSlot, TriSlot+1); + int VertexSlot_NextU = goRound + 1; + if ( VertexSlot_NextU >= subdivs_u ) + VertexSlot_NextU = 0; + VertexSlot_NextU = goUp + (1+subdivs_v) * VertexSlot_NextU; + + m_Triangles[ TriSlot_A ].vertices[ 0 ] = &m_Vertices[ VertexSlot ]; + m_Triangles[ TriSlot_A ].vertices[ 1 ] = &m_Vertices[ VertexSlot + 1 ]; + m_Triangles[ TriSlot_A ].vertices[ 2 ] = &m_Vertices[ VertexSlot_NextU ]; + + TriSlot_A++; + m_Triangles[ TriSlot_A ].vertices[ 0 ] = &m_Vertices[ VertexSlot + 1 ]; + m_Triangles[ TriSlot_A ].vertices[ 1 ] = &m_Vertices[ VertexSlot_NextU + 1]; + m_Triangles[ TriSlot_A ].vertices[ 2 ] = &m_Vertices[ VertexSlot_NextU ]; + } + } + TriSlot_A++; + int TriSlot_B = 0; + for ( int goUp = 1; goUp < subdivs_v; goUp++ ) + { + for ( int goRound = 0; goRound < subdivs_u; goRound++ ) + { + int VertexSlot = goUp + (1+subdivs_v) * goRound + iverts_onehalf; + TriSlot_B = TriSlot_A + (goUp-1) * 2 + (subdivs_v-1) * goRound * 2; + //Msg("writing triangle: %i and %i\n", TriSlot, TriSlot+1); + int VertexSlot_NextU = goRound + 1; + if ( VertexSlot_NextU >= subdivs_u ) + VertexSlot_NextU = 0; + VertexSlot_NextU = goUp + (1+subdivs_v) * VertexSlot_NextU + iverts_onehalf; + + m_Triangles[ TriSlot_B ].vertices[ 0 ] = &m_Vertices[ VertexSlot + 1 ]; + m_Triangles[ TriSlot_B ].vertices[ 1 ] = &m_Vertices[ VertexSlot ]; + m_Triangles[ TriSlot_B ].vertices[ 2 ] = &m_Vertices[ VertexSlot_NextU ]; + + TriSlot_B++; + m_Triangles[ TriSlot_B ].vertices[ 0 ] = &m_Vertices[ VertexSlot + 1 ]; + m_Triangles[ TriSlot_B ].vertices[ 1 ] = &m_Vertices[ VertexSlot_NextU ]; + m_Triangles[ TriSlot_B ].vertices[ 2 ] = &m_Vertices[ VertexSlot_NextU + 1]; + } + } + TriSlot_B++; + for ( int goRound = 0; goRound < subdivs_u; goRound++ ) + { + int VertexSlot = (1+subdivs_v) * goRound; + + int VertexSlot_u_plus = goRound + 1; + if ( VertexSlot_u_plus >= subdivs_u ) + VertexSlot_u_plus = 0; + VertexSlot_u_plus = (1+subdivs_v) * VertexSlot_u_plus + 1; + //Msg("writing triangle: %i\n", TriSlot_B); + + m_Triangles[ TriSlot_B ].vertices[ 1 ] = &m_Vertices[ VertexSlot ]; + m_Triangles[ TriSlot_B ].vertices[ 2 ] = &m_Vertices[ VertexSlot + 1 ]; + m_Triangles[ TriSlot_B ].vertices[ 0 ] = &m_Vertices[ VertexSlot_u_plus ]; + TriSlot_B++; + } + + for ( int goRound = 0; goRound < subdivs_u; goRound++ ) + { + int VertexSlot = (1+subdivs_v) * goRound + iverts_onehalf; + + int VertexSlot_u_plus = goRound + 1; + if ( VertexSlot_u_plus >= subdivs_u ) + VertexSlot_u_plus = 0; + VertexSlot_u_plus = (1+subdivs_v) * VertexSlot_u_plus + iverts_onehalf + 1; + //Msg("writing triangle: %i\n", TriSlot_B); + + m_Triangles[ TriSlot_B ].vertices[ 0 ] = &m_Vertices[ VertexSlot + 1 ]; + m_Triangles[ TriSlot_B ].vertices[ 1 ] = &m_Vertices[ VertexSlot ]; + m_Triangles[ TriSlot_B ].vertices[ 2 ] = &m_Vertices[ VertexSlot_u_plus ]; + TriSlot_B++; + } + +/// SETUP UVS + // m_iNumTriangles + // m_iNumVertices + // iverts_onehalf + for ( int side = 0; side <= 1; side++ ) + { + for ( int goUp = 0; goUp <= subdivs_v; goUp++ ) + { + for ( int goRound = 0; goRound < subdivs_u; goRound++ ) + { + int VertexSlot = goUp + (1+subdivs_v) * goRound + side * iverts_onehalf; + CHLSL_Vertex &vert = m_Vertices[ VertexSlot ]; + Vector dir( vert.pos[0], vert.pos[1], 0 ); + + dir.NormalizeInPlace(); + dir *= 0.5f * goUp/(float)subdivs_v; + + vert.uv[0][ 0 ] = 0.5f + dir.x; + vert.uv[0][ 1 ] = 0.5f + dir.y; + } + } + } + //for ( int side = 0; side <= 1; side++ ) + //{ + // for ( int goUp = 0; goUp <= subdivs_v; goUp++ ) + // { + // for ( int goRound = 0; goRound < subdivs_u; goRound++ ) + // { + // int VertexSlot = goUp + (1+subdivs_v) * goRound + side * iverts_onehalf; + // CHLSL_Vertex &vert = m_Vertices[ VertexSlot ]; + + // float _a = goRound / float(subdivs_u-1); + // float _b = goUp / float(subdivs_v); + + // vert.uv[0][ 0 ] = _a; + // vert.uv[0][ 1 ] = _b; + // } + // } + //} + + GenerateTangentSpace(); +} + +void CHLSL_Mesh::GenerateTangentSpace() +{ + //for ( int t = 0; t < m_iNumTriangles; t++ ) + //{ + // CHLSL_Triangle &tri = m_Triangles[ t ]; + // for ( int v = 0; v < 3; v++ ) + // { + // CHLSL_Vertex &vert = tri.vertices[ v ]; + // } + //} + + for (int a = 0; a < m_iNumVertices; a++) + { + CHLSL_Vertex &vert = m_Vertices[a]; + Q_memset( vert.tangent_s, 0, sizeof( float ) * 4 ); + Q_memset( vert.tangent_t, 0, sizeof( float ) * 3 ); + } + + CHLSL_Triangle *tri = m_Triangles; + for (int a = 0; a < m_iNumTriangles; a++) + { + CHLSL_Vertex &vert_1 = *tri->vertices[0]; + CHLSL_Vertex &vert_2 = *tri->vertices[1]; + CHLSL_Vertex &vert_3 = *tri->vertices[2]; + + Vector v1; + Vector v2; + Vector v3; + VectorCopy( vert_1.pos, v1.Base() ); + VectorCopy( vert_2.pos, v2.Base() ); + VectorCopy( vert_3.pos, v3.Base() ); +#if 0 + Vector w1( vert_1.uv[0][0], vert_1.uv[0][1], 0 ); + Vector w2( vert_2.uv[0][0], vert_2.uv[0][1], 0 ); + Vector w3( vert_3.uv[0][0], vert_3.uv[0][1], 0 ); + + Vector tan_s_2d( 1, 0, 0 ); + Vector tan_t_2d( 0, 1, 0 ); + Vector delta_vert2 = v2 - v1; + Vector delta_vert3 = v3 - v1; + Vector delta_uv2 = w2 - w1; + Vector delta_uv3 = w3 - w1; + + Vector n; + VectorCopy( vert_1.normal, n.Base() ); + delta_vert2 -= DotProduct( delta_vert2, n ) * n; + delta_vert3 -= DotProduct( delta_vert3, n ) * n; + + //delta_vert2.NormalizeInPlace(); + //delta_vert3.NormalizeInPlace(); + delta_uv2.NormalizeInPlace(); + delta_uv3.NormalizeInPlace(); + + Vector sdir( vec3_origin ); + Vector tdir( vec3_origin ); + + sdir += DotProduct( tan_s_2d, delta_uv2 ) * delta_vert2; + sdir += DotProduct( tan_s_2d, delta_uv3 ) * delta_vert3; + + tdir += DotProduct( tan_t_2d, delta_uv2 ) * delta_vert2; + tdir += DotProduct( tan_t_2d, delta_uv3 ) * delta_vert3; +#else + + Vector2D w1( vert_1.uv[0][0], vert_1.uv[0][1] ); + Vector2D w2( vert_2.uv[0][0], vert_2.uv[0][1] ); + Vector2D w3( vert_3.uv[0][0], vert_3.uv[0][1] ); + + float x1 = v2.x - v1.x; + float x2 = v3.x - v1.x; + float y1 = v2.y - v1.y; + float y2 = v3.y - v1.y; + float z1 = v2.z - v1.z; + float z2 = v3.z - v1.z; + + float s1 = w2.x - w1.x; + float s2 = w3.x - w1.x; + float t1 = w2.y - w1.y; + float t2 = w3.y - w1.y; + + float r = (s1 * t2 - s2 * t1); + if ( r != 0 ) + r = 1.0f / r; + + Vector sdir((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, + (t2 * z1 - t1 * z2) * r); + Vector tdir((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, + (s1 * z2 - s2 * z1) * r); + +#endif + for ( int i = 0; i < 3; i++ ) + { + Assert( IsFinite( vert_1.tangent_s[i] ) ); + Assert( IsFinite( vert_2.tangent_s[i] ) ); + Assert( IsFinite( vert_3.tangent_s[i] ) ); + Assert( IsFinite( vert_1.tangent_t[i] ) ); + Assert( IsFinite( vert_2.tangent_t[i] ) ); + Assert( IsFinite( vert_3.tangent_t[i] ) ); + + vert_1.tangent_s[i] += sdir[i]; + vert_2.tangent_s[i] += sdir[i]; + vert_3.tangent_s[i] += sdir[i]; + + vert_1.tangent_t[i] += tdir[i]; + vert_2.tangent_t[i] += tdir[i]; + vert_3.tangent_t[i] += tdir[i]; + } + //tan1[i1] += sdir; + //tan1[i2] += sdir; + //tan1[i3] += sdir; + // + //tan2[i1] += tdir; + //tan2[i2] += tdir; + //tan2[i3] += tdir; + + tri++; + } + for (int a = 0; a < m_iNumVertices; a++) + { + CHLSL_Vertex &vert = m_Vertices[a]; + + Vector n; + Vector s; + Vector t; + VectorCopy( vert.normal, n.Base() ); + VectorCopy( vert.tangent_s, s.Base() ); + VectorCopy( vert.tangent_t, t.Base() ); + + n.NormalizeInPlace(); + s.NormalizeInPlace(); + t.NormalizeInPlace(); + +#if 0 + Vector delta = s + ( t - s ) * 0.5f; + Vector bidelta; + CrossProduct( delta, n, bidelta ); + t = bidelta + ( delta - bidelta ) * 0.5f; + t -= n * DotProduct( t, n ); + t.NormalizeInPlace(); + CrossProduct( n, t, s ); + s.NormalizeInPlace(); +#endif +#if 1 + //if ( !IsFinite(t.x) || !IsFinite(t.y) || !IsFinite(t.z) ) + // t.Init(0,0,1); + //if ( !IsFinite(s.x) || !IsFinite(s.y) || !IsFinite(s.z) ) + // s.Init(0,0,1); + s = (s - n * DotProduct(n, s)); + t = (t - n * DotProduct(n, t)) * -1.0f; + s.NormalizeInPlace(); + t.NormalizeInPlace(); + float w = (DotProduct(CrossProduct(n, s), t) < 0.0F) ? 1.0F : -1.0F; + +#endif + + //t *= -1.0f; + VectorCopy( s.Base(), vert.tangent_s ); + VectorCopy( t.Base(), vert.tangent_t ); + + vert.tangent_s[3] = w; + + } + + // for (long a = 0; a < m_iNumVertices; a++) + // { + //CHLSL_Vertex &vert = *m_Vertices[a]; + // // const Vector& n = + //Vector normal( vert.pos[0], vert.pos[1], vert.pos[2] ); + // const Vector& t = tan1[a]; + // + // // Gram-Schmidt orthogonalize + // tangent[a] = VectorNormalize( (t - n * DotProduct(n, t)) ); + // + // // Calculate handedness + // tangent[a].w = (Dot(Cross(n, t), tan2[a]) < 0.0F) ? -1.0F : 1.0F; + // } +} \ No newline at end of file diff --git a/sp/src/shadereditor/chlsl_mesh.h b/sp/src/shadereditor/chlsl_mesh.h new file mode 100644 index 00000000..29360e32 --- /dev/null +++ b/sp/src/shadereditor/chlsl_mesh.h @@ -0,0 +1,65 @@ +#ifndef CHLSL_MESH_H +#define CHLSL_MESH_H + +#include "editorCommon.h" + +struct CHLSL_Vertex; +struct CHLSL_Triangle; +class CHLSL_Mesh; + +struct CHLSL_Vertex +{ + CHLSL_Vertex(); + ~CHLSL_Vertex(); + //CHLSL_Vertex( const CHLSL_Vertex &o ); + + float pos[3]; + float normal[3]; + + float tangent_s[4]; + float tangent_t[3]; + + float uv[3][2]; +}; + +struct CHLSL_Triangle +{ + CHLSL_Triangle(); + ~CHLSL_Triangle(); + //CHLSL_Triangle( const CHLSL_Triangle &o ); + + CHLSL_Vertex *vertices[3]; +}; + +class CHLSL_Mesh +{ +public: + CHLSL_Mesh(); + ~CHLSL_Mesh(); + CHLSL_Mesh( const CHLSL_Mesh &o ); + + void CreateSphere( float radius, int subdiv ); + void CreateCube( float size, int subdiv ); + void CreateCylinder( float size, int subdiv ); + void CreatePlane( float size, int subdiv ); + + const int GetNumVertices(){ return m_iNumVertices; }; + CHLSL_Vertex *GetVertices(){ return m_Vertices; }; + + const int GetNumTriangles(){ return m_iNumTriangles; }; + CHLSL_Triangle *GetTriangles(){ return m_Triangles; }; + +private: + + CHLSL_Vertex *m_Vertices; + int m_iNumVertices; + + CHLSL_Triangle *m_Triangles; + int m_iNumTriangles; + + void GenerateTangentSpace(); +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/chlsl_variable.cpp b/sp/src/shadereditor/chlsl_variable.cpp new file mode 100644 index 00000000..e2e4de9a --- /dev/null +++ b/sp/src/shadereditor/chlsl_variable.cpp @@ -0,0 +1,186 @@ + +#include "cbase.h" +#include "editorCommon.h" + + + +CHLSL_Var::CHLSL_Var() +{ + m_tType = HLSLVAR_FLOAT1; + + m_bCanBeOverwritten = true; + m_bCanBeDeclared = true; + m_bGotDeclared = false; + bCustomName = false; + _varName = NULL; + pOwner = NULL; + + m_iRTMapIndex = 0; + + m_pTex = NULL; + m_pMat = NULL; + + AllocCheck_Alloc(); +} + +CHLSL_Var::CHLSL_Var( const CHLSL_Var& other ) +{ + m_tType = other.m_tType; + m_iRTMapIndex = 0; + + m_bCanBeOverwritten = other.m_bCanBeOverwritten; + m_bCanBeDeclared = other.m_bCanBeDeclared; + m_bGotDeclared = other.m_bGotDeclared; + bCustomName = other.bCustomName; + pOwner = NULL; + + //if ( m_tType == HLSLVAR_PP_RT ) + // m_pTex = other.m_pTex; + //else if ( m_tType == HLSLVAR_PP_MATERIAL ) + // m_pMat = other.m_pMat; + //else + { + m_pTex = NULL; + m_pMat = NULL; + } + + _varName = NULL; + if ( other._varName != NULL ) + { + int len = Q_strlen(other._varName) + 2; + _varName = new char[len]; + Q_snprintf(_varName,len,"%s",other._varName); + } + + AllocCheck_Alloc(); +} +CHLSL_Var::CHLSL_Var( HLSLVariableTypes type ) +{ + m_bCanBeOverwritten = true; + m_bCanBeDeclared = true; + m_bGotDeclared = false; + bCustomName = false; + _varName = NULL; + + m_iRTMapIndex = 0; + + pOwner = NULL; + m_tType = type; + + m_pTex = NULL; + m_pMat = NULL; + + AllocCheck_Alloc(); +} +CHLSL_Var::~CHLSL_Var() +{ + if ( _varName ) + delete [] _varName; + + AllocCheck_Free(); +} +void CHLSL_Var::Init() +{ + m_tType = HLSLVAR_FLOAT1; + + m_bCanBeOverwritten = true; + m_bCanBeDeclared = true; + m_bGotDeclared = false; + bCustomName = false; + _varName = NULL; + + m_iRTMapIndex = 0; +} + +IMaterial *CHLSL_Var::GetMaterial() +{ + Assert( m_tType == HLSLVAR_PP_MATERIAL ); + //Assert( m_pMat ); + + return m_pMat; +} +ITexture *CHLSL_Var::GetTexture() +{ + Assert( m_tType == HLSLVAR_PP_RT ); + //Assert( m_pTex ); + + return m_pTex; +} +void CHLSL_Var::SetMaterial( IMaterial *pMat ) +{ + Assert( m_tType == HLSLVAR_PP_MATERIAL ); + + m_pMat = pMat; +} +void CHLSL_Var::SetTexture( ITexture *pTex ) +{ + Assert( m_tType == HLSLVAR_PP_RT ); + + m_pTex = pTex; +} + +const bool &CHLSL_Var::WasDeclared() +{ + return m_bGotDeclared; +} +const void CHLSL_Var::OnDeclare() +{ + m_bGotDeclared = true; +} +void CHLSL_Var::DeclareMe( WriteContext_FXC &context, bool init ) +{ + if ( WasDeclared() ) + return; + char tmp[MAXTARGC]; + const char *codename = GetVarCodeNameFromFlag(GetType()); + Q_snprintf( tmp, MAXTARGC, "%s ", codename ); + context.buf_code.PutString( tmp ); + if ( init ) + { + Q_snprintf( tmp, MAXTARGC, "%s = (%s)0;\n", GetName(), codename ); + context.buf_code.PutString( tmp ); + } + OnDeclare(); +} + +const bool &CHLSL_Var::CanBeOverwritten() +{ + return m_bCanBeOverwritten; +} +const void CHLSL_Var::MakeConstantOnly() +{ + m_bCanBeOverwritten = false; + m_bCanBeDeclared = false; +} +const void CHLSL_Var::ResetVarInfo() +{ + m_bGotDeclared = false; +} +CHLSL_SolverBase *CHLSL_Var::GetOwner() +{ + return pOwner; +} +void CHLSL_Var::SetOwner( CHLSL_SolverBase *n ) +{ + pOwner = n; +} +void CHLSL_Var::Cleanup() +{ +} +void CHLSL_Var::SetName( const char *name, bool Custom ) +{ + delete [] _varName; + int len = Q_strlen( name ) + 2; + _varName = new char[ len ]; + Q_snprintf( _varName, len, "%s", name ); + + bCustomName = Custom; +} +const char *CHLSL_Var::GetName() +{ + return _varName; +} +const bool CHLSL_Var::HasCustomName() +{ + return bCustomName; +} diff --git a/sp/src/shadereditor/chlsl_variable.h b/sp/src/shadereditor/chlsl_variable.h new file mode 100644 index 00000000..477a4403 --- /dev/null +++ b/sp/src/shadereditor/chlsl_variable.h @@ -0,0 +1,306 @@ +#ifndef CHLSLVAR_H +#define CHLSLVAR_H + +#include "editorCommon.h" + +class CBaseNode; + +class CHLSL_Var +{ +public: + CHLSL_Var( HLSLVariableTypes type ); + virtual ~CHLSL_Var(); + + CHLSL_Var( const CHLSL_Var& other ); + + const HLSLVariableTypes &GetType(){ return m_tType; }; + + const bool &WasDeclared(); + const void OnDeclare(); + void DeclareMe( WriteContext_FXC &context, bool init = false ); + + const bool &CanBeOverwritten(); + const void MakeConstantOnly(); + + CHLSL_SolverBase *GetOwner(); + void SetOwner( CHLSL_SolverBase *n ); + + const void ResetVarInfo(); + void Cleanup(); + + void SetName( const char *name, bool Custom = false ); + const char *GetName(); + const bool HasCustomName(); + + const int &GetMapIndex(){ return m_iRTMapIndex; }; + void ResetMapIndex(){ m_iRTMapIndex = 0; }; + void SetMapIndex( const int idx ){ m_iRTMapIndex = idx; }; + +public: + + IMaterial *GetMaterial(); + ITexture *GetTexture(); + void SetMaterial( IMaterial *pMat ); + void SetTexture( ITexture *pTex ); + +private: + CHLSL_Var(); + void Init(); + + HLSLVariableTypes m_tType; + int m_iRTMapIndex; + + bool m_bCanBeDeclared; + bool m_bGotDeclared; + + bool m_bCanBeOverwritten; + char *_varName; + + bool bCustomName; + CHLSL_SolverBase *pOwner; + + union + { + ITexture *m_pTex; + IMaterial *m_pMat; + }; +}; + +//#if 1 //DEBUG +//extern void PrintError(); +//#define ON_VAR_ERROR PrintError(); +//#else +//#define ON_VAR_ERROR ((void)0); +//#endif +// +//inline CHLSL_Var& CHLSL_Var::operator=(const CHLSL_Var &o) +//{ +// Q_memcpy( m_Vars, o.m_Vars, varsSize ); +// return *this; +//} +//inline void CHLSL_Var::LoadType( const CHLSL_Var &o ) +//{ +// m_iVarSize = o.m_iVarSize; +// m_tType = o.m_tType; +//} +// +//inline CHLSL_Var& CHLSL_Var::operator+=(const CHLSL_Var &o) +//{ +// if ( m_tType == o.m_tType ) +// { +// for ( int i = 0; i < m_iVarSize; i++ ) +// m_Vars[ i ] += o.m_Vars[ i ]; +// } +// else if ( m_tType != HLSLVAR_FLOAT1 && o.m_tType == HLSLVAR_FLOAT1 ) +// { +// for ( int i = 0; i < m_iVarSize; i++ ) +// m_Vars[ i ] += o.m_Vars[ 0 ]; +// } +// else +// ON_VAR_ERROR +// +// return *this; +//} +// +//inline CHLSL_Var CHLSL_Var::operator+(const CHLSL_Var& o) const +//{ +// CHLSL_Var n; +// if ( m_tType == HLSLVAR_FLOAT1 && o.m_tType != HLSLVAR_FLOAT1 ) +// { +// n = o; +// n.LoadType( o ); +// n += *this; +// } +// else +// { +// n = *this; +// n.LoadType( *this ); +// n += o; +// } +// return n; +//} +// +//inline CHLSL_Var& CHLSL_Var::operator-=(const CHLSL_Var &o) +//{ +// if ( m_tType == o.m_tType ) +// { +// for ( int i = 0; i < m_iVarSize; i++ ) +// m_Vars[ i ] -= o.m_Vars[ i ]; +// } +// else if ( m_tType != HLSLVAR_FLOAT1 && o.m_tType == HLSLVAR_FLOAT1 ) +// { +// for ( int i = 0; i < m_iVarSize; i++ ) +// m_Vars[ i ] -= o.m_Vars[ 0 ]; +// } +// else +// ON_VAR_ERROR +// +// return *this; +//} +// +//inline CHLSL_Var CHLSL_Var::operator-(const CHLSL_Var& o) const +//{ +// CHLSL_Var n; +// +// if ( m_tType == HLSLVAR_FLOAT1 && o.m_tType != HLSLVAR_FLOAT1 ) +// { +// n = o; +// n.LoadType( o ); +// n -= *this; +// } +// else +// { +// n = *this; +// n.LoadType( *this ); +// n -= o; +// } +// +// return n; +//} +// +//inline CHLSL_Var& CHLSL_Var::operator*=(const CHLSL_Var &o) +//{ +// if ( o.m_tType >= HLSLVAR_MATRIX3X3 ) +// { +// VMatrix other; +// o.FillMatrix( &o, other ); +// if ( m_tType >= HLSLVAR_MATRIX3X3 ) +// { +// VMatrix local = GetMatrix(); +// VMatrix dst; +// //MatrixMultiply( local, other, dst ); +// MatrixMultiply( other, local, dst ); +// } +// else if ( m_tType == HLSLVAR_FLOAT3 ) +// { +// // 3 * 3x3 +// // Vector3DMultiply +// +// // 3 * 4x3 +// // Vector3DMultiplyPosition +// +// // 3 * 4x4 +// // Vector3DMultiplyPositionProjective +// +// Vector out; +// switch ( o.m_tType ) +// { +// case HLSLVAR_MATRIX3X3: +// Vector3DMultiply( other, GetVec3(), out ); +// SetVec3( out ); +// break; +// case HLSLVAR_MATRIX4X3: +// Vector3DMultiplyPosition( other, GetVec3(), out ); +// SetVec3( out ); +// break; +// case HLSLVAR_MATRIX4X4: +// // remove auto projection? +//#if 1 +// Vector4D tmp( m_Vars[0], m_Vars[1], m_Vars[2], 1 ); +// Vector4D outTmp; +// Vector4DMultiply( other, tmp, outTmp ); +// //Vector lol( m_Vars[0], m_Vars[1], m_Vars[2] ), derp; +// //Vector3DMultiplyPositionProjective( other, lol, derp ); +// //Msg("%f %f %f\n", derp.x, derp.y, derp.z); +// //out.x = outTmp.x; out.y = outTmp.y; out.z = outTmp.z; +// SetVec4( outTmp ); +//#else +// Vector3DMultiplyPositionProjective( other, GetVec3(), out ); +// SetVec3( out ); +//#endif +// break; +// } +// } +// else if ( m_tType == HLSLVAR_FLOAT4 ) +// { +// Vector4D out; +// switch ( o.m_tType ) +// { +// case HLSLVAR_MATRIX3X3: +// case HLSLVAR_MATRIX4X3: +// case HLSLVAR_MATRIX4X4: +// Vector4DMultiply( other, GetVec4(), out ); +// break; +// } +// SetVec4( out ); +// } +// else +// ON_VAR_ERROR +// } +// else if ( m_tType == o.m_tType ) +// { +// for ( int i = 0; i < m_iVarSize; i++ ) +// m_Vars[ i ] *= o.m_Vars[ i ]; +// } +// else if ( m_tType != HLSLVAR_FLOAT1 && o.m_tType == HLSLVAR_FLOAT1 ) +// { +// for ( int i = 0; i < m_iVarSize; i++ ) +// m_Vars[ i ] *= o.m_Vars[ 0 ]; +// } +// else +// ON_VAR_ERROR +// +// return *this; +//} +// +//inline CHLSL_Var CHLSL_Var::operator*(const CHLSL_Var& o) const +//{ +// CHLSL_Var n; +// +// if ( ( m_tType == HLSLVAR_FLOAT1 && o.m_tType != HLSLVAR_FLOAT1 ) || +// ( m_tType >= HLSLVAR_MATRIX3X3 ) ) +// { +// n = o; +// n.LoadType( o ); +// n *= *this; +// } +// else +// { +// n = *this; +// n.LoadType( *this ); +// n *= o; +// } +// +// return n; +//} +// +//inline CHLSL_Var& CHLSL_Var::operator/=(const CHLSL_Var &o) +//{ +// if ( m_tType == o.m_tType ) //&& m_tType <= HLSLVAR_FLOAT4 ) +// { +// for ( int i = 0; i < m_iVarSize; i++ ) +// m_Vars[ i ] /= o.m_Vars[ i ]; +// } +// else if ( m_tType != HLSLVAR_FLOAT1 && o.m_tType == HLSLVAR_FLOAT1 ) +// { +// for ( int i = 0; i < m_iVarSize; i++ ) +// m_Vars[ i ] /= o.m_Vars[ 0 ]; +// } +// else +// ON_VAR_ERROR +// +// return *this; +//} +// +//inline CHLSL_Var CHLSL_Var::operator/(const CHLSL_Var& o) const +//{ +// CHLSL_Var n; +// +// if ( ( m_tType == HLSLVAR_FLOAT1 && o.m_tType != HLSLVAR_FLOAT1 ) || +// ( m_tType != o.m_tType && m_tType >= HLSLVAR_MATRIX3X3 ) ) +// { +// n = o; +// n.LoadType( o ); +// n *= *this; +// } +// else +// { +// n = *this; +// n.LoadType( *this ); +// n *= o; +// } +// +// return n; +//} + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/ckvpacker.cpp b/sp/src/shadereditor/ckvpacker.cpp new file mode 100644 index 00000000..29fc64e3 --- /dev/null +++ b/sp/src/shadereditor/ckvpacker.cpp @@ -0,0 +1,218 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +char *CKVPacker::ConvertKVSafeString( const char *pStr, bool bMakeEscaped ) +{ + //const bool MakeCopy = true; + + if ( !pStr || !*pStr ) + return NULL; + + bool b_LF, b_CR, b_Backslash, b_DQuote; + + int iNewSize = 1; + const char *pRead = pStr; + bool bWasEscaping = false; + while ( *pRead ) + { + b_LF = *pRead == '\n'; + b_CR = *pRead == '\r'; + b_Backslash = *pRead == '\\'; + b_DQuote = *pRead == '"'; + + if ( bMakeEscaped && + (b_LF || b_CR || b_Backslash || b_DQuote) ) + iNewSize++; + else if ( !bMakeEscaped && + b_Backslash && !bWasEscaping ) //&& + { + //(*(pRead+1) == 'n') ) + iNewSize--; + bWasEscaping = true; + } + else + bWasEscaping = false; + pRead++; + iNewSize++; + } + + char *pOut = new char[ iNewSize ]; + pRead = pStr; + char *pWrite = pOut; + + while ( *pRead ) + { + b_LF = *pRead == '\n'; + b_CR = *pRead == '\r'; + b_Backslash = *pRead == '\\'; + b_DQuote = *pRead == '"'; + + if ( bMakeEscaped && + (b_LF || b_CR || b_Backslash || b_DQuote) ) + { + *pWrite = '\\'; + pWrite++; + + if ( b_LF ) + *pWrite = 'n'; + else if ( b_CR ) + *pWrite = 'r'; + else if ( b_DQuote ) + *pWrite = '\''; + else + *pWrite = '\\'; + } + else if ( !bMakeEscaped && + b_Backslash ) + { + pRead++; + + if ( *pRead == 'n' ) + *pWrite = '\n'; + else if ( *pRead == 'r' ) + *pWrite = '\r'; + else if ( *pRead == '\'' ) + *pWrite = '"'; + else + *pWrite = *pRead; + } + else + *pWrite = *pRead; + + pRead++; + pWrite++; + } + + Assert( iNewSize - 1 == pWrite - pOut ); + + *pWrite = '\0'; + + //if ( !MakeCopy ) + // delete [] pStr; + + return pOut; +} + +#define KVPACKER_MAX_CHARS_PER_STRING 1023 +#define KVPACKER_AMT_STR "_num_strings" +#define KVPACKER_PARTIAL_STR "_partial_" + +bool CKVPacker::KVPack( const char *pszStr, const char *pszKey, KeyValues *pKVTarget ) +{ + if ( !pszStr || !pszKey || !*pszKey ) + return false; + + const int iStrLen = Q_strlen( pszStr ); + const int iNumStrings = iStrLen / KVPACKER_MAX_CHARS_PER_STRING + 1; + + char tmpString[ KVPACKER_MAX_CHARS_PER_STRING + 1 ]; + const char *pRead = pszStr; + + char tmpKey[MAXTARGC]; + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s", pszKey, KVPACKER_AMT_STR ); + pKVTarget->SetInt( tmpKey, iNumStrings ); + + for ( int i = 0; i < iNumStrings; i++ ) + { + Assert( pRead - pszStr <= iStrLen ); + + Q_snprintf( tmpString, sizeof(tmpString), "%s", pRead ); + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s%02i", pszKey, KVPACKER_PARTIAL_STR, i ); + pKVTarget->SetString( tmpKey, tmpString ); + + pRead += KVPACKER_MAX_CHARS_PER_STRING; + } + + return true; +} + +char *CKVPacker::KVUnpack( KeyValues *pKVSource, const char *pszKey ) +{ + if ( !pKVSource || !pszKey || !*pszKey ) + return NULL; + + char tmpKey[MAXTARGC]; + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s", pszKey, KVPACKER_AMT_STR ); + const int numEntries = pKVSource->GetInt( tmpKey ); + + if ( numEntries <= 0 ) + return NULL; + + int iStrlen = 1; + CUtlVector< const char* > hRowList; + + for ( int i = 0; i < numEntries; i++ ) + { + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s%02i", pszKey, KVPACKER_PARTIAL_STR, i ); + const char *pszStr = pKVSource->GetString( tmpKey ); + + iStrlen += Q_strlen( pszStr ); + hRowList.AddToTail( pszStr ); + } + + char *pszOut = new char[ iStrlen ]; + *pszOut = '\0'; + + for ( int i = 0; i < hRowList.Count(); i++ ) + { + Q_strcat( pszOut, hRowList[i], iStrlen ); + } + + hRowList.Purge(); + + return pszOut; +} + +bool CKVPacker::KVCopyPacked( KeyValues *pKVSource, KeyValues *pKVTarget, const char *pszKey ) +{ + if ( !pKVSource || !pKVTarget ) + return false; + + char tmpKey[MAXTARGC]; + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s", pszKey, KVPACKER_AMT_STR ); + const int iNumStrings = pKVSource->GetInt( tmpKey ); + + pKVTarget->SetInt( tmpKey, iNumStrings ); + + int i = 0; + for ( ; i < iNumStrings; i++ ) + { + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s%02i", pszKey, KVPACKER_PARTIAL_STR, i ); + pKVTarget->SetString( tmpKey, pKVSource->GetString( tmpKey ) ); + } + + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s%02i", pszKey, KVPACKER_PARTIAL_STR, i ); + + for ( KeyValues *pTerminateMe = pKVTarget->FindKey( tmpKey ); pTerminateMe != NULL; + i++, Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s%02i", pszKey, KVPACKER_PARTIAL_STR, i ), + pTerminateMe = pKVTarget->FindKey( tmpKey ) ) + { + pKVTarget->RemoveSubKey( pTerminateMe ); + pTerminateMe->deleteThis(); + } + + return true; +} + +void CKVPacker::KVClearPacked( const char *pszKey, KeyValues *pKVTarget ) +{ + if ( !pszKey || !*pszKey || !pKVTarget ) + return; + + char tmpKey[MAXTARGC]; + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s", pszKey, KVPACKER_AMT_STR ); + pKVTarget->SetInt( tmpKey, 0 ); + + int i = 0; + + Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s%02i", pszKey, KVPACKER_PARTIAL_STR, i ); + for ( KeyValues *pTerminateMe = pKVTarget->FindKey( tmpKey ); pTerminateMe != NULL; + i++, Q_snprintf( tmpKey, sizeof(tmpKey), "%s%s%02i", pszKey, KVPACKER_PARTIAL_STR, i ), + pTerminateMe = pKVTarget->FindKey( tmpKey ) ) + { + pKVTarget->RemoveSubKey( pTerminateMe ); + pTerminateMe->deleteThis(); + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/ckvpacker.h b/sp/src/shadereditor/ckvpacker.h new file mode 100644 index 00000000..06efb213 --- /dev/null +++ b/sp/src/shadereditor/ckvpacker.h @@ -0,0 +1,22 @@ +#ifndef C_KV_PACKER_H +#define C_KV_PACKER_H + +#include "cbase.h" +#include "editorCommon.h" + + +class CKVPacker +{ +public: + + static char *ConvertKVSafeString( const char *pStr, bool bMakeEscaped ); + + static bool KVPack( const char *pszStr, const char *pszKey, KeyValues *pKVTarget ); + static char *KVUnpack( KeyValues *pKVSource, const char *pszKey ); + static bool KVCopyPacked( KeyValues *pKVSource, KeyValues *pKVTarget, const char *pszKey ); + static void KVClearPacked( const char *pszKey, KeyValues *pKVTarget ); +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/cregex.cpp b/sp/src/shadereditor/cregex.cpp new file mode 100644 index 00000000..9c3224d3 --- /dev/null +++ b/sp/src/shadereditor/cregex.cpp @@ -0,0 +1,352 @@ + +#include "cbase.h" +#include "editorcommon.h" + +#ifdef new +#undef new +#endif + +#include +#include "cRegex.h" + +static const char *g_szSyntaxList_Keywords[] = +{ + "static", + "extern", + "nointerpolation", + "precise", + "shared", + "groupshared", + "uniform", + "volatile", + + "const", + "row_major", + "column_major", + + "register", + "return", + "struct", + + "for", + "do", + "while", + "if", + "else", + + "true", + "false", + + "in", + "out", + "inout", +}; +static const int g_iNum_SyntaxList_Keywords = ARRAYSIZE( g_szSyntaxList_Keywords ); + +static const char *g_szSyntaxList_Preproc_Regex[] = +{ + "#[ \\t]*define(?:[ \\t]+.*)?", + "#[ \\t]*if[ \\t]+defined(?:[ \\t]+.*)?", + "#[ \\t]*if(?:[ \\t]{1,}.*)?", + "#[ \\t]*ifndef(?:[ \\t]+.*)?", + "#[ \\t]*ifdef(?:[ \\t]+.*)?", + "#[ \\t]*elif(?:[ \\t]+.*)?", + "#[ \\t]*else(?:[ \\t]+.*)?", + "#[ \\t]*endif(?:[ \\t]+.*)?", + "#[ \\t]*undef(?:[ \\t]+.*)?", + "#[ \\t]*include(?:[ \\t]+.*)?", +}; +static const int g_iNum_SyntaxList_Preproc_Regex = ARRAYSIZE( g_szSyntaxList_Preproc_Regex ); + +static const char *g_szSyntaxList_Datatypes_Regex[] = +{ + "double(?:[1-4]?|[1-4]x[1-4])", + "float(?:[1-4]?|[1-4]x[1-4])", + "half(?:[1-4]?|[1-4]x[1-4])", + "int(?:[1-4]?|[1-4]x[1-4])", + "uint(?:[1-4]?|[1-4]x[1-4])", + "bool(?:[1-4]?|[1-4]x[1-4])", + "HALF(?:[1-4]?|[1-4]x[1-4])", + "void", + "sampler(?:[1-3]D|CUBE)?", + "Buffer", + + "matrix", + "vector", + + "auto", + "multi", + + //"matrix[ \\t]{0,}<[ \\t]{0,}(double|float|half|HALF|int|uint|bool)[ \\t]{0,},[ \\t]{0,}[1-4][ \\t]{0,},[ \\t]{0,}[1-4][ \\t]{0,}>", + //"vector[ \\t]{0,}<[ \\t]{0,}(double|float|half|HALF|int|uint|bool)[ \\t]{0,},[ \\t]{0,}[1-4][ \\t]{0,}>", +}; +static const int g_iNum_SyntaxList_Datatypes_Regex = ARRAYSIZE( g_szSyntaxList_Datatypes_Regex ); + +static const char *g_szSyntaxList_Semantics[] = +{ + "POSITIONT", + "FOG", + "PSIZE", + "VFACE", + "VPOS", +}; +static const int g_iNum_SyntaxList_Semantics = ARRAYSIZE( g_szSyntaxList_Semantics ); + +static const char *g_szSyntaxList_Semantics_Regex[] = +{ + "TEXCOORD\\d*", + "BINORMAL\\d*", + "BLENDINDICES\\d*", + "BLENDWEIGHT\\d*", + "COLOR\\d*", + "NORMAL\\d*", + "POSITION\\d*", + "TANGENT\\d*", + "TESSFACTOR\\d*", + "DEPTH\\d*", +}; +static const int g_iNum_SyntaxList_Semantics_Regex = ARRAYSIZE( g_szSyntaxList_Semantics_Regex ); + +const char *g_szSyntax_Number_Regex = "^\\w?-?\\d*.?\\d+[eE]?-?\\d*[hHfFlLuU]?"; + +static char *__AllocCChar( const wchar_t *wC ) +{ + const int len = Q_wcslen( wC ) + 1; + char *c = new char[ len ]; + Q_UnicodeToUTF8( wC, c, len ); + c[len-1] = '\0'; + return c; +} + +int CRegex::MatchSyntax_KeyWord( const char *pWord ) +{ + for ( int i = 0; i < GetSyntaxNum_KeyWords(); i++ ) + if ( !Q_strcmp( pWord, GetSyntaxList_KeyWords()[i] ) ) + return i; + return -1; +} +int CRegex::MatchSyntax_KeyWord( const wchar_t *pWord ) +{ + char *c = __AllocCChar( pWord ); + int r = MatchSyntax_KeyWord( c ); + delete [] c; + return r; +} + +int CRegex::MatchSyntax_Semantic( const char *pWord ) +{ + int i = 0; + for ( ; i < GetSyntaxNum_Semantics(); i++ ) + if ( !Q_strcmp( pWord, GetSyntaxList_Semantics()[i] ) ) + return i; + for ( int i1 = 0; i1 < GetSyntaxNum_Semantics_Regex(); i1++ ) + if ( RegexMatch( pWord, GetSyntaxList_Semantics_Regex()[i1] ) ) + return i + i1; + return -1; +} +int CRegex::MatchSyntax_Semantic( const wchar_t *pWord ) +{ + char *c = __AllocCChar( pWord ); + int r = MatchSyntax_Semantic( c ); + delete [] c; + return r; +} + +int CRegex::MatchSyntax_Preproc( const char *pWord ) +{ + for ( int i = 0; i < GetSyntaxNum_Preproc_Regex(); i++ ) + if ( RegexMatch( pWord, GetSyntaxList_Preproc_Regex()[i] ) ) + return i; + return -1; +} +int CRegex::MatchSyntax_Preproc( const wchar_t *pWord ) +{ + char *c = __AllocCChar( pWord ); + int r = MatchSyntax_Preproc( c ); + delete [] c; + return r; +} + +int CRegex::MatchSyntax_Datatypes( const char *pWord ) +{ + for ( int i = 0; i < GetSyntaxNum_Datatypes_Regex(); i++ ) + if ( RegexMatch( pWord, GetSyntaxList_Datatypes_Regex()[i] ) ) + return i; + return -1; +} +int CRegex::MatchSyntax_Datatypes( const wchar_t *pWord ) +{ + char *c = __AllocCChar( pWord ); + int r = MatchSyntax_Datatypes( c ); + delete [] c; + return r; +} + + +int CRegex::MatchSyntax_Numbers( const char *pWord ) +{ + return RegexMatch( pWord, GetSyntaxRegex_Numbers() ) ? 1 : -1; +} +int CRegex::MatchSyntax_Numbers( const wchar_t *pWord ) +{ + char *c = __AllocCChar( pWord ); + int r = MatchSyntax_Numbers( c ); + delete [] c; + return r; +} + +const char **CRegex::GetSyntaxList_KeyWords(){ return g_szSyntaxList_Keywords; }; +const int &CRegex::GetSyntaxNum_KeyWords(){ return g_iNum_SyntaxList_Keywords; }; + +const char **CRegex::GetSyntaxList_Semantics(){ return g_szSyntaxList_Semantics; }; +const int &CRegex::GetSyntaxNum_Semantics(){ return g_iNum_SyntaxList_Semantics; }; + +const char **CRegex::GetSyntaxList_Preproc_Regex(){ return g_szSyntaxList_Preproc_Regex; }; +const int &CRegex::GetSyntaxNum_Preproc_Regex(){ return g_iNum_SyntaxList_Preproc_Regex; }; + +const char **CRegex::GetSyntaxList_Datatypes_Regex(){ return g_szSyntaxList_Datatypes_Regex; }; +const int &CRegex::GetSyntaxNum_Datatypes_Regex(){ return g_iNum_SyntaxList_Datatypes_Regex; }; + +const char **CRegex::GetSyntaxList_Semantics_Regex(){ return g_szSyntaxList_Semantics_Regex; }; +const int &CRegex::GetSyntaxNum_Semantics_Regex(){ return g_iNum_SyntaxList_Semantics_Regex; }; + +const char *CRegex::GetSyntaxRegex_Numbers(){ return g_szSyntax_Number_Regex; }; + +bool CRegex::RegexMatch( const char *cStr, const char *exp ) +{ + //std::string stdStr; + //stdStr.append( cStr ); + + std::tr1::regex reg( exp ); + //return std::tr1::regex_match( stdStr.begin(), stdStr.end(), reg, std::tr1::regex_constants::match_default ); + return std::tr1::regex_match( cStr, reg, std::tr1::regex_constants::match_default ); +} +bool CRegex::RegexMatch( const wchar_t *lStr, const char *exp ) +{ + char *cStr = __AllocCChar( lStr ); + bool r = RegexMatch( cStr, exp ); + delete [] cStr; + return r; +} +bool CharNeedsEscape( char c ) +{ + if ( c == '*' || + c == '.' || + c == '\\' || + c == '(' || + c == ')' || + c == '[' || + c == ']' || + c == '{' || + c == '}' || + c == '$' || + c == '^' || + c == '+' || + c == '?' || + c == '-' || + c == ',' || + c == ':' || + c == '=' || + c == '!' ) + return true; + + return false; +} +char *CRegex::AllocSafeString( char *str ) +{ + if ( !str || !*str ) + return NULL; + + int len = 1; + + char *walk = str; + while ( *walk ) + { + if ( CharNeedsEscape( *walk ) ) + len++; + + len++; + walk++; + } + + char *pOut = new char[ len ]; + + walk = str; + char *pWrite = pOut; + + while ( *walk ) + { + if ( CharNeedsEscape( *walk ) ) + { + *pWrite = '\\'; + pWrite++; + } + + *pWrite = *walk; + + pWrite++; + walk++; + } + + *pWrite = '\0'; + + return pOut; +} + + +static const Color g_ColSyntax_Keyword( 90, 210, 0, 255 ); +static const Color g_ColSyntax_Semantic( 40, 170, 80, 255 ); +static const Color g_ColSyntax_Preproc( 160, 80, 40, 255 ); +static const Color g_ColSyntax_Number( 255, 128, 32, 255 ); +static const Color g_ColSyntax_String( 200, 160, 16, 255 ); +static const Color g_ColSyntax_Bracket( 210, 160, 70, 255 ); + +const Color *CRegex::GetColorForWordBySyntax( const wchar_t *pWord, bool bStringLiterals, bool bBrackets, bool bHLSL ) +{ + if ( !pWord || !*pWord ) + return NULL; + + // number literals + if ( IS_NUMERICAL( *pWord ) || *pWord == L'.' || *pWord == L'-' ) + { + if ( MatchSyntax_Numbers( pWord ) != __REGEX_INVALID ) + return &g_ColSyntax_Number; + } + + if ( bStringLiterals ) + { + // strings + if ( *pWord == L'\"' || *pWord == L'\'' ) + return &g_ColSyntax_String; + } + + if ( bBrackets ) + { + // brackets + if ( ( IS_BRACKET( *pWord ) ) && //|| *pWord == L'<' || *pWord == L'>' ) && + Q_wcslen( pWord ) == 1 ) + return &g_ColSyntax_Bracket; + } + + if ( bHLSL ) + { + // datatypes/keywords + if ( MatchSyntax_KeyWord( pWord ) != __REGEX_INVALID ) + return &g_ColSyntax_Keyword; + + // semantics + if ( MatchSyntax_Semantic( pWord ) != __REGEX_INVALID ) + return &g_ColSyntax_Semantic; + + // datatypes/keywords, regex + int match_dtype = MatchSyntax_Datatypes( pWord ); + if ( match_dtype != __REGEX_INVALID && match_dtype < 12 ) + return &g_ColSyntax_Keyword; + + // pre processor + if ( MatchSyntax_Preproc( pWord ) != __REGEX_INVALID ) + return &g_ColSyntax_Preproc; + } + + return NULL; +} \ No newline at end of file diff --git a/sp/src/shadereditor/cregex.h b/sp/src/shadereditor/cregex.h new file mode 100644 index 00000000..e2ef8b8a --- /dev/null +++ b/sp/src/shadereditor/cregex.h @@ -0,0 +1,80 @@ +#ifndef C_REGEX_H +#define C_REGEX_H + + +#define IS_CONTROL_CHAR( x ) ( x == '\n' || x == '\r' ) +#define IS_CHAR( x ) ( x >= L'a' && x <= L'z' || x >= L'A' && x <= L'Z' || x == L'#' || x == L'_' ) +#define IS_NUMERICAL( x ) ( x >= L'0' && x <= L'9' ) //|| x == '-' ) ) //|| x == '.' ) +#define IS_SPACE( x ) ( x == L' ' || x == L'\t' || x == L'\r' ) + +#define IS_BRACKET_OPENING( x ) ( x == L'(' || x == L'[' || x == L'{' ) +#define IS_BRACKET_CLOSING( x ) ( x == L')' || x == L']' || x == L'}' ) +#define IS_BRACKET( x ) ( IS_BRACKET_OPENING( x ) || IS_BRACKET_CLOSING( x ) ) +#define IS_BRACKET_SAME_TYPE( x, y ) ( x == y ||\ + ( ( x == L'(' || x == L')' ) && ( y == L'(' || y == L')' ) ) ||\ + ( ( x == L'[' || x == L']' ) && ( y == L'[' || y == L']' ) ) ||\ + ( ( x == L'{' || x == L'}' ) && ( y == L'{' || y == L'}' ) ) ) + +#define __REGEX_INVALID -1 + +#define __REGEX_KEYWORDS_LASTACCESS_MOD 10 + +enum +{ + __REGEX__PREPROC_DEFINE = 0, + __REGEX__PREPROC_IF_DEFINED, + __REGEX__PREPROC_IF, + __REGEX__PREPROC_IFNDEF, + __REGEX__PREPROC_IFDEF, + __REGEX__PREPROC_ELIF, + __REGEX__PREPROC_ELSE, + __REGEX__PREPROC_ENDIF, + __REGEX__PREPROC_UNDEF, + __REGEX__PREPROC_INC, + __REGEX__PREPROC_, +}; + +class CRegex +{ +public: + + static bool RegexMatch( const wchar_t *lStr, const char *exp ); + static bool RegexMatch( const char *lStr, const char *exp ); + static const Color *GetColorForWordBySyntax( const wchar_t *pWord, bool bStringLiterals = true, bool bBrackets = true, bool bHLSL = true ); + static char *AllocSafeString( char *str ); + + + static int MatchSyntax_KeyWord( const char *pWord ); + static int MatchSyntax_KeyWord( const wchar_t *pWord ); + + static int MatchSyntax_Semantic( const char *pWord ); + static int MatchSyntax_Semantic( const wchar_t *pWord ); + + static int MatchSyntax_Preproc( const char *pWord ); + static int MatchSyntax_Preproc( const wchar_t *pWord ); + + static int MatchSyntax_Datatypes( const char *pWord ); + static int MatchSyntax_Datatypes( const wchar_t *pWord ); + + static int MatchSyntax_Numbers( const char *pWord ); + static int MatchSyntax_Numbers( const wchar_t *pWord ); + + + static const char **GetSyntaxList_KeyWords(); + static const int &GetSyntaxNum_KeyWords(); + + static const char **GetSyntaxList_Semantics(); + static const int &GetSyntaxNum_Semantics(); + + static const char **GetSyntaxList_Preproc_Regex(); + static const int &GetSyntaxNum_Preproc_Regex(); + + static const char **GetSyntaxList_Datatypes_Regex(); + static const int &GetSyntaxNum_Datatypes_Regex(); + + static const char **GetSyntaxList_Semantics_Regex(); + static const int &GetSyntaxNum_Semantics_Regex(); + + static const char *GetSyntaxRegex_Numbers(); +}; +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/editorcommon.cpp b/sp/src/shadereditor/editorcommon.cpp new file mode 100644 index 00000000..100e6277 --- /dev/null +++ b/sp/src/shadereditor/editorcommon.cpp @@ -0,0 +1,2256 @@ +#include "cbase.h" + +#include +#include +#include +#include +#include "ienginevgui.h" + +#include "vgui_controls/Controls.h" +#include "editorcommon.h" + + +ConVar sedit_draw_datatypes( "shaderEditor_render_datatypes", "1" ); +ConVar sedit_draw_shadows( "shaderEditor_render_shadows", "1" ); +ConVar sedit_draw_nodes( "shaderEditor_render_nodes", "1" ); +ConVar sedit_draw_jacks( "shaderEditor_render_jacks", "1" ); +ConVar sedit_draw_bridges( "shaderEditor_render_bridges", "1" ); + +ConVar sedit_2dprev_Enable( "shaderEditor_2dpreview_enable_draw", "1" ); +ConVar sedit_uv_adjust( "shaderEditor_2dpreview_adjustUV", "1" ); + +ConVar editor_movespeed( "shaderEditor_smooth_speed", "10" ); +ConVar editor_zoomspeed( "shaderEditor_zoom_speed", "0.65f" ); +ConVar editor_pull_speed_mul( "shaderEditor_pull_speed_multiply", "75" ); +ConVar editor_pull_speed_max( "shaderEditor_pull_speed_max", "20" ); + +ConVar sedit_mesh_size( "shaderEditor_3dpreview_meshSize", "50" ); +ConVar sedit_mesh_subdiv( "shaderEditor_3dpreview_meshSubdiv", "48" ); +ConVar sedit_prev_HOMFun( "shaderEditor_3dpreview_HOMFun", "0" ); + +ConVar sedit_screenshot_zoom( "shaderEditor_screenshot_zoom", "2" ); +ConVar sedit_screenshot_quali( "shaderEditor_screenshot_quality", "100" ); + +using namespace vgui; + +#define BOUNDS_EXTRUDE 30 + +const char *GetEditorTitle() +{ + return "Source Shader Editor v0.5 (Build 0244)"; +}; + +static const char *cversion_key = "cfmt_version"; +static const char *cversions[] = { + "canvasver#UNDEFINED", + "canvasver#002", + "canvasver#003", +}; +static const int cversions_num = ARRAYSIZE( cversions ); + +static const char *dumpversion_key = "dump_version"; +static const char *dumpversions[] = { + "dumpver#000", + "dumpver#001", +}; +static const int dumpversions_num = ARRAYSIZE( dumpversions ); + +const char *GetCanvasVersion_KeyName() +{ + return cversion_key; +} +const char *GetCanvasVersion( int i ) +{ + Assert( i >= 0 && i < cversions_num ); + return cversions[ i ]; +} +const char *GetCanvasVersion_Current() +{ + return GetCanvasVersion( cversions_num - 1 ); +} +const int &GetCanvasVersion_Amt() +{ + return cversions_num; +} + +const char *GetDumpVersion_KeyName() +{ + return dumpversion_key; +} +const char *GetDumpVersion( int i ) +{ + Assert( i >= 0 && i < dumpversions_num ); + return dumpversions[ i ]; +} +const char *GetDumpVersion_Current() +{ + return GetDumpVersion( dumpversions_num - 1 ); +} +const int &GetDumpVersion_Amt() +{ + return dumpversions_num; +} + +void UpgradeFromVersion( KeyValues *pCanvas, const char *oldVer ) +{ + bool bDoUpgrade = oldVer == NULL; + + for ( int i = 0; i < GetCanvasVersion_Amt(); i++ ) + { + bDoUpgrade = bDoUpgrade || !Q_stricmp( oldVer, GetCanvasVersion( i ) ); + + if ( !bDoUpgrade ) + continue; + + KeyValues *pNodes = pCanvas->FindKey( "nodes" ); + + // upgrading to version i from version i - 1.... + switch ( i ) + { + // from canvasver#002 to canvasver#003 + case 2: + { + if ( !pNodes ) + break; + + for ( int idx = 0;; idx++ ) + { + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "Node_%03i", idx ); + KeyValues *pKVNode = pNodes->FindKey( tmp ); + idx++; + + if ( !pKVNode ) + break; + + if ( pKVNode->GetInt( "iType" ) != HLSLNODE_VS_IN ) + continue; + + int dtype_tex = pKVNode->GetInt( "dTFlag_Texcoords", 0 ); + int dtype_col = pKVNode->GetInt( "dTFlag_Color", 0 ); + + if ( dtype_tex > 0 ) + for ( int u = 0; u < 3; u++ ) + pKVNode->SetInt( VarArgs( "dTFlag_Texcoords_%i", u ), dtype_tex ); + if ( dtype_col > 0 ) + for ( int u = 0; u < 2; u++ ) + pKVNode->SetInt( VarArgs( "dTFlag_Color_%i", u ), dtype_col ); + } + } + break; + } + } +} + +Color Lerp( const float &perc, const Color &a, const Color &b ) +{ + return Color( a[0] + (b[0] - a[0]) * perc, + a[1] + (b[1] - a[1]) * perc, + a[2] + (b[2] - a[2]) * perc, + a[3] + (b[3] - a[3]) * perc ); +} + +void PaintDynamicRotationStructure(DynRenderHelper info) +{ + Vector AngDir; + float rot = info.Rotation + 45.0f; + + QAngle Ang = QAngle(0,rot,0); + AngleVectors(Ang,&AngDir); + vgui::Vertex_t verts[4]; + float pxcenterx, pxcentery, px1x, px1y, px2x, px2y, pxoutx, pxouty; + Vector Direction = Vector(AngDir.x,AngDir.y,0); + Vector2D Dir, DirCrossed, Pos; + Pos.x = info.Orig.x; + Pos.y = info.Orig.y; + + VectorNormalize(Direction); + Vector CrossHelper = vec3_origin; + CrossProduct(Vector(0,0,1), Direction, CrossHelper); + CrossHelper.z = 0.0f; + VectorNormalize(CrossHelper); + Direction *= info.Size; + CrossHelper *= info.Size; + Dir.x = Direction.x; + Dir.y = Direction.y; + DirCrossed.x = CrossHelper.x; + DirCrossed.y = CrossHelper.y; + + pxoutx = Pos.x + Dir.x; + pxouty = Pos.y + Dir.y; + pxcenterx = Pos.x - Dir.x; + pxcentery = Pos.y - Dir.y; + + px1x = Pos.x - DirCrossed.x; + px1y = Pos.y - DirCrossed.y; + px2x = Pos.x + DirCrossed.x; + px2y = Pos.y + DirCrossed.y; + + float uv_minx, uv_maxx, uv_miny, uv_maxy; + uv_minx = 0.0f; + uv_maxx = 1.0f; + uv_miny = 0.0f; + uv_maxy = 1.0f; + + verts[0].m_TexCoord.Init( uv_minx, uv_miny ); + verts[0].m_Position.Init(pxcenterx, pxcentery); + verts[1].m_TexCoord.Init( uv_maxx, uv_miny ); + verts[1].m_Position.Init(px1x, px1y); + verts[2].m_TexCoord.Init( uv_maxx, uv_maxy ); + verts[2].m_Position.Init(pxoutx, pxouty); + verts[3].m_TexCoord.Init( uv_minx, uv_maxy ); + verts[3].m_Position.Init(px2x, px2y); + + vgui::surface()->DrawTexturedPolygon( 4, verts ); +} + +inline void UpdateSimpleObjectBounds( Vector2D &pos, Vector2D &size, Vector4D &bounds ) +{ + bounds.x = pos.x - BOUNDS_EXTRUDE; + bounds.y = pos.y + BOUNDS_EXTRUDE; + bounds.z = pos.x + size.x + BOUNDS_EXTRUDE; + bounds.w = pos.y + size.y - BOUNDS_EXTRUDE; +} +inline bool __InBounds( Vector2D &p, Vector2D &smin, Vector2D &smax ) +{ + if ( p.x >= smin.x && p.x <= smax.x && + p.y >= smin.y && p.y <= smax.y ) + return true; + return false; +} +inline bool __CrossesBounds( float &p_min, float &p_max, float &b_min, float &b_max ) +{ + if ( p_max < b_min ) + return false; + if ( p_min > b_max ) + return false; + return true; +} +inline bool ShouldSimpleDrawObject( vgui::Panel *parent, CNodeView *coordSystem, Vector4D &bounds ) +{ + Vector2D bpoint_00( bounds.x, bounds.y ); + Vector2D bpoint_11( bounds.z, bounds.w ); + + coordSystem->ToPanelSpace( bpoint_00 ); + coordSystem->ToPanelSpace( bpoint_11 ); + + int sx,sy; + parent->GetSize( sx, sy ); + Vector2D p_min( 0, 0 ); + Vector2D p_max( sx, sy ); + + if ( !__CrossesBounds( bpoint_00.x, bpoint_11.x, p_min.x, p_max.x ) || + !__CrossesBounds( bpoint_00.y, bpoint_11.y, p_min.y, p_max.y ) ) + return false; + + return true; +} +void DestroySolverStack( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ) +{ + DestroyVariablesInSolverStack( m_hSolvers ); + SaveDeleteVector( m_hSolvers ); +} +void DestroyVariablesInSolverStack( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ) +{ + CUtlVector< CHLSL_Var* > m_hVars; + ListVariables( m_hSolvers, m_hVars ); + SaveDeleteVector( m_hVars ); +} +void ResetVariables( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ) +{ + CUtlVector< CHLSL_Var* > m_hVars; + ListVariables( m_hSolvers, m_hVars ); + for ( int i = 0; i < m_hVars.Count(); i++ ) + { + CHLSL_Var *v = m_hVars[ i ]; + v->ResetVarInfo(); + } + m_hVars.Purge(); +} +void ListVariables( CUtlVector< CHLSL_SolverBase* > &m_hSolvers, CUtlVector< CHLSL_Var* > &m_hVars ) +{ + m_hVars.Purge(); + for ( int a = 0; a < m_hSolvers.Count(); a++ ) + { + CHLSL_SolverBase *pS = m_hSolvers[ a ]; + for ( int b = 0; b < pS->GetNumTargetVars(); b++ ) + { + CHLSL_Var *pV = pS->GetTargetVar( b ); + if ( m_hVars.IsValidIndex( m_hVars.Find( pV ) ) ) + continue; + m_hVars.AddToTail( pV ); + } + } +} +void InitializeVariableNames( CUtlVector< CHLSL_SolverBase* > &m_hSolvers, WriteContext_FXC &context ) +{ + context.m_hActive_Solvers = &m_hSolvers; + CUtlVector< CHLSL_Var* > m_hVars; + ListVariables( m_hSolvers, m_hVars ); + int _index = 0; + + for ( int i = 0; i < m_hSolvers.Count(); i++ ) + m_hSolvers[i]->Invoke_VarInit( context ); + + char tmp[MAXTARGC]; + for ( int i = 0; i < m_hVars.Count(); i++ ) + { + CHLSL_Var *var = m_hVars[ i ]; + if ( !var->GetName() || !var->HasCustomName() ) + { + Q_snprintf( tmp, MAXTARGC, "_var%i", _index ); + var->SetName( tmp ); + _index++; + } + } + + for ( int i = 0; i < m_hSolvers.Count(); i++ ) + m_hSolvers[i]->Invoke_VarInit_PostStep(); + + m_hVars.Purge(); +} +void ClearSolverInfo( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ) +{ + for ( int i = 0; i < m_hSolvers.Count(); i++ ) + { + CHLSL_SolverBase *s = m_hSolvers[ i ]; + s->ClearInfo(); + } +} +void ClearVariableInfo( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ) +{ + CUtlVector< CHLSL_Var* > m_hVars; + ListVariables( m_hSolvers, m_hVars ); + for ( int i = 0; i < m_hVars.Count(); i++ ) + { + CHLSL_Var *v = m_hVars[ i ]; + v->Cleanup(); + } + m_hVars.Purge(); +} +void ResetVariableIndices( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ) +{ + CUtlVector< CHLSL_Var* > m_hVars; + ListVariables( m_hSolvers, m_hVars ); + for ( int i = 0; i < m_hVars.Count(); i++ ) + { + CHLSL_Var *v = m_hVars[ i ]; + v->ResetMapIndex(); + } + m_hVars.Purge(); +} +void CopySolvers( const CUtlVector< CBaseNode* > &m_hSolvedNodes, + CUtlVector< CHLSL_SolverBase* > &m_hOutput ) +{ + CUtlVector< CBaseNode* > m_hMainList; + CUtlVector< CHLSL_SolverBase* > m_hMainList_Solvers; + m_hMainList.AddVectorToTail( m_hSolvedNodes ); + + CUtlVector< CBaseContainerNode* > m_hContainerStack; + for ( int a = 0; a < m_hMainList.Count(); a++ ) + { + CBaseNode *pN = m_hMainList[ a ]; + CBaseContainerNode *pC = pN->GetAsContainer(); + + // enter and exit containers + if ( pC && pC->GetNumSolvers() >= 3 ) + { + if ( m_hContainerStack.IsValidIndex( m_hContainerStack.Find( pC ) ) ) + { + m_hContainerStack.FindAndRemove( pC ); + m_hMainList_Solvers.AddToTail( pC->GetSolver( 2 ) ); + } + else + { + m_hContainerStack.AddToTail( pC ); + m_hMainList_Solvers.AddToTail( pC->GetSolver( 0 ) ); + m_hMainList_Solvers.AddToTail( pC->GetSolver( 1 ) ); + } + continue; + } + + for ( int b = 0; b < pN->GetNumSolvers(); b++ ) + { + CHLSL_SolverBase *pS = pN->GetSolver( b ); + if ( m_hMainList_Solvers.IsValidIndex( m_hMainList_Solvers.Find( pS ) ) ) + continue; + m_hMainList_Solvers.AddToTail( pS ); + } + } + m_hContainerStack.Purge(); + + CopySolvers( m_hMainList_Solvers, m_hOutput ); + + m_hMainList_Solvers.Purge(); + m_hMainList.Purge(); +} +void CopySolvers( const CUtlVector< CHLSL_SolverBase* > &m_hInput, + CUtlVector< CHLSL_SolverBase* > &m_hOutput ) +{ + CUtlVector< CHLSL_SolverBase* > m_hMainList_Solvers; + CUtlVector< CHLSL_Var* > m_hMainList_Variables; + m_hOutput.Purge(); + + for ( int b = 0; b < m_hInput.Count(); b++ ) + { + CHLSL_SolverBase *pS = m_hInput[ b ]; + for ( int c = 0; c < pS->GetNumTargetVars(); c++ ) + { + CHLSL_Var *pV = pS->GetTargetVar( c ); + if ( m_hMainList_Variables.IsValidIndex( m_hMainList_Variables.Find( pV ) ) ) + continue; + + m_hMainList_Variables.AddToTail( pV ); + } + for ( int c = 0; c < pS->GetNumSourceVars(); c++ ) + { + CHLSL_Var *pV = pS->GetSourceVar( c ); + if ( m_hMainList_Variables.IsValidIndex( m_hMainList_Variables.Find( pV ) ) ) + continue; + + m_hMainList_Variables.AddToTail( pV ); + } + if ( m_hMainList_Solvers.IsValidIndex( m_hMainList_Solvers.Find( pS ) ) ) + continue; + + m_hMainList_Solvers.AddToTail( pS ); + } + + CUtlVector< CHLSL_SolverBase* > m_hCopied_Solvers; + CUtlVector< CHLSL_Var* > m_hCopied_Variables; +#if 1 + for ( int a = 0; a < m_hMainList_Solvers.Count(); a++ ) + { + CHLSL_SolverBase *pNewSolver = m_hMainList_Solvers[a]->Copy(); + m_hCopied_Solvers.AddToTail( pNewSolver ); + } + for ( int a = 0; a < m_hMainList_Variables.Count(); a++ ) + { + CHLSL_Var *pNewVar = new CHLSL_Var( *(m_hMainList_Variables[a]) ); + m_hCopied_Variables.AddToTail( pNewVar ); + } + //Msg("we counted %i VARS.\n", m_hMainList_Variables.Count()); + Assert( m_hCopied_Solvers.Count() == m_hMainList_Solvers.Count() ); + Assert( m_hCopied_Variables.Count() == m_hMainList_Variables.Count() ); + for ( int a = 0; a < m_hCopied_Solvers.Count(); a++ ) + m_hCopied_Solvers[ a ]->ReconnectVariables( m_hMainList_Solvers[a], m_hMainList_Variables, m_hCopied_Variables ); +#endif + + m_hOutput.AddVectorToTail( m_hCopied_Solvers ); + + m_hMainList_Solvers.Purge(); + m_hMainList_Variables.Purge(); + m_hCopied_Solvers.Purge(); + m_hCopied_Variables.Purge(); +} + +inline void ClipToScreenBounds( int &_x, int &_y, int &_sx, int &_sy ) +{ + int w,t; + engine->GetScreenSize( w, t ); + + // move + if ( ( _x + _sx ) > w ) + _x = w - _sx; + if ( ( _y + _sy ) > t ) + _y = t - _sy; + + // clamp + _x = max( _x, 0 ); + _y = max( _y, 0 ); + + // clamp + if ( ( _x + _sx ) > w ) + _sx = w; + if ( ( _y + _sy ) > t ) + _sy = t; +} + +static const char *VarTypeName[][2] = +{ + "Float1","float", + "Float2","float2", + "Float3","float3", + "Float4","float4", + "Matrix 3x3","float3x3", + "Matrix 4x3","float4x3", + "Matrix 4x4","float4x4", + + "Sampler","sampler", + + "RESERVED","RESERVED", + "RESERVED","RESERVED", + "RESERVED","RESERVED", + "RESERVED","RESERVED", + "RESERVED","RESERVED", + "RESERVED","RESERVED", + "RESERVED","RESERVED", + "RESERVED","RESERVED", + + "Master","nocode", + "Material","nocode", + "RT","nocode", +}; +const char *GetVarTypeName( int num ) +{ + return VarTypeName[ num ][ 0 ]; +} +const char *GetVarTypeNameCode( int num ) +{ + return VarTypeName[ num ][ 1 ]; +} +static const char *ResourceTypeName[RESOURCETYPE_][3] = +{ + "VARIABLE","VARIABLE","VARIABLE", + "vPos","POSITION","float3", + "vProjPos","POSITION","float4", + "vNormal","NORMAL","float3", + "vNormal","NORMAL","float4", + "vTangent_S","TANGENT","float3", + "vTangent_S","TANGENT","float4", + "vTangent_T","BINORMAL","float3", + "vFlexDelta","POSITION1","float3", + "vFlexDelta_Normal","NORMAL1","float3", + "vBoneWeights","BLENDWEIGHT","float4", + "vBoneIndices","BLENDINDICES","float4", + "vTexCoord_0","TEXCOORD0","float2", + "vTexCoord_1","TEXCOORD1","float2", + "vTexCoord_2","TEXCOORD2","float2", + "vTexCoord_3","TEXCOORD3","float2", + "vTexCoord_4","TEXCOORD4","float2", + "vTexCoord_5","TEXCOORD5","float2", + "vTexCoord_6","TEXCOORD6","float2", + "vTexCoord_7","TEXCOORD7","float2", + "vColor_0","COLOR0","float4", + "vColor_1","COLOR1","float4", + "vColor_2","COLOR2","float4", + "vColor_3","COLOR3","float4", + "vDepth","DEPTH","float", + "DUMMY","DUMMY","DUMMY", +}; +const char *GetResourceTypeName( int num ) +{ + return ResourceTypeName[ num ][ 0 ]; +} +const char *GetSemanticTypeName( int num ) +{ + return ResourceTypeName[ num ][ 1 ]; +} +const char *GetSemanticType( int num ) +{ + return ResourceTypeName[ num ][ 2 ]; +} +int GetVarTypeRowsRequired( int num ) +{ + if ( num <= 3 ) + return 1; + else if ( num <= 5 ) + return 3; + else if ( num <= 6 ) + return 4; + return 1; +} +int GetVarTypeFlag( int num ) +{ + return ( 1 << num ); +} +int GetVarFlagsVarValue( int flag ) +{ + for ( int i = 0; i < HLSLVAR_COUNT; i++ ) + if ( flag & ( 1 << i ) ) + return i; + return 0; +} +const char *GetVarCodeNameFromFlag( int flag ) +{ + return GetVarTypeNameCode(GetVarFlagsVarValue(flag)); +} + +int GetVarFlagsRowsRequired( int flag ) +{ + return GetVarTypeRowsRequired( GetVarFlagsVarValue( flag ) ); +} + +static const char *textype2name[HLSLTEX_] = +{ + "custom parameter", + + "Basetexture", + "Bumpmap", + "Lightmap", + "Lightmap bumpmap", + "Framebuffer", + "Envmap", + + "black", + "white", + "grey", + + "flashlight cookie", + "flashlight depth", + "flashlight random", + + "morph", +}; +const char *GetTextureTypeName( int idx ) +{ + Assert( idx >= 0 && idx < HLSLTEX_ ); + + return textype2name[ idx ]; +} + +static const char *itrcodestring[ITERATORCOND_] = +{ + "<", + ">", + "<=", + ">=", + "==", +}; +const char *GetConditionCodeString( int idx ) +{ + Assert( idx >= 0 && idx < 5 ); + return itrcodestring[ idx ]; +} +static const char *codetonemapname[] = +{ + "TONEMAP_SCALE_NONE", + "TONEMAP_SCALE_LINEAR", + "TONEMAP_SCALE_GAMMA", +}; +const char *GetCodeTonemapMacro( int idx ) +{ + Assert( idx >= 0 && idx < 3 ); + return codetonemapname[idx]; +} +static const char *codelightscalename[] = +{ + "LINEAR_LIGHT_SCALE", + "LIGHT_MAP_SCALE", + "ENV_MAP_SCALE", + "GAMMA_LIGHT_SCALE", + "g_cLightmapRGB", +}; +const char *GetLightscaleCodeString( int idx ) +{ + Assert( idx >= 0 && idx < 4 ); + return codelightscalename[ idx ]; +} +static const char *gamelightscalename[] = +{ + "Linear", + "Lightmap", + "Envmap", + "Gamma", + "Lightmap RGB", +}; +const char *GetLightscaleGameString( int idx ) +{ + Assert( idx >= 0 && idx < 4 ); + return gamelightscalename[ idx ]; +} + +static const sampinfo_t _samplerdatastruct[ TEXSAMP_MAX ] = +{ + { "Auto select", "ERROR", 0, false, "X" }, + + { "tex1D", "tex1D", 0, false, "U" }, + { "tex1Ddd", "tex1D", 0, true, "U" }, + { "tex1Dbias", "tex1Dbias", 3, false, "U__-t" }, + { "tex1Dgrad", "tex1Dgrad", 0, true, "U" }, + { "tex1Dlod", "tex1Dlod", 3, false, "U__-t" }, + { "tex1Dproj", "tex1Dproj", 3, false, "U__-t" }, + + { "tex2D", "tex2D", 1, false, "UV" }, + { "tex2Ddd", "tex2D", 1, true, "UV" }, + { "tex2Dbias", "tex2Dbias", 3, false, "UV_-t" }, + { "tex2Dgrad", "tex2Dgrad", 1, true, "UV" }, + { "tex2Dlod", "tex2Dlod", 3, false, "UV_-t" }, + { "tex2Dproj", "tex2Dproj", 3, false, "UV_-t" }, + + { "tex3D", "tex3D", 2, false, "UVW" }, + { "tex3Ddd", "tex3D", 2, true, "UVW" }, + { "tex3Dbias", "tex3Dbias", 3, false, "UVW-t" }, + { "tex3Dgrad", "tex3Dgrad", 2, true, "UVW" }, + { "tex3Dlod", "tex3Dlod", 3, false, "UVW-t" }, + { "tex3Dproj", "tex3Dproj", 3, false, "UVW-t" }, + + { "texCUBE", "texCUBE", 2, false, "Dir" }, + { "texCUBEdd", "texCUBE", 2, true, "Dir" }, + { "texCUBEbias", "texCUBEbias", 3, false, "Dir-t" }, + { "texCUBEgrad", "texCUBEgrad", 2, true, "Dir" }, + { "texCUBElod", "texCUBElod", 3, false, "Dir-t" }, + { "texCUBEproj", "texCUBEproj", 3, false, "Dir-t" }, +}; +const char *GetSamplerData_VisualName( const int &idx ) +{ + Assert( idx >= 0 && idx < TEXSAMP_MAX ); + return _samplerdatastruct[idx].sz_visualName; +} +const char *GetSamplerData_CodeName( const int &idx ) +{ + Assert( idx >= 0 && idx < TEXSAMP_MAX ); + return _samplerdatastruct[idx].sz_codeName; +} +const int GetSampleData_ComponentSize( const int &idx ) +{ + Assert( idx >= 0 && idx < TEXSAMP_MAX ); + return _samplerdatastruct[idx].i_componentSize; +} +const bool GetSamplerData_UseDerivative( const int &idx ) +{ + Assert( idx >= 0 && idx < TEXSAMP_MAX ); + return _samplerdatastruct[idx].b_derivativeInput; +} +const char *GetSamplerData_JackName( const int &idx ) +{ + Assert( idx >= 0 && idx < TEXSAMP_MAX ); + return _samplerdatastruct[idx].sz_jackname; +} + +static const char *fodpathcontexts[ FODPC_ ] = { + "fod_vtf", + "fod_mdl", + "fod_canvas", + "fod_dump", + "fod_ufunc", + "fod_vmt", +}; +const char *GetFODPathContext( int type ) +{ + Assert( type >= 0 && type < FODPC_ ); + return fodpathcontexts[ type ]; +} + +static const char *szComboNameList[HLSLCOMBO_MAX] = { + "ERROR_INVALID_COMBO", + "ERROR_CUSTOM_COMBO", + + "SKINNING", + "MORPHING", + + "STATIC_LIGHT", + "DYNAMIC_LIGHT", + "NUM_LIGHTS", + + "PIXELFOGTYPE", + "WRITEWATERFOGTODESTALPHA", + + "FLASHLIGHT", + "FLASHLIGHTDEPTHFILTERMODE", + "FLASHLIGHTSHADOWS", + + "COMPRESSED_VERTS", +}; +const char *GetComboNameByID( const int &ID ) +{ + Assert( HLSLCOMBO_MAX == ARRAYSIZE( szComboNameList ) ); + + Assert( ID > HLSLCOMBO_CUSTOM && ID < HLSLCOMBO_MAX ); + return szComboNameList[ ID ]; +} +const int GetComboIDByName( const char *name ) +{ + Assert( HLSLCOMBO_MAX == ARRAYSIZE( szComboNameList ) ); + + for ( int i = 0; i < HLSLCOMBO_MAX; i++ ) + if ( !Q_stricmp( name, szComboNameList[ i ] ) ) + return i; + return HLSLCOMBO_INVALID; +} +void UpdateComboDataByID( SimpleCombo *pCombo, const int &ID, bool bTotalInit ) +{ + Assert( HLSLCOMBO_MAX == ARRAYSIZE( szComboNameList ) ); + + int i_min = -1; + int i_max = -1; + bool b_static = false; + bool b_InPreviewMode = false; + + switch ( ID ) + { + case HLSLCOMBO_FLASHLIGHT_ENABLED: + i_min = 0; + i_max = 1; + b_static = true; + break; + case HLSLCOMBO_NUM_LIGHTS: + i_min = 0; + i_max = 4; + b_static = false; + break; + case HLSLCOMBO_VERTEXCOMPRESSION: + b_InPreviewMode = true; + case HLSLCOMBO_MORPHING: + case HLSLCOMBO_SKINNING: + case HLSLCOMBO_LIGHT_STATIC: + case HLSLCOMBO_LIGHT_DYNAMIC: + case HLSLCOMBO_PIXELFOG: + case HLSLCOMBO_WATERFOG_TOALPHA: + case HLSLCOMBO_FLASHLIGHT_DO_SHADOWS: + i_min = 0; + i_max = 1; + b_static = false; + break; + case HLSLCOMBO_FLASHLIGHT_FILTER_MODE: + i_min = 0; + i_max = 2; + b_static = true; + break; + default: + Assert(0); + } + + if ( ID >= 0 ) + { + pCombo->iComboType = ID; + if ( ID > HLSLCOMBO_CUSTOM ) + { + if ( pCombo->name ) + delete [] pCombo->name; + + const char *szNewName = GetComboNameByID( ID ); + pCombo->name = new char[Q_strlen(szNewName) + 1]; + Q_strcpy( pCombo->name, szNewName ); + } + } + + if ( bTotalInit ) + { + if ( i_min >= 0 ) + pCombo->min = i_min; + if ( i_max >= 0 ) + pCombo->max = i_max; + + pCombo->bInPreviewMode = b_InPreviewMode; + } +} +void UpdateComboDataByString( SimpleCombo *pCombo, const char *szName, bool bTotalInit ) +{ + int ID = GetComboIDByName( szName ); + if ( ID > HLSLCOMBO_INVALID ) + UpdateComboDataByID( pCombo, ID, bTotalInit ); +} +SimpleCombo *AllocateComboDataByID( const int &ID ) +{ + SimpleCombo *c = new SimpleCombo(); + UpdateComboDataByID( c, ID, true ); + return c; +} +const bool IsComboAvailableInPreviewMode( SimpleCombo *c ) +{ + if ( !c ) + return false; + + if ( c->iComboType == HLSLCOMBO_VERTEXCOMPRESSION ) + return true; + + return false; +} +void RemoveAllNonPreviewCombos( CUtlVector< SimpleCombo* >&list ) +{ + for ( int i = 0; i < list.Count(); i++ ) + { + if ( IsComboAvailableInPreviewMode( list[i] ) ) + continue; + + delete list[i]; + list.Remove( i ); + i--; + } +} + + +GenericShaderData::GenericShaderData() +{ + AllocCheck_Alloc(); + + name = NULL; + //bPreview = false; + shader = new BasicShaderCfg_t(); + pUNDEF_Identifiers = new IdentifierLists_t(); + iStackIdx = 0; +} +GenericShaderData::~GenericShaderData() +{ + AllocCheck_Free(); + + delete [] name; + delete shader; + delete pUNDEF_Identifiers; +} +GenericShaderData::GenericShaderData( const GenericShaderData &o ) +{ + AllocCheck_Alloc(); + + name = NULL; + VS_IN = SETUP_HLSL_VS_Input( o.VS_IN ); + VS_to_PS = SETUP_HLSL_VS_Output_PS_Input( o.VS_to_PS ); + PS_OUT = SETUP_HLSL_PS_Output( o.PS_OUT ); + + //bPreview = o.bPreview; + iStackIdx = o.iStackIdx; + shader = NULL; + if ( o.shader ) + shader = new BasicShaderCfg_t( *o.shader ); + + AutoCopyStringPtr( o.name, &name ); + + pUNDEF_Identifiers = NULL; + if ( o.pUNDEF_Identifiers ) + pUNDEF_Identifiers = new IdentifierLists_t( *o.pUNDEF_Identifiers ); +} +bool GenericShaderData::IsPreview() +{ + Assert( shader != NULL ); + return shader->bPreviewMode; +} + + + +GenericPPEData::GenericPPEData() +{ + AllocCheck_Alloc(); + + bDoAutoUpdateFBCopy = true; +} +GenericPPEData::~GenericPPEData() +{ + AllocCheck_Free(); +} + +Preview2DContext::Preview2DContext() +{ + pRenderContext = NULL; + + pMat_PsIn = NULL; + pMat_PsInOP = NULL; +} + +SolverResources::SolverResources( int HierachyType ) +{ + Q_memset( this, 0, sizeof( SolverResources ) ); + m_iHierachyType = HierachyType; + + mx_Model.Identity(); + mx_View.Identity(); + mx_Proj.Identity(); +} +const int SolverResources::GetHierachyType() +{ + return m_iHierachyType; +} +bool SolverResources::IsVertexShader() +{ + return ( m_iHierachyType == HLSLHIERACHY_VS ); +} + +static const int __FloatSize = sizeof( float ); +inline void AutoCopyFloats( const void *src, void *dst, const int amt ) +{ + Q_memcpy( dst, src, __FloatSize * amt ); +} +inline void AutoCopyStringPtr( const char *src, char **dst ) +{ + *dst = NULL; + if ( !src || !*src ) + return; + + int len = Q_strlen( src ) + 1; + *dst = new char[len]; + Q_snprintf( *dst, len, "%s", src ); + (*dst)[len-1] = '\0'; +} + +//inline int GetChannelNumFromChar( const char *c ) +//{ +// switch ( *c ) +// { +// case 'r': +// case 'R': +// case 'x': +// case 'X': +// return 0; +// break; +// case 'g': +// case 'G': +// case 'y': +// case 'Y': +// return 1; +// break; +// case 'b': +// case 'B': +// case 'z': +// case 'Z': +// return 2; +// break; +// case 'a': +// case 'A': +// case 'w': +// case 'W': +// return 3; +// break; +// } +// return -1; +//} +//inline char GetCharFromChannelNum( const int i ) +//{ +// switch (i) +// { +// case 0: +// return 'x'; +// case 1: +// return 'y'; +// case 2: +// return 'z'; +// case 3: +// return 'w'; +// } +// return 'x'; +//} + + +inline int GetSlotsFromTypeFlag( int flag ) +{ + switch ( flag ) + { + default: + Assert(0); + break; + case HLSLVAR_FLOAT1: + return 1; + case HLSLVAR_FLOAT2: + return 2; + case HLSLVAR_FLOAT3: + return 3; + case HLSLVAR_FLOAT4: + return 4; + case HLSLVAR_MATRIX3X3: + return 9; + case HLSLVAR_MATRIX4X3: + return 12; + case HLSLVAR_MATRIX4X4: + return 16; + } + return 1; +} +inline int GetTypeFlagFromEnum( int i ) +{ + switch ( i ) + { + default: + Assert(0); + break; + case 1: + return HLSLVAR_FLOAT1; + case 2: + return HLSLVAR_FLOAT2; + case 3: + return HLSLVAR_FLOAT3; + case 4: + return HLSLVAR_FLOAT4; + + case 5: + return HLSLVAR_MATRIX3X3; + case 6: + return HLSLVAR_MATRIX4X3; + case 7: + return HLSLVAR_MATRIX4X4; + + case 8: + //Assert(0); + return HLSLVAR_SAMPLER; + } + return HLSLVAR_FLOAT1; +} + +int StringTabsWorth( const char *text ) +{ + return Q_strlen( text ) / 4; +} + +static const LimitReport_t limitreportdefaults[] = +{ + { "PS samplers", 0, AMT_PS_SAMPLERS }, + { "PS constants", 0, AMT_PS_CREG }, + + { "VS samplers", 0, AMT_VS_SAMPLERS }, + { "VS constants", 0, AMT_VS_CREG }, + + { "Vmt static", 0, AMT_VMT_STATIC }, + { "Vmt mutable", 0, AMT_VMT_MUTABLE }, + + { "Texture mismatch", 0, -1 }, +}; +const LimitReport_t &GetLimitReporterDefault( int i ) +{ + Assert( i >= 0 && i < LERROR_ ); + return limitreportdefaults[i]; +} +bool ReportErrors( GenericShaderData *data, CUtlVector< LimitReport_t* > &hErrorList ) +{ + bool bError = false; + LimitReport_t *report = NULL; + + for ( int i = LERROR__FIRST; i <= LERROR__LAST; i++ ) + { + Assert( report == NULL ); + report = new LimitReport_t( GetLimitReporterDefault( i ) ); + AllocCheck_AllocS("LimitReport_t"); + + int count_current = 0; + + switch ( i ) + { + case LERROR_PS_SAMPLER: + count_current = data->shader->pPS_Identifiers->hList_Textures.Count(); + break; + case LERROR_VS_SAMPLER: + count_current = data->shader->pVS_Identifiers->hList_Textures.Count(); + break; + case LERROR_PS_CONSTS: + case LERROR_VS_CONSTS: + { + const bool bPS = i == LERROR_PS_CONSTS; + IdentifierLists_t *pList = bPS ? data->shader->pPS_Identifiers : data->shader->pVS_Identifiers; + if ( !pList ) + break; + + for ( int a = 0; a < pList->hList_EConstants.Count(); a++ ) + { + int curSize = pList->hList_EConstants[a]->iConstSize; + if ( !HLSLENV_SHOULD_COUNT_CONST( pList->hList_EConstants[a]->iEnvC_ID, bPS ) ) + curSize = 0; + count_current += curSize; + } + } + break; + case LERROR_VMT_PARAMS_STATIC: + case LERROR_VMT_PARAMS_MUTABLE: + { + const int TargetEnvID = ( i == LERROR_VMT_PARAMS_STATIC ) ? HLSLENV_SMART_VMT_STATIC : HLSLENV_SMART_VMT_MUTABLE; + + CUtlVector< SimpleEnvConstant* >hListedConstants; + for ( int a = 0; a < 2; a++ ) + { + IdentifierLists_t *pList = a ? data->shader->pPS_Identifiers : data->shader->pVS_Identifiers; + if ( !pList ) + continue; + for ( int b = 0; b < pList->hList_EConstants.Count(); b++ ) + { + if ( pList->hList_EConstants[b]->iEnvC_ID != TargetEnvID ) + continue; + bool bContinue = false; + for ( int c = 0; c < hListedConstants.Count(); c++ ) + { + SimpleEnvConstant *pConstLast = hListedConstants[c]; + Assert( pConstLast->szSmartHelper && pList->hList_EConstants[b]->szSmartHelper ); + + if ( !Q_stricmp( pConstLast->szSmartHelper, pList->hList_EConstants[b]->szSmartHelper ) ) + bContinue = true; + } + if ( bContinue ) + continue; + + hListedConstants.AddToTail( pList->hList_EConstants[b] ); + count_current++; + } + } + hListedConstants.Purge(); + } + break; + case LERROR_GENERIC_DEMOTEXTURE_MISMTACH: + { + //cutlvector< simpletexture* >&htexlist = data->shader->pps_identifiers->hlist_textures; + //for ( int a = 0; a < htexlist.count(); a++ ) + //{ + // simpletexture &_tex_a = htexlist[a]; + // for ( int b = 0; b < htexlist.count(); b++ ) + // { + // simpletexture &_tex_b = htexlist[b]; + // if ( a == b ) + // continue; + // + + // } + //} + } + break; + } + + report->i_cur = count_current; + hErrorList.AddToTail( report ); + + bError = bError || (report->i_cur > report->i_max); + report = NULL; + } + return bError; +} + +WriteContext_FXC::WriteContext_FXC() +{ + buf_combos.SetBufferType( true, true ); + buf_samplers.SetBufferType( true, true ); + buf_constants.SetBufferType( true, true ); + buf_arrays.SetBufferType( true, true ); + buf_functions_globals.SetBufferType( true, true ); + buf_functions_bodies.SetBufferType( true, true ); + buf_semantics_In.SetBufferType( true, true ); + buf_semantics_Out.SetBufferType( true, true ); + buf_code.SetBufferType( true, true ); + + buf_combos.EnableDirectives( true ); + buf_samplers.EnableDirectives( true ); + buf_constants.EnableDirectives( true ); + buf_arrays.EnableDirectives( true ); + buf_functions_globals.EnableDirectives( true ); + buf_functions_bodies.EnableDirectives( true ); + buf_semantics_In.EnableDirectives( true ); + buf_semantics_Out.EnableDirectives( true ); + buf_code.EnableDirectives( true ); + + bPreview = true; + + m_hActive_Solvers = NULL; + m_pActive_Identifiers = NULL; +} + +RunCodeContext::RunCodeContext( bool bPreview, bool bScene ) +{ + pRenderContext = NULL; + bPreviewMode = bPreview; + bSceneMode = bScene; +} +const bool &RunCodeContext::IsUsingPreview() const +{ + return bPreviewMode; +} +const bool &RunCodeContext::IsSceneMode() const +{ + return bSceneMode; +} + +void SetupForRendering( CUtlVector< CHLSL_SolverBase* > &hStack ) +{ + for ( int i = 0; i < hStack.Count(); i++ ) + hStack[ i ]->Invoke_RenderInit(); +} + +void UniquifyComboList( CUtlVector< SimpleCombo* > &_combos ) +{ + CUtlVector< SimpleCombo* > _newlist; + for ( int i = 0; i < _combos.Count(); i++ ) + { + SimpleCombo *c = _combos[i]; + bool bAdd = true; + for ( int x = 0; x < _newlist.Count(); x++ ) + { + SimpleCombo *n = _newlist[x]; + if ( !Q_stricmp( c->name, n->name ) /*&& + c->bStatic == n->bStatic*/ ) + { + bAdd = false; + if ( n->iComboType <= HLSLCOMBO_CUSTOM ) + n->iComboType = c->iComboType; + n->max = max( n->max, c->max ); + n->bStatic = n->bStatic || c->bStatic; + } + } + if ( !bAdd ) + { + delete c; + continue; + } + _newlist.AddToTail( c ); + } + _combos.Purge(); + _combos.AddVectorToTail( _newlist ); + _newlist.Purge(); +} +void UniquifyTextureList( CUtlVector< SimpleTexture* > &_tex ) +{ + CUtlVector< SimpleTexture* > _newlist; + for ( int i = 0; i < _tex.Count(); i++ ) + { + SimpleTexture *cur = _tex[i]; + bool bAdd = true; + CUtlVector< HNODE* >hNodesToAdd; + for ( int a = 0; a < _newlist.Count(); a++ ) + { + SimpleTexture *output = _newlist[a]; + if ( output->iTextureMode != cur->iTextureMode ) + continue; + if ( cur->iTextureMode == HLSLTEX_CUSTOMPARAM && + Q_stricmp( cur->szParamName, output->szParamName ) ) + continue; + + bAdd = false; + output->m_hTargetNodes.AddVectorToTail( cur->m_hTargetNodes ); + cur->m_hTargetNodes.Purge(); + } + if ( !bAdd ) + { + delete cur; + continue; + } + + cur->iSamplerIndex = _newlist.Count(); + _newlist.AddToTail( cur ); + } + _tex.Purge(); + _tex.AddVectorToTail( _newlist ); + _newlist.Purge(); +} +//bool CountConstant( int envcid, bool bPS ) +//{ +// if ( envcid <= HLSLENV_FOG_PARAMS ) +// return true; +// if ( !bPS && envcid == HLSLENV_FLASHLIGHT_VPMATRIX ) +// return true; +// if ( envcid == HLSLENV_SMART_CALLBACK || +// envcid == HLSLENV_SMART_VMT_STATIC || +// envcid == HLSLENV_SMART_VMT_MUTABLE ) +// return true; +// return false; +//} +void UniquifyConstantList( bool bPS, CUtlVector< SimpleEnvConstant* > &_const ) +{ + CUtlVector< SimpleEnvConstant* > _newlist; + int currentNormalizedNum = 0; + for ( int i = 0; i < _const.Count(); i++ ) + { + SimpleEnvConstant *cur = _const[i]; + bool bAdd = true; + for ( int a = 0; a < _newlist.Count(); a++ ) + { + SimpleEnvConstant *output = _newlist[a]; + if ( output->iEnvC_ID != cur->iEnvC_ID ) + continue; + + if ( HLSLENV_IS_SMART_CONST( output->iEnvC_ID ) ) + { + Assert( output->szSmartHelper && cur->szSmartHelper ); + if ( Q_stricmp( output->szSmartHelper, cur->szSmartHelper ) ) + continue; + } + + if ( output->iEnvC_ID == HLSLENV_CUSTOM_MATRIX && + output->iSmartNumComps != cur->iSmartNumComps ) + continue; + + bAdd = false; + } + if ( !bAdd ) + { + delete cur; + continue; + } + + Assert( cur->iConstSize > 0 ); + + if ( HLSLENV_SHOULD_COUNT_CONST( cur->iEnvC_ID, bPS ) ) + { + cur->iHLSLRegister = currentNormalizedNum; + currentNormalizedNum += cur->iConstSize; + } + + _newlist.AddToTail( cur ); + } + _const.Purge(); + _const.AddVectorToTail( _newlist ); + _newlist.Purge(); +} +void UniquifyFunctionList( CUtlVector< SimpleFunction* > &_funcs ) +{ + CUtlVector< SimpleFunction* > _newlist; + for ( int i = 0; i < _funcs.Count(); i++ ) + { + SimpleFunction *f = _funcs[i]; + bool bAdd = true; + for ( int x = 0; x < _newlist.Count(); x++ ) + { + SimpleFunction *n = _newlist[x]; + + Assert( f->szFuncName && n->szFuncName ); + bool bSameFunctionName = !Q_strcmp( f->szFuncName, n->szFuncName ); + bool bSameParams = f->hParams.Count() == n->hParams.Count(); + if ( bSameParams ) + { + for ( int p = 0; p < f->hParams.Count(); p++ ) + { + if ( f->hParams[p] != n->hParams[p] ) + bSameParams = false; + } + } + + if ( bSameFunctionName && bSameParams ) + { + bAdd = false; + } + } + if ( !bAdd ) + { + delete f; + continue; + } + _newlist.AddToTail( f ); + } + _funcs.Purge(); + _funcs.AddVectorToTail( _newlist ); + _newlist.Purge(); +} +void ClearSingleIdentifier( IdentifierLists_t *id ) +{ + SaveDeleteVector( id->hList_Combos ); + SaveDeleteVector( id->hList_Textures ); + SaveDeleteVector( id->hList_EConstants ); + SaveDeleteVector( id->hList_Arrays ); + SaveDeleteVector( id->hList_Functions ); +} +void ClearIdentifiers( GenericShaderData &data ) +{ + ClearSingleIdentifier( data.shader->pVS_Identifiers ); + ClearSingleIdentifier( data.shader->pPS_Identifiers ); + ClearSingleIdentifier( data.pUNDEF_Identifiers ); +} +void AllocateIdentifiers( IdentifierLists_t &Identifiers, CUtlVector< CHLSL_SolverBase* > &hStack ) +{ + for ( int i = 0; i < hStack.Count(); i++ ) + { + hStack[ i ]->Invoke_IdentifierAllocate( Identifiers ); + } +} +void UniquifyIdentifiers( bool bPS, IdentifierLists_t &Identifiers ) +{ + UniquifyComboList( Identifiers.hList_Combos ); + UniquifyTextureList( Identifiers.hList_Textures ); + UniquifyConstantList( bPS, Identifiers.hList_EConstants ); + UniquifyFunctionList( Identifiers.hList_Functions ); + + if ( !bPS ) + { + SimpleTexture *pMorph = NULL; + for (int i = 0; i < Identifiers.hList_Textures.Count() && !pMorph; i++ ) + if ( Identifiers.hList_Textures[i]->iTextureMode == HLSLTEX_MORPH ) + pMorph = Identifiers.hList_Textures[i]; + + if ( pMorph ) + { + Identifiers.hList_Textures.FindAndRemove( pMorph ); + Identifiers.hList_Textures.AddToTail( pMorph ); + for (int i = 0; i < Identifiers.hList_Textures.Count(); i++ ) + Identifiers.hList_Textures[i]->iSamplerIndex = i; + } + } +} +void CalcNumDynamicCombos( IdentifierLists_t &Identifiers, bool bPreview ) +{ + Identifiers.inum_DynamicCombos = 1; + for ( int i = 0; i < Identifiers.hList_Combos.Count(); i++ ) + { + if ( Identifiers.hList_Combos[i]->bStatic ) + continue; + + if ( bPreview && !Identifiers.hList_Combos[i]->bInPreviewMode ) + continue; + + int curAmt = Identifiers.hList_Combos[i]->GetAmt(); + Identifiers.inum_DynamicCombos *= curAmt; + } +} + +#define GAUSS_BIAS_LIMIT (0.99999f) +float GaussianWeight_1D_Internal( const int &iSample_pos, const int &iKernel_size, const float &flBias ) +{ + const long double flDistribution = ( ( iKernel_size + 1 ) / 6.0f ) - flBias; + const long double flPos = ( (float)iSample_pos ) - ( ( ( iKernel_size - 1.0f ) / 2.0f ) ); + + long double flWeight = 1.0f / ( sqrt( 2.0f * M_PI_F ) * flDistribution ); + flWeight *= exp( -1.0f * ( pow( flPos, 2 ) / ( 2.0f * pow( flDistribution, 2 ) ) ) ); + return flWeight; +} +float GaussianWeight_1D( const int &iSample_pos, const int &iKernel_size, const float &flBias ) +{ + const float flBiasClamped = clamp( flBias, -GAUSS_BIAS_LIMIT, GAUSS_BIAS_LIMIT ); + long double flAccum = 0; + for ( int i = 0; i < iKernel_size; i++ ) + flAccum += GaussianWeight_1D_Internal( i, iKernel_size, flBiasClamped ); + + long double flRemainder = ( 1.0f - flAccum ); + long double flWeight = GaussianWeight_1D_Internal( iSample_pos, iKernel_size, flBiasClamped ); + float flFinalWeight = flWeight + ( flRemainder * ( flWeight / flAccum ) ); + return flFinalWeight; +} + +float GaussianWeight_2D_Internal( const int &iPos_X, const int &iPos_Y, + const int &iSize_X, const int &iSize_Y, + const float &flBias ) +{ + const long double flDistribution_x = ( ( iSize_X + 1 ) / 6.0f ) - flBias; + const long double flPos_x = ( (float)iPos_X ) - ( ( ( iSize_X - 1.0f ) / 2.0f ) ); + const long double flDistribution_y = ( ( iSize_Y + 1 ) / 6.0f ) - flBias; + const long double flPos_y = ( (float)iPos_Y ) - ( ( ( iSize_Y - 1.0f ) / 2.0f ) ); + + const long double center_x = 0; + const long double center_y = 0; + const long double amplitude = 1.0f; + + long double step_x = pow( flPos_x - center_x, 2 ) / ( 2.0f * pow( flDistribution_x, 2 ) ); + long double step_y = pow( flPos_y - center_y, 2 ) / ( 2.0f * pow( flDistribution_y, 2 ) ); + long double exponent = -1.0f * ( step_x + step_y ); + + return amplitude * exp( exponent ); +} +float GaussianWeight_2D( const int &iPos_X, const int &iPos_Y, + const int &iSize_X, const int &iSize_Y, + const float &flBias ) +{ + const float flBiasClamped = clamp( flBias, -GAUSS_BIAS_LIMIT, GAUSS_BIAS_LIMIT ); + long double flAccum = 0; + for ( int x = 0; x < iSize_X; x++ ) + for ( int y = 0; y < iSize_Y; y++ ) + flAccum += GaussianWeight_2D_Internal( x, y, iSize_X, iSize_Y, flBiasClamped ); + + long double flRemainder = ( 1.0f - flAccum ); + long double flWeight = GaussianWeight_2D_Internal( iPos_X, iPos_Y, iSize_X, iSize_Y, flBiasClamped ); + return flWeight + ( flRemainder * ( flWeight / flAccum ) ); +} + + +//CON_COMMAND( gauss_1d, "pos kernelsize bias" ) +//{ +// if ( args.ArgC() < 3 ) +// return; +// +// int pos = atoi( args[ 1 ] ); +// int size = atoi( args[ 2 ] ); +// float bias = 0; +// if ( args.ArgC() >= 4 ) +// bias = atof( args[3] ); +// +// float weight = GaussianWeight_1D( pos, size, bias ); +// Msg( "gauss 1d, pos: %i, kernelsize: %i, bias: %f, weight: %f\n", pos, size, bias, weight ); +//} +//CON_COMMAND( gauss_2d, "posx posy sizex sizey bias" ) +//{ +// if ( args.ArgC() < 5 ) +// return; +// +// int posx = atoi( args[ 1 ] ); +// int posy = atoi( args[ 2 ] ); +// int sizex = atoi( args[ 3 ] ); +// int sizey = atoi( args[ 4 ] ); +// float bias = 0; +// if ( args.ArgC() >= 6 ) +// bias = atof( args[5] ); +// +// float weight = GaussianWeight_2D( posx, posy, sizex, sizey, bias ); +// Msg( "gauss 2d, pos: %i/%i, kernelsize: %i/%i, bias: %f, weight: %f\n", posx, posy, sizex, sizey, bias, weight ); +//} + +void BuildFormatFlags( BasicShaderCfg_t &data, CUtlVector< CHLSL_SolverBase* > &hVertexshaderStack, CUtlVector< CHLSL_SolverBase* > &hPixelhaderStack ) +{ + data.iVFMT_flags = VERTEX_POSITION; +#ifndef SHADER_EDITOR_DLL_SWARM + data.iVFMT_flags |= VERTEX_FORMAT_VERTEX_SHADER; +#endif + data.iVFMT_numTexcoords = 1; + data.iVFMT_numUserData = 0; + data.bRefractionSupport = false; + data.bVertexLighting = false; + + for (int i = 0; i < hVertexshaderStack.Count(); i++) + { + CHLSL_Solver_ReadSemantics *_read = dynamic_cast< CHLSL_Solver_ReadSemantics* >( hVertexshaderStack[i] ); + if ( _read ) + { + ResourceType_t type = _read->GetResourceType(); + switch ( type ) + { + case RESOURCETYPE_NORMAL_4: +#ifndef SHADER_EDITOR_DLL_2006 + data.iVFMT_flags |= VERTEX_FORMAT_COMPRESSED; +#endif +#ifdef SHADER_EDITOR_DLL_SWARM + data.iVFMT_flags |= VERTEX_FORMAT_PAD_POS_NORM; +#endif + case RESOURCETYPE_NORMAL: + data.iVFMT_flags |= VERTEX_NORMAL; + break; + + case RESOURCETYPE_TANGENTS_4: + data.iVFMT_numUserData = 4; + //data.iVFMT_flags |= VERTEX_TANGENT_T; + data.iVFMT_flags |= VERTEX_USERDATA_SIZE( data.iVFMT_numUserData ); + break; + case RESOURCETYPE_TANGENTS_3: + data.iVFMT_flags |= VERTEX_TANGENT_S; + break; + case RESOURCETYPE_TANGENTT: + data.iVFMT_flags |= VERTEX_TANGENT_T; + break; + + case RESOURCETYPE_COLOR_0: + case RESOURCETYPE_COLOR_1: + case RESOURCETYPE_COLOR_2: + case RESOURCETYPE_COLOR_3: + data.iVFMT_flags |= VERTEX_COLOR; + break; + + case RESOURCETYPE_FLEXDELTA: + case RESOURCETYPE_BONE_WEIGHTS: + case RESOURCETYPE_BONE_INDICES: + data.iVFMT_flags |= VERTEX_BONE_INDEX; + data.iVFMT_flags |= VERTEX_BONEWEIGHT( 3 ); + break; + + case RESOURCETYPE_TEXCOORD_2: + case RESOURCETYPE_TEXCOORD_1: + case RESOURCETYPE_TEXCOORD_0: + { + int texcoordNum = type - RESOURCETYPE_TEXCOORD_0; + CHLSL_Solver_ReadSemantics *_readVertex = dynamic_cast< CHLSL_Solver_ReadSemantics* >( hVertexshaderStack[i] ); + + Assert( _readVertex ); + Assert( texcoordNum >= 0 && texcoordNum < 3 ); + + data.iVFMT_texDim[ texcoordNum ] = GetVarFlagsVarValue( _readVertex->GetTexcoordFlag( texcoordNum ) ) + 1; + data.iVFMT_numTexcoords = max( data.iVFMT_numTexcoords, texcoordNum + 1 ); + + data.iVFMT_flags |= VERTEX_TEXCOORD_SIZE( texcoordNum, data.iVFMT_texDim[ texcoordNum ] ); + break; + } + } + } + + CHLSL_Solver_StdVLight *_vlight = dynamic_cast< CHLSL_Solver_StdVLight* >( hVertexshaderStack[i] ); + if ( _vlight ) + { + data.bVertexLighting = true; + } + } + for (int i = 0; i < hPixelhaderStack.Count(); i++) + { + CHLSL_Solver_TextureSample *_texSample = dynamic_cast< CHLSL_Solver_TextureSample* >( hPixelhaderStack[i] ); + if ( _texSample ) + { + if ( _texSample->GetTextureMode() == HLSLTEX_FRAMEBUFFER ) + data.bRefractionSupport = true; + } + + CHLSL_Solver_StdMorph *_morph = dynamic_cast< CHLSL_Solver_StdMorph* >( hPixelhaderStack[i] ); + if ( _morph ) + { + //data.iVFMT_numTexcoords = 3; + } + } + + //if ( data.iVFMT_numUserData ) + // data.iVFMT_flags &= ~VERTEX_TANGENT_S; + + if ( data.bVertexLighting ) + data.iVFMT_flags &= ~VERTEX_COLOR; +} + +extern CViewSetup_SEdit_Shared _MainView; + +void __pSolve_Time( float *_fl4 ) +{ + _fl4[ 0 ] = GetEditorTime(); //engine->Time(); +} +void __pSolve_Origin( float *_fl4 ) +{ + _fl4[ 2 ] = 0.5f; +} +void __pSolve_ViewForward( float *_fl4 ) +{ + _fl4[2] = -1; +} +void __pSolve_ViewRight( float *_fl4 ) +{ + _fl4[1] = -1; +} +void __pSolve_ViewUp( float *_fl4 ) +{ + _fl4[0] = 1; +} +void __pSolve_ViewDepth( float *_fl4 ) +{ + _fl4[0] = _MainView.zFar; +} +void __pSolve_PixelSize( float *_fl4 ) +{ + _fl4[0] = 0.05f; + _fl4[1] = 0.05f; +} +void __pSolve_Dummy( float *_fl4 ){} +static econstdata econstinfoarray[] = +{ + { "_g_Time", "secs", HLSLVAR_FLOAT1, "Time", HLSLNODE_CONSTANT_TIME, &::__pSolve_Time }, + { "_g_VecOrig", "orig", HLSLVAR_FLOAT3, "View origin", HLSLNODE_CONSTANT_VIEW_ORIGIN, &::__pSolve_Origin }, + { "_g_VecForward", "fwd", HLSLVAR_FLOAT3, "View forward", HLSLNODE_CONSTANT_VIEW_FORWARD, &::__pSolve_ViewForward }, + { "_g_VecRight", "right", HLSLVAR_FLOAT3, "View right", HLSLNODE_CONSTANT_VIEW_RIGHT, &::__pSolve_ViewRight }, + { "_g_VecUp", "up", HLSLVAR_FLOAT3, "View up", HLSLNODE_CONSTANT_VIEW_UP, &::__pSolve_ViewUp }, + { "_g_WorldDepth", "depth", HLSLVAR_FLOAT1, "View world depth", HLSLNODE_CONSTANT_VIEW_WORLDSPACE_DEPTH, &::__pSolve_ViewDepth }, + { "_g_TexelSize", "size", HLSLVAR_FLOAT2, "FB texelsize", HLSLNODE_CONSTANT_FB_PIXELSIZE, &::__pSolve_PixelSize }, + { "_g_FogParams", "data", HLSLVAR_FLOAT4, "Fog params", HLSLNODE_CONSTANT_FOGPARAMS, &::__pSolve_Dummy }, +}; +econstdata *EConstant_GetData( int i ) +{ + Assert( i >= 0 && i <= 7 ); + return &(econstinfoarray[i]); +} + +static const customMatrix_t cmatrixData[] = { + { "float4x3", "g_cCMatrix_View", "View", 3, HLSLVAR_MATRIX4X3 }, + { "float4x4", "g_cCMatrix_Proj", "Proj", 4, HLSLVAR_MATRIX4X4 }, + { "float4x4", "g_cCMatrix_ViewProj", "ViewProj", 4, HLSLVAR_MATRIX4X4 }, + + { "float4x3", "g_cCMatrix_ViewInv", "View Inv", 3, HLSLVAR_MATRIX4X3 }, + { "float4x4", "g_cCMatrix_ProjInv", "Proj Inv", 4, HLSLVAR_MATRIX4X4 }, + { "float4x4", "g_cCMatrix_ViewProjInv", "ViewProj Inv", 4, HLSLVAR_MATRIX4X4 }, +}; +const customMatrix_t *GetCMatrixInfo( int ID ) +{ + Assert( ID >= 0 && ID < CMATRIX_LAST ); + return &(cmatrixData[ ID ]); +} + +#define NUM_DEFAULT_PUZZLES_PER_ROW 4 //8 + +int curPuzzleIndex = 0; +int curPuzzlesPerRow = 0; + +//ITexture *_tex_PingPong[2] = {0,0}; +static int sizeold = 0; +static int puzzlesize = 0; + +static bool bAdded = false; +void ReloadCommon( int f ) +{ + //pEditorRoot->DeleteProceduralMaterials(); + //pEditorRoot->AllocProceduralMaterials(); + if ( pEditorRoot ) + pEditorRoot->UpdateVariablePointer(); +} + +//CON_COMMAND( manualrestore, "" ) +//{ +// pEditorRoot->UpdateVariablePointer(); +//} +static CTextureReference _FFB; +ITexture *GetFBTex() +{ + if ( !_FFB ) //|| IsErrorTexture( _FFB ) ) + { + _FFB.Init( materials->FindTexture( "_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET ) ); + Assert( !IsErrorTexture( _FFB ) ); + } + return _FFB; +} +static CTextureReference _FFB_Small; +ITexture *GetFBTexSmall() +{ + if ( !_FFB_Small ) + { + _FFB_Small.Init( materials->FindTexture( "_rt_SmallFB1", TEXTURE_GROUP_RENDER_TARGET ) ); + Assert( !IsErrorTexture( _FFB_Small ) ); + } + return _FFB_Small; +} +static CTextureReference _tex_PingPong[3]; +ITexture *GetPingPongRT( int num ) +{ + if ( !_tex_PingPong[num] ) + { + _tex_PingPong[num].Init( materials->FindTexture( VarArgs("_rt_SEdit_pingpong_%i",num), TEXTURE_GROUP_RENDER_TARGET ) ); + Assert( !IsErrorTexture( _tex_PingPong[num] ) ); + } + return _tex_PingPong[num]; +} +static CTextureReference _teX_fbcopy; +ITexture *GetFBCopyTex() +{ + if ( !_teX_fbcopy ) + { + _teX_fbcopy.Init( materials->FindTexture( "_rt_SEdit_FramebufferCopy", TEXTURE_GROUP_RENDER_TARGET ) ); + Assert( !IsErrorTexture( _teX_fbcopy ) ); + } + return _teX_fbcopy; +} +static CTextureReference _teX_Skymask; +ITexture *GetSkymaskTex() +{ + if ( !_teX_Skymask ) + { + _teX_Skymask.Init( materials->FindTexture( "_rt_SEdit_Skymask", TEXTURE_GROUP_RENDER_TARGET ) ); + Assert( !IsErrorTexture( _teX_Skymask ) ); + } + return _teX_Skymask; +} + +static SEDIT_SKYMASK_MODE iSkymask = SKYMASK_OFF; +const bool IsSkymaskAvailable() +{ + return iSkymask != SKYMASK_OFF; +} +const SEDIT_SKYMASK_MODE GetSkymaskMode() +{ + return iSkymask; +} + +#define FALLBACK_RTS 1 + +void AllocRTs( int size ) +{ + if ( !bAdded ) + { + materials->AddRestoreFunc( ReloadCommon ); + bAdded = true; + } + if (sizeold == size) + return; + + //ITexture *tmp = materials->FindTexture( "_rt_SEdit_pingpong_0", TEXTURE_GROUP_OTHER, false ); + //ForceDeleteTexture( &tmp ); + //if ( !IsErrorTexture(tmp) ) + // tmp->Release(); + //tmp = materials->FindTexture( "_rt_SEdit_pingpong_1", TEXTURE_GROUP_OTHER, false ); + //ForceDeleteTexture( &tmp ); + //if ( !IsErrorTexture(tmp) ) + // tmp->Release(); + //tmp = materials->FindTexture( "_rt_SEdit_FramebufferCopy", TEXTURE_GROUP_OTHER, false ); + //ForceDeleteTexture( &tmp ); + //if ( !IsErrorTexture(tmp) ) + // tmp->Release(); + //tmp = materials->FindTexture( "_rt_SEdit_pingpong_2", TEXTURE_GROUP_OTHER, false ); + //ForceDeleteTexture( &tmp ); + //if ( !IsErrorTexture(tmp) ) + // tmp->Release(); + + int flags = TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | + TEXTUREFLAGS_RENDERTARGET | TEXTUREFLAGS_NODEPTHBUFFER | + TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT; + + ImageFormat RT_format_0 = IMAGE_FORMAT_RGBA32323232F; +#if FALLBACK_RTS + ImageFormat RT_format_1 = IMAGE_FORMAT_RGBA8888; +#endif + + + materials->BeginRenderTargetAllocation(); + + ITexture *tmp = NULL; + tmp = materials->CreateNamedRenderTargetTextureEx( "_rt_SEdit_pingpong_0", + size, size, + RT_SIZE_NO_CHANGE, + RT_format_0, + MATERIAL_RT_DEPTH_NONE, + flags, 0 ); +#if FALLBACK_RTS + if ( !tmp ) + tmp = materials->CreateNamedRenderTargetTextureEx( "_rt_SEdit_pingpong_0", + size, size, + RT_SIZE_NO_CHANGE, + RT_format_1, + MATERIAL_RT_DEPTH_NONE, + flags, 0 ); +#endif + + int size2 = 2; //size; + + tmp = NULL; + tmp = materials->CreateNamedRenderTargetTextureEx( "_rt_SEdit_pingpong_1", + size2, size2, + RT_SIZE_NO_CHANGE, + RT_format_0, + MATERIAL_RT_DEPTH_NONE, + flags, 0 ); +#if FALLBACK_RTS + if ( !tmp ) + tmp = materials->CreateNamedRenderTargetTextureEx( "_rt_SEdit_pingpong_1", + size2, size2, + RT_SIZE_NO_CHANGE, + RT_format_1, + MATERIAL_RT_DEPTH_NONE, + flags, 0 ); +#endif + tmp = NULL; + tmp = materials->CreateNamedRenderTargetTextureEx( "_rt_SEdit_FramebufferCopy", + 128, 128, + RT_SIZE_FULL_FRAME_BUFFER, + IMAGE_FORMAT_RGB888, + MATERIAL_RT_DEPTH_NONE, + flags, 0 ); + + tmp = materials->CreateNamedRenderTargetTextureEx( "_rt_SEdit_pingpong_2", + size, size, + RT_SIZE_NO_CHANGE, + IMAGE_FORMAT_RGB888, + MATERIAL_RT_DEPTH_NONE, + flags, 0 ); + +#if 0 + materials->CreateNamedRenderTargetTextureEx( "_rt_vst", + 128, 128, + RT_SIZE_OFFSCREEN, + IMAGE_FORMAT_RGBA16161616F, + MATERIAL_RT_DEPTH_NONE, + TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_NODEBUGOVERRIDE | +TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE | TEXTUREFLAGS_VERTEXTEXTURE, 0 ); +#endif + +#if 0 + ImageFormat imt_dt = materials->GetShadowDepthTextureFormat(); + Warning( "depth tex format: %i\n", imt_dt ); + ITexture *dtex = materials->CreateNamedRenderTargetTextureEx( "_rt_depthtextest", 100, 99, RT_SIZE_NO_CHANGE, imt_dt, MATERIAL_RT_DEPTH_ONLY, flags ); + Warning( "depth tex alloc state: %d\n", (!IsErrorTexture( dtex )) ); + Warning( "depth tex values sanity test: %d\n", ( dtex && dtex->GetActualWidth() == dtex->GetMappingWidth() && dtex->GetActualWidth() == 100 && + dtex->GetActualHeight() == dtex->GetMappingHeight() && dtex->GetActualHeight() == 99 ) ); +#endif + + materials->EndRenderTargetAllocation(); + + Assert( !IsErrorTexture( GetPingPongRT(0) ) ); + Assert( !IsErrorTexture( GetPingPongRT(2) ) ); + + Assert( GetPingPongRT(0)->GetMappingWidth() == size && GetPingPongRT(0)->GetMappingHeight() == size ); + Assert( GetPingPongRT(2)->GetMappingWidth() == size && GetPingPongRT(2)->GetMappingHeight() == size ); + + Assert( !IsErrorTexture( GetFBCopyTex() ) ); + + sizeold = size; +} +void AllocSkymask( SEDIT_SKYMASK_MODE iSkymaskMode ) +{ + iSkymask = clamp( iSkymaskMode, SKYMASK_OFF, SKYMASK_FULL ); + if ( !IsSkymaskAvailable() ) + return; + + int flags = TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_RENDERTARGET | TEXTUREFLAGS_NODEPTHBUFFER; + + RenderTargetSizeMode_t rtsizemode = ( iSkymask == SKYMASK_QUARTER ) ? RT_SIZE_HDR : RT_SIZE_FULL_FRAME_BUFFER; + + materials->BeginRenderTargetAllocation(); + { + materials->CreateNamedRenderTargetTextureEx( "_rt_SEdit_Skymask", + 128, 128, + rtsizemode, + IMAGE_FORMAT_RGBA8888, + MATERIAL_RT_DEPTH_NONE, + flags | TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT, 0 ); + } + materials->EndRenderTargetAllocation(); +} + +const int &GetRTPuzzleSize() +{ + return puzzlesize; +} +const int &GetRTSize() +{ + return sizeold; +} + +void ResetTileInfo() +{ + Assert( sizeold ); + Assert( !IsErrorTexture( GetPingPongRT(0) ) ); + + curPuzzleIndex = 0; + puzzlesize = sizeold / NUM_DEFAULT_PUZZLES_PER_ROW; + curPuzzlesPerRow = NUM_DEFAULT_PUZZLES_PER_ROW; +} +void CalcPuzzleSize( int numSolvers ) +{ + Assert( sizeold ); + while ( (numSolvers-1) > (curPuzzlesPerRow*curPuzzlesPerRow) ) + curPuzzlesPerRow *= 2; + + puzzlesize = sizeold / curPuzzlesPerRow; + + Assert( gProcShaderCTRL ); + if ( gProcShaderCTRL ) + { + float deltapixelsize = ( curPuzzlesPerRow / (float)sizeold ) * 0.5f; + gProcShaderCTRL->SetNormalizedPuzzleDelta( deltapixelsize ); + } +} + +const int &GetCurrentPuzzleIndex() +{ + return curPuzzleIndex; +} +void OnPuzzleDrawn() +{ + curPuzzleIndex++; +} +void GetUVsForPuzzle( const int &num, Vector2D &min, Vector2D &max, bool bAddClamp ) +{ + Assert( num <= (curPuzzlesPerRow*curPuzzlesPerRow) ); + + double puzzleUVSize = 1.0f / curPuzzlesPerRow; + int row = num / curPuzzlesPerRow; + int column = num % curPuzzlesPerRow; + + min.Init( column * puzzleUVSize, row * puzzleUVSize ); + max = min; + max.x += puzzleUVSize; + max.y += puzzleUVSize; + + if ( bAddClamp ) + { + float deltapixelsize = 0.75f / (float)sizeold; + min.x += deltapixelsize; + min.y += deltapixelsize; + max.x -= deltapixelsize; + max.y -= deltapixelsize; + } + else + { + float deltapixelsize = sedit_uv_adjust.GetFloat() / (float)sizeold; // lé magic + //float deltapixelsize = ( curPuzzlesPerRow / (float)sizeold ) * 0.1f; + //min.x += deltapixelsize; + //min.y += deltapixelsize; + max.x += deltapixelsize; + max.y += deltapixelsize; + } +} +void GetCurPuzzleView( int &x, int &y, int &w, int &t ) +{ + Assert( curPuzzleIndex <= (curPuzzlesPerRow*curPuzzlesPerRow) ); + + int puzzlePixelSize = sizeold / curPuzzlesPerRow; + int row = curPuzzleIndex / curPuzzlesPerRow; + int column = curPuzzleIndex % curPuzzlesPerRow; + + x = column * puzzlePixelSize; + y = row * puzzlePixelSize; + w = t = puzzlePixelSize; +} + +void CleanupString( const char *pSrc, char *pOut, int maxLength, bool AllowSpaces, bool AllowUnderscore, bool AllowNumbers, bool AllowNumberInFirstPlace ) +{ + Assert( maxLength > 1 ); + int slotWrite = 0; + const char *walk = pSrc; + + while (walk && *walk && slotWrite < (maxLength-1)) + { + if ( ( *walk >= 'a' && *walk <= 'z' ) || + ( *walk >= 'A' && *walk <= 'Z' ) || + ( AllowNumbers && *walk >= '0' && *walk <= '9' ) || + ( AllowUnderscore && *walk == '_' ) || + ( *walk == ' ' ) ) + { + pOut[slotWrite] = *walk; + if ( !AllowSpaces && *walk == ' ' ) + pOut[slotWrite] = '_'; + else if (!AllowNumberInFirstPlace && !slotWrite && *walk >= '0' && *walk <= '9') + pOut[slotWrite] = '_'; + slotWrite++; + } + walk++; + } + + pOut[slotWrite] = '\0'; +} + +void ForceDeleteMaterial( IMaterial **pMat ) +{ + if ( !GetMatSysShutdownHelper()->IsShuttingDown() ) + { +#if 0 + const char *pszName = (*pMat)->GetName(); + const char *pszTexGroup = (*pMat)->GetTextureGroupName(); + + char tmp[MAX_PATH]; + char tmpTexGroup[MAX_PATH]; + + Q_snprintf( tmpTexGroup, sizeof(tmpTexGroup), "%s", pszTexGroup ? pszTexGroup : TEXTURE_GROUP_OTHER ); + + if ( pszName ) + { + Q_snprintf( tmp, sizeof(tmp), "%s", pszName ); + + while ( !IsErrorMaterial( materials->FindProceduralMaterial( tmp, tmpTexGroup, NULL ) ) ) + { + (*pMat)->Release(); + (*pMat)->DeleteIfUnreferenced(); + } + } + else +#endif + { + //Assert( 0 ); + + // yuck. shoot me now. + for (int i = 0; i < 99; i++ ) +#ifdef SHADER_EDITOR_DLL_2006 + (*pMat)->DecrementReferenceCount(); +#else + (*pMat)->Release(); +#endif + + (*pMat)->DeleteIfUnreferenced(); + } + } + + (*pMat) = NULL; +} +// same shit again. +void ForceDeleteTexture( ITexture **pTex ) +{ + if ( !GetMatSysShutdownHelper()->IsShuttingDown() ) + { + const char *pszName = (*pTex)->GetName(); + + char tmp[MAX_PATH]; + if ( pszName ) + { + Q_snprintf( tmp, sizeof(tmp), "%s", pszName ); + + while ( !IsErrorTexture( materials->FindTexture( tmp, TEXTURE_GROUP_OTHER, false ) ) ) + { +#ifdef SHADER_EDITOR_DLL_2006 + (*pTex)->DecrementReferenceCount(); +#else + (*pTex)->Release(); +#endif + (*pTex)->DeleteIfUnreferenced(); + } + } + else + { + Assert( 0 ); + +#ifdef SHADER_EDITOR_DLL_2006 + (*pTex)->DecrementReferenceCount(); +#else + (*pTex)->Release(); +#endif + (*pTex)->DeleteIfUnreferenced(); + } + } + + (*pTex) = NULL; +} + +IMaterialVar *FindMaterialVar( IMaterial *pMat, const char *varName ) +{ + bool bSuccess = false; + IMaterialVar *pVar = pMat->FindVar( varName, &bSuccess ); + return bSuccess ? pVar : NULL; +} +bool SetMaterialVar_String( IMaterial *pMat, const char *varName, const char *value ) +{ + IMaterialVar *pVar = FindMaterialVar( pMat, varName ); + if ( !pVar ) + return false; + pVar->SetStringValue( value ); + return true; +} +bool SetMaterialVar_Vec( IMaterial *pMat, const char *varName, const float a, const float b, const float c, const float d ) +{ + IMaterialVar *pVar = FindMaterialVar( pMat, varName ); + if ( !pVar ) + return false; + pVar->SetVecValue( a, b, c, d ); + return true; +} +bool SetMaterialVar_Vec( IMaterial *pMat, const char *varName, const float a, const float b, const float c ) +{ + IMaterialVar *pVar = FindMaterialVar( pMat, varName ); + if ( !pVar ) + return false; + pVar->SetVecValue( a, b, c ); + return true; +} +bool SetMaterialVar_Vec( IMaterial *pMat, const char *varName, const float a, const float b ) +{ + IMaterialVar *pVar = FindMaterialVar( pMat, varName ); + if ( !pVar ) + return false; + pVar->SetVecValue( a, b ); + return true; +} +bool SetMaterialVar_Vec( IMaterial *pMat, const char *varName, const float a ) +{ + IMaterialVar *pVar = FindMaterialVar( pMat, varName ); + if ( !pVar ) + return false; + pVar->SetFloatValue( a ); + return true; +} +bool SetMaterialVar_Int( IMaterial *pMat, const char *varName, const int a ) +{ + IMaterialVar *pVar = FindMaterialVar( pMat, varName ); + if ( !pVar ) + return false; + pVar->SetIntValue( a ); + return true; +} + +void BuildUserFunctionName( const char *pFunctionName, const CUtlVector< __funcParamSetup* > &sharedOutputs, char *pszDest, int buflen ) +{ + if ( buflen ) + pszDest[0] = '\0'; + + if ( buflen < 6 ) + return; + + Q_snprintf( pszDest, buflen, "void %s(", pFunctionName ); + + char *pWalk = pszDest + 5; + while ( pWalk && *pWalk ) + { + if ( *pWalk == ' ' ) + *pWalk = '_'; + pWalk++; + } + +#if DEBUG + bool bHitOutput = false; +#endif + + for ( int i = 0; i < sharedOutputs.Count(); i++ ) + { + __funcParamSetup *pData = sharedOutputs[i]; + +#if DEBUG + bHitOutput = bHitOutput || pData->bOutput; + Assert( pData->bOutput == bHitOutput ); +#endif + + Q_strcat( pszDest, pData->bOutput ? " out " : " in ", buflen ); + Q_strcat( pszDest, GetVarCodeNameFromFlag( pData->iFlag ), buflen ); + Q_strcat( pszDest, " ", buflen ); + Q_strcat( pszDest, pData->GetSafeName( i ), buflen ); + + if ( i < sharedOutputs.Count() - 1 ) + Q_strcat( pszDest, ",", buflen ); + else + Q_strcat( pszDest, " ", buflen ); + } + + Q_strcat( pszDest, ")", buflen ); +} + +void BuildUserFunctionName( const char *pFunctionName, const CUtlVector< __funcParamSetup* > &input, const CUtlVector< __funcParamSetup* > &output, + char *pszDest, int buflen ) +{ + CUtlVector< __funcParamSetup* >hOutputs; + for ( int i = 0; i < input.Count(); i++ ) + hOutputs.AddToTail( new __funcParamSetup( *input[i] ) ); + for ( int i = 0; i < output.Count(); i++ ) + hOutputs.AddToTail( new __funcParamSetup( *output[i] ) ); + + BuildUserFunctionName( pFunctionName, hOutputs, pszDest, buflen ); + + hOutputs.PurgeAndDeleteElements(); +} + +void BuildDefaultFunctionName( char *pszDest, int buflen, CBaseNode *pNode ) +{ + Q_snprintf( pszDest, buflen, "UserFunction_%u", pNode->GetUniqueIndex() ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/editorcommon.h b/sp/src/shadereditor/editorcommon.h new file mode 100644 index 00000000..ae68fc7b --- /dev/null +++ b/sp/src/shadereditor/editorcommon.h @@ -0,0 +1,1253 @@ +#ifndef EDITORCOMMON_H +#define EDITORCOMMON_H + +#pragma warning( default: 4800 ) // enable: forcing value to bool 'true' or 'false' (performance warning) +#pragma warning( disable: 4005 ) // disable: macro redefinition + +//#if DEBUG +//#include +//class DbgOutput +//{ +//public: +// DbgOutput(); +// ~DbgOutput(); +// +// void DbgOps( const char *pname, bool bDealloc ); +// +//private: +// void OnAllocated( const char *pname ); +// void OnFreed( const char *pname ); +//}; +//extern DbgOutput __dbgOutput; +// +//#define AllocCheck_Alloc() __dbgOutput.DbgOps( typeid(this).name(), false ) +//#define AllocCheck_Free() __dbgOutput.DbgOps( typeid(this).name(), true ) +//#define AllocCheck_AllocS(x) __dbgOutput.DbgOps( x, false ) +//#define AllocCheck_FreeS(x) __dbgOutput.DbgOps( x, true ) +//#else +#define AllocCheck_Alloc() ((void)NULL) +#define AllocCheck_Free() ((void)NULL) +#define AllocCheck_AllocS(x) ((void)NULL) +#define AllocCheck_FreeS(x) ((void)NULL) +//#endif + +float GetEditorTime(); +void EngineCopy( const char *a, const char *b ); + +#include "exported_utilities.h" + +#ifdef SHADER_EDITOR_DLL_SWARM + +#include "vgui_surfacelib/ifontsurface.h" + +void VCRHook_WaitForSingleObject( + __in HANDLE hHandle, + __in DWORD dwMilliseconds + ); +#elif SHADER_EDITOR_DLL_2006 + +class CMatRenderContextPtr +{ +public: + CMatRenderContextPtr( IMaterialSystem *pMat ) + { + m = pMat; + }; + + operator IMaterialSystem*() { + return m; + }; + + IMaterialSystem* operator->() { + return m; + }; + + const IMaterialSystem* operator->() const { + return m; + }; + +private: + IMaterialSystem *m; +}; + +#define IMatRenderContext IMaterialSystem + +#endif + +#include "const.h" +#include "vgui_controls/controls.h" +#include "tier0/fasttimer.h" +#include "../../materialsystem/stdshaders/cpp_shader_constant_register_map.h" + +//#include "vgui_controls/utilities.h" + +#include "interface/dll_init.h" + +class vgui::Panel; +class CJack; +class CBaseNode; +class CNodeView; +class CSolveThread; + +class CHLSL_Var; +class CHLSL_SolverBase; + +struct GenericShaderData; + +#define SHOW_SEDIT_ERRORS ( DEBUG ) + +#define MAXTARGC 512 + +//void SetupVguiTex( int &var, const char *tex ); + +#define NODE_DRAW_SHADOW_DELTA 5 +#define NODE_DRAW_COLOR_SHADOW Color( 0, 0, 0, 50 ) + +#define DRAWCOLOR_ERRORLEVEL_UNDEFINED Color( 140, 140, 160, 255 ) +#define DRAWCOLOR_ERRORLEVEL_FAIL Color( 128, 0, 0, 255 ) + +#define DRAWCOLOR_BRIDGE_TMP_COL_ORANGE Color( 240, 160, 0, 255 ) +#define DRAWCOLOR_BRIDGE_TMP_COL_TRANS Color( 0, 0, 0, 196 ) + +#define TOKENCHANNELS_SUPPORTED_COLOR Color( 96, 96, 0, 128 ) + +#define JACK_COLOR_NORM Color( 15, 15, 15, 255 ) +#define JACK_COLOR_R Color( 200, 0, 0, 255 ) +#define JACK_COLOR_G Color( 0, 200, 0, 255 ) +#define JACK_COLOR_B Color( 0, 0, 200, 255 ) +#define JACK_COLOR_A Color( 200, 200, 200, 255 ) +#define JACK_COLOR_PPMASTER Color( 50, 180, 60, 255 ) + +#define JACK_COLOR_NAME Color( 210, 210, 220, 255 ) +#define JACK_COLOR_NAME_FOCUS Color( 160, 255, 160, 255 ) + +#define JACK_COLOR_FOCUS Color( 240, 200, 50, 255 ) + +#define JACK_COLOR_DATATYPE_UNDEFINED Color( 100, 100, 100, 255 ) +#define JACK_COLOR_DATATYPE Color( 160, 160, 160, 255 ) +#define JACK_COLOR_DATATYPE_DARK Color( 32, 32, 32, 255 ) + +#define JACK_TEXT_INSET 3 + +#define VIEWZOOM_OUT_MAX 8.0f +#define VIEWZOOM_IN_MAX 0.001f + +#define NODEVIEWHISTORY_MAXUNDO 21 + +#define PSIN_ERROR_WHEN_VSOUT_ERROR 0 + +#define ENABLE_HISTORY 1 +#define DO_SOLVING 1 + +#define ENABLE_AUTOCOMP_PARSER 1 + +#define MAKE_DEFAULT_CANVAS_EDITABLE 0 + +Color Lerp( const float &perc, const Color &a, const Color &b ); + +extern ConVar sedit_draw_datatypes; +extern ConVar sedit_draw_shadows; +extern ConVar sedit_draw_nodes; +extern ConVar sedit_draw_jacks; +extern ConVar sedit_draw_bridges; + +extern ConVar sedit_2dprev_Enable; +extern ConVar sedit_prev_HOMFun; +extern ConVar editor_movespeed; +extern ConVar editor_zoomspeed; +extern ConVar editor_pull_speed_mul; +extern ConVar editor_pull_speed_max; + +extern ConVar sedit_mesh_size; +extern ConVar sedit_mesh_subdiv; + +extern ConVar sedit_screenshot_zoom; +extern ConVar sedit_screenshot_quali; + +const char *GetCanvasVersion_KeyName(); +const char *GetCanvasVersion( int i ); +const char *GetCanvasVersion_Current(); +const int &GetCanvasVersion_Amt(); +void UpgradeFromVersion( KeyValues *pCanvas, const char *oldVer ); + +const char *GetDumpVersion_KeyName(); +const char *GetDumpVersion( int i ); +const char *GetDumpVersion_Current(); +const int &GetDumpVersion_Amt(); + +const char *GetEditorTitle(); + +enum HLSLNodeTypes +{ + HLSLNODE_INVALID = 0, + + HLSLNODE_VS_IN, + HLSLNODE_VS_OUT, + HLSLNODE_PS_IN, + HLSLNODE_PS_OUT, + + HLSLNODE_CONSTANT_LOCAL, + HLSLNODE_UNUSED_0, + + // sync with HLSLEnvironmentConstants !! + HLSLNODE_CONSTANT_VIEW_ORIGIN, + HLSLNODE_CONSTANT_VIEW_FORWARD, + HLSLNODE_CONSTANT_VIEW_RIGHT, + HLSLNODE_CONSTANT_VIEW_UP, + HLSLNODE_CONSTANT_VIEW_WORLDSPACE_DEPTH, + // till here + HLSLNODE_CONSTANT_TIME, + + HLSLNODE_MATRIX_MODELVIEWPROJ, + HLSLNODE_MATRIX_VIEWPROJ, + HLSLNODE_MATRIX_MODEL, + HLSLNODE_MATRIX_VIEWMODEL, + + HLSLNODE_MATH_ADD, + HLSLNODE_MATH_SUBTRACT, + HLSLNODE_MATH_MULTIPLY, + HLSLNODE_MATH_DIVIDE, + HLSLNODE_MATH_LERP, + HLSLNODE_MATH_FRAC, + + HLSLNODE_MATH_DOT, + HLSLNODE_MATH_LENGTH, + HLSLNODE_MATH_NORMALIZE, + HLSLNODE_MATH_APPEND, + HLSLNODE_MATH_SWIZZLE, + HLSLNODE_UNUSED_1, + + HLSLNODE_TEXTURE_SAMPLER, + + HLSLNODE_CONTROLFLOW_LOOP, + HLSLNODE_CONTROLFLOW_COMBO, + + HLSLNODE_UTILITY_DECLARE, + HLSLNODE_UTILITY_ASSIGN, + + HLSLNODE_MATH_SMOOTHSTEP, + HLSLNODE_MATH_STEP, + HLSLNODE_MATH_CLAMP, + HLSLNODE_MATH_MIN, + HLSLNODE_MATH_MAX, + HLSLNODE_MATH_SIN, + HLSLNODE_MATH_COS, + HLSLNODE_MATH_TAN, + HLSLNODE_MATH_ASIN, + HLSLNODE_MATH_ACOS, + HLSLNODE_MATH_ATAN, + HLSLNODE_MATH_SINH, + HLSLNODE_MATH_COSH, + HLSLNODE_MATH_TANH, + HLSLNODE_MATH_ATAN2, + + HLSLNODE_MATH_POW, + HLSLNODE_MATH_ROUND, + HLSLNODE_MATH_FLOOR, + HLSLNODE_MATH_CEIL, + HLSLNODE_MATH_ABS, + HLSLNODE_MATH_FMOD, + + HLSLNODE_TEXTURE_TRANSFORM, + + HLSLNODE_MATH_DEGREES, + HLSLNODE_MATH_RADIANS, + + HLSLNODE_VECTOR_REFLECT, + HLSLNODE_VECTOR_REFRACT, + + HLSLNODE_MATH_SATURATE, + HLSLNODE_MATH_INVERT, + HLSLNODE_MATH_SIGN, + HLSLNODE_MATH_SQRT, + + HLSLNODE_VECTOR_CROSS, + + HLSLNODE_CONSTANT_FB_PIXELSIZE, + + HLSLNODE_STUDIO_VERTEXLIGHTING, + HLSLNODE_STUDIO_PIXELSHADER_LIGHTING, + HLSLNODE_STUDIO_SKINNING, + HLSLNODE_STUDIO_MORPH, + + HLSLNODE_CONSTANT_FOGPARAMS, + HLSLNODE_UTILITY_FOG, + HLSLNODE_UTILITY_FINAL, + + HLSLNODE_MATRIX_COMPOSE, + + HLSLNODE_STUDIO_PIXELSHADER_SPECLIGHTING, + + HLSLNODE_MATRIX_FLASHLIGHT, + HLSLNODE_UTILITY_FLASHLIGHT, + + HLSLNODE_CONSTANT_CALLBACK, + HLSLNODE_CONSTANT_VP_MUTABLE, + HLSLNODE_CONSTANT_VP_STATIC, + HLSLNODE_CONSTANT_LIGHTSCALE, + HLSLNODE_CONSTANT_RANDOM, + + HLSLNODE_MATH_LOG, + HLSLNODE_MATH_LOG2, + HLSLNODE_MATH_LOG10, + + HLSLNODE_MATH_EXP, + HLSLNODE_MATH_EXP2, + + HLSLNODE_CONSTANT_BUMPBASIS, + + HLSLNODE_MATH_DDX, + HLSLNODE_MATH_DDY, + + HLSLNODE_MATRIX_CUSTOM, + + HLSLNODE_CONSTANT_ARRAY, + + HLSLNODE_CONTROLFLOW_CONDITION, + HLSLNODE_CONTROLFLOW_BREAK, + + HLSLNODE_TEXTURE_SAMPLEROBJECT, + + HLSLNODE_TEXTURE_PARALLAX, + HLSLNODE_TEXTURE_PARALLAX_SHADOW, + + HLSLNODE_CONSTANT_FLASHLIGHTPOS, + + HLSLNODE_CONTROLFLOW_CLIP, + + HLSLNODE_UTILITY_CUSTOMCODE, + + HLSLNODE_VECTOR_DISTANCE, + + HLSLNODE_STUDIO_VCOMPRESSION, + + + /// UNRELATED + HLSLNODE_OTHER_ = 1000, + HLSLNODE_OTHER_COMMENT, + + + /// POST PROCESSING + HLSLNODE_POSTPROCESSING_ = 2000, + HLSLNODE_POSTPROCESSING_INPUT, + HLSLNODE_POSTPROCESSING_OUTPUT, + + HLSLNODE_POSTPROCESSING_CLEAR_BUFFERS, + HLSLNODE_POSTPROCESSING_DRAW_MATERIAL, + HLSLNODE_POSTPROCESSING_UPDATE_FB, + + HLSLNODE_POSTPROCESSING_PUSH_VP, + HLSLNODE_POSTPROCESSING_POP_VP, + HLSLNODE_POSTPROCESSING_SET_RT, + + HLSLNODE_POSTPROCESSING_CREATE_RT, + HLSLNODE_POSTPROCESSING_CREATE_MAT, + HLSLNODE_POSTPROCESSING_COPY_RT, + + HLSLNODE_POSTPROCESSING_RENDER_VIEW, + + HLSLNODE_, +}; + +enum HLSLVariableTypes +{ + HLSLVAR_FLOAT1 = ( 1 << 0 ), + HLSLVAR_FLOAT2 = ( 1 << 1 ), + HLSLVAR_FLOAT3 = ( 1 << 2 ), + HLSLVAR_FLOAT4 = ( 1 << 3 ), + + HLSLVAR_MATRIX3X3 = ( 1 << 4 ), + HLSLVAR_MATRIX4X3 = ( 1 << 5 ), + HLSLVAR_MATRIX4X4 = ( 1 << 6 ), + + HLSLVAR_SAMPLER = ( 1 << 7 ), + + HLSLVAR_PP_MASTER = ( 1 << 16 ), + HLSLVAR_PP_MATERIAL = ( 1 << 17 ), + HLSLVAR_PP_RT = ( 1 << 18 ), + + HLSLVAR_COUNT = 19, + + // KEEP IN SYNC: + // NUM_CBOX_VARTYPES + // NUM_CBOX_VARTYPES_CFULL + // GetTypeFlagFromEnum + // VarTypeName +}; + +#define VSTOPS_NUM_TEXCOORDS 8 +#define VSTOPS_NUM_COLORS 2 + +#define NUM_CBOX_VARTYPES 7 +#define NUM_CBOX_VARTYPES_CFULL 8 + +enum HLSLJackVarCluster +{ + HLSLJACKFLAGS_F1, + HLSLJACKFLAGS_F2, + HLSLJACKFLAGS_F3, + HLSLJACKFLAGS_F4, + + HLSLJACKFLAGS_F1_TO_F4, + + HLSLJACKFLAGS_VECTOR, + HLSLJACKFLAGS_UV, + HLSLJACKFLAGS_MATRIX, + + HLSLJACKFLAGS_ALL, + HLSLJACKFLAGS_, +}; + +enum HLSLJackColorCode +{ + HLSLJACK_COLOR_NORM = 0, + HLSLJACK_COLOR_RGB, + HLSLJACK_COLOR_R, + HLSLJACK_COLOR_G, + HLSLJACK_COLOR_B, + HLSLJACK_COLOR_A, + HLSLJACK_COLOR_PPMASTER, +}; + +enum HLSLHierachyType +{ + HLSLHIERACHY_PENDING = -2, // for temp hierachy when sorting everthing + + HLSLHIERACHY_MULTIPLE = -1, + HLSLHIERACHY_NONE = 0, + HLSLHIERACHY_PS = ( 1 << 0 ), + HLSLHIERACHY_VS = ( 1 << 1 ), + //HLSLHIERACHY_TEMPLATE_PS = ( 1 << 2 ), + //HLSLHIERACHY_TEMPLATE_VS = ( 1 << 3 ), + HLSLHIERACHY_POST_PROCESS = ( 1 << 2 ), +}; + +enum NodeErrorLevel_t +{ + ERRORLEVEL_NONE = 0, + ERRORLEVEL_UNDEFINED, + ERRORLEVEL_FAIL, +}; + +enum RenderSystem_t +{ + RENDERMODE_SOFTWARE = 0, + RENDERMODE_SOFTWARE_POSTPROCESS, + RENDERMODE_HARDWARE, + RENDERMODE_HARDWARE_POSTPROCESS, + RENDERMODE_, +}; + +enum PreviewMode_t +{ + PVMODE_FINAL_COMBINED = 0, + PVMODE_PER_NODE_CACHED, +}; + +enum +{ + LSCALE_LINEAR = 0, + LSCALE_LIGHTMAP, + LSCALE_ENVMAP, + LSCALE_GAMMA, + LSCALE_LIGHTMAP_RGB, + + LSCALE_MAX = ( LSCALE_GAMMA + 1 ), +}; +enum +{ + ITERATORCOND_SMALLER = 0, + ITERATORCOND_GREATER, + ITERATORCOND_SEQUAL, + ITERATORCOND_GEQUAL, + ITERATORCOND_EQUAL, + + ITERATORCOND_, +}; + +struct customMatrix_t +{ + char *szdataTypeName; + char *szIdentifierName; + char *szCanvasName; + int iRegSize; + int iHLSLVarFlag; +}; +const customMatrix_t *GetCMatrixInfo( int ID ); + +const char *GetConditionCodeString( int idx ); +const char *GetCodeTonemapMacro( int idx ); +const char *GetLightscaleCodeString( int idx ); +const char *GetLightscaleGameString( int idx ); + +struct sampinfo_t +{ + const char *sz_visualName; + const char *sz_codeName; + int i_componentSize; + bool b_derivativeInput; + const char *sz_jackname; +}; +enum +{ + TEXSAMP_AUTO = 0, + + TEXSAMP_1D, + TEXSAMP_1D_DELTA, + TEXSAMP_1D_BIAS, + TEXSAMP_1D_GRAD, + TEXSAMP_1D_LOD, + TEXSAMP_1D_PROJ, + + TEXSAMP_2D, + TEXSAMP_2D_DELTA, + TEXSAMP_2D_BIAS, + TEXSAMP_2D_GRAD, + TEXSAMP_2D_LOD, + TEXSAMP_2D_PROJ, + + TEXSAMP_3D, + TEXSAMP_3D_DELTA, + TEXSAMP_3D_BIAS, + TEXSAMP_3D_GRAD, + TEXSAMP_3D_LOD, + TEXSAMP_3D_PROJ, + + TEXSAMP_CUBE, + TEXSAMP_CUBE_DELTA, + TEXSAMP_CUBE_BIAS, + TEXSAMP_CUBE_GRAD, + TEXSAMP_CUBE_LOD, + TEXSAMP_CUBE_PROJ, + + TEXSAMP_MAX, +}; + +const char *GetSamplerData_VisualName( const int &idx ); +const char *GetSamplerData_CodeName( const int &idx ); +const int GetSampleData_ComponentSize( const int &idx ); +const bool GetSamplerData_UseDerivative( const int &idx ); +const char *GetSamplerData_JackName( const int &idx ); + +struct DynRenderHelper +{ + Vector2D Orig; + float Size; + float Rotation; +}; + +extern void PaintDynamicRotationStructure(DynRenderHelper info); + +struct WriteContext_FXC; + +#include "../materialsystem/IVProcShader.h" +#include "../../game/client/ShaderEditor/ISEdit_ModelRender.h" +#include "interface/PPEHelper.h" + +float GaussianWeight_1D( const int &iSample_pos, const int &iKernel_size, const float &flBias = 0 ); +float GaussianWeight_2D( const int &iPos_X, const int &iPos_Y, const int &iSize_X, const int &iSize_Y, const float &flBias = 0 ); + +void CreateDirectoryStrings(); +void OverrideDirectories( const char *pszWorkingDirectory, const char *pszCompilePath, const char *pszLocalCompilePath, + const char *pszGamePath, const char *pszCanvas, const char *pszShaderSource, const char *pszDumps, + const char *pszUserFunctions, const char *pszEditorRoot ); +void CreateDirectories(); +void DestroyDirectoryStrings(); +void PreviewCleanup(); +#ifdef SHADER_EDITOR_DLL_SWARM +void InitSwarmShaders(); +#endif + +const char *GetWorkingDirectory(); +const char *GetAccountName(); +const char *GetGamePath(); +const char *GetBinaryPath(); +const char *GetBinaryPath_Local(); +const char *GetCanvasDirectory(); +const char *GetShaderSourceDirectory(); +const char *GetDumpDirectory(); +const char *GetUserFunctionDirectory(); +const char *GetEditorRootDirectory(); +#ifdef SHADER_EDITOR_DLL_SWARM +const char *GetSwarmShaderDirectory(); +#endif + +const bool IsInEditMode(); + +void ComposeShaderName( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride = false ); // fxc +void ComposeShaderPath( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride = false ); +void ComposeShaderName_Compiled( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride = false ); // vcs +void ComposeShaderPath_Compiled( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride = false ); +void ComposeShaderPath_CompiledEngine( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride = false ); + +struct __outputsetup; +void BuildUserFunctionName( const char *pFunctionName, const CUtlVector< __funcParamSetup* > &sharedOutputs, char *pszDest, int buflen ); +void BuildUserFunctionName( const char *pFunctionName, const CUtlVector< __funcParamSetup* > &input, const CUtlVector< __funcParamSetup* > &output, + char *pszDest, int buflen ); +void BuildDefaultFunctionName( char *pszDest, int buflen, CBaseNode *pNode ); + +const char *GetTextureTypeName( int idx ); +const char *GetVarTypeName( int num ); +const char *GetVarTypeNameCode( int num ); +const char *GetResourceTypeName( int num ); +const char *GetSemanticTypeName( int num ); +const char *GetSemanticType( int num ); + +int GetVarTypeRowsRequired( int num ); +int GetVarTypeFlag( int num ); +int GetVarFlagsVarValue( int flag ); +const char *GetVarCodeNameFromFlag( int flag ); +int GetVarFlagsRowsRequired( int flag ); + +extern inline void AutoCopyFloats( const void *src, void *dst, const int amt ); +extern inline void AutoCopyStringPtr( const char *src, char **dst ); + +//extern inline int GetChannelNumFromChar( const char *c ); +//extern inline char GetCharFromChannelNum( const int i ); + +extern inline int GetSlotsFromTypeFlag( int flag ); +extern inline int GetTypeFlagFromEnum( int i ); + +extern inline void UpdateSimpleObjectBounds( Vector2D &pos, Vector2D &size, Vector4D &bounds ); +extern inline bool ShouldSimpleDrawObject( vgui::Panel *parent, CNodeView *coordSystem, Vector4D &bounds ); + +extern inline void ClipToScreenBounds( int &_x, int &_y, int &_sx, int &_sy ); + +template +void SaveDeleteVector( CUtlVector &m_hItems ) +{ + CUtlVector< T > m_hTmp; + m_hTmp.AddVectorToTail( m_hItems ); + m_hItems.Purge(); + m_hTmp.PurgeAndDeleteElements(); +} +void DestroySolverStack( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ); +void DestroyVariablesInSolverStack( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ); + +void ListVariables( CUtlVector< CHLSL_SolverBase* > &m_hSolvers, CUtlVector< CHLSL_Var* > &m_hVars ); +void InitializeVariableNames( CUtlVector< CHLSL_SolverBase* > &m_hSolvers, WriteContext_FXC &context ); +void ResetVariables( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ); +void ClearVariableInfo( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ); +void ResetVariableIndices( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ); + +void ClearSolverInfo( CUtlVector< CHLSL_SolverBase* > &m_hSolvers ); + +void CopySolvers( const CUtlVector< CBaseNode* > &m_hSolvedNodes, + CUtlVector< CHLSL_SolverBase* > &m_hOutput ); +void CopySolvers( const CUtlVector< CHLSL_SolverBase* > &m_hInput, + CUtlVector< CHLSL_SolverBase* > &m_hOutput ); + +void ClearIdentifiers( GenericShaderData &data ); +void SetupForRendering( CUtlVector< CHLSL_SolverBase* > &hStack ); +void AllocateIdentifiers( IdentifierLists_t &Identifiers, CUtlVector< CHLSL_SolverBase* > &hStack ); +void UniquifyIdentifiers( bool bPS, IdentifierLists_t &Identifiers ); +void CalcNumDynamicCombos( IdentifierLists_t &Identifiers, bool bPreview ); + +int StringTabsWorth( const char *text ); +void CleanupString( const char *pSrc, char *pOut, int maxLength, bool AllowSpaces = false, bool AllowUnderscore = true, bool AllowNumbers = true, bool AllowNumberInFirstPlace = false ); + +const char *GetComboNameByID( const int &ID ); +const int GetComboIDByName( const char *name ); +void UpdateComboDataByString( SimpleCombo *pCombo, const char *szName, bool bTotalInit = true ); +void UpdateComboDataByID( SimpleCombo *pCombo, const int &ID, bool bTotalInit = true ); +SimpleCombo *AllocateComboDataByID( const int &ID ); +const bool IsComboAvailableInPreviewMode( SimpleCombo *c ); +void RemoveAllNonPreviewCombos( CUtlVector< SimpleCombo* >&list ); + +typedef unsigned int HCURSTACKIDX; + +#include "materialsystem/itexture.h" +void BuildFormatFlags( BasicShaderCfg_t &data, CUtlVector< CHLSL_SolverBase* > &hVertexshaderStack, CUtlVector< CHLSL_SolverBase* > &hPixelhaderStack ); +struct econstdata +{ + char *varname; + char *jackname; + int varflag; + char *nodename; + int nodetype; + void (*PreviewSolve)(float *_fl4); +}; +econstdata *EConstant_GetData( int i ); + + +ITexture *GetFBTex(); +ITexture *GetFBTexSmall(); +ITexture *GetPingPongRT( int num ); +ITexture *GetFBCopyTex(); +ITexture *GetSkymaskTex(); + +const bool IsSkymaskAvailable(); +const SEDIT_SKYMASK_MODE GetSkymaskMode(); + +void AllocRTs( int size ); +void AllocSkymask( SEDIT_SKYMASK_MODE iSkymaskMode ); +//void DeallocPingPongRTs(); +const int &GetRTSize(); +const int &GetRTPuzzleSize(); + +void ResetTileInfo(); +void CalcPuzzleSize( int numSolvers ); + +const int &GetCurrentPuzzleIndex(); +void OnPuzzleDrawn(); +void GetUVsForPuzzle( const int &num, Vector2D &min, Vector2D &max, bool bAddClamp = false ); +void GetCurPuzzleView( int &x, int &y, int &w, int &t ); + +void ReloadGameShaders( GenericShaderData *data, char **pszMaterialList = NULL, int iNumMaterials = 0 ); +void DoMaterialReload(); +void QuickRefreshEditorShader(); + +struct SETUP_HLSL_VS_Input +{ + SETUP_HLSL_VS_Input() + { + iTexcoords_num = 1; + iVertexcolor_num = 0; + bFlexDelta_enabled = false; + bNormal_enabled = false; + bTangentspace_enabled = false; + bBlendweights_enabled = false; + bNormal_enabled_compression = false; + bTangentspace_enabled_skinning = false; + for ( int i = 0; i < 3; i++ ) + iDataTypeFlag_TexCoords[i] = HLSLVAR_FLOAT2; + for ( int i = 0; i < 2; i++ ) + iDataTypeFlag_Color[i] = HLSLVAR_FLOAT4; + }; + int iTexcoords_num; + int iVertexcolor_num; + + bool bFlexDelta_enabled; + bool bNormal_enabled; + bool bTangentspace_enabled; + bool bBlendweights_enabled; + + bool bNormal_enabled_compression; + bool bTangentspace_enabled_skinning; + + int iDataTypeFlag_TexCoords[3]; + int iDataTypeFlag_Color[2]; +}; +struct SETUP_HLSL_VS_Output_PS_Input +{ + SETUP_HLSL_VS_Output_PS_Input() + { + iTexcoords_num = 1; + iVertexcolor_num = 0; + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + iTexCoordFlag[ i ] = HLSLVAR_FLOAT2; + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + iColorFlag[ i ] = HLSLVAR_FLOAT4; + }; + int iTexcoords_num; + int iVertexcolor_num; + + int iTexCoordFlag[ VSTOPS_NUM_TEXCOORDS ]; + int iColorFlag[ VSTOPS_NUM_COLORS ]; +}; +struct SETUP_VSOUTPSIN_CustomNames +{ + SETUP_VSOUTPSIN_CustomNames() + { + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + names_texcoords[i][0] = '\0'; + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + names_colors[i][0] = '\0'; + }; + + char names_texcoords[VSTOPS_NUM_TEXCOORDS][20]; + char names_colors[VSTOPS_NUM_COLORS][20]; +}; +struct SETUP_HLSL_PS_Output +{ + SETUP_HLSL_PS_Output() + { + iNumRTs = 1; + bDepth = false; + }; + int iNumRTs; + bool bDepth; +}; + + +/* +//// NOTES //// +// tangentspace +// tangent S uvdir: 0,0 - 1,0 +// tangent T uvdir: 0,1 - 0,0 // flipped +/////////////// +*/ +// per vertex +struct Solver_VS_Input +{ + //Solver_VS_Input(); + + float vecPos[3]; + float vecNormal[3]; + float vecTangentS[4]; + float vecTangentT[3]; + float vecFlexDelta[3]; + + float boneWeights[4]; + float boneIndices[4]; + + float texCoord_[3][2]; + float color_[2][4]; +}; +struct Solver_VSOut_PSIn +{ + //Solver_VSOut_PSIn(); + + // VS only + float vecProjPos[4]; + + float texCoord_[8][4]; + float color_[2][4]; +}; +struct Solver_PS_Output +{ + //Solver_PS_Output(); + + float color_[4][4]; + float depth; +}; +struct SolverResources +{ + SolverResources( int HierachyType ); + + const int GetHierachyType(); + bool IsVertexShader(); + + Solver_VSOut_PSIn vsout_psin; + union + { + Solver_VS_Input vs_in; + Solver_PS_Output ps_out; + }; + + VMatrix mx_Model; + VMatrix mx_View; + VMatrix mx_Proj; +private: + int m_iHierachyType; +}; + +struct Preview2DContext +{ +public: + Preview2DContext(); + + IMatRenderContext *pRenderContext; + + IMaterial *pMat_PsIn; + IMaterialVar *pMat_PsInOP; +}; + +struct GenericShaderData +{ +public: + GenericShaderData(); + ~GenericShaderData(); + GenericShaderData( const GenericShaderData &o ); + + // + char *name; + bool IsPreview(); + //bool bPreview; + HCURSTACKIDX iStackIdx; + + SETUP_HLSL_VS_Input VS_IN; + SETUP_HLSL_VS_Output_PS_Input VS_to_PS; + SETUP_HLSL_PS_Output PS_OUT; + // + + BasicShaderCfg_t *shader; + IdentifierLists_t *pUNDEF_Identifiers; +}; + +struct GenericPPEData +{ +public: + GenericPPEData(); + ~GenericPPEData(); + + bool bDoAutoUpdateFBCopy; +}; + +struct WriteContext_FXC +{ + WriteContext_FXC(); + + CUtlBufferEditor buf_combos; + CUtlBufferEditor buf_samplers; + CUtlBufferEditor buf_constants; + CUtlBufferEditor buf_arrays; + CUtlBufferEditor buf_functions_globals; + CUtlBufferEditor buf_functions_bodies; + CUtlBufferEditor buf_semantics_In; + CUtlBufferEditor buf_semantics_Out; + CUtlBufferEditor buf_code; + + bool bPreview; + + CUtlVector< CHLSL_SolverBase* > *m_hActive_Solvers; + IdentifierLists_t *m_pActive_Identifiers; + +private: + WriteContext_FXC( const WriteContext_FXC &o ); +}; + +struct RunCodeContext +{ +public: + RunCodeContext( bool bPreview = false, bool bScene = false ); + + IMatRenderContext *pRenderContext; + const bool &IsUsingPreview() const; + const bool &IsSceneMode() const; + +private: + bool bPreviewMode; + bool bSceneMode; +}; + +struct BridgeRestoreInfo +{ + BridgeRestoreInfo() + { + idx = -1; + resType = -1; + iMode = -1; + }; + CJack *pJackOther; + + int idx; + char jackSelfName[80]; + int resType; + + int iMode; +}; + +class ISolverRequester +{ +public: + + virtual void OnSolverUpdated( CNodeView *pCaller, GenericShaderData *pData, + bool VSReady, bool PSReady ) = 0; + virtual void OnSolverErrored() = 0; +}; + +enum FodPathContexts +{ + FODPC_VTF = 0, + FODPC_MDL, + FODPC_CANVAS, + FODPC_DUMPFILE, + FODPC_USERFUNCTION, + FODPC_VMT, + + FODPC_, +}; +const char *GetFODPathContext( int type ); + +struct LimitReport_t +{ + char *sz_name; // should always point to a string literal + int i_cur; + int i_max; +}; +enum +{ + LERROR_PS_SAMPLER, + LERROR_PS_CONSTS, + + LERROR_VS_SAMPLER, + LERROR_VS_CONSTS, + + LERROR_VMT_PARAMS_STATIC, + LERROR_VMT_PARAMS_MUTABLE, + + LERROR_GENERIC_DEMOTEXTURE_MISMTACH, + LERROR_, +}; +#define LERROR__FIRST LERROR_PS_SAMPLER +#define LERROR__LAST LERROR_VMT_PARAMS_MUTABLE + +const LimitReport_t &GetLimitReporterDefault( int i ); +bool ReportErrors( GenericShaderData *data, CUtlVector< LimitReport_t* > &hErrorList ); + +#define RT_NAME_MAX 64 + +struct RTDef +{ +public: + RTDef(); + RTDef( const char *pszName, + ImageFormat format, RenderTargetSizeMode_t sizemode, MaterialRenderTargetDepth_t depthmode, + int x, int y, unsigned int rtflags ); + ~RTDef(); + + bool IsValid(); + + void Allocate(); + void Deallocate(); + void Modify( const char *pszName = NULL, + ImageFormat *format = NULL, RenderTargetSizeMode_t *sizemode = NULL, MaterialRenderTargetDepth_t *depthmode = NULL, + int *x = NULL, int *y = NULL, unsigned int *rtflags = NULL ); + void Modify( RTDef &src ); + + bool IsDirty(); + void MakeDirty(); + bool IsFlaggedForDeletion(); + void FlagForDeletion(); + void Revalidate(); + + const char *GetName() const; + ImageFormat GetImgFormat(); + RenderTargetSizeMode_t GetSizeMode(); + MaterialRenderTargetDepth_t GetDepthMode(); + unsigned int GetFlags(); + int GetSizeX(); + int GetSizeY(); + +private: + //RTDef( const RTDef &o ); + + char szRTName[RT_NAME_MAX]; + ImageFormat Format; + MaterialRenderTargetDepth_t DepthMode; + RenderTargetSizeMode_t SizeMode; + unsigned int iRTFlags; + int x, y; + + bool bDirty; + bool bFlaggedForDeletion; + + ITexture *ref; +}; + +#include "tier1/smartptr.h" + +#define MAX_ZOOM_FONTS 85 + +#define CRUCIALNODE_MIN_SIZE_X 55 + +#define CRUCIALNODE_CANVAS_BASE_X 320 +#define CRUCIALNODE_CANVAS_BASE_Y 160 +#define CRUCIALNODE_CANVAS_OFFSET_Y 30 + +#define PREVIEW_SIZE_NODE 80 + +#define SHEET_SLIDER_THUMB_SIZE 12 + +typedef HNODE HAUTOSOLVER; + +void ForceDeleteMaterial( IMaterial **pMat ); +void ForceDeleteTexture( ITexture **pTex ); +IMaterialVar *FindMaterialVar( IMaterial *pMat, const char *varName ); +bool SetMaterialVar_String( IMaterial *pMat, const char *varName, const char *value ); +bool SetMaterialVar_Vec( IMaterial *pMat, const char *varName, const float a, const float b, const float c, const float d ); +bool SetMaterialVar_Vec( IMaterial *pMat, const char *varName, const float a, const float b, const float c ); +bool SetMaterialVar_Vec( IMaterial *pMat, const char *varName, const float a, const float b ); +bool SetMaterialVar_Vec( IMaterial *pMat, const char *varName, const float a ); +bool SetMaterialVar_Int( IMaterial *pMat, const char *varName, const int a ); + +void GeneralFramebufferUpdate( IMatRenderContext *pRenderContext ); +void UpdateScreenEffectTexture( ITexture *pTexture, int x, int y, int w, int h, bool bDestFullScreen = false, Rect_t *pActualRect = NULL ); + +#include "filesystem.h" +#include "utlbuffer.h" +#include "interface/EditorInit.h" +#include "gShaderDumps.h" +#include "gRendertargetConfig.h" +#include "gPostProcessingCache.h" +#include "cKVPacker.h" + +#include "vgui_controls/Controls.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + +#include "materialsystem/imaterial.h" +#include "materialsystem/imaterialvar.h" + +#include "cHLSL_Image.h" +#include "cHLSL_Mesh.h" +#include "cHLSL_Variable.h" +#include "solver/hlsl_solver.h" + +#include "vBridge.h" +#include "vJack.h" +#include "nodes/vBaseNode.h" + +#include "nodes/vBaseContainer.h" +#include "nodes/vNode_Matrices.h" +#include "nodes/vNode_Add.h" +#include "nodes/vNode_Subtract.h" +#include "nodes/vNode_Multiply.h" +#include "nodes/vNode_Divide.h" +#include "nodes/vNode_Cross.h" +#include "nodes/vNode_Swizzle.h" +#include "nodes/vNode_Dot.h" +#include "nodes/vNode_VecAppend.h" +#include "nodes/vNode_VectorRef.h" +#include "nodes/vNode_BaseEvaluate.h" +#include "nodes/vNode_Lerp.h" +#include "nodes/vNode_BaseRange.h" +#include "nodes/vNode_Constant.h" +#include "nodes/vNode_EnvC.h" +#include "nodes/vNode_Utility.h" +#include "nodes/vNode_MCompose.h" +#include "nodes/vNode_Callback.h" +#include "nodes/vNode_VmtParam.h" +#include "nodes/vNode_Array.h" +#include "nodes/vNode_Break.h" +#include "nodes/vNode_Custom.h" + +#include "nodes/vNode_TexSample.h" +#include "nodes/vNode_TexTransform.h" +#include "nodes/vNode_Sampler.h" +#include "nodes/vNode_Parallax.h" + +#include "nodes/vNode_Loop.h" +#include "nodes/vNode_Combo.h" +#include "nodes/vNode_Condition.h" + +#include "nodes/vNode_Std_VLight.h" +#include "nodes/vNode_Std_PLight.h" +#include "nodes/vNode_Std_Skinning.h" +#include "nodes/vNode_VCompression.h" + +#include "nodes/vNode_Fog.h" +#include "nodes/vNode_Final.h" +#include "nodes/vNode_Flashlight.h" +#include "nodes/vNode_Lightscale.h" + +#include "nodes/vNode_VsInput.h" +#include "nodes/vNode_VsOutput.h" +#include "nodes/vNode_PsInput.h" +#include "nodes/vNode_PsOutput.h" + + + +#include "nodes/postprocessing/vNode_PP_Base.h" +#include "nodes/postprocessing/vNode_PP_RT.h" +#include "nodes/postprocessing/vNode_PP_Mat.h" +#include "nodes/postprocessing/vNode_PP_Operations.h" +#include "nodes/postprocessing/vNode_PP_DrawMat.h" +#include "nodes/postprocessing/vNode_PP_RenderView.h" + + + +#include "nodes/vNode_Comment.h" + + + +#include "vBaseDiag.h" +#include "vDialogNew.h" +#include "vDialogConfig.h" +#include "vDialogPPEConfig.h" +#include "vDialogSPrecache.h" +#include "vDialogEditorConfig.h" +#include "vDialogRTList.h" +#include "vDialogPPEffectPrecache.h" +#include "vDialogRecompileAll.h" + +#include "vNodeViewError.h" +#include "vNodeView.h" +#include "vEditorFlowGraphPage.h" +#include "vEditorFlowGraphSheet.h" +#include "vEditorRoot.h" +#include "vRenderPanel.h" +#include "vPreview.h" + + + +enum +{ + TCMD_COMMON_NONE = 0, + TCMD_COMMON_EXIT, +}; + +struct __threadcmds_common +{ + __threadcmds_common(){}; + int _cmd; +}; +struct __threadcmds_CompileCommand +{ + __threadcmds_CompileCommand( HAUTOSOLVER Caller ) + { + __vs = NULL; + __ps = NULL; + __undef = NULL; + __data = NULL; + _Requester = Caller; + // bHaltOnError = false; + + AllocCheck_Alloc(); + }; + ~__threadcmds_CompileCommand() + { + delete __vs; + delete __ps; + delete __undef; + delete __data; + + AllocCheck_Free(); + }; + void *__vs; + void *__ps; + void *__undef; + + GenericShaderData *__data; + + HAUTOSOLVER _Requester; + + //bool bHaltOnError; +}; +struct __threadcmds_CompileCallback +{ + __threadcmds_CompileCallback( HAUTOSOLVER Target ) + { + _Target = Target; + _ExitCode = 0; + _data = NULL; + _activeFlags = 0; + + AllocCheck_Alloc(); + }; + + ~__threadcmds_CompileCallback() + { + delete _data; + + AllocCheck_Free(); + }; + + HAUTOSOLVER _Target; + int _ExitCode; + int _activeFlags; + + GenericShaderData *_data; +}; + +extern CEditorRoot *pEditorRoot; + +#include "threads/cSolverCallback.h" +//#include "custom/cSolveThread.h" +#include "threads/cBaseThread.h" +#include "threads/cCompileThread.h" +#include "threads/cThreadManager.h" + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/exported_utilities.cpp b/sp/src/shadereditor/exported_utilities.cpp new file mode 100644 index 00000000..2c605e88 --- /dev/null +++ b/sp/src/shadereditor/exported_utilities.cpp @@ -0,0 +1,1586 @@ + +#include "cbase.h" +#include "exported_utilities.h" + +#include "utlbuffer.h" +#include +#include +#include +#include +#include +#include "tier1/strtools.h" +#include "tier1/characterset.h" + +#if defined( _WIN32 ) || defined( WIN32 ) +#define PATHSEPARATOR(c) ((c) == '\\' || (c) == '/') +#else //_WIN32 +#define PATHSEPARATOR(c) ((c) == '/') +#endif //_WIN32 + +#ifdef SHADER_EDITOR_DLL_2006 + +IFileSystem *getdllFS() +{ + return filesystem; +} +void setdllFS(IFileSystem*fs) +{ + filesystem = fs; +} + +void GetMatricesForView( CViewSetup &setup, VMatrix &view, VMatrix &proj, VMatrix &viewproj ) +{ + Frustum f; + render->Push3DView( setup, 0, false, NULL, f ); + materials->GetMatrix( MATERIAL_VIEW, &view ); + materials->GetMatrix( MATERIAL_PROJECTION, &proj ); + MatrixMultiply( view, proj, viewproj ); + render->PopView(f); +} + +void InitLightDirectional( LightDesc_t &l, Vector dir, Vector color ) +{ + l.m_Type=MATERIAL_LIGHT_DIRECTIONAL; + l.m_Color=color; + l.m_Direction=dir; + l.m_Range=0.0; // infinite + l.m_Attenuation0=1.0; + l.m_Attenuation1=0; + l.m_Attenuation2=0; + l.RecalculateDerivedValues(); +} +#endif + +char *V_StripFirstDir (char *path) +{ + int len_max; + len_max = V_strlen( path )-1; + if ( len_max <= 0 ) + return NULL; + + int pos = 0; + + while ( pos <= len_max && + !PATHSEPARATOR( path[pos] ) ) + { + pos++; + } + + if ( PATHSEPARATOR( path[pos] ) && pos < len_max ) + pos++; + + //path[ pos ] = 0; + return &path[ pos ]; +} +void V_IsolateFirstDir (char *path) +{ + int lengthMax; + int pos = 0; + + lengthMax = V_strlen( path )-1; + if ( lengthMax <= 0 ) + return; + + while ( pos <= lengthMax && + !PATHSEPARATOR( path[pos] ) ) + { + pos++; + } + + path[ pos ] = 0; +} + + + + +CUtlBufferEditor::CUtlBufferEditor( int growSize, int initSize, int nFlags ) : + m_Memory( growSize, initSize ), m_Error(0) +{ + m_Get = 0; + m_Put = 0; + m_nTab = 0; + m_nOffset = 0; + m_Flags = nFlags; + if ( (initSize != 0) && !IsReadOnly() ) + { + m_nMaxPut = -1; + AddNullTermination(); + } + else + { + m_nMaxPut = 0; + } + SetOverflowFuncs( &CUtlBufferEditor::GetOverflow, &CUtlBufferEditor::PutOverflow ); +} + +CUtlBufferEditor::CUtlBufferEditor( const void *pBuffer, int nSize, int nFlags ) : + m_Memory( (unsigned char*)pBuffer, nSize ), m_Error(0) +{ +// Assert( nSize != 0 ); + + m_Get = 0; + m_Put = 0; + m_nTab = 0; + m_nOffset = 0; + m_Flags = nFlags; + if ( IsReadOnly() ) + { + m_nMaxPut = nSize; + } + else + { + m_nMaxPut = -1; + AddNullTermination(); + } + SetOverflowFuncs( &CUtlBufferEditor::GetOverflow, &CUtlBufferEditor::PutOverflow ); +} + + +//----------------------------------------------------------------------------- +// Modifies the buffer to be binary or text; Blows away the buffer and the CONTAINS_CRLF value. +//----------------------------------------------------------------------------- +void CUtlBufferEditor::SetBufferType( bool bIsText, bool bContainsCRLF ) +{ +#ifdef _DEBUG + // If the buffer is empty, there is no opportunity for this stuff to fail + if ( TellMaxPut() != 0 ) + { + if ( IsText() ) + { + if ( bIsText ) + { + Assert( ContainsCRLF() == bContainsCRLF ); + } + else + { + Assert( ContainsCRLF() ); + } + } + else + { + if ( bIsText ) + { + Assert( bContainsCRLF ); + } + } + } +#endif + + if ( bIsText ) + { + m_Flags |= TEXT_BUFFER; + } + else + { + m_Flags &= ~TEXT_BUFFER; + } + if ( bContainsCRLF ) + { + m_Flags |= CONTAINS_CRLF; + } + else + { + m_Flags &= ~CONTAINS_CRLF; + } +} + + +//----------------------------------------------------------------------------- +// Attaches the buffer to external memory.... +//----------------------------------------------------------------------------- +void CUtlBufferEditor::SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags ) +{ + m_Memory.SetExternalBuffer( (unsigned char*)pMemory, nSize ); + + // Reset all indices; we just changed memory + m_Get = 0; + m_Put = nInitialPut; + m_nTab = 0; + m_Error = 0; + m_nOffset = 0; + m_Flags = nFlags; + m_nMaxPut = -1; + AddNullTermination(); +} + +//----------------------------------------------------------------------------- +// Assumes an external buffer but manages its deletion +//----------------------------------------------------------------------------- +void CUtlBufferEditor::AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags ) +{ +#ifdef SHADER_EDITOR_DLL_2006 + Assert(0); +#else + m_Memory.AssumeMemory( (unsigned char*) pMemory, nSize ); +#endif + + // Reset all indices; we just changed memory + m_Get = 0; + m_Put = nInitialPut; + m_nTab = 0; + m_Error = 0; + m_nOffset = 0; + m_Flags = nFlags; + m_nMaxPut = -1; + AddNullTermination(); +} + +//----------------------------------------------------------------------------- +// Makes sure we've got at least this much memory +//----------------------------------------------------------------------------- +void CUtlBufferEditor::EnsureCapacity( int num ) +{ + // Add one extra for the null termination + num += 1; + if ( m_Memory.IsExternallyAllocated() ) + { + if ( IsGrowable() && ( m_Memory.NumAllocated() < num ) ) + { + m_Memory.ConvertToGrowableMemory( 0 ); + } + else + { + num -= 1; + } + } + + m_Memory.EnsureCapacity( num ); +} + + +//----------------------------------------------------------------------------- +// Base get method from which all others derive +//----------------------------------------------------------------------------- +void CUtlBufferEditor::Get( void* pMem, int size ) +{ + if ( CheckGet( size ) ) + { + memcpy( pMem, &m_Memory[m_Get - m_nOffset], size ); + m_Get += size; + } +} + + +//----------------------------------------------------------------------------- +// This will get at least 1 byte and up to nSize bytes. +// It will return the number of bytes actually read. +//----------------------------------------------------------------------------- +int CUtlBufferEditor::GetUpTo( void *pMem, int nSize ) +{ + if ( CheckArbitraryPeekGet( 0, nSize ) ) + { + memcpy( pMem, &m_Memory[m_Get - m_nOffset], nSize ); + m_Get += nSize; + return nSize; + } + return 0; +} + + +//----------------------------------------------------------------------------- +// Eats whitespace +//----------------------------------------------------------------------------- +void CUtlBufferEditor::EatWhiteSpace() +{ + if ( IsText() && IsValid() ) + { + while ( CheckGet( sizeof(char) ) ) + { + if ( !isspace( *(const unsigned char*)PeekGet() ) ) + break; + m_Get += sizeof(char); + } + } +} + + +//----------------------------------------------------------------------------- +// Eats C++ style comments +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::EatCPPComment() +{ + if ( IsText() && IsValid() ) + { + // If we don't have a a c++ style comment next, we're done + const char *pPeek = (const char *)PeekGet( 2 * sizeof(char), 0 ); + if ( !pPeek || ( pPeek[0] != '/' ) || ( pPeek[1] != '/' ) ) + return false; + + // Deal with c++ style comments + m_Get += 2; + + // read complete line + for ( char c = GetChar(); IsValid(); c = GetChar() ) + { + if ( c == '\n' ) + break; + } + return true; + } + return false; +} + + +//----------------------------------------------------------------------------- +// Peeks how much whitespace to eat +//----------------------------------------------------------------------------- +int CUtlBufferEditor::PeekWhiteSpace( int nOffset ) +{ + if ( !IsText() || !IsValid() ) + return 0; + + while ( CheckPeekGet( nOffset, sizeof(char) ) ) + { + if ( !isspace( *(unsigned char*)PeekGet( nOffset ) ) ) + break; + nOffset += sizeof(char); + } + + return nOffset; +} + + +//----------------------------------------------------------------------------- +// Peek size of sting to come, check memory bound +//----------------------------------------------------------------------------- +int CUtlBufferEditor::PeekStringLength() +{ + if ( !IsValid() ) + return 0; + + // Eat preceeding whitespace + int nOffset = 0; + if ( IsText() ) + { + nOffset = PeekWhiteSpace( nOffset ); + } + + int nStartingOffset = nOffset; + + do + { + int nPeekAmount = 128; + + // NOTE: Add 1 for the terminating zero! + if ( !CheckArbitraryPeekGet( nOffset, nPeekAmount ) ) + { + if ( nOffset == nStartingOffset ) + return 0; + return nOffset - nStartingOffset + 1; + } + + const char *pTest = (const char *)PeekGet( nOffset ); + + if ( !IsText() ) + { + for ( int i = 0; i < nPeekAmount; ++i ) + { + // The +1 here is so we eat the terminating 0 + if ( pTest[i] == 0 ) + return (i + nOffset - nStartingOffset + 1); + } + } + else + { + for ( int i = 0; i < nPeekAmount; ++i ) + { + // The +1 here is so we eat the terminating 0 + if ( isspace((unsigned char)pTest[i]) || (pTest[i] == 0) ) + return (i + nOffset - nStartingOffset + 1); + } + } + + nOffset += nPeekAmount; + + } while ( true ); +} + + +//----------------------------------------------------------------------------- +// Peek size of line to come, check memory bound +//----------------------------------------------------------------------------- +int CUtlBufferEditor::PeekLineLength() +{ + if ( !IsValid() ) + return 0; + + int nOffset = 0; + int nStartingOffset = nOffset; + + do + { + int nPeekAmount = 128; + + // NOTE: Add 1 for the terminating zero! + if ( !CheckArbitraryPeekGet( nOffset, nPeekAmount ) ) + { + if ( nOffset == nStartingOffset ) + return 0; + return nOffset - nStartingOffset + 1; + } + + const char *pTest = (const char *)PeekGet( nOffset ); + + for ( int i = 0; i < nPeekAmount; ++i ) + { + // The +2 here is so we eat the terminating '\n' and 0 + if ( pTest[i] == '\n' || pTest[i] == '\r' ) + return (i + nOffset - nStartingOffset + 2); + // The +1 here is so we eat the terminating 0 + if ( pTest[i] == 0 ) + return (i + nOffset - nStartingOffset + 1); + } + + nOffset += nPeekAmount; + + } while ( true ); +} + + +//----------------------------------------------------------------------------- +// Does the next bytes of the buffer match a pattern? +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::PeekStringMatch( int nOffset, const char *pString, int nLen ) +{ + if ( !CheckPeekGet( nOffset, nLen ) ) + return false; + return !Q_strncmp( (const char*)PeekGet(nOffset), pString, nLen ); +} + + +//----------------------------------------------------------------------------- +// This version of PeekStringLength converts \" to \\ and " to \, etc. +// It also reads a " at the beginning and end of the string +//----------------------------------------------------------------------------- +int CUtlBufferEditor::PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize ) +{ + if ( !IsText() || !pConv ) + return PeekStringLength(); + + // Eat preceeding whitespace + int nOffset = 0; + if ( IsText() ) + { + nOffset = PeekWhiteSpace( nOffset ); + } + + if ( !PeekStringMatch( nOffset, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) ) + return 0; + + // Try to read ending ", but don't accept \" + int nActualStart = nOffset; + nOffset += pConv->GetDelimiterLength(); + int nLen = 1; // Starts at 1 for the '\0' termination + + do + { + if ( PeekStringMatch( nOffset, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) ) + break; + + if ( !CheckPeekGet( nOffset, 1 ) ) + break; + + char c = *(const char*)PeekGet( nOffset ); + ++nLen; + ++nOffset; + if ( c == pConv->GetEscapeChar() ) + { + int nLength = pConv->MaxConversionLength(); + if ( !CheckArbitraryPeekGet( nOffset, nLength ) ) + break; + + pConv->FindConversion( (const char*)PeekGet(nOffset), &nLength ); + nOffset += nLength; + } + } while (true); + + return bActualSize ? nLen : nOffset - nActualStart + pConv->GetDelimiterLength() + 1; +} + + +//----------------------------------------------------------------------------- +// Reads a null-terminated string +//----------------------------------------------------------------------------- +void CUtlBufferEditor::GetString( char* pString, int nMaxChars ) +{ + if (!IsValid()) + { + *pString = 0; + return; + } + + if ( nMaxChars == 0 ) + { + nMaxChars = INT_MAX; + } + + // Remember, this *includes* the null character + // It will be 0, however, if the buffer is empty. + int nLen = PeekStringLength(); + + if ( IsText() ) + { + EatWhiteSpace(); + } + + if ( nLen == 0 ) + { + *pString = 0; + m_Error |= GET_OVERFLOW; + return; + } + + // Strip off the terminating NULL + if ( nLen <= nMaxChars ) + { + Get( pString, nLen - 1 ); + pString[ nLen - 1 ] = 0; + } + else + { + Get( pString, nMaxChars - 1 ); + pString[ nMaxChars - 1 ] = 0; + SeekGet( SEEK_CURRENT, nLen - 1 - nMaxChars ); + } + + // Read the terminating NULL in binary formats + if ( !IsText() ) + { + VerifyEquals( GetChar(), 0 ); + } +} + + +//----------------------------------------------------------------------------- +// Reads up to and including the first \n +//----------------------------------------------------------------------------- +void CUtlBufferEditor::GetLine( char* pLine, int nMaxChars ) +{ + Assert( IsText() && !ContainsCRLF() ); + + if ( !IsValid() ) + { + *pLine = 0; + return; + } + + if ( nMaxChars == 0 ) + { + nMaxChars = INT_MAX; + } + + // Remember, this *includes* the null character + // It will be 0, however, if the buffer is empty. + int nLen = PeekLineLength(); + if ( nLen == 0 ) + { + *pLine = 0; + m_Error |= GET_OVERFLOW; + return; + } + + // Strip off the terminating NULL + if ( nLen <= nMaxChars ) + { + Get( pLine, nLen - 1 ); + pLine[ nLen - 1 ] = 0; + } + else + { + Get( pLine, nMaxChars - 1 ); + pLine[ nMaxChars - 1 ] = 0; + SeekGet( SEEK_CURRENT, nLen - 1 - nMaxChars ); + } +} + + +//----------------------------------------------------------------------------- +// This version of GetString converts \ to \\ and " to \", etc. +// It also places " at the beginning and end of the string +//----------------------------------------------------------------------------- +char CUtlBufferEditor::GetDelimitedCharInternal( CUtlCharConversion *pConv ) +{ + char c = GetChar(); + if ( c == pConv->GetEscapeChar() ) + { + int nLength = pConv->MaxConversionLength(); + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + return '\0'; + + c = pConv->FindConversion( (const char *)PeekGet(), &nLength ); + SeekGet( SEEK_CURRENT, nLength ); + } + + return c; +} + +char CUtlBufferEditor::GetDelimitedChar( CUtlCharConversion *pConv ) +{ + if ( !IsText() || !pConv ) + return GetChar( ); + return GetDelimitedCharInternal( pConv ); +} + +void CUtlBufferEditor::GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars ) +{ + if ( !IsText() || !pConv ) + { + GetString( pString, nMaxChars ); + return; + } + + if (!IsValid()) + { + *pString = 0; + return; + } + + if ( nMaxChars == 0 ) + { + nMaxChars = INT_MAX; + } + + EatWhiteSpace(); + if ( !PeekStringMatch( 0, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) ) + return; + + // Pull off the starting delimiter + SeekGet( SEEK_CURRENT, pConv->GetDelimiterLength() ); + + int nRead = 0; + while ( IsValid() ) + { + if ( PeekStringMatch( 0, pConv->GetDelimiter(), pConv->GetDelimiterLength() ) ) + { + SeekGet( SEEK_CURRENT, pConv->GetDelimiterLength() ); + break; + } + + char c = GetDelimitedCharInternal( pConv ); + + if ( nRead < nMaxChars ) + { + pString[nRead] = c; + ++nRead; + } + } + + if ( nRead >= nMaxChars ) + { + nRead = nMaxChars - 1; + } + pString[nRead] = '\0'; +} + + +//----------------------------------------------------------------------------- +// Checks if a get is ok +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::CheckGet( int nSize ) +{ + if ( m_Error & GET_OVERFLOW ) + return false; + + if ( TellMaxPut() < m_Get + nSize ) + { + m_Error |= GET_OVERFLOW; + return false; + } + + if ( ( m_Get < m_nOffset ) || ( m_Memory.NumAllocated() < m_Get - m_nOffset + nSize ) ) + { + if ( !OnGetOverflow( nSize ) ) + { + m_Error |= GET_OVERFLOW; + return false; + } + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Checks if a peek get is ok +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::CheckPeekGet( int nOffset, int nSize ) +{ + if ( m_Error & GET_OVERFLOW ) + return false; + + // Checking for peek can't set the overflow flag + bool bOk = CheckGet( nOffset + nSize ); + m_Error &= ~GET_OVERFLOW; + return bOk; +} + + +//----------------------------------------------------------------------------- +// Call this to peek arbitrarily long into memory. It doesn't fail unless +// it can't read *anything* new +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::CheckArbitraryPeekGet( int nOffset, int &nIncrement ) +{ + if ( TellGet() + nOffset >= TellMaxPut() ) + { + nIncrement = 0; + return false; + } + + if ( TellGet() + nOffset + nIncrement > TellMaxPut() ) + { + nIncrement = TellMaxPut() - TellGet() - nOffset; + } + + // NOTE: CheckPeekGet could modify TellMaxPut for streaming files + // We have to call TellMaxPut again here + CheckPeekGet( nOffset, nIncrement ); + int nMaxGet = TellMaxPut() - TellGet(); + if ( nMaxGet < nIncrement ) + { + nIncrement = nMaxGet; + } + return (nIncrement != 0); +} + + +//----------------------------------------------------------------------------- +// Peek part of the butt +//----------------------------------------------------------------------------- +const void* CUtlBufferEditor::PeekGet( int nMaxSize, int nOffset ) +{ + if ( !CheckPeekGet( nOffset, nMaxSize ) ) + return NULL; + return &m_Memory[ m_Get + nOffset - m_nOffset ]; +} + + +//----------------------------------------------------------------------------- +// Change where I'm reading +//----------------------------------------------------------------------------- +void CUtlBufferEditor::SeekGet( SeekType_t type, int offset ) +{ + switch( type ) + { + case SEEK_HEAD: + m_Get = offset; + break; + + case SEEK_CURRENT: + m_Get += offset; + break; + + case SEEK_TAIL: + m_Get = m_nMaxPut - offset; + break; + } + + if ( m_Get > m_nMaxPut ) + { + m_Error |= GET_OVERFLOW; + } + else + { + m_Error &= ~GET_OVERFLOW; + if ( m_Get < m_nOffset || m_Get >= m_nOffset + Size() ) + { + OnGetOverflow( -1 ); + } + } +} + + +//----------------------------------------------------------------------------- +// Parse... +//----------------------------------------------------------------------------- + +#pragma warning ( disable : 4706 ) + +int CUtlBufferEditor::VaScanf( const char* pFmt, va_list list ) +{ + Assert( pFmt ); + if ( m_Error || !IsText() ) + return 0; + + int numScanned = 0; + int nLength; + char c; + char* pEnd; + while ( c = *pFmt++ ) + { + // Stop if we hit the end of the buffer + if ( m_Get >= TellMaxPut() ) + { + m_Error |= GET_OVERFLOW; + break; + } + + switch (c) + { + case ' ': + // eat all whitespace + EatWhiteSpace(); + break; + + case '%': + { + // Conversion character... try to convert baby! + char type = *pFmt++; + if (type == 0) + return numScanned; + + switch(type) + { + case 'c': + { + char* ch = va_arg( list, char * ); + if ( CheckPeekGet( 0, sizeof(char) ) ) + { + *ch = *(const char*)PeekGet(); + ++m_Get; + } + else + { + *ch = 0; + return numScanned; + } + } + break; + + case 'i': + case 'd': + { + int* i = va_arg( list, int * ); + + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + *i = 0; + return numScanned; + } + + *i = strtol( (char*)PeekGet(), &pEnd, 10 ); + int nBytesRead = (int)( pEnd - (char*)PeekGet() ); + if ( nBytesRead == 0 ) + return numScanned; + m_Get += nBytesRead; + } + break; + + case 'x': + { + int* i = va_arg( list, int * ); + + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + *i = 0; + return numScanned; + } + + *i = strtol( (char*)PeekGet(), &pEnd, 16 ); + int nBytesRead = (int)( pEnd - (char*)PeekGet() ); + if ( nBytesRead == 0 ) + return numScanned; + m_Get += nBytesRead; + } + break; + + case 'u': + { + unsigned int* u = va_arg( list, unsigned int *); + + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + *u = 0; + return numScanned; + } + + *u = strtoul( (char*)PeekGet(), &pEnd, 10 ); + int nBytesRead = (int)( pEnd - (char*)PeekGet() ); + if ( nBytesRead == 0 ) + return numScanned; + m_Get += nBytesRead; + } + break; + + case 'f': + { + float* f = va_arg( list, float *); + + // NOTE: This is not bullet-proof; it assumes numbers are < 128 characters + nLength = 128; + if ( !CheckArbitraryPeekGet( 0, nLength ) ) + { + *f = 0.0f; + return numScanned; + } + + *f = (float)strtod( (char*)PeekGet(), &pEnd ); + int nBytesRead = (int)( pEnd - (char*)PeekGet() ); + if ( nBytesRead == 0 ) + return numScanned; + m_Get += nBytesRead; + } + break; + + case 's': + { + char* s = va_arg( list, char * ); + GetString( s ); + } + break; + + default: + { + // unimplemented scanf type + Assert(0); + return numScanned; + } + break; + } + + ++numScanned; + } + break; + + default: + { + // Here we have to match the format string character + // against what's in the buffer or we're done. + if ( !CheckPeekGet( 0, sizeof(char) ) ) + return numScanned; + + if ( c != *(const char*)PeekGet() ) + return numScanned; + + ++m_Get; + } + } + } + return numScanned; +} + +#pragma warning ( default : 4706 ) + +int CUtlBufferEditor::Scanf( const char* pFmt, ... ) +{ + va_list args; + + va_start( args, pFmt ); + int count = VaScanf( pFmt, args ); + va_end( args ); + + return count; +} + + +//----------------------------------------------------------------------------- +// Advance the get index until after the particular string is found +// Do not eat whitespace before starting. Return false if it failed +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::GetToken( const char *pToken ) +{ + Assert( pToken ); + + // Look for the token + int nLen = Q_strlen( pToken ); + + int nSizeToCheck = Size() - TellGet() - m_nOffset; + + int nGet = TellGet(); + do + { + int nMaxSize = TellMaxPut() - TellGet(); + if ( nMaxSize < nSizeToCheck ) + { + nSizeToCheck = nMaxSize; + } + if ( nLen > nSizeToCheck ) + break; + + if ( !CheckPeekGet( 0, nSizeToCheck ) ) + break; + + const char *pBufStart = (const char*)PeekGet(); + const char *pFoundEnd = Q_strnistr( pBufStart, pToken, nSizeToCheck ); + if ( pFoundEnd ) + { + size_t nOffset = (size_t)pFoundEnd - (size_t)pBufStart; + SeekGet( CUtlBufferEditor::SEEK_CURRENT, nOffset + nLen ); + return true; + } + + SeekGet( CUtlBufferEditor::SEEK_CURRENT, nSizeToCheck - nLen - 1 ); + nSizeToCheck = Size() - (nLen-1); + + } while ( true ); + + SeekGet( CUtlBufferEditor::SEEK_HEAD, nGet ); + return false; +} + + +//----------------------------------------------------------------------------- +// (For text buffers only) +// Parse a token from the buffer: +// Grab all text that lies between a starting delimiter + ending delimiter +// (skipping whitespace that leads + trails both delimiters). +// Note the delimiter checks are case-insensitive. +// If successful, the get index is advanced and the function returns true, +// otherwise the index is not advanced and the function returns false. +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen ) +{ + int nCharsToCopy = 0; + int nCurrentGet = 0; + + size_t nEndingDelimLen; + + // Starting delimiter is optional + char emptyBuf = '\0'; + if ( !pStartingDelim ) + { + pStartingDelim = &emptyBuf; + } + + // Ending delimiter is not + Assert( pEndingDelim && pEndingDelim[0] ); + nEndingDelimLen = Q_strlen( pEndingDelim ); + + int nStartGet = TellGet(); + char nCurrChar; + int nTokenStart = -1; + EatWhiteSpace( ); + while ( *pStartingDelim ) + { + nCurrChar = *pStartingDelim++; + if ( !isspace((unsigned char)nCurrChar) ) + { + if ( tolower( GetChar() ) != tolower( nCurrChar ) ) + goto parseFailed; + } + else + { + EatWhiteSpace(); + } + } + + EatWhiteSpace(); + nTokenStart = TellGet(); + if ( !GetToken( pEndingDelim ) ) + goto parseFailed; + + nCurrentGet = TellGet(); + nCharsToCopy = (nCurrentGet - nEndingDelimLen) - nTokenStart; + if ( nCharsToCopy >= nMaxLen ) + { + nCharsToCopy = nMaxLen - 1; + } + + if ( nCharsToCopy > 0 ) + { + SeekGet( CUtlBufferEditor::SEEK_HEAD, nTokenStart ); + Get( pString, nCharsToCopy ); + if ( !IsValid() ) + goto parseFailed; + + // Eat trailing whitespace + for ( ; nCharsToCopy > 0; --nCharsToCopy ) + { + if ( !isspace( (unsigned char)pString[ nCharsToCopy-1 ] ) ) + break; + } + } + pString[ nCharsToCopy ] = '\0'; + + // Advance the Get index + SeekGet( CUtlBufferEditor::SEEK_HEAD, nCurrentGet ); + return true; + +parseFailed: + // Revert the get index + SeekGet( SEEK_HEAD, nStartGet ); + pString[0] = '\0'; + return false; +} + + +//----------------------------------------------------------------------------- +// Parses the next token, given a set of character breaks to stop at +//----------------------------------------------------------------------------- +int CUtlBufferEditor::ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments ) +{ + Assert( nMaxLen > 0 ); + pTokenBuf[0] = 0; + + // skip whitespace + comments + while ( true ) + { + if ( !IsValid() ) + return -1; + EatWhiteSpace(); + if ( bParseComments ) + { + if ( !EatCPPComment() ) + break; + } + else + { + break; + } + } + + char c = GetChar(); + + // End of buffer + if ( c == 0 ) + return -1; + + // handle quoted strings specially + if ( c == '\"' ) + { + int nLen = 0; + while( IsValid() ) + { + c = GetChar(); + if ( c == '\"' || !c ) + { + pTokenBuf[nLen] = 0; + return nLen; + } + pTokenBuf[nLen] = c; + if ( ++nLen == nMaxLen ) + { + pTokenBuf[nLen-1] = 0; + return nMaxLen; + } + } + + // In this case, we hit the end of the buffer before hitting the end qoute + pTokenBuf[nLen] = 0; + return nLen; + } + + // parse single characters + if ( IN_CHARACTERSET( *pBreaks, c ) ) + { + pTokenBuf[0] = c; + pTokenBuf[1] = 0; + return 1; + } + + // parse a regular word + int nLen = 0; + while ( true ) + { + pTokenBuf[nLen] = c; + if ( ++nLen == nMaxLen ) + { + pTokenBuf[nLen-1] = 0; + return nMaxLen; + } + c = GetChar(); + if ( !IsValid() ) + break; + + if ( IN_CHARACTERSET( *pBreaks, c ) || c == '\"' || c <= ' ' ) + { + SeekGet( SEEK_CURRENT, -1 ); + break; + } + } + + pTokenBuf[nLen] = 0; + return nLen; +} + + + +//----------------------------------------------------------------------------- +// Serialization +//----------------------------------------------------------------------------- +void CUtlBufferEditor::Put( const void *pMem, int size ) +{ + if ( size && CheckPut( size ) ) + { + memcpy( &m_Memory[m_Put - m_nOffset], pMem, size ); + m_Put += size; + + AddNullTermination(); + } +} + + +//----------------------------------------------------------------------------- +// Writes a null-terminated string +//----------------------------------------------------------------------------- +void CUtlBufferEditor::PutString( const char* pString ) +{ + if (!IsText()) + { + if ( pString ) + { + // Not text? append a null at the end. + size_t nLen = Q_strlen( pString ) + 1; + Put( pString, nLen * sizeof(char) ); + return; + } + else + { + PutTypeBin( 0 ); + } + } + else if (pString) + { + int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab; + if ( nTabCount > 0 ) + { + if ( WasLastCharacterCR() ) + { + if ( !IsDirectiveLine( pString ) ) + PutTabs(); + } + + const char* pEndl = strchr( pString, '\n' ); + while ( pEndl ) + { + size_t nSize = (size_t)pEndl - (size_t)pString + sizeof(char); + Put( pString, nSize ); + pString = pEndl + 1; + if ( *pString ) + { + if ( !IsDirectiveLine( pString ) ) + PutTabs(); + pEndl = strchr( pString, '\n' ); + } + else + { + pEndl = NULL; + } + } + } + size_t nLen = Q_strlen( pString ); + if ( nLen ) + { + Put( pString, nLen * sizeof(char) ); + } + } +} + + +//----------------------------------------------------------------------------- +// This version of PutString converts \ to \\ and " to \", etc. +// It also places " at the beginning and end of the string +//----------------------------------------------------------------------------- +inline void CUtlBufferEditor::PutDelimitedCharInternal( CUtlCharConversion *pConv, char c ) +{ + int l = pConv->GetConversionLength( c ); + if ( l == 0 ) + { + PutChar( c ); + } + else + { + PutChar( pConv->GetEscapeChar() ); + Put( pConv->GetConversionString( c ), l ); + } +} + +void CUtlBufferEditor::PutDelimitedChar( CUtlCharConversion *pConv, char c ) +{ + if ( !IsText() || !pConv ) + { + PutChar( c ); + return; + } + + PutDelimitedCharInternal( pConv, c ); +} + +void CUtlBufferEditor::PutDelimitedString( CUtlCharConversion *pConv, const char *pString ) +{ + if ( !IsText() || !pConv ) + { + PutString( pString ); + return; + } + + if ( WasLastCharacterCR() ) + { + PutTabs(); + } + Put( pConv->GetDelimiter(), pConv->GetDelimiterLength() ); + + int nLen = pString ? Q_strlen( pString ) : 0; + for ( int i = 0; i < nLen; ++i ) + { + PutDelimitedCharInternal( pConv, pString[i] ); + } + + if ( WasLastCharacterCR() ) + { + PutTabs(); + } + Put( pConv->GetDelimiter(), pConv->GetDelimiterLength() ); +} + + +void CUtlBufferEditor::VaPrintf( const char* pFmt, va_list list ) +{ + char temp[2048]; +#ifdef _DEBUG + int nLen = +#endif + Q_vsnprintf( temp, sizeof( temp ), pFmt, list ); + Assert( nLen < 2048 ); + PutString( temp ); +} + +void CUtlBufferEditor::Printf( const char* pFmt, ... ) +{ + va_list args; + + va_start( args, pFmt ); + VaPrintf( pFmt, args ); + va_end( args ); +} + + +//----------------------------------------------------------------------------- +// Calls the overflow functions +//----------------------------------------------------------------------------- +void CUtlBufferEditor::SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc ) +{ + m_GetOverflowFunc = getFunc; + m_PutOverflowFunc = putFunc; +} + + +//----------------------------------------------------------------------------- +// Calls the overflow functions +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::OnPutOverflow( int nSize ) +{ + return (this->*m_PutOverflowFunc)( nSize ); +} + +bool CUtlBufferEditor::OnGetOverflow( int nSize ) +{ + return (this->*m_GetOverflowFunc)( nSize ); +} + + +//----------------------------------------------------------------------------- +// Checks if a put is ok +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::PutOverflow( int nSize ) +{ + if ( m_Memory.IsExternallyAllocated() ) + { + if ( !IsGrowable() ) + return false; + + m_Memory.ConvertToGrowableMemory( 0 ); + } + + while( Size() < m_Put - m_nOffset + nSize ) + { + m_Memory.Grow(); + } + + return true; +} + +bool CUtlBufferEditor::GetOverflow( int nSize ) +{ + return false; +} + + +//----------------------------------------------------------------------------- +// Checks if a put is ok +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::CheckPut( int nSize ) +{ + if ( ( m_Error & PUT_OVERFLOW ) || IsReadOnly() ) + return false; + + if ( ( m_Put < m_nOffset ) || ( m_Memory.NumAllocated() < m_Put - m_nOffset + nSize ) ) + { + if ( !OnPutOverflow( nSize ) ) + { + m_Error |= PUT_OVERFLOW; + return false; + } + } + return true; +} + +void CUtlBufferEditor::SeekPut( SeekType_t type, int offset ) +{ + int nNextPut = m_Put; + switch( type ) + { + case SEEK_HEAD: + nNextPut = offset; + break; + + case SEEK_CURRENT: + nNextPut += offset; + break; + + case SEEK_TAIL: + nNextPut = m_nMaxPut - offset; + break; + } + + // Force a write of the data + // FIXME: We could make this more optimal potentially by writing out + // the entire buffer if you seek outside the current range + + // NOTE: This call will write and will also seek the file to nNextPut. + OnPutOverflow( -nNextPut-1 ); + m_Put = nNextPut; + + AddNullTermination(); +} + + +void CUtlBufferEditor::ActivateByteSwapping( bool bActivate ) +{ + m_Byteswap.ActivateByteSwapping( bActivate ); +} + +void CUtlBufferEditor::SetBigEndian( bool bigEndian ) +{ + m_Byteswap.SetTargetBigEndian( bigEndian ); +} + +bool CUtlBufferEditor::IsBigEndian( void ) +{ + return m_Byteswap.IsTargetBigEndian(); +} + + +//----------------------------------------------------------------------------- +// null terminate the buffer +//----------------------------------------------------------------------------- +void CUtlBufferEditor::AddNullTermination( void ) +{ + if ( m_Put > m_nMaxPut ) + { + if ( !IsReadOnly() && ((m_Error & PUT_OVERFLOW) == 0) ) + { + // Add null termination value + if ( CheckPut( 1 ) ) + { + m_Memory[m_Put - m_nOffset] = 0; + } + else + { + // Restore the overflow state, it was valid before... + m_Error &= ~PUT_OVERFLOW; + } + } + m_nMaxPut = m_Put; + } +} + + +//----------------------------------------------------------------------------- +// Converts a buffer from a CRLF buffer to a CR buffer (and back) +// Returns false if no conversion was necessary (and outBuf is left untouched) +// If the conversion occurs, outBuf will be cleared. +//----------------------------------------------------------------------------- +bool CUtlBufferEditor::ConvertCRLF( CUtlBufferEditor &outBuf ) +{ + if ( !IsText() || !outBuf.IsText() ) + return false; + + if ( ContainsCRLF() == outBuf.ContainsCRLF() ) + return false; + + int nInCount = TellMaxPut(); + + outBuf.Purge(); + outBuf.EnsureCapacity( nInCount ); + + bool bFromCRLF = ContainsCRLF(); + + // Start reading from the beginning + int nGet = TellGet(); + int nPut = TellPut(); + int nGetDelta = 0; + int nPutDelta = 0; + + const char *pBase = (const char*)Base(); + int nCurrGet = 0; + while ( nCurrGet < nInCount ) + { + const char *pCurr = &pBase[nCurrGet]; + if ( bFromCRLF ) + { + const char *pNext = Q_strnistr( pCurr, "\r\n", nInCount - nCurrGet ); + if ( !pNext ) + { + outBuf.Put( pCurr, nInCount - nCurrGet ); + break; + } + + int nBytes = (size_t)pNext - (size_t)pCurr; + outBuf.Put( pCurr, nBytes ); + outBuf.PutChar( '\n' ); + nCurrGet += nBytes + 2; + if ( nGet >= nCurrGet - 1 ) + { + --nGetDelta; + } + if ( nPut >= nCurrGet - 1 ) + { + --nPutDelta; + } + } + else + { + const char *pNext = Q_strnchr( pCurr, '\n', nInCount - nCurrGet ); + if ( !pNext ) + { + outBuf.Put( pCurr, nInCount - nCurrGet ); + break; + } + + int nBytes = (size_t)pNext - (size_t)pCurr; + outBuf.Put( pCurr, nBytes ); + outBuf.PutChar( '\r' ); + outBuf.PutChar( '\n' ); + nCurrGet += nBytes + 1; + if ( nGet >= nCurrGet ) + { + ++nGetDelta; + } + if ( nPut >= nCurrGet ) + { + ++nPutDelta; + } + } + } + + Assert( nPut + nPutDelta <= outBuf.TellMaxPut() ); + + outBuf.SeekGet( SEEK_HEAD, nGet + nGetDelta ); + outBuf.SeekPut( SEEK_HEAD, nPut + nPutDelta ); + + return true; +} + +void CUtlBufferEditor::WriteToBuffer( CUtlBuffer &buf ) +{ + int size = TellPut(); + + buf.Put( Base(), size ); +} diff --git a/sp/src/shadereditor/exported_utilities.h b/sp/src/shadereditor/exported_utilities.h new file mode 100644 index 00000000..b2705501 --- /dev/null +++ b/sp/src/shadereditor/exported_utilities.h @@ -0,0 +1,932 @@ +#ifndef GENERAL_UTILITIES +#define GENERAL_UTILITIES + +char *V_StripFirstDir (char *path); +void V_IsolateFirstDir (char *path); + + +#define Q_StripFirstDir V_StripFirstDir +#define Q_IsolateFirstDir V_IsolateFirstDir + +#ifdef SHADER_EDITOR_DLL_2006 + +#include "exportedtier1/byteswap.h" +#include "exportedtier1/characterset.h" + +template < typename T > +class CPlainAutoPtr +{ +public: + explicit CPlainAutoPtr( T *p = NULL ) : m_p( p ) {} + ~CPlainAutoPtr( void ) { Delete(); } + +public: + void Delete( void ) { delete Detach(); } + +private: // Disallow copying, use Detach() instead to avoid ambiguity + CPlainAutoPtr( CPlainAutoPtr const &x ); + CPlainAutoPtr & operator = ( CPlainAutoPtr const &x ); + +public: + void Attach( T *p ) { m_p = p; } + T * Detach( void ) { T * p( m_p ); m_p = NULL; return p; } + +public: + bool IsValid( void ) const { return m_p != NULL; } + T * Get( void ) const { return m_p; } + T * operator -> ( void ) const { return Get(); } + T & operator * ( void ) const { return *Get(); } + +private: + T * m_p; +}; + +void GetMatricesForView( CViewSetup &setup, VMatrix &view, VMatrix &proj, VMatrix &viewproj ); + +void InitLightDirectional( LightDesc_t &l, Vector dir, Vector color ); + +#endif + + +class CUtlBufferEditor +{ +public: + enum SeekType_t + { + SEEK_HEAD = 0, + SEEK_CURRENT, + SEEK_TAIL + }; + + // flags + enum BufferFlags_t + { + TEXT_BUFFER = 0x1, // Describes how get + put work (as strings, or binary) + EXTERNAL_GROWABLE = 0x2, // This is used w/ external buffers and causes the utlbuf to switch to reallocatable memory if an overflow happens when Putting. + CONTAINS_CRLF = 0x4, // For text buffers only, does this contain \n or \n\r? + READ_ONLY = 0x8, // For external buffers; prevents null termination from happening. + AUTO_TABS_DISABLED = 0x10, // Used to disable/enable push/pop tabs + DIRECTIVE_TEST_ENABLED = 0x20, // Used to disable/enable push/pop tabs + }; + + // Overflow functions when a get or put overflows + typedef bool (CUtlBufferEditor::*UtlBufferOverflowFunc_t)( int nSize ); + + void WriteToBuffer( CUtlBuffer &buf ); + + // Constructors for growable + external buffers for serialization/unserialization + CUtlBufferEditor( int growSize = 0, int initSize = 0, int nFlags = 0 ); + CUtlBufferEditor( const void* pBuffer, int size, int nFlags = 0 ); + // This one isn't actually defined so that we catch contructors that are trying to pass a bool in as the third param. + CUtlBufferEditor( const void *pBuffer, int size, bool crap ); + + unsigned char GetFlags() const; + + // NOTE: This will assert if you attempt to recast it in a way that + // is not compatible. The only valid conversion is binary-> text w/CRLF + void SetBufferType( bool bIsText, bool bContainsCRLF ); + + // Makes sure we've got at least this much memory + void EnsureCapacity( int num ); + + // Attaches the buffer to external memory.... + void SetExternalBuffer( void* pMemory, int nSize, int nInitialPut, int nFlags = 0 ); + bool IsExternallyAllocated() const; + void AssumeMemory( void *pMemory, int nSize, int nInitialPut, int nFlags = 0 ); + + FORCEINLINE void ActivateByteSwappingIfBigEndian( void ) + { + if ( IsX360() ) + ActivateByteSwapping( true ); + } + + + // Controls endian-ness of binary utlbufs - default matches the current platform + void ActivateByteSwapping( bool bActivate ); + void SetBigEndian( bool bigEndian ); + bool IsBigEndian( void ); + + // Resets the buffer; but doesn't free memory + void Clear(); + + // Clears out the buffer; frees memory + void Purge(); + + // Read stuff out. + // Binary mode: it'll just read the bits directly in, and characters will be + // read for strings until a null character is reached. + // Text mode: it'll parse the file, turning text #s into real numbers. + // GetString will read a string until a space is reached + char GetChar( ); + unsigned char GetUnsignedChar( ); + short GetShort( ); + unsigned short GetUnsignedShort( ); + int GetInt( ); + int GetIntHex( ); + unsigned int GetUnsignedInt( ); + float GetFloat( ); + double GetDouble( ); + void GetString( char* pString, int nMaxChars = 0 ); + void Get( void* pMem, int size ); + void GetLine( char* pLine, int nMaxChars = 0 ); + + // Used for getting objects that have a byteswap datadesc defined + template void GetObjects( T *dest, int count = 1 ); + + // This will get at least 1 byte and up to nSize bytes. + // It will return the number of bytes actually read. + int GetUpTo( void *pMem, int nSize ); + + // This version of GetString converts \" to \\ and " to \, etc. + // It also reads a " at the beginning and end of the string + void GetDelimitedString( CUtlCharConversion *pConv, char *pString, int nMaxChars = 0 ); + char GetDelimitedChar( CUtlCharConversion *pConv ); + + // This will return the # of characters of the string about to be read out + // NOTE: The count will *include* the terminating 0!! + // In binary mode, it's the number of characters until the next 0 + // In text mode, it's the number of characters until the next space. + int PeekStringLength(); + + // This version of PeekStringLength converts \" to \\ and " to \, etc. + // It also reads a " at the beginning and end of the string + // NOTE: The count will *include* the terminating 0!! + // In binary mode, it's the number of characters until the next 0 + // In text mode, it's the number of characters between "s (checking for \") + // Specifying false for bActualSize will return the pre-translated number of characters + // including the delimiters and the escape characters. So, \n counts as 2 characters when bActualSize == false + // and only 1 character when bActualSize == true + int PeekDelimitedStringLength( CUtlCharConversion *pConv, bool bActualSize = true ); + + // Just like scanf, but doesn't work in binary mode + int Scanf( const char* pFmt, ... ); + int VaScanf( const char* pFmt, va_list list ); + + // Eats white space, advances Get index + void EatWhiteSpace(); + + // Eats C++ style comments + bool EatCPPComment(); + + // (For text buffers only) + // Parse a token from the buffer: + // Grab all text that lies between a starting delimiter + ending delimiter + // (skipping whitespace that leads + trails both delimiters). + // If successful, the get index is advanced and the function returns true, + // otherwise the index is not advanced and the function returns false. + bool ParseToken( const char *pStartingDelim, const char *pEndingDelim, char* pString, int nMaxLen ); + + // Advance the get index until after the particular string is found + // Do not eat whitespace before starting. Return false if it failed + // String test is case-insensitive. + bool GetToken( const char *pToken ); + + // Parses the next token, given a set of character breaks to stop at + // Returns the length of the token parsed in bytes (-1 if none parsed) + int ParseToken( characterset_t *pBreaks, char *pTokenBuf, int nMaxLen, bool bParseComments = true ); + + // Write stuff in + // Binary mode: it'll just write the bits directly in, and strings will be + // written with a null terminating character + // Text mode: it'll convert the numbers to text versions + // PutString will not write a terminating character + void PutChar( char c ); + void PutUnsignedChar( unsigned char uc ); + void PutShort( short s ); + void PutUnsignedShort( unsigned short us ); + void PutInt( int i ); + void PutUnsignedInt( unsigned int u ); + void PutFloat( float f ); + void PutDouble( double d ); + void PutString( const char* pString ); + void Put( const void* pMem, int size ); + + // Used for putting objects that have a byteswap datadesc defined + template void PutObjects( T *src, int count = 1 ); + + // This version of PutString converts \ to \\ and " to \", etc. + // It also places " at the beginning and end of the string + void PutDelimitedString( CUtlCharConversion *pConv, const char *pString ); + void PutDelimitedChar( CUtlCharConversion *pConv, char c ); + + // Just like printf, writes a terminating zero in binary mode + void Printf( const char* pFmt, ... ); + void VaPrintf( const char* pFmt, va_list list ); + + // What am I writing (put)/reading (get)? + void* PeekPut( int offset = 0 ); + const void* PeekGet( int offset = 0 ) const; + const void* PeekGet( int nMaxSize, int nOffset ); + + // Where am I writing (put)/reading (get)? + int TellPut( ) const; + int TellGet( ) const; + + // What's the most I've ever written? + int TellMaxPut( ) const; + + // How many bytes remain to be read? + // NOTE: This is not accurate for streaming text files; it overshoots + int GetBytesRemaining() const; + + // Change where I'm writing (put)/reading (get) + void SeekPut( SeekType_t type, int offset ); + void SeekGet( SeekType_t type, int offset ); + + // Buffer base + const void* Base() const; + void* Base(); + + // memory allocation size, does *not* reflect size written or read, + // use TellPut or TellGet for that + int Size() const; + + // Am I a text buffer? + bool IsText() const; + + // Can I grow if I'm externally allocated? + bool IsGrowable() const; + + // Am I valid? (overflow or underflow error), Once invalid it stays invalid + bool IsValid() const; + + // Do I contain carriage return/linefeeds? + bool ContainsCRLF() const; + + // Am I read-only + bool IsReadOnly() const; + + // Converts a buffer from a CRLF buffer to a CR buffer (and back) + // Returns false if no conversion was necessary (and outBuf is left untouched) + // If the conversion occurs, outBuf will be cleared. + bool ConvertCRLF( CUtlBufferEditor &outBuf ); + + // Push/pop pretty-printing tabs + void PushTab(); + void PopTab(); + + // Temporarily disables pretty print + void EnableTabs( bool bEnable ); + + void EnableDirectives( bool bEnable ); + +protected: + // error flags + enum + { + PUT_OVERFLOW = 0x1, + GET_OVERFLOW = 0x2, + MAX_ERROR_FLAG = GET_OVERFLOW, + }; + + void SetOverflowFuncs( UtlBufferOverflowFunc_t getFunc, UtlBufferOverflowFunc_t putFunc ); + + bool OnPutOverflow( int nSize ); + bool OnGetOverflow( int nSize ); + +protected: + // Checks if a get/put is ok + bool CheckPut( int size ); + bool CheckGet( int size ); + + void AddNullTermination( ); + + // Methods to help with pretty-printing + bool WasLastCharacterCR(); + bool IsDirectiveLine( const char *stringIn ); + void PutTabs(); + + // Help with delimited stuff + char GetDelimitedCharInternal( CUtlCharConversion *pConv ); + void PutDelimitedCharInternal( CUtlCharConversion *pConv, char c ); + + // Default overflow funcs + bool PutOverflow( int nSize ); + bool GetOverflow( int nSize ); + + // Does the next bytes of the buffer match a pattern? + bool PeekStringMatch( int nOffset, const char *pString, int nLen ); + + // Peek size of line to come, check memory bound + int PeekLineLength(); + + // How much whitespace should I skip? + int PeekWhiteSpace( int nOffset ); + + // Checks if a peek get is ok + bool CheckPeekGet( int nOffset, int nSize ); + + // Call this to peek arbitrarily long into memory. It doesn't fail unless + // it can't read *anything* new + bool CheckArbitraryPeekGet( int nOffset, int &nIncrement ); + + template void GetType( T& dest, const char *pszFmt ); + template void GetTypeBin( T& dest ); + template void GetObject( T *src ); + + template void PutType( T src, const char *pszFmt ); + template void PutTypeBin( T src ); + template void PutObject( T *src ); + + CUtlMemory m_Memory; + int m_Get; + int m_Put; + + unsigned char m_Error; + unsigned char m_Flags; + unsigned char m_Reserved; +#if defined( _X360 ) + unsigned char pad; +#endif + + int m_nTab; + int m_nMaxPut; + int m_nOffset; + + UtlBufferOverflowFunc_t m_GetOverflowFunc; + UtlBufferOverflowFunc_t m_PutOverflowFunc; + + CByteswap m_Byteswap; +}; + + +// Stream style output operators for CUtlBufferEditor +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, char v ) +{ + b.PutChar( v ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, unsigned char v ) +{ + b.PutUnsignedChar( v ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, short v ) +{ + b.PutShort( v ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, unsigned short v ) +{ + b.PutUnsignedShort( v ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, int v ) +{ + b.PutInt( v ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, unsigned int v ) +{ + b.PutUnsignedInt( v ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, float v ) +{ + b.PutFloat( v ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, double v ) +{ + b.PutDouble( v ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, const char *pv ) +{ + b.PutString( pv ); + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, const Vector &v ) +{ + b << v.x << " " << v.y << " " << v.z; + return b; +} + +inline CUtlBufferEditor &operator<<( CUtlBufferEditor &b, const Vector2D &v ) +{ + b << v.x << " " << v.y; + return b; +} + + + +//----------------------------------------------------------------------------- +// Where am I reading? +//----------------------------------------------------------------------------- +inline int CUtlBufferEditor::TellGet( ) const +{ + return m_Get; +} + + +//----------------------------------------------------------------------------- +// How many bytes remain to be read? +//----------------------------------------------------------------------------- +inline int CUtlBufferEditor::GetBytesRemaining() const +{ + return m_nMaxPut - TellGet(); +} + + +//----------------------------------------------------------------------------- +// What am I reading? +//----------------------------------------------------------------------------- +inline const void* CUtlBufferEditor::PeekGet( int offset ) const +{ + return &m_Memory[ m_Get + offset - m_nOffset ]; +} + + +//----------------------------------------------------------------------------- +// Unserialization +//----------------------------------------------------------------------------- + +template +inline void CUtlBufferEditor::GetObject( T *dest ) +{ + if ( CheckGet( sizeof(T) ) ) + { + if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) + { + *dest = *(T *)PeekGet(); + } + else + { + m_Byteswap.SwapFieldsToTargetEndian( dest, (T*)PeekGet() ); + } + m_Get += sizeof(T); + } + else + { + Q_memset( &dest, 0, sizeof(T) ); + } +} + + +template +inline void CUtlBufferEditor::GetObjects( T *dest, int count ) +{ + for ( int i = 0; i < count; ++i, ++dest ) + { + GetObject( dest ); + } +} + + +template +inline void CUtlBufferEditor::GetTypeBin( T &dest ) +{ + if ( CheckGet( sizeof(T) ) ) + { + if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) + { + dest = *(T *)PeekGet(); + } + else + { + m_Byteswap.SwapBufferToTargetEndian( &dest, (T*)PeekGet() ); + } + m_Get += sizeof(T); + } + else + { + dest = 0; + } +} + +template <> +inline void CUtlBufferEditor::GetTypeBin< float >( float &dest ) +{ + if ( CheckGet( sizeof( float ) ) ) + { + unsigned int pData = (unsigned int)PeekGet(); + if ( IsX360() && ( pData & 0x03 ) ) + { + // handle unaligned read + ((unsigned char*)&dest)[0] = ((unsigned char*)pData)[0]; + ((unsigned char*)&dest)[1] = ((unsigned char*)pData)[1]; + ((unsigned char*)&dest)[2] = ((unsigned char*)pData)[2]; + ((unsigned char*)&dest)[3] = ((unsigned char*)pData)[3]; + } + else + { + // aligned read + dest = *(float *)pData; + } + if ( m_Byteswap.IsSwappingBytes() ) + { + m_Byteswap.SwapBufferToTargetEndian< float >( &dest, &dest ); + } + m_Get += sizeof( float ); + } + else + { + dest = 0; + } +} + +template +inline void CUtlBufferEditor::GetType( T &dest, const char *pszFmt ) +{ + if (!IsText()) + { + GetTypeBin( dest ); + } + else + { + dest = 0; + Scanf( pszFmt, &dest ); + } +} + +inline char CUtlBufferEditor::GetChar( ) +{ + char c; + GetType( c, "%c" ); + return c; +} + +inline unsigned char CUtlBufferEditor::GetUnsignedChar( ) +{ + unsigned char c; + GetType( c, "%u" ); + return c; +} + +inline short CUtlBufferEditor::GetShort( ) +{ + short s; + GetType( s, "%d" ); + return s; +} + +inline unsigned short CUtlBufferEditor::GetUnsignedShort( ) +{ + unsigned short s; + GetType( s, "%u" ); + return s; +} + +inline int CUtlBufferEditor::GetInt( ) +{ + int i; + GetType( i, "%d" ); + return i; +} + +inline int CUtlBufferEditor::GetIntHex( ) +{ + int i; + GetType( i, "%x" ); + return i; +} + +inline unsigned int CUtlBufferEditor::GetUnsignedInt( ) +{ + unsigned int u; + GetType( u, "%u" ); + return u; +} + +inline float CUtlBufferEditor::GetFloat( ) +{ + float f; + GetType( f, "%f" ); + return f; +} + +inline double CUtlBufferEditor::GetDouble( ) +{ + double d; + GetType( d, "%f" ); + return d; +} + + +//----------------------------------------------------------------------------- +// Where am I writing? +//----------------------------------------------------------------------------- +inline unsigned char CUtlBufferEditor::GetFlags() const +{ + return m_Flags; +} + + +//----------------------------------------------------------------------------- +// +//----------------------------------------------------------------------------- +inline bool CUtlBufferEditor::IsExternallyAllocated() const +{ + return m_Memory.IsExternallyAllocated(); +} + + +//----------------------------------------------------------------------------- +// Where am I writing? +//----------------------------------------------------------------------------- +inline int CUtlBufferEditor::TellPut( ) const +{ + return m_Put; +} + + +//----------------------------------------------------------------------------- +// What's the most I've ever written? +//----------------------------------------------------------------------------- +inline int CUtlBufferEditor::TellMaxPut( ) const +{ + return m_nMaxPut; +} + + +//----------------------------------------------------------------------------- +// What am I reading? +//----------------------------------------------------------------------------- +inline void* CUtlBufferEditor::PeekPut( int offset ) +{ + return &m_Memory[m_Put + offset - m_nOffset]; +} + + +//----------------------------------------------------------------------------- +// Various put methods +//----------------------------------------------------------------------------- + +template +inline void CUtlBufferEditor::PutObject( T *src ) +{ + if ( CheckPut( sizeof(T) ) ) + { + if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) + { + *(T *)PeekPut() = *src; + } + else + { + m_Byteswap.SwapFieldsToTargetEndian( (T*)PeekPut(), src ); + } + m_Put += sizeof(T); + AddNullTermination(); + } +} + + +template +inline void CUtlBufferEditor::PutObjects( T *src, int count ) +{ + for ( int i = 0; i < count; ++i, ++src ) + { + PutObject( src ); + } +} + + +template +inline void CUtlBufferEditor::PutTypeBin( T src ) +{ + if ( CheckPut( sizeof(T) ) ) + { + if ( !m_Byteswap.IsSwappingBytes() || ( sizeof( T ) == 1 ) ) + { + *(T *)PeekPut() = src; + } + else + { + m_Byteswap.SwapBufferToTargetEndian( (T*)PeekPut(), &src ); + } + m_Put += sizeof(T); + AddNullTermination(); + } +} + +template +inline void CUtlBufferEditor::PutType( T src, const char *pszFmt ) +{ + if (!IsText()) + { + PutTypeBin( src ); + } + else + { + Printf( pszFmt, src ); + } +} + +//----------------------------------------------------------------------------- +// Methods to help with pretty-printing +//----------------------------------------------------------------------------- +inline bool CUtlBufferEditor::WasLastCharacterCR() +{ + if ( !IsText() || (TellPut() == 0) ) + return false; + return ( *( const char * )PeekPut( -1 ) == '\n' ); +} +inline bool CUtlBufferEditor::IsDirectiveLine( const char *stringIn ) +{ + if ( !(m_Flags & DIRECTIVE_TEST_ENABLED) ) + return false; + + const char *walk = stringIn; + while ( walk && *walk ) + { + if ( *walk == '#' ) + return true; + if ( *walk != '\t' && + *walk != ' ' ) + break; + walk++; + } + return false; +} +inline void CUtlBufferEditor::PutTabs() +{ + int nTabCount = ( m_Flags & AUTO_TABS_DISABLED ) ? 0 : m_nTab; + for (int i = nTabCount; --i >= 0; ) + { + PutTypeBin( '\t' ); + } +} + + +//----------------------------------------------------------------------------- +// Push/pop pretty-printing tabs +//----------------------------------------------------------------------------- +inline void CUtlBufferEditor::PushTab( ) +{ + ++m_nTab; +} + +inline void CUtlBufferEditor::PopTab() +{ + if ( --m_nTab < 0 ) + { + m_nTab = 0; + } +} + + +//----------------------------------------------------------------------------- +// Temporarily disables pretty print +//----------------------------------------------------------------------------- +inline void CUtlBufferEditor::EnableTabs( bool bEnable ) +{ + if ( bEnable ) + { + m_Flags &= ~AUTO_TABS_DISABLED; + } + else + { + m_Flags |= AUTO_TABS_DISABLED; + } +} +inline void CUtlBufferEditor::EnableDirectives( bool bEnable ) +{ + if ( bEnable ) + m_Flags |= DIRECTIVE_TEST_ENABLED; + else + m_Flags &= ~DIRECTIVE_TEST_ENABLED; +} + +inline void CUtlBufferEditor::PutChar( char c ) +{ + if ( WasLastCharacterCR() ) + { + PutTabs(); + } + + PutTypeBin( c ); +} + +inline void CUtlBufferEditor::PutUnsignedChar( unsigned char c ) +{ + PutType( c, "%u" ); +} + +inline void CUtlBufferEditor::PutShort( short s ) +{ + PutType( s, "%d" ); +} + +inline void CUtlBufferEditor::PutUnsignedShort( unsigned short s ) +{ + PutType( s, "%u" ); +} + +inline void CUtlBufferEditor::PutInt( int i ) +{ + PutType( i, "%d" ); +} + +inline void CUtlBufferEditor::PutUnsignedInt( unsigned int u ) +{ + PutType( u, "%u" ); +} + +inline void CUtlBufferEditor::PutFloat( float f ) +{ + PutType( f, "%f" ); +} + +inline void CUtlBufferEditor::PutDouble( double d ) +{ + PutType( d, "%f" ); +} + + +//----------------------------------------------------------------------------- +// Am I a text buffer? +//----------------------------------------------------------------------------- +inline bool CUtlBufferEditor::IsText() const +{ + return (m_Flags & TEXT_BUFFER) != 0; +} + + +//----------------------------------------------------------------------------- +// Can I grow if I'm externally allocated? +//----------------------------------------------------------------------------- +inline bool CUtlBufferEditor::IsGrowable() const +{ + return (m_Flags & EXTERNAL_GROWABLE) != 0; +} + + +//----------------------------------------------------------------------------- +// Am I valid? (overflow or underflow error), Once invalid it stays invalid +//----------------------------------------------------------------------------- +inline bool CUtlBufferEditor::IsValid() const +{ + return m_Error == 0; +} + + +//----------------------------------------------------------------------------- +// Do I contain carriage return/linefeeds? +//----------------------------------------------------------------------------- +inline bool CUtlBufferEditor::ContainsCRLF() const +{ + return IsText() && ((m_Flags & CONTAINS_CRLF) != 0); +} + + +//----------------------------------------------------------------------------- +// Am I read-only +//----------------------------------------------------------------------------- +inline bool CUtlBufferEditor::IsReadOnly() const +{ + return (m_Flags & READ_ONLY) != 0; +} + + +//----------------------------------------------------------------------------- +// Buffer base and size +//----------------------------------------------------------------------------- +inline const void* CUtlBufferEditor::Base() const +{ + return m_Memory.Base(); +} + +inline void* CUtlBufferEditor::Base() +{ + return m_Memory.Base(); +} + +inline int CUtlBufferEditor::Size() const +{ + return m_Memory.NumAllocated(); +} + + +//----------------------------------------------------------------------------- +// Clears out the buffer; frees memory +//----------------------------------------------------------------------------- +inline void CUtlBufferEditor::Clear() +{ + m_Get = 0; + m_Put = 0; + m_Error = 0; + m_nOffset = 0; + m_nMaxPut = -1; + AddNullTermination(); +} + +inline void CUtlBufferEditor::Purge() +{ + m_Get = 0; + m_Put = 0; + m_nOffset = 0; + m_nMaxPut = 0; + m_Error = 0; + m_Memory.Purge(); +} + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/gdirectories.cpp b/sp/src/shadereditor/gdirectories.cpp new file mode 100644 index 00000000..12ce94aa --- /dev/null +++ b/sp/src/shadereditor/gdirectories.cpp @@ -0,0 +1,582 @@ + +#include "cbase.h" + +#include + +#include "editorCommon.h" + +using namespace std; + +#define MASTERPATH_MAXLEN 512 + +static char _wd[MASTERPATH_MAXLEN]; +static char _acc[MASTERPATH_MAXLEN]; +static char _compilePath[MASTERPATH_MAXLEN]; +static char _compilePath_Local[MASTERPATH_MAXLEN]; +static char _gamePath[MASTERPATH_MAXLEN]; +static char _canvasDir[MASTERPATH_MAXLEN]; +static char _shaderSource[MASTERPATH_MAXLEN]; +static char _DumpFiles[MASTERPATH_MAXLEN]; +static char _uFuncs[MASTERPATH_MAXLEN]; +static char _seditRoot[MASTERPATH_MAXLEN]; + +#ifdef SHADER_EDITOR_DLL_SWARM +static char _swarmShaderDir[MASTERPATH_MAXLEN]; +#endif + +static char _wd_override[MASTERPATH_MAXLEN] = { 0 }; // better safe than sorry +static char _compilePath_override[MASTERPATH_MAXLEN] = { 0 }; +static char _compilePath_Local_override[MASTERPATH_MAXLEN] = { 0 }; +static char _gamePath_override[MASTERPATH_MAXLEN] = { 0 }; +static char _canvasDir_override[MASTERPATH_MAXLEN] = { 0 }; +static char _shaderSource_override[MASTERPATH_MAXLEN] = { 0 }; +static char _DumpFiles_override[MASTERPATH_MAXLEN] = { 0 }; +static char _uFuncs_override[MASTERPATH_MAXLEN] = { 0 }; +static char _seditRoot_override[MASTERPATH_MAXLEN] = { 0 }; + +void OverrideDirectories( const char *pszWorkingDirectory, const char *pszCompilePath, const char *pszLocalCompilePath, + const char *pszGamePath, const char *pszCanvas, const char *pszShaderSource, const char *pszDumps, + const char *pszUserFunctions, const char *pszEditorRoot ) +{ + if ( pszWorkingDirectory != NULL ) + Q_strncpy( _wd_override, pszWorkingDirectory, sizeof( _wd_override ) ); + + if ( pszCompilePath != NULL ) + Q_strncpy( _compilePath_override, pszCompilePath, sizeof( _compilePath_override ) ); + + if ( pszLocalCompilePath != NULL ) + Q_strncpy( _compilePath_Local_override, pszLocalCompilePath, sizeof( _compilePath_Local_override ) ); + + if ( pszGamePath != NULL ) + Q_strncpy( _gamePath_override, pszGamePath, sizeof( _gamePath_override ) ); + + if ( pszCanvas != NULL ) + Q_strncpy( _canvasDir_override, pszCanvas, sizeof( _canvasDir_override ) ); + + if ( pszShaderSource != NULL ) + Q_strncpy( _shaderSource_override, pszShaderSource, sizeof( _shaderSource_override ) ); + + if ( pszDumps != NULL ) + Q_strncpy( _DumpFiles_override, pszDumps, sizeof( _DumpFiles_override ) ); + + if ( pszUserFunctions != NULL ) + Q_strncpy( _uFuncs_override, pszUserFunctions, sizeof( _uFuncs_override ) ); + + if ( pszEditorRoot != NULL ) + Q_strncpy( _seditRoot_override, pszEditorRoot, sizeof( _seditRoot_override ) ); +} + +void ApplyDirectoryOverrides() +{ +#define _OVERRIDE_DIR( x ) \ + if ( *(x##_override) ) \ + Q_strncpy( x, x##_override, sizeof( x ) ); + + _OVERRIDE_DIR( _wd ); + _OVERRIDE_DIR( _compilePath ); + _OVERRIDE_DIR( _compilePath_Local ); + _OVERRIDE_DIR( _gamePath ); + _OVERRIDE_DIR( _canvasDir ); + _OVERRIDE_DIR( _shaderSource ); + _OVERRIDE_DIR( _DumpFiles ); + _OVERRIDE_DIR( _uFuncs ); + _OVERRIDE_DIR( _seditRoot ); +} + +void CreateDirectoryStrings() +{ + DestroyDirectoryStrings(); + + char _wdTmp[ MASTERPATH_MAXLEN ]; + char szSearchPath[ MASTERPATH_MAXLEN ]; + + if ( g_pFullFileSystem->GetSearchPath( "EXECUTABLE_PATH", false, szSearchPath, sizeof( szSearchPath ) ) > 0 ) + { + Q_strncpy( _wdTmp, szSearchPath, MASTERPATH_MAXLEN ); + } + else + { + *szSearchPath = 0; + + if ( !g_pFullFileSystem->GetCurrentDirectory( _wdTmp, MASTERPATH_MAXLEN ) ) + getcwd( _wdTmp, sizeof( _wdTmp ) ); + } + + Q_FixSlashes( _wdTmp ); + + Q_strncpy( _wd, _wdTmp, MASTERPATH_MAXLEN ); + + char *sapps = Q_stristr( _wdTmp, "steamapps" ); + + if ( sapps ) + { + sapps = Q_StripFirstDir( sapps ); + Q_IsolateFirstDir( sapps ); + Q_snprintf( _acc, MASTERPATH_MAXLEN, "%s", sapps ); + + *sapps = '\0'; + } + else + { + Warning( "Unable to find account name/common\n" ); + Q_snprintf( _acc, MASTERPATH_MAXLEN, "common" ); + } + + //char *smods = Q_stristr( _wdTmp, "SourceMods" ); + const char *_game = engine->GetGameDirectory(); + + Q_snprintf( _gamePath, MASTERPATH_MAXLEN, "%s", _game ); + Q_FixSlashes( _gamePath ); + + KeyValues *pKV = new KeyValues("cfg"); + const char *localize = "..\\..\\..\\..\\"; + +#ifdef SHADER_EDITOR_DLL_SWARM + const char *defCMP = "alien swarm/bin"; + const char *defCMPKey = "compiler_swarm"; +#elif SHADER_EDITOR_DLL_2006 + const char *defCMP = "sourcesdk/bin/ep1/bin"; + const char *defCMPKey = "compiler_2006"; +#elif SHADER_EDITOR_DLL_2013 + const char *defCMP = ""; + const char *defCMPKey = "compiler_2013"; +#else + const char *defCMP = "sourcesdk/bin/source2007/bin"; + const char *defCMPKey = "compiler"; +#endif + + const char *_cmp = defCMP; + if ( pKV->LoadFromFile( g_pFullFileSystem, "shadereditorui/path_config.txt", "MOD" ) ) + _cmp = pKV->GetString( defCMPKey, defCMP ); + +#ifdef SHADER_EDITOR_DLL_2013 + Q_snprintf( _compilePath, MASTERPATH_MAXLEN, "%s/bin", _wd ); +#else + Q_snprintf( _compilePath, MASTERPATH_MAXLEN, "%s%s/%s", _wdTmp, _acc, _cmp ); +#endif + +#ifdef SHADER_EDITOR_DLL_2013 + char szCurrentDir[ MASTERPATH_MAXLEN ]; + Q_FileBase( _wd, szCurrentDir, MASTERPATH_MAXLEN ); + Q_snprintf( _compilePath_Local, MASTERPATH_MAXLEN, "%scommon\\%s\\bin", localize, szCurrentDir ); +#else + Q_snprintf( _compilePath_Local, MASTERPATH_MAXLEN, "%s%s\\%s", localize, _acc, _cmp ); +#endif + +#ifdef SHADER_EDITOR_DLL_2013 + if ( *szSearchPath != 0 ) + { + Q_strncpy( _compilePath, szSearchPath, sizeof( _compilePath ) ); + Q_strncpy( _compilePath_Local, szSearchPath, sizeof( _compilePath_Local ) ); + } +#endif + + Q_FixSlashes( _compilePath ); + Q_FixSlashes( _compilePath_Local ); + pKV->deleteThis(); + + + const char *__localrootdir = "shadereditorui"; + Q_snprintf( _seditRoot, MASTERPATH_MAXLEN, "%s/%s", _gamePath, __localrootdir ); + Q_FixSlashes( _seditRoot ); + + const char *__localcanvasdir = "canvas"; + Q_snprintf( _canvasDir, MASTERPATH_MAXLEN, "%s/%s", _seditRoot, __localcanvasdir ); + Q_FixSlashes( _canvasDir ); + + const char *__localsrcdir = "shader_src"; + Q_snprintf( _shaderSource, MASTERPATH_MAXLEN, "%s/%s", _seditRoot, __localsrcdir ); + Q_FixSlashes( _shaderSource ); + + const char *__localdumpdir = "dumps"; + Q_snprintf( _DumpFiles, MASTERPATH_MAXLEN, "%s/%s", _seditRoot, __localdumpdir ); + Q_FixSlashes( _DumpFiles ); + + const char *__localufuncdir = "user_functions"; + Q_snprintf( _uFuncs, MASTERPATH_MAXLEN, "%s/%s", _seditRoot, __localufuncdir ); + Q_FixSlashes( _uFuncs ); + +#ifdef SHADER_EDITOR_DLL_SWARM + const char *__swarmShaderTarget = "platform/shaders/fxc"; + Q_snprintf( _swarmShaderDir, MASTERPATH_MAXLEN, "%s/%s", _wd, __swarmShaderTarget ); + Q_FixSlashes( _swarmShaderDir ); +#endif + + + ApplyDirectoryOverrides(); + + CreateDirectories(); + + + if ( shaderEdit->ShouldShowPrimaryDbg() ) + { + Msg( "wd: %s\n", _wd ); +#ifdef SHADER_EDITOR_DLL_SWARM + Msg( "swarm parent name: %s\n", _acc ); + Msg( "swarm shader path: %s\n", _swarmShaderDir ); +#else + Msg( "acc: %s\n", _acc ); +#endif + Msg( "game: %s\n", _gamePath ); + Msg( "editor root: %s\n", _seditRoot ); + Msg( "binaries: %s\n", _compilePath ); + Msg( "binaries local: %s\n", _compilePath_Local ); + Msg( "canvas: %s\n", _canvasDir ); + Msg( "funcs: %s\n", _uFuncs ); + Msg( "src: %s\n", _shaderSource ); + } +} +void CreateDirectories() +{ + if ( !g_pFullFileSystem->IsDirectory( _canvasDir, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( _canvasDir, "MOD" ); + + if ( !g_pFullFileSystem->IsDirectory( _DumpFiles, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( _DumpFiles, "MOD" ); + if ( !g_pFullFileSystem->IsDirectory( _shaderSource, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( _shaderSource, "MOD" ); + + char tmpDir[MASTERPATH_MAXLEN]; + Q_snprintf( tmpDir, sizeof( tmpDir ), "%s/shaders/fxc", _shaderSource ); + Q_FixSlashes( tmpDir ); + if ( !g_pFullFileSystem->IsDirectory( tmpDir, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( tmpDir, "MOD" ); + Q_snprintf( tmpDir, sizeof( tmpDir ), "%s/shaders/psh", _shaderSource ); + Q_FixSlashes( tmpDir ); + if ( !g_pFullFileSystem->IsDirectory( tmpDir, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( tmpDir, "MOD" ); + Q_snprintf( tmpDir, sizeof( tmpDir ), "%s/shaders/vsh", _shaderSource ); + Q_FixSlashes( tmpDir ); + if ( !g_pFullFileSystem->IsDirectory( tmpDir, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( tmpDir, "MOD" ); + + + Q_snprintf( tmpDir, sizeof( tmpDir ), "%s/shaders", _gamePath ); + Q_FixSlashes( tmpDir ); + if ( !g_pFullFileSystem->IsDirectory( tmpDir, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( tmpDir, "MOD" ); + Q_snprintf( tmpDir, sizeof( tmpDir ), "%s/shaders/fxc", _gamePath ); + Q_FixSlashes( tmpDir ); + if ( !g_pFullFileSystem->IsDirectory( tmpDir, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( tmpDir, "MOD" ); + Q_snprintf( tmpDir, sizeof( tmpDir ), "%s/shaders/psh", _gamePath ); + Q_FixSlashes( tmpDir ); + if ( !g_pFullFileSystem->IsDirectory( tmpDir, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( tmpDir, "MOD" ); + Q_snprintf( tmpDir, sizeof( tmpDir ), "%s/shaders/vsh", _gamePath ); + Q_FixSlashes( tmpDir ); + if ( !g_pFullFileSystem->IsDirectory( tmpDir, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( tmpDir, "MOD" ); + +#ifdef SHADER_EDITOR_DLL_SWARM + if ( !g_pFullFileSystem->IsDirectory( _shaderSource ) ) + g_pFullFileSystem->CreateDirHierarchy( _shaderSource ); + + Q_snprintf( tmpDir, sizeof( tmpDir ), "%s/fxc", _shaderSource ); + Q_FixSlashes( tmpDir ); + if ( !g_pFullFileSystem->IsDirectory( tmpDir ) ) + g_pFullFileSystem->CreateDirHierarchy( tmpDir ); +#endif +} +void DestroyDirectoryStrings() +{ +} +const char *GetWorkingDirectory() +{ + return _wd; +} +const char *GetAccountName() +{ + return _acc; +} +const char *GetGamePath() +{ + return _gamePath; +} +const char *GetBinaryPath() +{ + return _compilePath; +} +const char *GetBinaryPath_Local() +{ + return _compilePath_Local; +} +const char *GetCanvasDirectory() +{ + return _canvasDir; +} +const char *GetShaderSourceDirectory() +{ + return _shaderSource; +} +const char *GetDumpDirectory() +{ + return _DumpFiles; +} +const char *GetUserFunctionDirectory() +{ + return _uFuncs; +} +const char *GetEditorRootDirectory() +{ + return _seditRoot; +} +#ifdef SHADER_EDITOR_DLL_SWARM +const char *GetSwarmShaderDirectory() +{ + return _swarmShaderDir; +} +#endif + +void ComposeShaderName( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride ) +{ + const bool bPreview = data->IsPreview(); + const bool sm2b = data->shader->iShaderModel == SM_20B; + Q_snprintf( out, maxbuf, "%s_%s%s%s%s", data->name, + (bPosOverride?"pos_":""), + (bPreview?"preview_":""), + ((bPS)? + (sm2b?"ps20b":"ps30"): + (sm2b?"vs20":"vs30") + ), + (bExtension?".fxc":"") + ); + Q_FixSlashes( out ); + //Q_strlower( out ); +} +void ComposeShaderPath( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride ) +{ + char sname[MASTERPATH_MAXLEN]; + ComposeShaderName( data, bPS, bExtension, sname, sizeof( sname ), bPosOverride ); + Q_snprintf( out, maxbuf, "%s/%s", GetShaderSourceDirectory(), sname ); + Q_FixSlashes( out ); +} + + +void ComposeShaderName_Compiled( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride ) +{ + const bool bPreview = data->IsPreview(); + const bool sm2b = data->shader->iShaderModel == SM_20B; + Q_snprintf( out, maxbuf, "%s_%s%s%s%s", data->name, + (bPosOverride?"pos_":""), + (bPreview?"preview_":""), + ((bPS)? + (sm2b?"ps20b":"ps30"): + (sm2b?"vs20":"vs30") + ), + (bExtension?".vcs":"") + ); + Q_FixSlashes( out ); + //Q_strlower( out ); +} +void ComposeShaderPath_Compiled( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride ) +{ + char sname[MASTERPATH_MAXLEN]; + ComposeShaderName_Compiled( data, bPS, bExtension, sname, sizeof( sname ), bPosOverride ); + Q_snprintf( out, maxbuf, "%s/shaders/fxc/%s", GetShaderSourceDirectory(), sname ); + Q_FixSlashes( out ); +} + +void ComposeShaderPath_CompiledEngine( GenericShaderData *data, bool bPS, bool bExtension, char *out, int maxbuf, bool bPosOverride ) +{ + char sname[MASTERPATH_MAXLEN]; + ComposeShaderName_Compiled( data, bPS, bExtension, sname, sizeof( sname ), bPosOverride ); +#if 0 //def SHADER_EDITOR_DLL_SWARM + Q_snprintf( out, maxbuf, "%s/%s", GetSwarmShaderDirectory(), sname ); + + if ( !bPosOverride ) + ShaderNameToSwarmUnique( out, maxbuf ); +#else + Q_snprintf( out, maxbuf, "%s/shaders/fxc/%s", GetGamePath(), sname ); +#endif + Q_FixSlashes( out ); +} + + +bool bIsHex( const char &c ) +{ + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} + +#define pFnFilenameMask( x ) bool(* x )( const char *pszFilename ) +#define pFnFilenameMask_Declare( x ) bool x( const char *pszFilename ) + +pFnFilenameMask_Declare( CheckPreviewMask ) +{ + int len = Q_strlen( pszFilename ); + if ( len > 7 ) + { + bool bFileOkay = true; + for ( int i = 0; i < 6; i++ ) + if ( !bIsHex(pszFilename[i]) ) + bFileOkay = false; + if ( pszFilename[6] != '_' ) + bFileOkay = false; + return bFileOkay; + } + + return false; +} + +void ListFiles( const char *dir, CUtlVector< char* > &hFiles, const char *pszExtension = NULL, pFnFilenameMask( pCheck ) = NULL ) +{ + int dirlen = Q_strlen( dir ); + + FileFindHandle_t _handle; + char tmp[MASTERPATH_MAXLEN]; +// Q_snprintf( tmp, MAX_PATH, "%s\\*_preview_*.*", dir ); + Q_snprintf( tmp, sizeof( tmp ), "%s\\*.%s", dir, (pszExtension ? pszExtension : "*") ); + + char curFile[ MASTERPATH_MAXLEN ] = { '\0' }; + const char *tmpFile = g_pFullFileSystem->FindFirst( tmp, &_handle ); + if ( tmpFile ) + Q_strncpy( curFile, tmpFile, sizeof(curFile) ); + + while ( curFile[0] ) + { + bool bAddFile = pCheck ? pCheck( curFile ) : true; + + if ( bAddFile ) + { + int len = Q_strlen( curFile ); + len = len + dirlen + 2; + char *Addme = new char [len]; + Q_snprintf( Addme, len, "%s\\%s", dir, curFile ); + hFiles.AddToTail( Addme ); + } + + const char *tmpFile = g_pFullFileSystem->FindNext( _handle ); + if ( tmpFile ) + Q_strncpy( curFile, tmpFile, sizeof(curFile) ); + else + curFile[0] = '\0'; + } + + g_pFullFileSystem->FindClose( _handle ); +} + + +void PreviewCleanup() +{ + const bool bDBG = shaderEdit->ShouldShowPrimaryDbg(); + CUtlVector< char* >hFiles; + if ( bDBG ) + Msg("*** cleanup start ***\n"); + char tmp[MASTERPATH_MAXLEN]; + Q_snprintf( tmp, sizeof( tmp ), "%s", GetShaderSourceDirectory() ); + ListFiles( tmp, hFiles, NULL, &CheckPreviewMask ); + Q_snprintf( tmp, sizeof( tmp ), "%s\\shaders\\fxc", GetShaderSourceDirectory() ); + ListFiles( tmp, hFiles, NULL, &CheckPreviewMask ); + Q_snprintf( tmp, sizeof( tmp ), "%s\\shaders\\fxc", GetGamePath() ); + ListFiles( tmp, hFiles, NULL, &CheckPreviewMask ); +#if 0 //def SHADER_EDITOR_DLL_SWARM + Q_snprintf( tmp, sizeof( tmp ), "%s", GetSwarmShaderDirectory() ); + ListFiles( tmp, hFiles, NULL, &CheckPreviewMask ); +#endif + if ( bDBG ) + Msg("killing %i files:\n", hFiles.Count()); + for ( int i = 0; i < hFiles.Count(); i++ ) + { + if ( !hFiles[ i ] ) + { + Assert( 0 ); + continue; + } + + Q_memset( tmp, 0, sizeof( tmp ) ); + if ( *hFiles[ i ] ) + { + if ( g_pFullFileSystem->FileExists( hFiles[ i ] ) ) + { + g_pFullFileSystem->RemoveFile( hFiles[ i ] ); + if ( bDBG ) + Msg("deleting: %s\n", hFiles[ i ]); + } + else if ( g_pFullFileSystem->FullPathToRelativePath( hFiles[ i ], tmp, MASTERPATH_MAXLEN ) ) + { + g_pFullFileSystem->RemoveFile( tmp, "MOD" ); + if ( bDBG ) + Msg("deleting: %s\n", tmp); + } + } + delete [] hFiles[ i ]; + } + hFiles.Purge(); + if ( bDBG ) + Msg("*** cleanup end ***\n"); +} + + +#ifdef SHADER_EDITOR_DLL_SWARM +void CopyAllFiles( const char *pPathSrc, const char *pPathDst, const char *pszExtension = NULL, const bool bNoOverride = false, const bool bSwarmShader = false ) +{ + const bool bDBG = shaderEdit->ShouldShowPrimaryDbg(); + CUtlVector< char* >hFiles; + + ListFiles( pPathSrc, hFiles, pszExtension ); + + char fullPathSrc[MASTERPATH_MAXLEN]; + char fullPathTarget[MASTERPATH_MAXLEN]; + const char *filename; + + for ( int i = 0; i < hFiles.Count(); i++ ) + { + Assert( hFiles[i] != NULL ); + + if ( !g_pFullFileSystem->RelativePathToFullPath( hFiles[i], "MOD", fullPathSrc, sizeof(fullPathSrc) ) ) + Q_snprintf( fullPathSrc, sizeof(fullPathSrc), "%s", hFiles[i] ); + + filename = Q_UnqualifiedFileName( hFiles[i] ); + Q_snprintf( fullPathTarget, sizeof(fullPathTarget), "%s/%s", pPathDst, filename ); + + if ( bSwarmShader ) + ShaderNameToSwarmUnique( fullPathTarget, sizeof(fullPathTarget) ); + + if ( bNoOverride && g_pFullFileSystem->FileExists( fullPathTarget ) ) + continue; + + if ( bDBG ) + Msg( "FILE SRC: %s - FILE TARGET: %s\n", fullPathSrc, fullPathTarget ); + + EngineCopy( fullPathSrc, fullPathTarget ); + + delete [] hFiles[i]; + } + + hFiles.Purge(); +} + +void InitSwarmShaders() +{ + const bool bDBG = shaderEdit->ShouldShowPrimaryDbg(); + if ( bDBG ) + Msg("*** swarm auto copy start ***\n"); + + char swarm_shaders_dst[MASTERPATH_MAXLEN]; + if ( !g_pFullFileSystem->RelativePathToFullPath( GetSwarmShaderDirectory(), "MOD", swarm_shaders_dst, sizeof(swarm_shaders_dst) ) ) + Q_snprintf( swarm_shaders_dst, sizeof(swarm_shaders_dst), "%s", GetSwarmShaderDirectory() ); + + char user_shaders_src[MASTERPATH_MAXLEN]; + Q_snprintf( user_shaders_src, sizeof( user_shaders_src ), "%s\\shaders\\fxc", GetShaderSourceDirectory() ); + + char editor_shaders_src[MASTERPATH_MAXLEN]; + Q_snprintf( editor_shaders_src, sizeof( editor_shaders_src ), "%s\\redistribute\\shaders", GetEditorRootDirectory() ); + + CopyAllFiles( user_shaders_src, swarm_shaders_dst, "vcs", false, true ); + CopyAllFiles( editor_shaders_src, swarm_shaders_dst, "vcs" ); + + char editor_compiler_src[MASTERPATH_MAXLEN]; + Q_snprintf( editor_compiler_src, sizeof( editor_compiler_src ), "%s\\redistribute\\compiler", GetEditorRootDirectory() ); + + CopyAllFiles( editor_compiler_src, GetBinaryPath(), "dll", true ); + + if ( bDBG ) + Msg("*** swarm auto copy end ***\n"); +} +#endif + + +CON_COMMAND( shaderEditor_filecleanup, "" ) +{ + PreviewCleanup(); +} \ No newline at end of file diff --git a/sp/src/shadereditor/gpostprocessingcache.cpp b/sp/src/shadereditor/gpostprocessingcache.cpp new file mode 100644 index 00000000..1d55e52e --- /dev/null +++ b/sp/src/shadereditor/gpostprocessingcache.cpp @@ -0,0 +1,723 @@ + +#include "cbase.h" +#ifndef SHADER_EDITOR_DLL_2006 +#include "tier1/callqueue.h" +#endif +#include "editorCommon.h" + + +static CPostProcessingCache gs_ppcache; +CPostProcessingCache *GetPPCache(){ return &gs_ppcache; }; + + +EditorRenderViewCommand_Data::EditorRenderViewCommand_Data() +{ + AllocCheck_Alloc(); + + m_pszCallbackName = NULL; + functor = NULL; +} +EditorRenderViewCommand_Data::~EditorRenderViewCommand_Data() +{ + AllocCheck_Free(); + + delete [] m_pszCallbackName; + + for ( int i = 0; i < hValues_String.Count(); i++ ) + delete [] hValues_String[i]; +} +EditorRenderViewCommand_Data::EditorRenderViewCommand_Data( const EditorRenderViewCommand_Data &o ) +{ + AllocCheck_Alloc(); + + functor = o.functor; + + hValues_Bool.AddVectorToTail( o.hValues_Bool ); + hValues_Int.AddVectorToTail( o.hValues_Int ); + hValues_Float.AddVectorToTail( o.hValues_Float ); + + for ( int i = 0; i < o.hValues_String.Count(); i++ ) + { + int len = Q_strlen( o.hValues_String[i] ) + 1; + char *pszCpy = new char[ len ]; + Q_strcpy( pszCpy, o.hValues_String[i] ); + hValues_String.AddToTail( pszCpy ); + } + + AutoCopyStringPtr( o.m_pszCallbackName, &m_pszCallbackName ); +} +void EditorRenderViewCommand_Data::AddBoolValue( bool bVal ) +{ + hValues_Bool.AddToTail( bVal ); +} +void EditorRenderViewCommand_Data::AddIntValue( int iVal ) +{ + hValues_Int.AddToTail( iVal ); +} +void EditorRenderViewCommand_Data::AddFloatValue( float flVal ) +{ + hValues_Float.AddToTail( flVal ); +} +void EditorRenderViewCommand_Data::AddStringValue( const char *pszVal ) +{ + const char *pszDef = ""; + if ( !pszVal ) + pszVal = pszDef; + + int len = Q_strlen( pszVal ) + 1; + char *pStr = new char[ len ]; + + Q_strcpy( pStr, pszVal ); + hValues_String.AddToTail( pStr ); +} +const bool EditorRenderViewCommand_Data::GetBoolVal( const int &slot ) +{ + return hValues_Bool[ slot ]; +} +const int EditorRenderViewCommand_Data::GetIntVal( const int &slot ) +{ + return hValues_Int[ slot ]; +} +const float EditorRenderViewCommand_Data::GetFloatVal( const int &slot ) +{ + return hValues_Float[ slot ]; +} +const char *EditorRenderViewCommand_Data::GetStringVal( const int &slot ) +{ + return hValues_String[ slot ]; +} +void EditorRenderViewCommand_Data::ClearAllValues() +{ + for ( int i = 0; i < hValues_String.Count(); i++ ) + delete [] hValues_String[i]; + + hValues_Bool.Purge(); + hValues_Int.Purge(); + hValues_Float.Purge(); + hValues_String.Purge(); + + delete [] m_pszCallbackName; + m_pszCallbackName = NULL; +} +const char *EditorRenderViewCommand_Data::GetName() +{ + return m_pszCallbackName; +} +void EditorRenderViewCommand_Data::SetName( const char *name ) +{ + delete [] m_pszCallbackName; + m_pszCallbackName = NULL; + + AutoCopyStringPtr( name, &m_pszCallbackName ); + + if ( !m_pszCallbackName ) + { + m_pszCallbackName = new char[1]; + *m_pszCallbackName = '\0'; + } +} +void EditorRenderViewCommand_Data::ValidateMemory() +{ + if ( !GetName() ) + return; + + int index = GetName() ? GetPPCache()->FindVrCallback( GetName() ) : -1; + Assert( index >= 0 ); + + if ( index < 0 ) + return; + + EditorRenderViewCommand_Definition *pDef = GetPPCache()->GetVrCallback( index ); + if ( !pDef ) + return; + + functor = pDef->functor; + + while ( GetNumBool() < pDef->GetNumVars( EditorRenderViewCommand_Definition::VAR_BOOL ) ) + AddBoolValue( false ); + while ( GetNumInt() < pDef->GetNumVars( EditorRenderViewCommand_Definition::VAR_INT ) ) + AddIntValue( 0 ); + while ( GetNumFloat() < pDef->GetNumVars( EditorRenderViewCommand_Definition::VAR_FLOAT ) ) + AddFloatValue( 0 ); + while ( GetNumString() < pDef->GetNumVars( EditorRenderViewCommand_Definition::VAR_STRING ) ) + AddStringValue( "" ); +} +void EditorRenderViewCommand_Data::CallFunction() +{ + Assert( functor != NULL ); + + if ( functor == NULL ) + return; + + functor( hValues_Bool.Base(), hValues_Int.Base(), hValues_Float.Base(), hValues_String.Base() ); +} + + + + + +EditorRenderViewCommand_Definition::EditorRenderViewCommand_Definition() +{ + AllocCheck_Alloc(); + + m_pszCallbackName = NULL; + + for ( int i = 0; i < VAR_AMT; i++ ) + hVar_Names.AddToTail( new CUtlVector< char* >() ); +} +EditorRenderViewCommand_Definition::~EditorRenderViewCommand_Definition() +{ + AllocCheck_Free(); + + for ( int i = 0; i < VAR_AMT; i++ ) + { + for ( int s = 0; s < hVar_Names[i]->Count(); s++ ) + delete [] hVar_Names[i]->Element( s ); + } + + hVar_Names.PurgeAndDeleteElements(); + + delete [] m_pszCallbackName; +} +void EditorRenderViewCommand_Definition::AddVarToList( int type, const char *szName ) +{ + Assert( type >= 0 && type < VAR_AMT ); + + int len = Q_strlen( szName ) + 1; + char *szCopiedName = new char[ len ]; + Q_strcpy( szCopiedName, szName ); + + hVar_Names[ type ]->AddToTail( szCopiedName ); +} +const char *EditorRenderViewCommand_Definition::GetVarName( int type, int slot ) +{ + Assert( type >= 0 && type < VAR_AMT ); + Assert( slot >= 0 && slot < hVar_Names[ type ]->Count() ); + + return hVar_Names[ type ]->Element( slot ); +} +const int EditorRenderViewCommand_Definition::GetNumVars( int type ) +{ + Assert( type >= 0 && type < VAR_AMT ); + return hVar_Names[ type ]->Count(); +} +const char *EditorRenderViewCommand_Definition::GetName() +{ + return m_pszCallbackName; +} +void EditorRenderViewCommand_Definition::SetName( const char *name ) +{ + delete [] m_pszCallbackName; + m_pszCallbackName = NULL; + + AutoCopyStringPtr( name, &m_pszCallbackName ); + + if ( !m_pszCallbackName ) + { + m_pszCallbackName = new char[1]; + *m_pszCallbackName = '\0'; + } +} + + + + + +EditorPostProcessingEffect::EditorPostProcessingEffect() +{ + AllocCheck_Alloc(); + + Init(); +} +EditorPostProcessingEffect::EditorPostProcessingEffect( CUtlVector< CHLSL_SolverBase* > &hSolvers, GenericPPEData &config, bool bCopySolvers ) +{ + AllocCheck_Alloc(); + + Init(); + + bOwnsSolvers = bCopySolvers; + + this->config = config; + if ( bCopySolvers ) + CopySolvers( hSolvers, hSolverArray ); + else + hSolverArray.AddVectorToTail( hSolvers ); + + bReady = true; +} +void EditorPostProcessingEffect::Init() +{ + pszName = NULL; + pszPath = NULL; + bStartEnabled = false; + bReady = false; + bIsEnabled = false; + bOwnsSolvers = true; +} +EditorPostProcessingEffect::~EditorPostProcessingEffect() +{ + AllocCheck_Free(); + + delete [] pszName; + delete [] pszPath; + + if ( bOwnsSolvers ) + DestroySolverStack( hSolverArray ); + else + hSolverArray.Purge(); +} +EditorPostProcessingEffect::EditorPostProcessingEffect( const EditorPostProcessingEffect &o ) +{ + AllocCheck_Alloc(); + + pszName = NULL; + pszPath = NULL; + + AutoCopyStringPtr( o.pszName, &pszName ); + AutoCopyStringPtr( o.pszPath, &pszPath ); + bStartEnabled = o.bStartEnabled; + bIsEnabled = o.bIsEnabled; + bReady = o.bReady; + config = o.config; + bOwnsSolvers = o.bOwnsSolvers; + + if ( o.hSolverArray.Count() ) + CopySolvers( o.hSolverArray, hSolverArray ); +} +int EditorPostProcessingEffect::LoadPostProcessingChain( const char *Path, bool bStartEnabled ) +{ + if ( !Path || !*Path ) + return CPostProcessingCache::PPE_INVALID_INPUT; + + delete [] pszName; + delete [] pszPath; + DestroySolverStack( hSolverArray ); + + this->bStartEnabled = bStartEnabled; + bIsEnabled = bStartEnabled; + AutoCopyStringPtr( Path, &pszPath ); + + char fileBase[MAX_PATH*4]; + Q_FileBase( Path, fileBase, sizeof( fileBase ) ); + + if ( *fileBase ) + { + int len = Q_strlen( fileBase ) + 1; + pszName = new char[ len + 1 ]; + Q_strcpy( pszName, fileBase ); + } + + int retVal = CNodeView::CreatePPSolversFromFile( Path, hSolverArray, config ); + + bReady = retVal == CPostProcessingCache::PPE_OKAY; + + return retVal; +} +void EditorPostProcessingEffect::ReplacePostProcessingChain( CUtlVector< CHLSL_SolverBase* > &hNewSolvers ) +{ + DestroySolverStack( hSolverArray ); + CopySolvers( hNewSolvers, hSolverArray ); +} +IMaterial *EditorPostProcessingEffect::FindMaterial( const char *pszNodeName ) +{ + for ( int i = 0; i < hSolverArray.Count(); i++ ) + { + CHLSL_Solver_PP_Mat *pMatSolver = dynamic_cast< CHLSL_Solver_PP_Mat* >( hSolverArray[i] ); + + if ( !pMatSolver ) + continue; + + if ( !pMatSolver->GetNumTargetVars() ) + continue; + + IMaterial *pMat = pMatSolver->GetMaterial(); + + if ( IsErrorMaterial( pMat ) ) + continue; + + if ( !pMatSolver->GetNodeName() || !*pMatSolver->GetNodeName() ) + continue; + + if ( Q_stricmp( pMatSolver->GetNodeName(), pszNodeName ) ) + continue; + + return pMat; + } + + return NULL; +} + + + + + +CPostProcessingCache::CPostProcessingCache() : CAutoGameSystem( "postprocessingcache" ) +{ + m_bVrCallbacksLocked = false; +} + +CPostProcessingCache::~CPostProcessingCache() +{ + hEffects.Purge(); + m_hVrCallbacks.PurgeAndDeleteElements(); +} + +bool CPostProcessingCache::Init() +{ + //LoadPrecacheFile(); + + return true; +} + +void CPostProcessingCache::Shutdown() +{ +} + +int CPostProcessingCache::GetNumPostProcessingEffects() +{ + return hEffects.Count(); +} + +EditorPostProcessingEffect *CPostProcessingCache::GetPostProcessingEffect( int num ) +{ + return &hEffects[num]; +} + +int CPostProcessingCache::FindPostProcessingEffect( const char *name ) +{ + for ( int i = 0; i < hEffects.Count(); i++ ) + { + if ( !hEffects[i].pszName ) + continue; + + if ( !Q_stricmp( name, hEffects[i].pszName ) ) + return i; + } + return -1; +} + +CPostProcessingCache::PPE_Error CPostProcessingCache::AddPostProcessingEffect( EditorPostProcessingEffect *effect ) +{ + if ( !effect || !effect->pszName || !*effect->pszName ) + return PPE_INVALID_INPUT; + + for ( int i = 0; i < hEffects.Count(); i++ ) + if ( hEffects[i].pszName && !Q_stricmp( hEffects[i].pszName, effect->pszName ) ) + return PPE_INVALID_INPUT; + + hEffects.AddToTail( *effect ); + return PPE_OKAY; +} + +CPostProcessingCache::PPE_Error CPostProcessingCache::LoadPostProcessingEffect( const char *path, bool bStartEnabled ) +{ + EditorPostProcessingEffect effect; + CPostProcessingCache::PPE_Error error = (CPostProcessingCache::PPE_Error)effect.LoadPostProcessingChain( path, bStartEnabled ); + + if ( error != PPE_OKAY ) + return error; + + return AddPostProcessingEffect( &effect ); +} + +void CPostProcessingCache::DeletePostProcessingEffect( int index ) +{ + if ( !hEffects.IsValidIndex( index ) ) + return; + + hEffects.Remove( index ); +} + +int PPESort( const EditorPostProcessingEffect *p1, const EditorPostProcessingEffect *p2 ) +{ + if ( !(*p1).pszName || !(*p2).pszName ) + return 0; + + return Q_stricmp( (*p1).pszName, (*p2).pszName ); +} +void CPostProcessingCache::SortPostProcessingEffects() +{ + hEffects.Sort( PPESort ); +} +void CPostProcessingCache::MoveEffectAlongList( int index, bool bUp ) +{ + if ( !hEffects.IsValidIndex( index ) ) + return; + + if ( index == 0 && bUp ) + return; + if ( index == hEffects.Count() - 1 && !bUp ) + return; + + EditorPostProcessingEffect effect = hEffects[index]; + hEffects.Remove( index ); + + if ( bUp ) + hEffects.InsertBefore( index - 1, effect ); + else + hEffects.InsertAfter( index, effect ); +} + +void CPostProcessingCache::InitializeMaterials() +{ + CMatRenderContextPtr pRenderContext( materials ); + RunCodeContext rContext( false, false ); + rContext.pRenderContext = pRenderContext; + + for ( int i = 0; i < hEffects.Count(); i++ ) + { + EditorPostProcessingEffect *effect = &hEffects[i]; + + for ( int s = 0; s < effect->hSolverArray.Count(); s++ ) + { + Assert( dynamic_cast< CHLSL_Solver_PP_Base* >( effect->hSolverArray[s] ) || + dynamic_cast< CHLSL_Solver_Dummy* >( effect->hSolverArray[s] ) ); + + if ( dynamic_cast< CHLSL_Solver_PP_Mat* >( effect->hSolverArray[s] ) != NULL ) + { + effect->hSolverArray[s]->Invoke_ExecuteCode( rContext ); + + Assert( effect->hSolverArray[s]->GetNumTargetVars() > 0 && + !IsErrorMaterial( effect->hSolverArray[s]->GetTargetVar(0)->GetMaterial() ) ); + } + } + } +} + +void CPostProcessingCache::RenderAllEffects( bool bScene ) +{ + for ( int i = 0; i < hEffects.Count(); i++ ) + { + if ( !hEffects[i].bReady ) + continue; + + if ( !hEffects[i].bIsEnabled ) + continue; + + RenderSinglePPE( &hEffects[i], false, bScene ); + } +} + +void CPostProcessingCache::RenderSinglePPE( EditorPostProcessingEffect *effect, bool bPreviewMode, bool bSceneMode, bool bOwnsEffect ) +{ + RenderSinglePPE( effect, -1, -1, -1, -1, bPreviewMode, bSceneMode, bOwnsEffect ); +} + +void CPostProcessingCache::RenderSinglePPE( EditorPostProcessingEffect *effect, int x, int y, int w, int h, + bool bPreviewMode, bool bSceneMode, bool bOwnsEffect ) +{ + if ( !effect ) + return; + + CMatRenderContextPtr pRenderContext( materials ); + + static ConVarRef r_queued_post_processing( "r_queued_post_processing", "1" ); + +#ifndef SHADER_EDITOR_DLL_2006 + if ( !bSceneMode && r_queued_post_processing.GetInt() ) + { + ICallQueue *pCallQueue = pRenderContext->GetCallQueue(); + if ( pCallQueue ) + { + AssertMsg( !bOwnsEffect, "Mem leak." ); + + EditorPostProcessingEffect *pNewEffect = new EditorPostProcessingEffect( *effect ); + return pCallQueue->QueueCall( CPostProcessingCache::RenderSinglePPE, pNewEffect, x, y, w, h, bPreviewMode, bSceneMode, true ); + } + } +#endif + + if ( !bSceneMode && effect->config.bDoAutoUpdateFBCopy ) + { + if ( w > 0 ) + { + UpdateScreenEffectTexture( GetFBTex(), x, y, w, h, true ); + } + else + { + GeneralFramebufferUpdate( pRenderContext ); + } + } + + RunCodeContext rContext( bPreviewMode, bSceneMode ); + rContext.pRenderContext = pRenderContext; + + for ( int i = 0; i < effect->hSolverArray.Count(); i++ ) + { + Assert( dynamic_cast< CHLSL_Solver_PP_Base* >( effect->hSolverArray[i] ) || + dynamic_cast< CHLSL_Solver_Dummy* >( effect->hSolverArray[i] ) ); + + effect->hSolverArray[i]->Invoke_ExecuteCode( rContext ); + } + + if ( bOwnsEffect ) + { + delete effect; + } +} + +void CPostProcessingCache::RefreshAllPPEMaterials() +{ + for ( int i = 0; i < hEffects.Count(); i++ ) + { + RefreshAllPPEMaterials( hEffects[i].hSolverArray ); + } + + if ( IsInEditMode() ) + { + for ( int i = 0; i < pEditorRoot->GetNumFlowGraphs(); i++ ) + { + CNodeView *pView = pEditorRoot->GetFlowGraph( i ); + + if ( pView->GetFlowgraphType() != CNodeView::FLOWGRAPH_POSTPROC ) + continue; + + RefreshAllPPEMaterials( pView->AccessSolverStack_POSTPROC() ); + } + } +} + +void CPostProcessingCache::RefreshAllPPEMaterials( CUtlVector< CHLSL_SolverBase* > &hSolvers ) +{ + for ( int i = 0; i < hSolvers.Count(); i++ ) + { + CHLSL_Solver_PP_Mat *pMatSolver = dynamic_cast< CHLSL_Solver_PP_Mat* >( hSolvers[i] ); + if ( !pMatSolver ) + continue; + + if ( !pMatSolver->GetNumTargetVars() ) + continue; + + IMaterial *pMat = pMatSolver->GetTargetVar(0)->GetMaterial(); + + if ( IsErrorMaterial( pMat ) ) + { + Assert( 0 ); + return; + } + + pMat->Refresh(); + } +} + +const char *CPostProcessingCache::GetPPEffectPrecacheFile() +{ + static char tmp[MAX_PATH*4]; + Q_snprintf( tmp, sizeof(tmp), "%s/postprocessing_precache.txt", GetEditorRootDirectory() ); + + return tmp; +} + +void CPostProcessingCache::LoadPrecacheFile() +{ + KeyValues *pKV = new KeyValues( "pp_precache" ); + + if ( pKV->LoadFromFile( g_pFullFileSystem, GetPPEffectPrecacheFile() ) ) + { + for ( KeyValues *pSub = pKV->GetFirstTrueSubKey(); pSub; pSub = pSub->GetNextTrueSubKey() ) + { + const char *pszEffectPath = pSub->GetString( "effect_path" ); + if ( !*pszEffectPath ) + continue; + + const bool bStartEnabled = !!pSub->GetInt( "effect_start_enabled" ); + + EditorPostProcessingEffect effect; + if ( effect.LoadPostProcessingChain( pszEffectPath, bStartEnabled ) != PPE_OKAY ) + { + Warning( "Unable to precache post processing effect: %s!!!\n", pszEffectPath ); + continue; + } + + if ( AddPostProcessingEffect( &effect ) != PPE_OKAY ) + Warning( "Unable to add post processing effect '%s' to precache list, duplicate names?\n", pszEffectPath ); + } + } + + pKV->deleteThis(); + + InitializeMaterials(); +} + +void CPostProcessingCache::SavePrecacheFile() +{ + KeyValues *pKV = new KeyValues( "pp_precache" ); + + for ( int i = 0; i < hEffects.Count(); i++ ) + { + EditorPostProcessingEffect *effect = &hEffects[i]; + + if ( !effect->pszName || !effect->pszPath ) + continue; + + KeyValues *pKVEffect = new KeyValues( VarArgs("effect_%02i",i) ); + + pKVEffect->SetString( "effect_path", effect->pszPath ); + pKVEffect->SetInt( "effect_start_enabled", effect->bStartEnabled ? 1 : 0 ); + + pKV->AddSubKey( pKVEffect ); + } + + pKV->SaveToFile( g_pFullFileSystem, GetPPEffectPrecacheFile() ); + + pKV->deleteThis(); +} + +void CPostProcessingCache::ClearInvalidEntries() +{ + for ( int i = 0; i < hEffects.Count(); i++ ) + { + if ( !hEffects[i].pszName || !hEffects[i].pszPath || + !*hEffects[i].pszName || !*hEffects[i].pszPath || + !hEffects[i].bReady ) + { + hEffects.Remove( i ); + i--; + } + } +} + + +void CPostProcessingCache::LockVrCallbacks() +{ + m_bVrCallbacksLocked = true; +} + +bool CPostProcessingCache::AddVrCallback( EditorRenderViewCommand_Definition *pCallback ) +{ + for ( int i = 0; i < m_hVrCallbacks.Count(); i++ ) + { + if ( !Q_stricmp( pCallback->GetName(), m_hVrCallbacks[i]->GetName() ) ) + { + delete pCallback; + return false; + } + } + + m_hVrCallbacks.AddToTail( pCallback ); + return true; +} + +int CPostProcessingCache::GetNumVrCallbacks() +{ + if ( !m_bVrCallbacksLocked ) + return 0; + + return m_hVrCallbacks.Count(); +} + +EditorRenderViewCommand_Definition *CPostProcessingCache::GetVrCallback( int index ) +{ + if ( !m_bVrCallbacksLocked ) + return NULL; + + return m_hVrCallbacks[ index ]; +} + +int CPostProcessingCache::FindVrCallback( const char *szName ) +{ + for ( int i = 0; i < m_hVrCallbacks.Count() && m_bVrCallbacksLocked; i++ ) + if ( !Q_stricmp( m_hVrCallbacks[i]->GetName(), szName ) ) + return i; + return -1; +} \ No newline at end of file diff --git a/sp/src/shadereditor/gpostprocessingcache.h b/sp/src/shadereditor/gpostprocessingcache.h new file mode 100644 index 00000000..42ac0003 --- /dev/null +++ b/sp/src/shadereditor/gpostprocessingcache.h @@ -0,0 +1,174 @@ +#ifndef POST_PROCESSING_CACHE_H +#define POST_PROCESSING_CACHE_H + +#include "cbase.h" +#include "editorCommon.h" + +// used to actually call the func +struct EditorRenderViewCommand_Data +{ +public: + + EditorRenderViewCommand_Data(); + ~EditorRenderViewCommand_Data(); + EditorRenderViewCommand_Data( const EditorRenderViewCommand_Data &o ); + + void AddBoolValue( bool bVal ); + void AddIntValue( int iVal ); + void AddFloatValue( float flVal ); + void AddStringValue( const char *pszVal ); + + const bool GetBoolVal( const int &slot ); + const int GetIntVal( const int &slot ); + const float GetFloatVal( const int &slot ); + const char *GetStringVal( const int &slot ); + + const int GetNumBool(){ return hValues_Bool.Count(); }; + const int GetNumInt(){ return hValues_Int.Count(); }; + const int GetNumFloat(){ return hValues_Float.Count(); }; + const int GetNumString(){ return hValues_String.Count(); }; + + void ClearAllValues(); + void ValidateMemory(); + void CallFunction(); + + const char *GetName(); + void SetName( const char *name ); + +private: + CUtlVector< bool > hValues_Bool; + CUtlVector< int > hValues_Int; + CUtlVector< float > hValues_Float; + CUtlVector< char* > hValues_String; + + char *m_pszCallbackName; + + pFnVrCallback( functor ); +}; + +// instantiated through the client +struct EditorRenderViewCommand_Definition +{ +public: + + EditorRenderViewCommand_Definition(); + ~EditorRenderViewCommand_Definition(); + + enum + { + VAR_BOOL = 0, + VAR_INT, + VAR_FLOAT, + VAR_STRING, + VAR_AMT, + }; + + const char *GetName(); + void SetName( const char *name ); + + void AddVarToList( int type, const char *szName ); + const char *GetVarName( int type, int slot ); + const int GetNumVars( int type ); + + pFnVrCallback( functor ); + + EditorRenderViewCommand_Data defaults; + +private: + EditorRenderViewCommand_Definition( const EditorRenderViewCommand_Definition &o ); + + CUtlVector< CUtlVector< char* >* >hVar_Names; + char *m_pszCallbackName; +}; + + +struct EditorPostProcessingEffect +{ +public: + + EditorPostProcessingEffect(); + EditorPostProcessingEffect( CUtlVector< CHLSL_SolverBase* > &hSolvers, GenericPPEData &config, bool bCopySolvers = true ); + ~EditorPostProcessingEffect(); + EditorPostProcessingEffect( const EditorPostProcessingEffect &o ); + + void Init(); + + char *pszName; + char *pszPath; + + bool bStartEnabled; + bool bReady; + bool bIsEnabled; + bool bOwnsSolvers; + + int LoadPostProcessingChain( const char *Path, bool bStartEnabled ); + void ReplacePostProcessingChain( CUtlVector< CHLSL_SolverBase* > &hNewSolvers ); + IMaterial *FindMaterial( const char *pszNodeName ); + + CUtlVector< CHLSL_SolverBase* > hSolverArray; + GenericPPEData config; +}; + + +class CPostProcessingCache : public CAutoGameSystem +{ +public: + + CPostProcessingCache(); + ~CPostProcessingCache(); + + enum PPE_Error + { + PPE_OKAY = 0, + PPE_INVALID_INPUT, + PPE_INVALID_GRAPH_TYPE, + PPE_GRAPH_NOT_VALID, + }; + + virtual bool Init(); + virtual void Shutdown(); + + const char *GetPPEffectPrecacheFile(); + void LoadPrecacheFile(); + void SavePrecacheFile(); + void ClearInvalidEntries(); + + void RefreshAllPPEMaterials(); + void RefreshAllPPEMaterials( CUtlVector< CHLSL_SolverBase* > &hSolvers ); + + int GetNumPostProcessingEffects(); + EditorPostProcessingEffect *GetPostProcessingEffect( int num ); + int FindPostProcessingEffect( const char *name ); + PPE_Error AddPostProcessingEffect( EditorPostProcessingEffect *effect ); + PPE_Error LoadPostProcessingEffect( const char *path, bool bStartEnabled ); + void DeletePostProcessingEffect( int index ); + + void SortPostProcessingEffects(); + void MoveEffectAlongList( int index, bool bUp ); + + void RenderAllEffects( bool bScene ); + static void RenderSinglePPE( EditorPostProcessingEffect *effect, bool bPreviewMode = false, bool bSceneMode = false, bool bOwnsEffect = false ); + static void RenderSinglePPE( EditorPostProcessingEffect *effect, int x, int y, int w, int h, + bool bPreviewMode = false, bool bSceneMode = false, bool bOwnsEffect = false ); + + void LockVrCallbacks(); + bool AddVrCallback( EditorRenderViewCommand_Definition *pCallback ); + int GetNumVrCallbacks(); + EditorRenderViewCommand_Definition *GetVrCallback( int index ); + int FindVrCallback( const char *szName ); + +private: + + CUtlVector< EditorPostProcessingEffect >hEffects; + CUtlVector< EditorRenderViewCommand_Definition* > m_hVrCallbacks; + + bool m_bVrCallbacksLocked; + + void InitializeMaterials(); + +}; + + +CPostProcessingCache *GetPPCache(); + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/grendertargetconfig.cpp b/sp/src/shadereditor/grendertargetconfig.cpp new file mode 100644 index 00000000..d7e623f0 --- /dev/null +++ b/sp/src/shadereditor/grendertargetconfig.cpp @@ -0,0 +1,468 @@ + +#include "cbase.h" +#include "editorCommon.h" + +static CMaterialSysDeletionHelper gMatSysDelHint; +CMaterialSysDeletionHelper *GetMatSysShutdownHelper(){ return &gMatSysDelHint;}; + +RTDef::RTDef() +{ + szRTName[0] = '\0'; + ref = NULL; + Format = IMAGE_FORMAT_RGBA8888; + DepthMode = MATERIAL_RT_DEPTH_NONE; + SizeMode = RT_SIZE_NO_CHANGE; + x = y = RT_DEFAULT_SIZE; + + bDirty = false; + bFlaggedForDeletion = false; +} + +RTDef::RTDef( const char *pszName, + ImageFormat format, RenderTargetSizeMode_t sizemode, MaterialRenderTargetDepth_t depthmode, + int x, int y, unsigned int rtflags ) +{ + Assert( pszName && *pszName ); + + Q_snprintf( szRTName, sizeof(szRTName), "%s", pszName ); + ref = NULL; + Format = format; + DepthMode = depthmode; + SizeMode = sizemode; + iRTFlags = rtflags; + this->x = x; + this->y = y; + + bDirty = true; + bFlaggedForDeletion = false; + //ref.InitRenderTarget( 256, 256, sizemode, format, depthmode, false, pszName ); +} + +RTDef::~RTDef() +{ + //if ( !GetMatSysShutdownHelper()->IsShuttingDown() && ref.IsValid() ) + // ref.Shutdown(); + //ref.Shutdown( true ); +} + +const char *RTDef::GetName() const +{ + return szRTName; +} +ImageFormat RTDef::GetImgFormat() +{ + return Format; +} +RenderTargetSizeMode_t RTDef::GetSizeMode() +{ + return SizeMode; +} +MaterialRenderTargetDepth_t RTDef::GetDepthMode() +{ + return DepthMode; +} +unsigned int RTDef::GetFlags() +{ + return iRTFlags; +} +int RTDef::GetSizeX() +{ + return x; +} +int RTDef::GetSizeY() +{ + return y; +} + +bool RTDef::IsValid() +{ + return ref != NULL; //ref.IsValid(); +} + +void RTDef::Allocate() +{ + Assert( *GetName() ); + + RenderTargetSizeMode_t local_sizemode = SizeMode; + + if ( local_sizemode == RT_SIZE_HALF_FRAME_BUFFER ) + local_sizemode = RT_SIZE_NO_CHANGE; + + ITexture *pTex = materials->CreateNamedRenderTargetTextureEx( szRTName, + x, y, SizeMode, Format, DepthMode, iRTFlags, 0 ); + //ref.Init( pTex ); + ref = pTex; + + bDirty = false; +} + +void RTDef::Deallocate() +{ + if ( ref != NULL ) //ref.IsValid() ) + { + //ITexture *pTex = ref; + //ref.Shutdown( false ); + + //ForceDeleteTexture( &pTex ); + + //ForceDeleteTexture( &ref ); + //ref.Shutdown( true ); + + ref = NULL; + } +} + +void RTDef::Modify( RTDef &src ) +{ + Modify( src.GetName(), &src.Format, &src.SizeMode, &src.DepthMode, &src.x, &src.y, &src.iRTFlags ); +} + +void RTDef::Modify( const char *pszName, + ImageFormat *format, RenderTargetSizeMode_t *sizemode, MaterialRenderTargetDepth_t *depthmode, + int *x, int *y, unsigned int *rtflags ) +{ + bool bChanges = false; + if ( pszName != NULL && Q_strlen( pszName ) ) + { + bChanges = bChanges || Q_strcmp( szRTName, pszName ); + Q_snprintf( szRTName, sizeof(szRTName), "%s", pszName ); + } + + if ( format != NULL ) + { + bChanges = bChanges || Format != *format; + Format = *format; + } + + if ( depthmode != NULL ) + { + bChanges = bChanges || DepthMode != *depthmode; + DepthMode = *depthmode; + } + + if ( sizemode != NULL ) + { + bChanges = bChanges || SizeMode != *sizemode; + SizeMode = *sizemode; + } + + if ( rtflags != NULL ) + { + bChanges = bChanges || iRTFlags != *rtflags; + iRTFlags = *rtflags; + } + + if ( x != NULL ) + { + bChanges = bChanges || this->x != *x; + this->x = *x; + } + + if ( y != NULL ) + { + bChanges = bChanges || this->y != *y; + this->y = *y; + } + + if ( bChanges ) + MakeDirty(); +} + +bool RTDef::IsDirty() +{ + return bDirty; +} + +void RTDef::MakeDirty() +{ + bDirty = true; +} + +bool RTDef::IsFlaggedForDeletion() +{ + return bFlaggedForDeletion; +} + +void RTDef::FlagForDeletion() +{ + bFlaggedForDeletion = true; +} + +void RTDef::Revalidate() +{ + bFlaggedForDeletion = false; +} + +static RenderTargetManager gs_RenderTargetManager; +RenderTargetManager *GetRTManager(){ return &gs_RenderTargetManager; }; + +//CUtlVector< RTDef > RenderTargetManager::m_hRTs; + +void UpdateCustomAutoSizing() +{ + int bbx, bby; + materials->GetBackBufferDimensions( bbx, bby ); + + int halfx = bbx / 2; + int halfy = bby / 2; + + for ( int i = 0; i < GetRTManager()->GetNumRTs(); i++ ) + { + RTDef *rt = GetRTManager()->GetRT(i); + + if ( rt->GetSizeMode() == RT_SIZE_HALF_FRAME_BUFFER ) + { + rt->Modify( NULL, NULL, NULL, NULL, &halfx, &halfy ); + } + } +} + +#ifdef SHADER_EDITOR_DLL_2006 +void EditorRTs_Release() +{ + GetRTManager()->MakeRTCacheDirty(); +} +void EditorRTs_Restore( int nChangeFlags ) +{ + GetRTManager()->MakeRTCacheDirty(); +} +#else +void EditorRTs_ModeChangeCallback() +{ + GetRTManager()->MakeRTCacheDirty(); +} +#endif + +RenderTargetManager::RenderTargetManager() : CAutoGameSystemPerFrame( "rtmanagersys" ) +{ + m_bCacheDirty = false; +} + +RenderTargetManager::~RenderTargetManager() +{ + //Assert( !m_hRTs.Count() ); +} + +const char *RenderTargetManager::GetRTSetupFilePath() +{ + static char rtpath[MAX_PATH*4]; + Q_snprintf( rtpath, sizeof(rtpath), "%s/rtsetup.txt", GetEditorRootDirectory() ); + return rtpath; +} + +bool RenderTargetManager::Init() +{ + KeyValues *pRTSetup = new KeyValues( "rt_setup" ); + + if ( pRTSetup->LoadFromFile( g_pFullFileSystem, GetRTSetupFilePath() ) ) + { + for ( KeyValues *pSub = pRTSetup->GetFirstTrueSubKey(); pSub; pSub = pSub->GetNextTrueSubKey() ) + { + const char *pszName = pSub->GetString( "rt_name" ); + + if ( !pszName || !*pszName ) + continue; + + ImageFormat format = (ImageFormat)pSub->GetInt( "rt_imgformat", IMAGE_FORMAT_RGBA8888 ); + RenderTargetSizeMode_t sizemode = (RenderTargetSizeMode_t)pSub->GetInt( "rt_sizemode", RT_SIZE_FULL_FRAME_BUFFER ); + MaterialRenderTargetDepth_t depthmode = (MaterialRenderTargetDepth_t)pSub->GetInt( "rt_depthmode", MATERIAL_RT_DEPTH_NONE ); + unsigned int flags = (unsigned int)pSub->GetInt( "rt_flags", 0 ); + int x = pSub->GetInt( "rt_size_x", 0 ); + int y = pSub->GetInt( "rt_size_y", 0 ); + + RTDef rt( pszName, format, sizemode, depthmode, x, y, flags ); + m_hRTs.AddToTail( rt ); + } + } + + pRTSetup->deleteThis(); + +#ifdef SHADER_EDITOR_DLL_2006 + materials->AddReleaseFunc( &EditorRTs_Release ); + materials->AddRestoreFunc( &EditorRTs_Restore ); +#else + materials->AddModeChangeCallBack( &EditorRTs_ModeChangeCallback ); +#endif + UpdateRTsToMatSys( true ); + + return true; +} + +void RenderTargetManager::Shutdown() +{ + for ( int i = 0; i < m_hRTs.Count(); i++ ) + m_hRTs[i].FlagForDeletion(); + + UpdateRTsToMatSys(); +#ifdef SHADER_EDITOR_DLL_2006 + materials->RemoveReleaseFunc( &EditorRTs_Release ); + materials->RemoveRestoreFunc( &EditorRTs_Restore ); +#else + materials->RemoveModeChangeCallBack( &EditorRTs_ModeChangeCallback ); +#endif +} + +void RenderTargetManager::PreRender() +{ + if ( m_bCacheDirty ) + { + m_bCacheDirty = false; + + UpdateCustomAutoSizing(); + UpdateRTsToMatSys(); + } +} + +void RenderTargetManager::MakeRTCacheDirty() +{ + m_bCacheDirty = true; +} + +void RenderTargetManager::SaveRTsToFile() +{ + KeyValues *pRTSetup = new KeyValues( "rt_setup" ); + + for ( int i = 0; i < m_hRTs.Count(); i++ ) + { + RTDef *rt = &m_hRTs[i]; + + if ( !Q_strlen( rt->GetName() ) ) + continue; + + if ( rt->IsFlaggedForDeletion() ) + continue; + + KeyValues *pSub = new KeyValues( VarArgs("rt_%02i",i) ); + + pSub->SetString( "rt_name", rt->GetName() ); + pSub->SetInt( "rt_imgformat", rt->GetImgFormat() ); + pSub->SetInt( "rt_sizemode", rt->GetSizeMode() ); + pSub->SetInt( "rt_depthmode", rt->GetDepthMode() ); + pSub->SetInt( "rt_flags", rt->GetFlags() ); + pSub->SetInt( "rt_size_x", rt->GetSizeX() ); + pSub->SetInt( "rt_size_y", rt->GetSizeY() ); + + pRTSetup->AddSubKey( pSub ); + } + + pRTSetup->SaveToFile( g_pFullFileSystem, GetRTSetupFilePath() ); + pRTSetup->deleteThis(); +} + +void RenderTargetManager::UpdateRTsToMatSys( bool bOnStartup ) +{ + bool bHasDirtyRTs = false; + + for ( int i = 0; i < m_hRTs.Count() && !bHasDirtyRTs; i++ ) + { + RTDef *rt = &m_hRTs[i]; + + bHasDirtyRTs = /*rt->IsFlaggedForDeletion() ||*/ rt->IsDirty(); + } + + if ( !bHasDirtyRTs ) + return; + + if ( GetMatSysShutdownHelper()->IsShuttingDown() ) + { + m_hRTs.Purge(); + return; + } + + UpdateCustomAutoSizing(); + +#if 0 + materials->BeginRenderTargetAllocation(); + for ( int i = 0; i < m_hRTs.Count(); i++ ) + { + RTDef *rt = &m_hRTs[i]; + + if ( rt->IsFlaggedForDeletion() ) + { + rt->Deallocate(); + m_hRTs.Remove( i ); + i--; + continue; + } + + //Assert( rt->IsValid() ); + } + materials->EndRenderTargetAllocation(); +#endif + +#ifdef SHADER_EDITOR_DLL_SWARM + if ( !bOnStartup ) + { + // srsly? SRSLY? + materials->ReEnableRenderTargetAllocation_IRealizeIfICallThisAllTexturesWillBeUnloadedAndLoadTimeWillSufferHorribly(); + } +#endif + + materials->BeginRenderTargetAllocation(); + for ( int i = 0; i < m_hRTs.Count(); i++ ) + { + RTDef *rt = &m_hRTs[i]; + + if ( rt->IsDirty() ) + { + rt->Deallocate(); + rt->Allocate(); + } + + Assert( rt->IsValid() ); + } + materials->EndRenderTargetAllocation(); + +#ifdef SHADER_EDITOR_DLL_SWARM + engine->ClientCmd_Unrestricted( "mat_reloadallmaterials" ); +#endif +} + +int RenderTargetManager::GetNumRTs() +{ + return m_hRTs.Count(); +} + +RTDef *RenderTargetManager::GetRT( int id ) +{ + return &m_hRTs[id]; +} + +void RenderTargetManager::RemoveRT( int index ) +{ + m_hRTs.Remove( index ); +} + +void RenderTargetManager::AddRT( RTDef rt ) +{ + m_hRTs.AddToTail( rt ); +} + +int RTSort( const RTDef *p1, const RTDef *p2 ) +{ + return Q_stricmp( (*p1).GetName(), p2->GetName() ); +} +void RenderTargetManager::SortRTsByName() +{ + m_hRTs.Sort( RTSort ); +} + +RTDef *RenderTargetManager::FindRTByName( const char *name, bool bIgnoreFlaggedForDel ) +{ + for ( int i = 0; i < m_hRTs.Count(); i++ ) + if ( !Q_stricmp( name, m_hRTs[i].GetName() ) && + ( !bIgnoreFlaggedForDel || !m_hRTs[i].IsFlaggedForDeletion() ) ) + return &m_hRTs[i]; + + return NULL; +} + +int RenderTargetManager::FindRTIndexByName( const char *name, bool bIgnoreFlaggedForDel ) +{ + for ( int i = 0; i < m_hRTs.Count(); i++ ) + if ( !Q_stricmp( name, m_hRTs[i].GetName() ) && + ( !bIgnoreFlaggedForDel || !m_hRTs[i].IsFlaggedForDeletion() ) ) + return i; + + return -1; +} \ No newline at end of file diff --git a/sp/src/shadereditor/grendertargetconfig.h b/sp/src/shadereditor/grendertargetconfig.h new file mode 100644 index 00000000..14446f16 --- /dev/null +++ b/sp/src/shadereditor/grendertargetconfig.h @@ -0,0 +1,70 @@ +#ifndef RTCONFIG_H +#define RTCONFIG_H + +#include "cbase.h" +#include "editorCommon.h" + +#define RT_DEFAULT_SIZE 256 +#define RT_MAX_SIZE 4096 + +#ifdef SHADER_EDITOR_DLL_2013 +#define LAST_VALVE_RT_SIZEMODE RT_SIZE_REPLAY_SCREENSHOT +#else +#define LAST_VALVE_RT_SIZEMODE RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP +#endif + +#define RT_SIZE_HALF_FRAME_BUFFER ((RenderTargetSizeMode_t)(LAST_VALVE_RT_SIZEMODE+1)) + +class CMaterialSysDeletionHelper : public CAutoGameSystem +{ +public: + CMaterialSysDeletionHelper() : CAutoGameSystem( "matsysdeletionhelper" ){ + m_bShuttingDown = false; + }; + + void Shutdown(){ + m_bShuttingDown = true; + }; + + bool IsShuttingDown(){ return m_bShuttingDown; }; + +private: + bool m_bShuttingDown; +}; + + +class RenderTargetManager : public CAutoGameSystemPerFrame +{ +public: + + RenderTargetManager(); + ~RenderTargetManager(); + + bool Init(); + void Shutdown(); + void PreRender(); + + void MakeRTCacheDirty(); + void UpdateRTsToMatSys( bool bOnStartup = false ); + void SaveRTsToFile(); + const char *GetRTSetupFilePath(); + + int GetNumRTs(); + RTDef *GetRT( int id ); + void RemoveRT( int index ); + void AddRT( RTDef rt ); + RTDef *FindRTByName( const char *name, bool bIgnoreFlaggedForDel = false ); + int FindRTIndexByName( const char *name, bool bIgnoreFlaggedForDel = false ); + + void SortRTsByName(); + +private: + CUtlVector< RTDef > m_hRTs; + bool m_bCacheDirty; +}; + +RenderTargetManager *GetRTManager(); +CMaterialSysDeletionHelper *GetMatSysShutdownHelper(); + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/gshaderdumps.cpp b/sp/src/shadereditor/gshaderdumps.cpp new file mode 100644 index 00000000..39db097b --- /dev/null +++ b/sp/src/shadereditor/gshaderdumps.cpp @@ -0,0 +1,415 @@ + +#include "cbase.h" +#include "editorCommon.h" + +void GetDumpListFilePath( char *out, int maxlen ) +{ + Q_snprintf( out, maxlen, "%s/shaderlist.txt", ::GetDumpDirectory() ); + Q_FixSlashes( out ); +} + +KeyValues *df_LoadDump_List() +{ + char path_dump_list[MAX_PATH]; + GetDumpListFilePath( path_dump_list, MAX_PATH ); + + KeyValues *pKV = new KeyValues( "shaderlist" ); + pKV->LoadFromFile( g_pFullFileSystem, path_dump_list, "MOD" ); + return pKV; +} + +void df_SaveDump_List( KeyValues *pKV ) +{ + char path_dump_list[MAX_PATH]; + GetDumpListFilePath( path_dump_list, MAX_PATH ); + + pKV->SaveToFile( g_pFullFileSystem, path_dump_list, "MOD" ); + pKV->deleteThis(); +} + +void ReadGameShaders( CUtlVector &hList ) +{ + KeyValues *pKV = df_LoadDump_List(); + + KeyValues *pN = pKV->GetFirstValue(); + while ( pN ) + { + BasicShaderCfg_t *shader = BuildShaderData( pN->GetString() ); + hList.AddToTail( shader ); + + pN = pN->GetNextValue(); + } + + pKV->deleteThis(); +} + +void LoadGameShaders( bool bFirstRun ) +{ + CUtlVector< BasicShaderCfg_t* >hListShaders; + + ReadGameShaders( hListShaders ); + + for ( int i = 0; i < hListShaders.Count(); i++ ) + { + const int iIndex = bFirstRun ? -1 : gProcShaderCTRL->FindPreloadShader( hListShaders[i]->CanvasName ); + + if ( iIndex < 0 ) + { + gProcShaderCTRL->AddPreloadShader( hListShaders[i] ); + } + else + { + BasicShaderCfg_t *trash = (BasicShaderCfg_t*)gProcShaderCTRL->SwapPreloadShader( iIndex, hListShaders[i] ); + delete trash; + } + } + + hListShaders.Purge(); +} + + +void UnloadGameShaders() +{ + if ( !gProcShaderCTRL ) + return; + + while ( gProcShaderCTRL->GetNumPreloadShaders() ) + { + BasicShaderCfg_t *shader = ( BasicShaderCfg_t* )gProcShaderCTRL->GetAndRemovePreloadShader( 0 ); + delete shader; + } + + for ( int i = 0; i < 2; i++ ) + { + BasicShaderCfg_t *old = ( BasicShaderCfg_t* )gProcShaderCTRL->SwapShaderSystem( NULL, i ); + delete old; + } +} + + +void ReadKVIdents_Texture( CUtlVector< SimpleTexture* > &hList, KeyValues *pKV ) +{ + int itr = 0; + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "texsamp_%i", itr ); + KeyValues *c = pKV->FindKey( tmp ); + + while( c ) + { + SimpleTexture *tex = new SimpleTexture(); + + const char *paramname = c->GetString( "sz_param" ); + int len = Q_strlen( paramname ) + 1; + tex->szParamName = new char[ len ]; + Q_snprintf( tex->szParamName, MAX_PATH, "%s", paramname ); + + const char *fallbackname = c->GetString( "sz_fallback" ); + len = Q_strlen( fallbackname ) + 1; + tex->szFallbackName = new char[ len ]; + Q_snprintf( tex->szFallbackName, MAX_PATH, "%s", fallbackname ); + + tex->iSamplerIndex = c->GetInt( "i_sampidx" ); + tex->iTextureMode = c->GetInt( "i_texmode" ); + tex->bCubeTexture = !!c->GetInt( "i_cubemap" ); + tex->bSRGB = !!c->GetInt( "i_srgb" ); + + hList.AddToTail( tex ); + itr++; + Q_snprintf( tmp, MAX_PATH, "texsamp_%i", itr ); + c = pKV->FindKey( tmp ); + } +} +void ReadKVIdents_EConst( CUtlVector< SimpleEnvConstant* > &hList, KeyValues *pKV ) +{ + int itr = 0; + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "econst_%i", itr ); + KeyValues *c = pKV->FindKey( tmp ); + + while( c ) + { + SimpleEnvConstant *econst = new SimpleEnvConstant(); + + econst->iEnvC_ID = c->GetInt( "i_envconstidx" ); + econst->iHLSLRegister = c->GetInt( "i_normregister" ); + econst->iConstSize = c->GetInt( "i_econstsize" ); + econst->iSmartNumComps = c->GetInt( "i_smartcomps" ); + + const char *name = c->GetString( "sz_smartname" ); + int len = Q_strlen( name ) + 1; + econst->szSmartHelper = new char[ len ]; + Q_snprintf( econst->szSmartHelper, MAX_PATH, "%s", name ); + + for ( int i = 0; i < 4; i++ ) + { + char tmpdef[MAX_PATH]; + Q_snprintf( tmpdef, MAX_PATH, "fl_smartdefault_%02i", i ); + econst->flSmartDefaultValues[ i ] = c->GetFloat( tmpdef ); + } + + hList.AddToTail( econst ); + itr++; + Q_snprintf( tmp, MAX_PATH, "econst_%i", itr ); + c = pKV->FindKey( tmp ); + } +} +void ReadKVIdents_Combos( CUtlVector< SimpleCombo* > &hList, KeyValues *pKV ) +{ + int itr = 0; + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "combo_%i", itr ); + KeyValues *c = pKV->FindKey( tmp ); + + while( c ) + { + SimpleCombo *combo = new SimpleCombo(); + + const char *name = c->GetString( "sz_name" ); + int len = Q_strlen( name ) + 1; + combo->name = new char[ len ]; + Q_snprintf( combo->name, MAX_PATH, "%s", name ); + + combo->bStatic = !!c->GetInt( "i_static" ); + combo->min = c->GetInt( "i_min" ); + combo->max = c->GetInt( "i_max" ); + combo->iComboType = c->GetInt( "i_type" ); + + hList.AddToTail( combo ); + itr++; + Q_snprintf( tmp, MAX_PATH, "combo_%i", itr ); + c = pKV->FindKey( tmp ); + } +} +void ReadIdents( IdentifierLists_t &idents, KeyValues *pKV ) +{ + ReadKVIdents_Combos( idents.hList_Combos, pKV ); + ReadKVIdents_EConst( idents.hList_EConstants, pKV ); + ReadKVIdents_Texture( idents.hList_Textures, pKV ); + + idents.inum_DynamicCombos = pKV->GetInt( "i_numdcombos" ); +} +BasicShaderCfg_t *BuildShaderData( const char *dumpFileName ) +{ + KeyValues *pKV = new KeyValues( dumpFileName ); + char _path[MAX_PATH]; + Q_snprintf( _path, MAX_PATH, "%s/%s.dump", ::GetDumpDirectory(), dumpFileName ); + Q_FixSlashes( _path ); + pKV->LoadFromFile( g_pFullFileSystem, _path, "MOD" ); + + BasicShaderCfg_t *data = new BasicShaderCfg_t(); + + const char *szT = pKV->GetString( "vs_name" ); + int len = Q_strlen( szT ) + 1; + data->ProcVSName = new char[ len ]; + Q_snprintf( data->ProcVSName, len, "%s", szT ); + + szT = pKV->GetString( "ps_name" ); + len = Q_strlen( szT ) + 1; + data->ProcPSName = new char[ len ]; + Q_snprintf( data->ProcPSName, len, "%s", szT ); + + szT = pKV->GetString( "shader_filename" ); + len = Q_strlen( szT ) + 1; + data->Filename = new char[ len ]; + Q_snprintf( data->Filename, len, "%s", szT ); + Q_FixSlashes( data->Filename ); + + szT = pKV->GetName(); + len = Q_strlen( szT ) + 1; + data->CanvasName = new char[ len ]; + Q_snprintf( data->CanvasName, len, "%s", szT ); + + Q_snprintf( data->dumpversion, sizeof(data->dumpversion), "%s", pKV->GetString( GetDumpVersion_KeyName() ) ); + + data->iShaderModel = pKV->GetInt( "i_sm" ); + data->iCullmode = pKV->GetInt( "i_cull" ); + data->iAlphablendmode = pKV->GetInt( "i_ablend" ); + data->flAlphaTestRef = pKV->GetFloat( "fl_atestref" ); + data->iDepthtestmode = pKV->GetInt( "i_dtest" ); + data->iDepthwritemode = pKV->GetInt( "i_dwrite" ); + data->bsRGBWrite = !!pKV->GetInt( "i_srgbw" ); + + data->iVFMT_flags = pKV->GetInt( "i_vfmt_flags" ); + data->iVFMT_numTexcoords = pKV->GetInt( "i_vfmt_texcoords" ); + data->iVFMT_numUserData = pKV->GetInt( "i_vfmt_udata" ); + for ( int i = 0; i < 3; i++ ) + { + char tmp[48]; + Q_snprintf( tmp, sizeof(tmp), "i_vfmt_texcoordDim_%i", i ); + data->iVFMT_texDim[i] = pKV->GetInt( tmp, GetVarFlagsVarValue( HLSLVAR_FLOAT2 ) + 1 ); + } + + data->bVertexLighting = !!pKV->GetInt( "i_vlit" ); + data->bRefractionSupport = !!pKV->GetInt( "i_vrefract" ); + + KeyValues *pSubIdent_VS = pKV->FindKey( "identifiers_VS" ); + if ( pSubIdent_VS ) + ReadIdents( *data->pVS_Identifiers, pSubIdent_VS ); + + KeyValues *pSubIdent_PS = pKV->FindKey( "identifiers_PS" ); + if ( pSubIdent_PS ) + ReadIdents( *data->pPS_Identifiers, pSubIdent_PS ); + + pKV->deleteThis(); + return data; +} + + +KeyValues *__AllocKV_Texture( int i, SimpleTexture *c ) +{ + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "texsamp_%i", i ); + KeyValues *pKV = new KeyValues( tmp ); + + pKV->SetString( "sz_param", c->szParamName ); + pKV->SetString( "sz_fallback", c->szFallbackName ); + pKV->SetInt( "i_sampidx", c->iSamplerIndex ); + pKV->SetInt( "i_texmode", c->iTextureMode ); + pKV->SetInt( "i_cubemap", c->bCubeTexture ? 1 : 0 ); + pKV->SetInt( "i_srgb", c->bSRGB ? 1 : 0 ); + + return pKV; +} +/* + // custom parameter - uniquify this + char *szParamName; + // sampler index - defined on uniquify + int iSamplerIndex; + // texture mode, bind standard or from param? + int iTextureMode; + // do we need a cubemap lookup? + bool bCubeTexture; + bool bSRGB; +*/ +KeyValues *__AllocKV_EConst( int i, SimpleEnvConstant *c ) +{ + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "econst_%i", i ); + KeyValues *pKV = new KeyValues( tmp ); + + pKV->SetInt( "i_envconstidx", c->iEnvC_ID ); + pKV->SetInt( "i_normregister", c->iHLSLRegister ); + pKV->SetInt( "i_econstsize", c->iConstSize ); + pKV->SetInt( "i_smartcomps", c->iSmartNumComps ); + pKV->SetString( "sz_smartname", c->szSmartHelper ); + for ( int i = 0; i < 4; i++ ) + { + char tmpdef[MAX_PATH]; + Q_snprintf( tmpdef, MAX_PATH, "fl_smartdefault_%02i", i ); + pKV->SetFloat( tmpdef, c->flSmartDefaultValues[ i ] ); + } + + return pKV; +} +/* + int iEnvC_ID; + int iHLSLRegister; +*/ +KeyValues *__AllocKV_Combo( int i, SimpleCombo *c ) +{ + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "combo_%i", i ); + KeyValues *pKV = new KeyValues( tmp ); + + pKV->SetString( "sz_name", c->name ); + pKV->SetInt( "i_static", c->bStatic ? 1 : 0 ); + pKV->SetInt( "i_min", c->min ); + pKV->SetInt( "i_max", c->max ); + pKV->SetInt( "i_type", c->iComboType ); + + return pKV; +} +/* + char *name; + bool bStatic; + int min; + int max; +*/ +KeyValues *__AllocKV_Identifiers( IdentifierLists_t *pList ) +{ + KeyValues *pIdents = new KeyValues(""); + + for ( int i = 0; i < pList->hList_Combos.Count(); i++ ) + pIdents->AddSubKey( __AllocKV_Combo( i, pList->hList_Combos[i] ) ); + for ( int i = 0; i < pList->hList_EConstants.Count(); i++ ) + pIdents->AddSubKey( __AllocKV_EConst( i, pList->hList_EConstants[i] ) ); + for ( int i = 0; i < pList->hList_Textures.Count(); i++ ) + pIdents->AddSubKey( __AllocKV_Texture( i, pList->hList_Textures[i] ) ); + + pIdents->SetInt( "i_numdcombos", pList->inum_DynamicCombos ); + + return pIdents; +} +/* + CUtlVector< SimpleTexture* > hList_Textures; + CUtlVector< SimpleCombo* > hList_Combos; + CUtlVector< SimpleEnvConstant* > hList_EConstants; +*/ +void df_SaveDump_File( const char *canvasname, const BasicShaderCfg_t &shader ) +{ + KeyValues *pKV = new KeyValues( canvasname ); + char _path[MAX_PATH]; + Q_snprintf( _path, MAX_PATH, "%s/%s.dump", ::GetDumpDirectory(), canvasname ); + Q_FixSlashes( _path ); + + pKV->SetString( "vs_name", shader.ProcVSName ); + pKV->SetString( "ps_name", shader.ProcPSName ); + pKV->SetString( "shader_filename", shader.Filename ); + pKV->SetString( GetDumpVersion_KeyName(), GetDumpVersion_Current() ); + + pKV->SetInt( "i_sm", shader.iShaderModel ); + pKV->SetInt( "i_cull", shader.iCullmode ); + pKV->SetInt( "i_ablend", shader.iAlphablendmode ); + pKV->SetFloat( "fl_atestref", shader.flAlphaTestRef ); + pKV->SetInt( "i_dtest", shader.iDepthtestmode ); + pKV->SetInt( "i_dwrite", shader.iDepthwritemode ); + pKV->SetInt( "i_srgbw", shader.bsRGBWrite ? 1 : 0 ); + + pKV->SetInt( "i_vfmt_flags", shader.iVFMT_flags ); + pKV->SetInt( "i_vfmt_texcoords", shader.iVFMT_numTexcoords ); + pKV->SetInt( "i_vfmt_udata", shader.iVFMT_numUserData ); + for ( int i = 0; i < 3; i++ ) + { + char tmp[48]; + Q_snprintf( tmp, sizeof(tmp), "i_vfmt_texcoordDim_%i", i ); + pKV->SetInt( tmp, shader.iVFMT_texDim[i] ); + } + + pKV->SetInt( "i_vlit", shader.bVertexLighting ); + pKV->SetInt( "i_vrefract", shader.bRefractionSupport ); + + KeyValues *pKVIdentVS = __AllocKV_Identifiers( shader.pVS_Identifiers ); + pKVIdentVS->SetName( "identifiers_VS" ); + pKV->AddSubKey( pKVIdentVS ); + + KeyValues *pKVIdentPS = __AllocKV_Identifiers( shader.pPS_Identifiers ); + pKVIdentPS->SetName( "identifiers_PS" ); + pKV->AddSubKey( pKVIdentPS ); + + pKV->SaveToFile( g_pFullFileSystem, _path, "MOD" ); + pKV->deleteThis(); +} +/* +struct BasicShaderCfg_t +{ + char *ProcVSName; + char *ProcPSName; + + int iShaderModel; + int iCullmode; + int iAlphablendmode; + float flAlphaTestRef; + int iDepthtestmode; + int iDepthwritemode; + + int iVFMT_flags; + int iVFMT_numTexcoords; + int iVFMT_numUserData; + + //CUtlVector< SimpleCombo* > hList_Combos_VS; + //CUtlVector< SimpleCombo* > hList_Combos_PS; + + IdentifierLists_t *pVS_Identifiers; + IdentifierLists_t *pPS_Identifiers; +}; +*/ \ No newline at end of file diff --git a/sp/src/shadereditor/gshaderdumps.h b/sp/src/shadereditor/gshaderdumps.h new file mode 100644 index 00000000..dd76f8ea --- /dev/null +++ b/sp/src/shadereditor/gshaderdumps.h @@ -0,0 +1,16 @@ +#ifndef SHADERDUMPS_H +#define SHADERDUMPS_H + +#include "cbase.h" + +KeyValues *df_LoadDump_List(); // alloc +void df_SaveDump_List( KeyValues *pKV ); // dealloc + +BasicShaderCfg_t *BuildShaderData( const char *dumpFileName ); +void df_SaveDump_File( const char *canvasname, const BasicShaderCfg_t &shader ); + +void ReadGameShaders( CUtlVector &hList ); +void LoadGameShaders( bool bFirstRun = false ); +void UnloadGameShaders(); + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/interface/dll_init.cpp b/sp/src/shadereditor/interface/dll_init.cpp new file mode 100644 index 00000000..2f4fd7f0 --- /dev/null +++ b/sp/src/shadereditor/interface/dll_init.cpp @@ -0,0 +1,304 @@ + +#include "cbase.h" +#include "editorcommon.h" +#include "dll_init.h" + +#include "steam/steam_api.h" +#include "datacache/idatacache.h" +#include "engine/ienginesound.h" +#include "igameuifuncs.h" +#include "inputsystem/iinputsystem.h" +#include "client_factorylist.h" +//#include "initializer.h" +#include "vgui_init.h" +#include "tier0/icommandline.h" + +#ifdef SHADER_EDITOR_DLL_SWARM +#include "interfaces/interfaces.h" +#endif + +#ifdef SHADER_EDITOR_DLL_2006 +#include "cdll_convar.h" + +IMDLCache *mdlcache = NULL; +static CDLL_ConVarAccessor g_ConVarAccessor; +#endif + +IVEngineClient *engine = NULL; +IVModelRender *modelrender = NULL; +IVRenderView *render = NULL; +IDataCache *datacache = NULL; +IVModelInfoClient *modelinfo = NULL; +IEngineVGui *enginevgui = NULL; +ISpatialPartition* partition = NULL; +IFileSystem *filesystem = NULL; +IEngineSound *enginesound = NULL; +IUniformRandomStream *random = NULL; +static CGaussianRandomStream s_GaussianRandomStream; +CGaussianRandomStream *randomgaussian = &s_GaussianRandomStream; +IGameUIFuncs *gameuifuncs = NULL; +IInputSystem *inputsystem = NULL; +IUploadGameStats *gamestatsuploader = NULL; + +#ifndef SHADER_EDITOR_DLL_2006 +ISoundEmitterSystemBase *soundemitterbase = NULL; +static CSteamAPIContext g_SteamAPIContext; +CSteamAPIContext *steamapicontext = &g_SteamAPIContext; +#endif + +static CGlobalVarsBase dummyvars( true ); +CGlobalVarsBase *gpGlobals = &dummyvars; + + + + +#include "EditorInit.h" +#include "editorcommon.h" +#include "IVProcShader.h" + +CSysModule *ProcShaderModule = NULL; +IVProcShader *gProcShaderCTRL = NULL; +ISEditModelRender *sEditMRender = NULL; + +static bool bIsEditing = false; +const bool IsInEditMode() +{ + return bIsEditing; +} + +static void OnShaderEditor_RestoreFunc( int nChangeFlags ) +{ + shaderEdit->FlushPPEMaterialVarCache(); +} + + +bool ShaderEditorInterface::Init( CreateInterfaceFn appSystemFactory, CGlobalVarsBase *pGlobals, void *pSEditMRender, + bool bCreateEditor, bool bEnablePrimaryDebug, int iSkymaskMode ) +{ +#if DEBUG + //ToggleMemDbgLock(); +#endif + + sEditMRender = (ISEditModelRender*)pSEditMRender; + + bIsEditing = bCreateEditor; + m_bShowPrimaryDebug = bEnablePrimaryDebug; + + MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f ); + + gpGlobals = pGlobals; + +#ifdef SHADER_EDITOR_DLL_SWARM + ConnectInterfaces( &appSystemFactory, 1 ); +#endif + + ConnectTier1Libraries( &appSystemFactory, 1 ); + ConnectTier2Libraries( &appSystemFactory, 1 ); + ConnectTier3Libraries( &appSystemFactory, 1 ); + + if ( (engine = (IVEngineClient *)appSystemFactory( VENGINE_CLIENT_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (modelrender = (IVModelRender *)appSystemFactory( VENGINE_HUDMODEL_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (render = (IVRenderView *)appSystemFactory( VENGINE_RENDERVIEW_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (datacache = (IDataCache*)appSystemFactory(DATACACHE_INTERFACE_VERSION, NULL )) == NULL ) + return false; +#ifdef SHADER_EDITOR_DLL_2006 + if ( (mdlcache = (IMDLCache*)appSystemFactory( MDLCACHE_INTERFACE_VERSION, NULL )) == NULL ) + return false; +#else + if ( !mdlcache ) + return false; +#endif + if ( (modelinfo = (IVModelInfoClient *)appSystemFactory(VMODELINFO_CLIENT_INTERFACE_VERSION, NULL )) == NULL ) + return false; + if ( (enginevgui = (IEngineVGui *)appSystemFactory(VENGINE_VGUI_VERSION, NULL )) == NULL ) + return false; + if ( (enginesound = (IEngineSound *)appSystemFactory(IENGINESOUND_CLIENT_INTERFACE_VERSION, NULL)) == NULL ) + return false; +#ifdef SHADER_EDITOR_DLL_2006 + setdllFS( (IFileSystem *)appSystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL) ); + if ( g_pFullFileSystem == NULL ) + return false; +#else + if ( (filesystem = (IFileSystem *)appSystemFactory(FILESYSTEM_INTERFACE_VERSION, NULL)) == NULL ) + return false; +#endif + if ( (random = (IUniformRandomStream *)appSystemFactory(VENGINE_CLIENT_RANDOM_INTERFACE_VERSION, NULL)) == NULL ) + return false; + if ( (gameuifuncs = (IGameUIFuncs * )appSystemFactory( VENGINE_GAMEUIFUNCS_VERSION, NULL )) == NULL ) + return false; + if ( (inputsystem = (IInputSystem *)appSystemFactory(INPUTSYSTEM_INTERFACE_VERSION, NULL)) == NULL ) + return false; + + factorylist_t factories; + factories.appSystemFactory = appSystemFactory; + FactoryList_Store( factories ); + + if( !g_pMaterialSystemHardwareConfig ) + return false; + + s_GaussianRandomStream.AttachToStream( random ); + +#ifdef SHADER_EDITOR_DLL_2006 + //if ( bCreateEditor ) + // ConCommandBaseMgr::OneTimeInit(&g_ConVarAccessor); +#else + ConVar_Register( FCVAR_CLIENTDLL ); +#endif + + CreateDirectoryStrings(); + + //if (!Initializer::InitializeAllObjects()) + // return false; + + if (!VGui_Editor_Startup( appSystemFactory )) + return false; + +#ifdef SHADER_EDITOR_DLL_SWARM + const char *pszModuleName = "game_shader_generic_eshader_SWARM.dll"; +#elif SHADER_EDITOR_DLL_2006 + const char *pszModuleName = "game_shader_generic_eshader_2006.dll"; +#elif SHADER_EDITOR_DLL_2013 + //const char *pszModuleName = "game_shader_generic_eshader_2013.dll"; + const char *pszModuleName = "game_shader_dx6.dll"; +#elif SHADER_EDITOR_DLL_PORTAL2 + const char *pszModuleName = "game_shader_generic_eshader_PORTAL2.dll"; +#else + const char *pszModuleName = "game_shader_generic_eshader_2007.dll"; +#endif + + char modulePath[MAX_PATH]; + Q_snprintf( modulePath, sizeof( modulePath ), "%s/bin/%s", engine->GetGameDirectory(), pszModuleName ); + ProcShaderModule = Sys_LoadModule( modulePath ); + if ( ProcShaderModule ) + { + CreateInterfaceFn ProcShaderFactory = Sys_GetFactory( ProcShaderModule ); + gProcShaderCTRL = ProcShaderFactory ? ((IVProcShader *) ProcShaderFactory( PROCSHADER_INTERFACE_VERSION, NULL )) : NULL; + } + + if ( !gProcShaderCTRL ) + { + Warning( "Cannot load %s.\n", pszModuleName ); + return false; + } + else if ( !gProcShaderCTRL->Init( appSystemFactory, gPPEHelper ) ) + { + Warning( "Cannot init shader interface.\n" ); + return false; + } + + if ( !IGameSystem::InitAllSystems() ) + return false; + + ICommandLine *pCom = CommandLine(); + const int iRtDefaultSize = 1024; + const int iRtSize = pCom ? pCom->ParmValue( "-graphrtsize", iRtDefaultSize ) : iRtDefaultSize; + + if ( bCreateEditor ) + AllocRTs( iRtSize ); + + AllocSkymask( (SEDIT_SKYMASK_MODE)iSkymaskMode ); + + PreviewCleanup(); +#if 0 //def SHADER_EDITOR_DLL_SWARM + InitSwarmShaders(); +#endif + + VGui_Editor_CreateGlobalPanels( bCreateEditor ); + + if ( bCreateEditor ) + ResetTileInfo(); + + if ( bCreateEditor ) + CheckDirectories(); + + materials->AddRestoreFunc( &OnShaderEditor_RestoreFunc ); + + return true; +} + +void ShaderEditorInterface::PrecacheData() +{ + static bool bNoDoublePrecache = false; + if ( bNoDoublePrecache ) + { + Warning( "Don't call PrecacheData() twice.\n" ); + return; + } + + bNoDoublePrecache = true; + + LoadGameShaders( true ); + GetPPCache()->LoadPrecacheFile(); +} + +void ShaderEditorInterface::OverridePaths( const char *pszWorkingDirectory, const char *pszCompilePath, const char *pszLocalCompilePath, + const char *pszGamePath, const char *pszCanvas, const char *pszShaderSource, const char *pszDumps, + const char *pszUserFunctions, const char *pszEditorRoot ) +{ + OverrideDirectories( pszWorkingDirectory, pszCompilePath, pszLocalCompilePath, pszGamePath, + pszCanvas, pszShaderSource, pszDumps, pszUserFunctions, pszEditorRoot ); +} + +void ShaderEditorInterface::Shutdown() +{ + materials->RemoveRestoreFunc( &OnShaderEditor_RestoreFunc ); + + GetMatSysShutdownHelper()->Shutdown(); + + UnloadGameShaders(); + + if ( gProcShaderCTRL ) + gProcShaderCTRL->Shutdown(); + + PreviewCleanup(); + + //Initializer::FreeAllObjects(); + + IGameSystem::ShutdownAllSystems(); + + VGui_Editor_Shutdown(); + + DisconnectTier3Libraries( ); + DisconnectTier2Libraries( ); +#ifndef SHADER_EDITOR_DLL_2006 + ConVar_Unregister(); +#endif + DisconnectTier1Libraries( ); + +#ifdef SHADER_EDITOR_DLL_SWARM + DisconnectInterfaces(); +#endif + +#if DEBUG + //ToggleMemDbgLock(); +#endif +} + +char *VarArgs( char *format, ... ) +{ + va_list argptr; + static char string[1024]; + + va_start (argptr, format); + Q_vsnprintf (string, sizeof( string ), format,argptr); + va_end (argptr); + + return string; +} + +int ScreenHeight( void ) +{ + int w, h; + engine->GetScreenSize( w, h ); + return h; +} + +int ScreenWidth( void ) +{ + int w, h; + engine->GetScreenSize( w, h ); + return w; +} \ No newline at end of file diff --git a/sp/src/shadereditor/interface/dll_init.h b/sp/src/shadereditor/interface/dll_init.h new file mode 100644 index 00000000..009b8624 --- /dev/null +++ b/sp/src/shadereditor/interface/dll_init.h @@ -0,0 +1,78 @@ +#ifndef DLL_INIT_H +#define DLL_INIT_H +#ifdef _WIN32 +#pragma once +#endif + +//#include "iclientnetworkable.h" +#include "utllinkedlist.h" +#include "cdll_int.h" +#include "eiface.h" +#include +#ifdef SHADER_EDITOR_DLL_2006 +#include "vector.h" +#include "datacache/imdlcache.h" +#else +#include "mathlib/vector.h" +#endif +#include +#include "materialsystem/materialsystemutil.h" +#include "cmodel.h" +#include "utlvector.h" +#include "engine/IEngineTrace.h" +#include "engine/IStaticPropMgr.h" +#include "networkvar.h" + +class IVModelRender; +class IVEngineClient; +class IVModelRender; +class IVRenderView; +class IMaterialSystem; +class IDataCache; +class IMDLCache; +class IVModelInfoClient; +class IEngineVGui; +class IFileSystem; +class IUniformRandomStream; +class CGaussianRandomStream; +class IEngineSound; +class IMatSystemSurface; +class IMaterialSystemHardwareConfig; +class IGameUIFuncs; +class CGlobalVarsBase; +class IInputSystem; +class CSteamAPIContext; + +extern IVModelRender *modelrender; +extern IVEngineClient *engine; +extern IVModelRender *modelrender; +extern IVRenderView *render; +extern IMaterialSystem *materials; +extern IMaterialSystemHardwareConfig *g_pMaterialSystemHardwareConfig; +extern IDataCache *datacache; +extern IMDLCache *mdlcache; +extern IVModelInfoClient *modelinfo; +extern IEngineVGui *enginevgui; +extern IFileSystem *filesystem; +extern IUniformRandomStream *random; +extern CGaussianRandomStream *randomgaussian; +extern IEngineSound *enginesound; +extern IMatSystemSurface *g_pMatSystemSurface; +extern IGameUIFuncs *gameuifuncs; +extern CGlobalVarsBase *gpGlobals; +extern IInputSystem *inputsystem; +extern CSteamAPIContext *steamapicontext; + +char *VarArgs( char *format, ... ); +int ScreenHeight( void ); +int ScreenWidth( void ); + + + + + + + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/interface/editorinit.cpp b/sp/src/shadereditor/interface/editorinit.cpp new file mode 100644 index 00000000..32ef3370 --- /dev/null +++ b/sp/src/shadereditor/interface/editorinit.cpp @@ -0,0 +1,1076 @@ + +#include "cbase.h" +#include "vgui/isystem.h" + +void EngineCopy( const char *a, const char *b ) +{ +#ifdef SHADER_EDITOR_DLL_2013 + engine->CopyLocalFile( a, b ); +#else + engine->CopyFile( a, b ); +#endif +} + +float GetEditorTime() +{ + return g_pVGuiSystem->GetCurrentTime(); +} + +#include +#include "EditorInit.h" +#include "editorcommon.h" + +#include +#include +#include +#include +#include + +#include "view_shared.h" +#include "materialsystem/imesh.h" + +void ForceTerminateCompilers() +{ + PROCESSENTRY32 entry; + entry.dwSize = sizeof(PROCESSENTRY32); + + HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + + if (Process32First(snapshot, &entry) == 1) + { + while (Process32Next(snapshot, &entry) == 1) + { + if (stricmp(entry.szExeFile, "shadercompile.exe") == 0) + { + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID); + + TerminateProcess( hProcess, 0 ); + + CloseHandle(hProcess); + } + } + } + + CloseHandle(snapshot); +} + + +#ifdef SHADER_EDITOR_DLL_SWARM +void VCRHook_WaitForSingleObject( + __in HANDLE hHandle, + __in DWORD dwMilliseconds + ) +{ + WaitForSingleObject( hHandle, dwMilliseconds ); +} +#endif + + +ShaderEditorInterface gShaderEditorInterface; +ShaderEditorInterface *shaderEdit = &gShaderEditorInterface; + +EXPOSE_SINGLE_INTERFACE_GLOBALVAR( ShaderEditorInterface, IVShaderEditor, SHADEREDIT_INTERFACE_VERSION, gShaderEditorInterface ); + +bool ShaderEditorInterface::bCallbackLock = false; +bool ShaderEditorInterface::bVrCallbackLock = false; + +ShaderEditorInterface::ShaderEditorInterface() + : m_iLastInvalidVarToken( SHADEREDIT_MVAR_TOKEN_INVALID ) + , m_iNextValidVarToken( SHADEREDIT_MVAR_TOKEN_INVALID + 1 ) +{ + m_bShowPrimaryDebug = false; + + for ( int i = 0; i < 3; i++ ) + pSkyMats[ i ] = NULL; +} + +ShaderEditorInterface::~ShaderEditorInterface() +{ + m_hFunctionCallbacks.PurgeAndDeleteElements(); + + //for ( int i = 0; i < 3; i++ ) + //{ + // if ( pSkyMats[ i ] == NULL ) + // continue; + + // pSkyMats[ i ]->Clear(); + // pSkyMats[ i ] = NULL; + //} +} + +using namespace vgui; + +#include "vgui_controls/controls.h" +#include "vgui_controls/panel.h" +#include "vgui_controls/animationcontroller.h" +#include +#include +#include +#include "vgui/ipanel.h" + +CViewSetup_SEdit_Shared _MainView; + + +void RenderFullScreenQuad( IMaterial *pMat ) +{ + CMatRenderContextPtr pRenderContext( materials ); + CMeshBuilder pMeshBuilder; + IMesh *pMesh = pRenderContext->GetDynamicMesh( true, 0, 0, pMat ); + pMeshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); + + pMeshBuilder.Position3f( -1, 1, 1 ); + pMeshBuilder.TexCoord2f( 0, 0, 0 ); + pMeshBuilder.AdvanceVertex(); + pMeshBuilder.Position3f( 1, 1, 1 ); + pMeshBuilder.TexCoord2f( 0, 1, 0 ); + pMeshBuilder.AdvanceVertex(); + pMeshBuilder.Position3f( 1, -1, 1 ); + pMeshBuilder.TexCoord2f( 0, 1, 1 ); + pMeshBuilder.AdvanceVertex(); + pMeshBuilder.Position3f( -1, -1, 1 ); + pMeshBuilder.TexCoord2f( 0, 0, 1 ); + pMeshBuilder.AdvanceVertex(); + + pMeshBuilder.End(); + pMesh->Draw(); +} + +void GeneralFramebufferUpdate( IMatRenderContext *pRenderContext ) +{ + Rect_t srcRect; + srcRect.x = 0; + srcRect.y = 0; + + materials->GetBackBufferDimensions( srcRect.width, srcRect.height ); + + ITexture *pTexture = GetFBTex(); + int nSrcWidth, nSrcHeight; + + pRenderContext->GetRenderTargetDimensions( nSrcWidth, nSrcHeight ); + pRenderContext->CopyRenderTargetToTextureEx( pTexture, 0, &srcRect ); + pRenderContext->SetFrameBufferCopyTexture( pTexture ); +} + +void UpdateScreenEffectTexture( ITexture *pTexture, int x, int y, int w, int h, bool bDestFullScreen, Rect_t *pActualRect ) +{ + Rect_t srcRect; + srcRect.x = x; + srcRect.y = y; + srcRect.width = w; + srcRect.height = h; + + CMatRenderContextPtr pRenderContext( materials ); + int nSrcWidth, nSrcHeight; + pRenderContext->GetRenderTargetDimensions( nSrcWidth, nSrcHeight ); + int nDestWidth = pTexture->GetActualWidth(); + int nDestHeight = pTexture->GetActualHeight(); + + Rect_t destRect = srcRect; + if( !bDestFullScreen && ( nSrcWidth > nDestWidth || nSrcHeight > nDestHeight ) ) + { + // the source and target sizes aren't necessarily the same (specifically in dx7 where + // nonpow2 rendertargets aren't supported), so lets figure it out here. + float scaleX = ( float )nDestWidth / ( float )nSrcWidth; + float scaleY = ( float )nDestHeight / ( float )nSrcHeight; + destRect.x = srcRect.x * scaleX; + destRect.y = srcRect.y * scaleY; + destRect.width = srcRect.width * scaleX; + destRect.height = srcRect.height * scaleY; + destRect.x = clamp( destRect.x, 0, nDestWidth ); + destRect.y = clamp( destRect.y, 0, nDestHeight ); + destRect.width = clamp( destRect.width, 0, nDestWidth - destRect.x ); + destRect.height = clamp( destRect.height, 0, nDestHeight - destRect.y ); + } + + pRenderContext->CopyRenderTargetToTextureEx( pTexture, 0, &srcRect, bDestFullScreen ? NULL : &destRect ); + pRenderContext->SetFrameBufferCopyTexture( pTexture ); + + if ( pActualRect ) + { + pActualRect->x = destRect.x; + pActualRect->y = destRect.y; + pActualRect->width = destRect.width; + pActualRect->height = destRect.height; + } +} + +void ShaderEditorInterface::OnFrame( float frametime ) +{ + if ( IsInEditMode() ) + { + static ConVarRef qMode( "mat_queue_mode" ); +#if defined( SHADER_EDITOR_DLL_SWARM ) || defined( SHADER_EDITOR_DLL_2013 ) + qMode.SetValue( "0" ); +#else + qMode.SetValue( "-1" ); +#endif + } + + IGameSystem::UpdateAllSystems( frametime ); +} +void ShaderEditorInterface::OnPreRender( void *viewsetup ) +{ + _MainView = *((CViewSetup_SEdit_Shared*)viewsetup); + + IGameSystem::PreRenderAllSystems(); +} +void ShaderEditorInterface::OnUpdateSkymask( bool bCombineMode, int x, int y, int w, int h ) +{ + SetFramebufferCopyTexOverride( NULL ); + + if ( !IsSkymaskAvailable() ) + return; + + //UpdateFramebufferTexture( true ); + + ITexture *pSkyMask = GetSkymaskTex(); + + if ( IsErrorTexture( pSkyMask ) ) + return; + + static CMaterialReference pMatSkyDraw = NULL; + static CMaterialReference pMatScreenRestore = NULL; + static CMaterialReference pMatCombineMasks = NULL; +#ifdef SHADER_EDITOR_DLL_2006 + pMatSkyDraw = materials->FindMaterial( "postprocessing/skymask_fill_0", TEXTURE_GROUP_OTHER ); + pMatCombineMasks = materials->FindMaterial( "postprocessing/skymask_fill_1", TEXTURE_GROUP_OTHER ); + pMatScreenRestore = materials->FindMaterial( "postprocessing/fb_restore", TEXTURE_GROUP_OTHER ); +#else + if ( !pMatSkyDraw ) + { + pSkyMats[ 0 ] = new KeyValues( "FILL_SKYMASK" ); + pSkyMats[ 0 ]->SetInt( "$COMBINEMODE", 0 ); + pMatSkyDraw.Init( "__sedit_skyfill", TEXTURE_GROUP_CLIENT_EFFECTS, pSkyMats[ 0 ] ); + //pMatSkyDraw->Refresh(); + //pKV->Clear(); + Assert( pMatSkyDraw ); + } + if ( !pMatScreenRestore ) + { + pSkyMats[ 1 ] = new KeyValues( "FULLSCREENQUAD_WRITEA" ); + pSkyMats[ 1 ]->SetString( "$BASETEXTURE", GetFBTex()->GetName() ); + pSkyMats[ 1 ]->SetInt( "$COMBINEMODE", 0 ); + pMatScreenRestore.Init( "__sedit_fbrestore", TEXTURE_GROUP_CLIENT_EFFECTS, pSkyMats[ 1 ] ); + //pMatScreenRestore->Refresh(); + //pKV->Clear(); + Assert( pMatScreenRestore ); + } + if ( !pMatCombineMasks ) + { + const char *skymaskname = pSkyMask->GetName(); + pSkyMats[ 2 ] = new KeyValues( "FILL_SKYMASK" ); + pSkyMats[ 2 ]->SetString( "$BASETEXTURE", skymaskname ); + pSkyMats[ 2 ]->SetInt( "$COMBINEMODE", 1 ); + pMatCombineMasks.Init( "__sedit_skyfill", TEXTURE_GROUP_CLIENT_EFFECTS, pSkyMats[ 2 ] ); + //pMatCombineMasks->Refresh(); + //pKV->Clear(); + Assert( pMatCombineMasks ); + } +#endif + + // _rt_SEdit_Skymask + CMatRenderContextPtr pRenderContext( materials ); + + IMaterial *pOperation = pMatSkyDraw; + if ( bCombineMode ) + pOperation = pMatCombineMasks; + + int dest_width = w; + int dest_height = h; + float src_x1 = w - 1; + float src_y1 = h - 1; + +#ifdef SHADER_EDITOR_DLL_2006 + Frustum frustum; + CViewSetup setup; + setup.angles = _MainView.angles; + setup.origin = _MainView.origin; + setup.x = _MainView.x; + setup.y = _MainView.y; + setup.width = _MainView.width; + setup.height = _MainView.height; + setup.fov = _MainView.fov; + setup.context = 0; + setup.m_bOrtho = false; + setup.m_flAspectRatio = _MainView.m_flAspectRatio; + setup.m_vUnreflectedOrigin = setup.origin; + render->Push3DView( setup, 0, false, NULL, frustum ); +#endif + + pRenderContext->PushRenderTargetAndViewport( NULL ); + //pRenderContext->Viewport( x, y, w, h ); + //pRenderContext->DepthRange( 0, 1 ); + //MaterialHeightClipMode_t hClipLast = pRenderContext->GetHeightClipMode(); + //pRenderContext->SetHeightClipMode( MATERIAL_HEIGHTCLIPMODE_DISABLE ); + //const bool bEnableClipping = pRenderContext->EnableClipping( false ); + +#ifndef SHADER_EDITOR_DLL_2006 + UpdateScreenEffectTexture( GetFBTex(), x, y, w, h ); + //pRenderContext->CopyRenderTargetToTexture( GetFBTex() ); +#endif + + // do ops + pRenderContext->DrawScreenSpaceRectangle( pOperation, + x, y, dest_width, dest_height, + x, y, src_x1, src_y1, + w, h ); + + // store to mask + UpdateScreenEffectTexture( pSkyMask, x, y, w, h, true ); + //pRenderContext->CopyRenderTargetToTexture( pSkyMask ); + + // restore fb +#ifndef SHADER_EDITOR_DLL_2006 + pRenderContext->DrawScreenSpaceRectangle( pMatScreenRestore, + x, y, w, h, + x, y, w - 1, h - 1, + w, h ); +#endif + + //pRenderContext->EnableClipping( bEnableClipping ); + //pRenderContext->SetHeightClipMode( hClipLast ); + pRenderContext->PopRenderTargetAndViewport(); + +#ifdef SHADER_EDITOR_DLL_2006 + render->PopView( frustum ); +#endif +} + +void ShaderEditorInterface::OnSceneRender() +{ + GetPPCache()->RenderAllEffects( true ); + + if ( IsInEditMode() ) + ::pEditorRoot->OnSceneRender(); +} +void ShaderEditorInterface::OnPostRender( bool bUpdateFB ) +{ + if ( bUpdateFB ) + UpdateFramebufferTexture( true, false ); + + SetFramebufferCopyTexOverride( NULL ); + + GetPPCache()->RenderAllEffects( false ); + + if ( IsInEditMode() ) + { + UpdateFramebufferTexture( true ); + + ::pEditorRoot->OnPostRender(); + } +} + +void ShaderEditorInterface::SetFramebufferCopyTexOverride( ITexture *tex ) +{ + CMatRenderContextPtr pRenderContext( materials ); + pRenderContext->SetFrameBufferCopyTexture( (tex!=NULL) ? tex : GetFBTex() ); +} +void ShaderEditorInterface::UpdateFramebufferTexture( bool bDoPush, bool bCopyToEditorTarget ) +{ + CMatRenderContextPtr pRenderContext( materials ); + + if ( bDoPush ) + pRenderContext->PushRenderTargetAndViewport(); + + pRenderContext->CopyRenderTargetToTexture( bCopyToEditorTarget ? ::GetFBCopyTex() : GetFBTex() ); + + if ( bDoPush ) + pRenderContext->PopRenderTargetAndViewport(); +} +void ShaderEditorInterface::RegisterClientCallback( const char *name, pFnClCallback(callback), int numComponents ) +{ + char tmp[MAX_PATH]; + ::CleanupString( name, tmp, sizeof(tmp) ); + + if ( bCallbackLock ) + return Warning( "callbacks have been locked!\n" ); + if ( !callback ) + return Warning( "can't register a null pointer as callback..\n" ); + if ( !name || !Q_strlen( tmp ) ) + return Warning( "can't register callback without name..\n" ); + + for ( int i = 0; i < m_hFunctionCallbacks.Count(); i++ ) + { + if ( !Q_stricmp( m_hFunctionCallbacks[i]->name, tmp ) ) + return Warning( "ambiguous callback name: %s\n", tmp ); + } + + + _clCallback *cb = new _clCallback(); + cb->func = callback; + cb->name = new char[ Q_strlen( tmp ) + 1 ]; + cb->numComps = clamp( numComponents, 1, 4 ); + Q_strcpy( cb->name, tmp ); + + m_hFunctionCallbacks.AddToTail( cb ); +} +void ShaderEditorInterface::LockClientCallbacks() +{ + bCallbackLock = true; + + Assert(gProcShaderCTRL); + + if ( gProcShaderCTRL ) + gProcShaderCTRL->LinkCallbacks( &m_hFunctionCallbacks ); +} +int ShaderEditorInterface::GetNumCallbacks() +{ + return m_hFunctionCallbacks.Count(); +} +_clCallback *ShaderEditorInterface::GetCallback( int idx ) +{ + Assert( m_hFunctionCallbacks.IsValidIndex( idx ) ); + return m_hFunctionCallbacks[ idx ]; +} +int ShaderEditorInterface::FindCallback( const char *name ) +{ + if ( !name || !Q_strlen( name ) ) + return -1; + for ( int i = 0; i < m_hFunctionCallbacks.Count(); i++ ) + { + if ( !Q_stricmp( m_hFunctionCallbacks[ i ]->name, name ) ) + return i; + } + return -1; +} + + +void ShaderEditorInterface::RegisterViewRenderCallback( const char *pszVrCName, pFnVrCallback(callback), + const char **pszBoolNames, const bool *pBoolDefaults, const int numBoolParams, + const char **pszIntNames, const int *pIntDefaults, const int numIntParams, + const char **pszFloatNames, const float *pFloatDefaults, const int numFloatParams, + const char **pszStringNames, const char **pStringDefaults, const int numStringParams ) +{ + char tmp[MAX_PATH]; + ::CleanupString( pszVrCName, tmp, sizeof(tmp) ); + + if ( bVrCallbackLock ) + return Warning( "vrcallbacks have been locked!\n" ); + //if ( !callback ) + // return Warning( "can't register a null pointer as callback..\n" ); + if ( !pszVrCName || !Q_strlen( tmp ) ) + return Warning( "can't register vrcallback without name..\n" ); + + for ( int i = 0; i < numBoolParams; i++ ) + if ( !pszBoolNames[i] || Q_strlen( pszBoolNames[i] ) < 1 ) + return Warning( "Bad bool parameter for vrcallback %s at pos %i!\n", pszVrCName, i ); + + for ( int i = 0; i < numIntParams; i++ ) + if ( !pszIntNames[i] || Q_strlen( pszIntNames[i] ) < 1 ) + return Warning( "Bad int parameter for vrcallback %s at pos %i!\n", pszVrCName, i ); + + for ( int i = 0; i < numFloatParams; i++ ) + if ( !pszFloatNames[i] || Q_strlen( pszFloatNames[i] ) < 1 ) + return Warning( "Bad float parameter for vrcallback %s at pos %i!\n", pszVrCName, i ); + + for ( int i = 0; i < numStringParams; i++ ) + if ( !pszStringNames[i] || Q_strlen( pszStringNames[i] ) < 1 ) + return Warning( "Bad string parameter for vrcallback %s at pos %i!\n", pszVrCName, i ); + + + EditorRenderViewCommand_Definition *pVRCDef = new EditorRenderViewCommand_Definition(); + + pVRCDef->SetName( tmp ); + pVRCDef->functor = callback; + + for ( int i = 0; i < numBoolParams; i++ ) + { + pVRCDef->AddVarToList( EditorRenderViewCommand_Definition::VAR_BOOL, pszBoolNames[i] ); + + if ( pBoolDefaults != NULL ) + pVRCDef->defaults.AddBoolValue( pBoolDefaults[i] ); + } + + for ( int i = 0; i < numIntParams; i++ ) + { + pVRCDef->AddVarToList( EditorRenderViewCommand_Definition::VAR_INT, pszIntNames[i] ); + + if ( pIntDefaults != NULL ) + pVRCDef->defaults.AddIntValue( pIntDefaults[i] ); + } + + for ( int i = 0; i < numFloatParams; i++ ) + { + pVRCDef->AddVarToList( EditorRenderViewCommand_Definition::VAR_FLOAT, pszFloatNames[i] ); + + if ( pFloatDefaults != NULL ) + pVRCDef->defaults.AddFloatValue( pFloatDefaults[i] ); + } + + for ( int i = 0; i < numStringParams; i++ ) + { + pVRCDef->AddVarToList( EditorRenderViewCommand_Definition::VAR_STRING, pszStringNames[i] ); + + if ( pStringDefaults != NULL ) + pVRCDef->defaults.AddStringValue( pStringDefaults[i] ); + } + + if ( !GetPPCache()->AddVrCallback( pVRCDef ) ) + return Warning( "duplicate vrcallback name: %s\n", tmp ); +} + +void ShaderEditorInterface::LockViewRenderCallbacks() +{ + bVrCallbackLock = true; + + GetPPCache()->LockVrCallbacks(); +} + +int ShaderEditorInterface::GetPPEIndex( const char *pszName ) +{ + return GetPPCache()->FindPostProcessingEffect( pszName ); +} + +bool ShaderEditorInterface::IsPPEEnabled( const int &index ) +{ + if ( index < 0 || index >= GetPPCache()->GetNumPostProcessingEffects() ) + return false; + + return GetPPCache()->GetPostProcessingEffect( index )->bIsEnabled; +} + +void ShaderEditorInterface::SetPPEEnabled( const int &index, const bool &bEnabled ) +{ + if ( index < 0 || index >= GetPPCache()->GetNumPostProcessingEffects() ) + return; + + GetPPCache()->GetPostProcessingEffect( index )->bIsEnabled = bEnabled; +} + +IMaterial *ShaderEditorInterface::GetPPEMaterial( const int &index, const char *pszNodeName ) +{ + if ( index < 0 || index >= GetPPCache()->GetNumPostProcessingEffects() ) + return NULL; + + return GetPPCache()->GetPostProcessingEffect( index )->FindMaterial( pszNodeName ); +} + +void ShaderEditorInterface::DrawPPEOnDemand( const int &index, const bool bInScene ) +{ + if ( index < 0 || index >= GetPPCache()->GetNumPostProcessingEffects() ) + return; + + GetPPCache()->RenderSinglePPE( GetPPCache()->GetPostProcessingEffect( index ), false, bInScene ); +} + +void ShaderEditorInterface::DrawPPEOnDemand( const int &index, int x, int y, int w, int h, const bool bInScene ) +{ + if ( index < 0 || index >= GetPPCache()->GetNumPostProcessingEffects() ) + return; + + GetPPCache()->RenderSinglePPE( GetPPCache()->GetPostProcessingEffect( index ), x, y, w, h, false, bInScene ); +} + +IMaterialVar *ShaderEditorInterface::GetPPEMaterialVarFast( ShaderEditVarToken &token, + const char *pszPPEName, const char *pszNodeName, const char *pszVarName ) +{ + if ( token == SHADEREDIT_MVAR_TOKEN_FAILED ) + return NULL; + + if ( token <= m_iLastInvalidVarToken ) + { + int iEffectIndex = GetPPCache()->FindPostProcessingEffect( pszPPEName ); + + if ( iEffectIndex < 0 ) + { + token = SHADEREDIT_MVAR_TOKEN_FAILED; + return NULL; + } + + IMaterial *pMaterial = GetPPCache()->GetPostProcessingEffect( iEffectIndex )->FindMaterial( pszNodeName ); + + if ( pMaterial == NULL ) + { + token = SHADEREDIT_MVAR_TOKEN_FAILED; + return NULL; + } + + bool bFound = false; + IMaterialVar *pVar = pMaterial->FindVar( pszVarName, &bFound ); + + if ( pVar == NULL + || !bFound ) + { + token = SHADEREDIT_MVAR_TOKEN_FAILED; + return NULL; + } + + token = m_iNextValidVarToken++; + m_cachedMVars.AddToTail( pVar ); + return pVar; + } + + int iLocalIndex = token - m_iLastInvalidVarToken - 1; + + Assert( iLocalIndex >= 0 && iLocalIndex < m_cachedMVars.Count() ); + return m_cachedMVars[ iLocalIndex ]; +} + +void ShaderEditorInterface::FlushPPEMaterialVarCache() +{ + m_iLastInvalidVarToken += m_cachedMVars.Count(); + + Assert( m_iNextValidVarToken == m_iLastInvalidVarToken + 1 ); + + m_cachedMVars.RemoveAll(); +} + +MainShaderEditorUpdate __g_ShaderEditorSystem( "shadereditorupd8r" ); +MainShaderEditorUpdate *gShaderEditorSystem = &__g_ShaderEditorSystem; + +#ifdef SHADER_EDITOR_DLL_2006 +void SchemeReloader_Restore( int ) +{ + if ( pEditorRoot ) + pEditorRoot->InvalidateLayout( false, true ); +} +#endif +void SchemeReloader() +{ + if ( pEditorRoot ) + pEditorRoot->InvalidateLayout( false, true ); +} + +MainShaderEditorUpdate::MainShaderEditorUpdate( char const *name ) : CAutoGameSystemPerFrame( name ) +{ + m_buf_Log.SetBufferType( true, true ); + + bDirty = false; + bCompilerRunning = false; + + _MainView.origin.Init(); + _MainView.angles.Init(); + _MainView.fov = 90; + _MainView.m_flAspectRatio = 1; + _MainView.x = _MainView.y = 0; + _MainView.width = _MainView.height = 256; + _MainView.zNear = 5; + _MainView.zFar = 100; +} + +MainShaderEditorUpdate::~MainShaderEditorUpdate() +{ + m_buf_Log.Purge(); + ForceTerminateCompilers(); +} + +bool MainShaderEditorUpdate::Init() +{ + if ( materials && IsInEditMode() ) +#ifdef SHADER_EDITOR_DLL_2006 + materials->AddReleaseFunc( &SchemeReloader ); + materials->AddRestoreFunc( &SchemeReloader_Restore ); +#else + materials->AddModeChangeCallBack( SchemeReloader ); +#endif + return true; +} + +void MainShaderEditorUpdate::UpdateConstants( const CViewSetup *_override ) +{ + CViewSetup_SEdit_Shared setup = CViewSetup_SEdit_Shared( *_override ); + UpdateConstants( &setup ); +} +void MainShaderEditorUpdate::UpdateConstants( const CViewSetup_SEdit_Shared *_override ) +{ + const CViewSetup_SEdit_Shared *_activeSetup = &_MainView; + if ( _override ) + _activeSetup = _override; + + Vector _fwd, _right, _up; + AngleVectors( _activeSetup->angles, &_fwd, &_right, &_up ); + + for ( int i = HLSLENV_AUTOCOPYCONST_FIRST; i <= HLSLENV_AUTOCOPYCONST_LAST; i++ ) + { + float _data[4] = { 0,0,0,0 }; + + switch ( i ) + { + default: + Assert(0); + break; + case HLSLENV_VIEW_ORIGIN: + AutoCopyFloats( _activeSetup->origin.Base(), _data, 3 ); + break; + case HLSLENV_VIEW_FWD: + AutoCopyFloats( _fwd.Base(), _data, 3 ); + break; + case HLSLENV_VIEW_RIGHT: + AutoCopyFloats( _right.Base(), _data, 3 ); + break; + case HLSLENV_VIEW_UP: + AutoCopyFloats( _up.Base(), _data, 3 ); + break; + case HLSLENV_VIEW_WORLDDEPTH: + _data[0] = _activeSetup->zFar; + break; + } + + gProcShaderCTRL->UpdateEnvironmentData( i, _data ); + } +} +void MainShaderEditorUpdate::PreRender() +{ + if ( !gProcShaderCTRL ) + return; + UpdateConstants(); +} + +void DoMaterialReload() +{ + g_pMaterialSystem->UncacheAllMaterials(); + g_pMaterialSystem->CacheUsedMaterials(); + g_pMaterialSystem->ReloadMaterials(); +} + +static vgui::PromptSimple *prompt = NULL; +static int iMatReloadStep = 0; + +void MainShaderEditorUpdate::BeginMaterialReload( bool bResetMode ) +{ + if ( pEditorRoot ) + { + if ( prompt ) + prompt->MarkForDeletion(); + + prompt = new vgui::PromptSimple( pEditorRoot, "" ); + prompt->SetText( "Reloading materials..." ); + + prompt->MakeReadyForUse(); + prompt->InvalidateLayout( true, true ); + prompt->QuickCenterLayout(); + + prompt->DisableFadeEffect(); + prompt->SetAlpha( 255 ); + prompt->SetBgColor( Color( 96, 64, 64, 200 ) ); + prompt->MoveToCenterOfScreen(); + + iMatReloadStep = bResetMode ? 2 : 1; + } +} +void MainShaderEditorUpdate::Update( float frametime ) +{ +#if 0 + ITexture *pBlah = materials->FindTexture( "_rt_vst", TEXTURE_GROUP_RENDER_TARGET ); + CMatRenderContextPtr pRenderContext( materials ); + pRenderContext->PushRenderTargetAndViewport( pBlah ); + pRenderContext->ClearColor4ub( RandomInt(0,255), RandomInt(0,255), RandomInt(0,255), RandomInt(0,255) ); + pRenderContext->ClearBuffers( true, false ); + pRenderContext->PopRenderTargetAndViewport(); +#endif + + vgui::GetAnimationController()->UpdateAnimations( GetEditorTime() ); //engine->Time() ); + if ( IsLogDirty() ) + { + char _out[1024]; + ParseLog( _out, sizeof( _out ) ); + Msg("%s",_out); + } + + if ( !IsInEditMode() ) + return; + + if ( iMatReloadStep ) + { + if ( prompt ) + { + prompt->MarkForDeletion(); + prompt = NULL; + } + ReloadGameShaders( (iMatReloadStep==1)?pEditorRoot->GetLastFullyCompiledShader():NULL, + pEditorRoot->GetReloadMaterialList(), pEditorRoot->GetNumReloadMaterials() ); + DoMaterialReload(); + iMatReloadStep = 0; + return; + } + + static bool testKeys[ 3 ] = { + false, + false, + false, + }; + + if ( !!input()->GetAppModalSurface() ) + return; + + bool bLocal = input()->IsKeyDown( KEY_F1 ); + if ( bLocal != testKeys[ 0 ] ) + { + testKeys[ 0 ] = bLocal; + if ( testKeys[ 0 ] ) + pEditorRoot->ToggleFullScreen(); + } + + bLocal = input()->IsKeyDown( KEY_F2 ); + if ( bLocal != testKeys[ 1 ] ) + { + testKeys[ 1 ] = bLocal; + if ( testKeys[ 1 ] ) + pEditorRoot->ToggleInput(); + } + + bLocal = input()->IsKeyDown( KEY_F3 ); + if ( bLocal != testKeys[ 2 ] ) + { + testKeys[ 2 ] = bLocal; + if ( testKeys[ 2 ] ) + pEditorRoot->ToggleVisible(); + } + + if ( input()->IsKeyDown( KEY_LCONTROL ) && + input()->IsKeyDown( KEY_LSHIFT ) && + input()->IsKeyDown( KEY_LALT ) && + input()->IsKeyDown( KEY_V ) ) + pEditorRoot->ActivateBuildMode(); +} + +void MainShaderEditorUpdate::QueueLog( const char *_data, int len ) +{ + m_BufferLock.Lock(); + + if ( !m_buf_Log.IsValid() ) + m_buf_Log.Purge(); + m_buf_Log.Put( _data, len ); + bDirty = true; + + m_BufferLock.Unlock(); +} +void MainShaderEditorUpdate::QueueLog( const char *_data ) +{ + m_BufferLock.Lock(); + + if ( !m_buf_Log.IsValid() ) + m_buf_Log.Purge(); + m_buf_Log.PutString( _data ); + bDirty = true; + + m_BufferLock.Unlock(); +} +void MainShaderEditorUpdate::ParseLog( char *logOut, int maxLen ) +{ + m_BufferLock.Lock(); + + int size = min( maxLen-1, m_buf_Log.TellPut() ); + m_buf_Log.Get( logOut, size ); + logOut[ size ] = '\0'; + m_buf_Log.Purge(); + bDirty = false; + + m_BufferLock.Unlock(); +} +bool MainShaderEditorUpdate::IsLogDirty() +{ + bool bOut = false; + m_BufferLock.Lock(); + bOut = bDirty; + m_BufferLock.Unlock(); + return bOut; +} + + +void MainShaderEditorUpdate::SetCompilerState( bool bRunning ) +{ + m_LockCompilerState.Lock(); + bCompilerRunning = bRunning; + m_LockCompilerState.Unlock(); +} +bool MainShaderEditorUpdate::IsCompilerRunning() +{ + m_LockCompilerState.Lock(); + bool bReturn = bCompilerRunning; + m_LockCompilerState.Unlock(); + return bReturn; +} + +void CheckDirectories() +{ + Assert( pEditorRoot ); + + char checkSCompile[MAX_PATH]; + Q_snprintf( checkSCompile, MAX_PATH, "%s\\shadercompile.exe", GetBinaryPath() ); + if ( !g_pFullFileSystem->FileExists( checkSCompile ) ) + { + vgui::PromptSimple *prompt = new vgui::PromptSimple( pEditorRoot, "ERROR" ); + + int screenx,screeny; + engine->GetScreenSize(screenx,screeny); + screenx /= 2; + screeny /= 2; + int promptsizex = 240; + int promptsizey = 200; + screenx -= promptsizex / 2; + screeny -= promptsizey / 2; + + prompt->SetSize( promptsizex, promptsizey ); + prompt->SetPos( screenx,screeny ); + + char errormsg[MAXTARGC]; + if ( !g_pFullFileSystem->IsDirectory( GetBinaryPath() ) ) + Q_snprintf( errormsg, MAXTARGC, "Binaries cannot be located. Please run Source SDK once." ); + else + Q_snprintf( errormsg, MAXTARGC, "shadercompile.exe cannot be found at %s! Try reinstalling the Source SDK.", GetBinaryPath() ); + + prompt->SetText( errormsg ); + prompt->AddButton( "Ok", "onclose_prompt" ); + + prompt->MakeReadyForUse(); + prompt->InvalidateLayout( true, true ); + } +} + +void ReloadGameShaders( GenericShaderData *data, char **pszMaterialList, int iNumMaterials ) +{ + const bool bIsOverriding = !!data; + char *CanvasName = NULL; + + if ( bIsOverriding ) + { + const char *ShaderName = data->name; + + int SwapIndex = ::gProcShaderCTRL->FindPreloadShader( ShaderName ); + if ( SwapIndex < 0 ) + { + const char *pszSearch = Q_stristr( data->name, "_" ); + if ( pszSearch ) + { + const char *ShaderName_Small = pszSearch + 1; + SwapIndex = ::gProcShaderCTRL->FindPreloadShader( ShaderName_Small ); + } + } + + CanvasName = new char[ Q_strlen( ShaderName ) + 1 ]; + Q_strcpy( CanvasName, ShaderName ); + + BasicShaderCfg_t *SwapData = new BasicShaderCfg_t( *data->shader ); + Assert( !SwapData->CanvasName ); + SwapData->CanvasName = CanvasName; + + // build shader names + static unsigned int _HackyIndexIncrement = 0; + { + int len = Q_strlen( SwapData->ProcPSName ) + 2 + 7; + char *uniquifyShader = new char[len]; + Q_snprintf( uniquifyShader, len, "%06X_%s", _HackyIndexIncrement, SwapData->ProcPSName ); + delete [] SwapData->ProcPSName; + SwapData->ProcPSName = uniquifyShader; + } + { + int len = Q_strlen( SwapData->ProcVSName ) + 2 + 7; + char *uniquifyShader = new char[len]; + Q_snprintf( uniquifyShader, len, "%06X_%s", _HackyIndexIncrement, SwapData->ProcVSName ); + delete [] SwapData->ProcVSName; + SwapData->ProcVSName = uniquifyShader; + } + + char *OldName = data->name; + char targetname[MAX_PATH]; + Q_snprintf( targetname, MAX_PATH, "%06X_%s", _HackyIndexIncrement, OldName ); + + // copy vcs files + char __path_compiler[MAX_PATH]; + char __path_engine[MAX_PATH]; + ComposeShaderPath_Compiled( data, false, true, __path_compiler, MAX_PATH ); + data->name = targetname; + ComposeShaderPath_CompiledEngine( data, false, true, __path_engine, MAX_PATH ); + EngineCopy( __path_compiler, __path_engine ); + + data->name = OldName; + ComposeShaderPath_Compiled( data, true, true, __path_compiler, MAX_PATH ); + data->name = targetname; + ComposeShaderPath_CompiledEngine( data, true, true, __path_engine, MAX_PATH ); + EngineCopy( __path_compiler, __path_engine ); + + + data->name = OldName; + _HackyIndexIncrement++; + + if ( SwapIndex >= 0 ) + { + // swap shader data + BasicShaderCfg_t *trash = (BasicShaderCfg_t*)gProcShaderCTRL->SwapPreloadShader( SwapIndex, SwapData ); + delete trash; + } + else + gProcShaderCTRL->AddPreloadShader( SwapData ); + } + + // reload materials + if ( pszMaterialList && iNumMaterials ) + { + for ( int i = 0; i < iNumMaterials; i++ ) + { + IMaterial *pMat = materials->FindMaterial( pszMaterialList[i], TEXTURE_GROUP_MODEL ); + if ( IsErrorMaterial( pMat ) ) + continue; + + KeyValues *pKV = new KeyValues( "" ); + char tmppath[ MAX_PATH ]; + Q_snprintf( tmppath, MAX_PATH, "materials/%s.vmt", pszMaterialList[i] ); + if ( !pKV->LoadFromFile( g_pFullFileSystem, tmppath ) ) + { + pKV->deleteThis(); + continue; + } + + if ( bIsOverriding ) + { + pKV->SetName( "EDITOR_SHADER" ); + pKV->SetString( "$SHADERNAME", CanvasName ); + + const char *curEnvmap = pKV->GetString( "$envmap" ); + if ( !curEnvmap || !*curEnvmap ) + pKV->SetString( "$envmap", "env_cubemap" ); + } + else + UnpackMaterial( pKV ); + + pMat->SetShaderAndParams( pKV ); + + pMat->Refresh(); + pMat->RecomputeStateSnapshots(); + + pKV->deleteThis(); + } + return; + } + + if ( !bIsOverriding ) + return; + + QuickRefreshEditorShader(); +} +void QuickRefreshEditorShader() +{ + const char *nameLast = NULL; + for ( MaterialHandle_t curMatHandle = g_pMaterialSystem->FirstMaterial(); + curMatHandle != g_pMaterialSystem->InvalidMaterial(); + curMatHandle = g_pMaterialSystem->NextMaterial( curMatHandle ) ) + { + IMaterial *pMat = g_pMaterialSystem->GetMaterial( curMatHandle ); + if ( IsErrorMaterial( pMat ) ) + continue; + + //bool bSanityTest = false; + //IMaterialVar *pVarBaseTexture = pMat->FindVar( "$basetexture", &bSanityTest, false ); + //if ( !pVarBaseTexture || !bSanityTest ) + // continue; + if ( !pMat->ShaderParamCount() ) + continue; + + const char *n = pMat->GetName(); + + if ( !n || (nameLast && !Q_strcmp( nameLast, n )) ) + continue; + nameLast = n; + + const char *shaderName = pMat->GetShaderName(); + if ( !shaderName ) + continue; + + if ( !Q_stricmp( shaderName, "EDITOR_SHADER" ) ) + { + pMat->Refresh(); + pMat->RecomputeStateSnapshots(); + } + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/interface/editorinit.h b/sp/src/shadereditor/interface/editorinit.h new file mode 100644 index 00000000..46a589b8 --- /dev/null +++ b/sp/src/shadereditor/interface/editorinit.h @@ -0,0 +1,116 @@ +#ifndef EDITORINIT_H +#define EDITORINIT_H + +class ShaderEditorInterface; + +#include "IVProcShader.h" +#include "IVShaderEditor.h" + + +class ShaderEditorInterface : public IVShaderEditor +{ +public: + ShaderEditorInterface(); + ~ShaderEditorInterface(); + + bool Init( CreateInterfaceFn appSystemFactory, CGlobalVarsBase *pGlobals, + void *pSEditMRender, + bool bCreateEditor, bool bEnablePrimaryDebug, int iSkymaskMode ); + void Shutdown(); + void PrecacheData(); + + void OverridePaths( const char *pszWorkingDirectory, const char *pszCompilePath, const char *pszLocalCompilePath, + const char *pszGamePath, const char *pszCanvas, const char *pszShaderSource, const char *pszDumps, + const char *pszUserFunctions, const char *pszEditorRoot ); + + void OnFrame( float frametime ); + void OnPreRender( void *viewsetup ); + void OnSceneRender(); + void OnUpdateSkymask( bool bCombineMode, int x, int y, int w, int h ); + void OnPostRender( bool bUpdateFB ); + + void RegisterClientCallback( const char *name, pFnClCallback(callback), int numComponents ); + void LockClientCallbacks(); + + int GetNumCallbacks(); + _clCallback *GetCallback( int idx ); + int FindCallback( const char *name ); + + void RegisterViewRenderCallback( const char *pszVrCName, pFnVrCallback(callback), + const char **pszBoolNames, const bool *pBoolDefaults, const int numBoolParams, + const char **pszIntNames, const int *pIntDefaults, const int numIntParams, + const char **pszFloatNames, const float *pFloatDefaults, const int numFloatParams, + const char **pszStringNames, const char **pStringDefaults, const int numStringParams ); + void LockViewRenderCallbacks(); + + int GetPPEIndex( const char *pszName ); + bool IsPPEEnabled( const int &index ); + void SetPPEEnabled( const int &index, const bool &bEnabled ); + IMaterial *GetPPEMaterial( const int &index, const char *pszNodeName ); + void DrawPPEOnDemand( const int &index, const bool bInScene ); + void DrawPPEOnDemand( const int &index, int x, int y, int w, int h, const bool bInScene ); + IMaterialVar *GetPPEMaterialVarFast( ShaderEditVarToken &token, + const char *pszPPEName, const char *pszNodeName, const char *pszVarName ); + + const bool ShouldShowPrimaryDbg(){ return m_bShowPrimaryDebug; }; + + void SetFramebufferCopyTexOverride( ITexture *tex ); + void UpdateFramebufferTexture( bool bDoPush = false, bool bCopyToEditorTarget = false ); + + void FlushPPEMaterialVarCache(); + +private: + static bool bCallbackLock; + static bool bVrCallbackLock; + bool m_bShowPrimaryDebug; + + CUtlVector< _clCallback* > m_hFunctionCallbacks; + + KeyValues *pSkyMats[3]; + + unsigned int m_iLastInvalidVarToken; + unsigned int m_iNextValidVarToken; + CUtlVector< IMaterialVar* > m_cachedMVars; +}; + + +class MainShaderEditorUpdate : public CAutoGameSystemPerFrame +{ +public: + MainShaderEditorUpdate( char const *name ); + ~MainShaderEditorUpdate(); + + virtual bool Init(); + virtual void Update( float frametime ); + + void QueueLog( const char *_data, int len ); + void QueueLog( const char *_data ); + void ParseLog( char *logOut, int maxLen ); + bool IsLogDirty(); + + void PreRender(); + void UpdateConstants( const CViewSetup *_override ); + void UpdateConstants( const CViewSetup_SEdit_Shared *_override = NULL ); + + void SetCompilerState( bool bRunning ); + bool IsCompilerRunning(); + + void BeginMaterialReload( bool bResetMode ); + +private: + CThreadMutex m_BufferLock; + CUtlBuffer m_buf_Log; + bool bDirty; + + CThreadMutex m_LockCompilerState; + bool bCompilerRunning; +}; + +extern void ForceTerminateCompilers(); + +extern ShaderEditorInterface *shaderEdit; +extern MainShaderEditorUpdate *gShaderEditorSystem; + +void CheckDirectories(); + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/interface/isedit_modelrender.h b/sp/src/shadereditor/interface/isedit_modelrender.h new file mode 100644 index 00000000..6db545e9 --- /dev/null +++ b/sp/src/shadereditor/interface/isedit_modelrender.h @@ -0,0 +1,41 @@ +#ifndef IV_SHADEREDITOR_MRENDER +#define IV_SHADEREDITOR_MRENDER + +#ifdef _WIN32 +#pragma once +#endif // _WIN32 + +#ifdef SHADER_EDITOR_DLL +#include "../public/tier1/interface.h" +#else +#include "interface.h" +#include "ShaderEditor/ShaderEditorSystem.h" +#endif // NOT SHADER_EDITOR_DLL + + +class ISEditModelRender +{ +public: + virtual bool LoadModel( const char *localPath ) = 0; + virtual void DestroyModel() = 0; + virtual void GetModelCenter( float *pFl3_ViewOffset ) = 0; + + virtual int QuerySequences( char ***list ) = 0; + virtual void SetSequence( const char *name ) = 0; + + virtual void ExecRender() = 0; + virtual void DoPostProc( int x, int y, int w, int h ) = 0; + virtual int MaterialPicker( char ***szMat ) = 0; + + virtual void DestroyCharPtrList( char ***szList ) = 0; +}; + + +#ifdef SHADER_EDITOR_DLL +extern ISEditModelRender *sEditMRender; +#else +class SEditModelRender; +extern SEditModelRender *sEditMRender; +#endif + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/interface/ppehelper.cpp b/sp/src/shadereditor/interface/ppehelper.cpp new file mode 100644 index 00000000..f0fceda3 --- /dev/null +++ b/sp/src/shadereditor/interface/ppehelper.cpp @@ -0,0 +1,81 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +static CPPEHelper __ppeHelper_Instance; +CPPEHelper *gPPEHelper = &__ppeHelper_Instance; + +CPPEHelper::CPPEHelper() +{ +} + +CPPEHelper::~CPPEHelper() +{ +} + +void CPPEHelper::DestroyKeyValues( KeyValues *pKV ) +{ + Assert( pKV ); + + pKV->deleteThis(); +} + +KeyValues *CPPEHelper::GetInlineMaterial( const char *szmatName ) +{ + if ( !szmatName ) + return NULL; + + for ( int i = 0; i < GetPPCache()->GetNumPostProcessingEffects(); i++ ) + { + CUtlVector &solver = GetPPCache()->GetPostProcessingEffect(i)->hSolverArray; + + KeyValues *pKV = GetInlineMaterial( szmatName, solver ); + if ( pKV != NULL ) + return pKV; + } + + if ( IsInEditMode() ) + { + for ( int i = 0; i < pEditorRoot->GetNumFlowGraphs(); i++ ) + { + CNodeView *pView = pEditorRoot->GetFlowGraph( i ); + + if ( pView->GetFlowgraphType() != CNodeView::FLOWGRAPH_POSTPROC ) + continue; + + CUtlVector &solver = pView->AccessSolverStack_POSTPROC(); + + KeyValues *pKV = GetInlineMaterial( szmatName, solver ); + if ( pKV != NULL ) + return pKV; + } + } + + Assert(0); + + return NULL; +} + +KeyValues *CPPEHelper::GetInlineMaterial( const char *szmatName, CUtlVector &hStack ) +{ + for ( int s = 0; s < hStack.Count(); s++ ) + { + CHLSL_Solver_PP_Mat *pMatSolver = dynamic_cast< CHLSL_Solver_PP_Mat* >( hStack[s] ); + if ( !pMatSolver ) + continue; + + if ( !pMatSolver->IsInline() ) + continue; + + if ( !pMatSolver->GetNumTargetVars() ) + continue; + + if ( !pMatSolver->GetMaterialName() || Q_strcmp( szmatName, pMatSolver->GetMaterialName() ) ) + continue; + + return pMatSolver->AccessKeyValues(); + } + + return NULL; +} \ No newline at end of file diff --git a/sp/src/shadereditor/interface/ppehelper.h b/sp/src/shadereditor/interface/ppehelper.h new file mode 100644 index 00000000..b6e410ab --- /dev/null +++ b/sp/src/shadereditor/interface/ppehelper.h @@ -0,0 +1,25 @@ +#ifndef PPE_HELPER_H +#define PPE_HELPER_H + +#include "cbase.h" + + +class CPPEHelper : public IVPPEHelper +{ +public: + + CPPEHelper(); + ~CPPEHelper(); + + KeyValues *GetInlineMaterial( const char *szmatName ); + void DestroyKeyValues( KeyValues *pKV ); + +private: + + KeyValues *GetInlineMaterial( const char *szmatName, CUtlVector &hStack ); + +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/ivshadereditor.h b/sp/src/shadereditor/ivshadereditor.h new file mode 100644 index 00000000..679ba518 --- /dev/null +++ b/sp/src/shadereditor/ivshadereditor.h @@ -0,0 +1,148 @@ +#ifndef IV_SHADEREDITOR +#define IV_SHADEREDITOR + +#ifdef _WIN32 +#pragma once +#endif // _WIN32 + +#define pFnClCallback( x ) void(* x )( float *pfl4 ) +#define pFnClCallback_Declare( x ) void x( float *pfl4 ) + +#define pFnVrCallback( x ) void(* x )( bool * const pbOptions, int * const piOptions,\ + float * const pflOptions, char ** const pszOptions ) +#define pFnVrCallback_Declare( x ) void x( bool * const pbOptions, int * const piOptions,\ + float * const pflOptions, char ** const pszOptions ) + +#define DEFINE_SHADEREDITOR_MATERIALVAR( effectName, nodeName, materialVarName, localVarName ) \ + static ShaderEditVarToken token_ ## localVarName = SHADEREDIT_MVAR_TOKEN_INVALID; \ + IMaterialVar *localVarName = shaderEdit->GetPPEMaterialVarFast( \ + token_ ## localVarName, effectName, nodeName, materialVarName ) + +#ifndef PROCSHADER_DLL + +#ifdef SHADER_EDITOR_DLL +#include "../public/tier1/interface.h" +#include "view_shared.h" +#else +#include "interface.h" +#include "../../game/client/ShaderEditor/ShaderEditorSystem.h" +#endif // NOT SHADER_EDITOR_DLL + +class IMaterial; +class IMaterialVar; + +typedef unsigned int ShaderEditVarToken; + +enum SEDIT_SKYMASK_MODE +{ + SKYMASK_OFF = 0, + SKYMASK_QUARTER, // render at 1/4 fb size where possible + SKYMASK_FULL, // render at full fb size +}; + +class CViewSetup_SEdit_Shared +{ +public: + CViewSetup_SEdit_Shared() + { + Q_memset( this, 0, sizeof( CViewSetup_SEdit_Shared ) ); + }; + CViewSetup_SEdit_Shared( const CViewSetup &o ) + { + x = o.x; + y = o.y; + width = o.width; + height = o.height; + fov = o.fov; + fovViewmodel = o.fovViewmodel; + origin = o.origin; + angles = o.angles; + zNear = o.zNear; + zFar = o.zFar; + zNearViewmodel = o.zNearViewmodel; + zFarViewmodel = o.zFarViewmodel; + m_flAspectRatio = o.m_flAspectRatio; + }; + int x,y,width,height; + float fov,fovViewmodel; + Vector origin; + QAngle angles; + float zNear,zFar,zNearViewmodel,zFarViewmodel; + float m_flAspectRatio; +}; + + +class IVShaderEditor : public IBaseInterface +{ +public: + virtual bool Init( CreateInterfaceFn appSystemFactory, CGlobalVarsBase *pGlobals, + void *pSEditMRender, + bool bCreateEditor, bool bEnablePrimaryDebug, int iSkymaskMode ) = 0; + virtual void Shutdown() = 0; + virtual void PrecacheData() = 0; + + // call before Init() to overwrite any paths, pass in NULL for the ones that shouldn't be overwritten + virtual void OverridePaths( const char *pszWorkingDirectory, + const char *pszCompilePath = NULL, // abs path to compiler binaries + const char *pszLocalCompilePath = NULL, // local path to compiler binaries, relative to shader source directory + const char *pszGamePath = NULL, + const char *pszCanvas = NULL, // path to canvas files + const char *pszShaderSource = NULL, // path to shader source files + const char *pszDumps = NULL, // path to shader configuration files + const char *pszUserFunctions = NULL, // path to custom function bodies + const char *pszEditorRoot = NULL ) = 0; // path to 'shadereditorui' home directory + + // update the lib + virtual void OnFrame( float frametime ) = 0; + virtual void OnPreRender( void *viewsetup ) = 0; + virtual void OnSceneRender() = 0; + virtual void OnUpdateSkymask( bool bCombineMode, int x, int y, int w, int h ) = 0; + virtual void OnPostRender( bool bUpdateFB ) = 0; + + // data callbacks for hlsl constants + virtual void RegisterClientCallback( const char *name, pFnClCallback(callback), int numComponents ) = 0; + virtual void LockClientCallbacks() = 0; + + // view render callbacks for post processing graphs + virtual void RegisterViewRenderCallback( const char *pszVrCName, pFnVrCallback(callback), + const char **pszBoolNames = NULL, const bool *pBoolDefaults = NULL, const int numBoolParams = 0, + const char **pszIntNames = NULL, const int *pIntDefaults = NULL, const int numIntParams = 0, + const char **pszFloatNames = NULL, const float *pFloatDefaults = NULL, const int numFloatParams = 0, + const char **pszStringNames = NULL, const char **pStringDefaults = NULL, const int numStringParams = 0 ) = 0; + virtual void LockViewRenderCallbacks() = 0; + + // post processing effect manipulation (precached effects accessible) + // the index becomes invalid when editing the precache list + virtual int GetPPEIndex( const char *pszName ) = 0; // returns -1 when not found, case insensitive + virtual bool IsPPEEnabled( const int &index ) = 0; + virtual void SetPPEEnabled( const int &index, const bool &bEnabled ) = 0; + virtual IMaterial *GetPPEMaterial( const int &index, const char *pszNodeName ) = 0; + + // Draws a PPE graph right now or adds it to the render queue (r_queued_post_processing!) + // Does not push a new RT but uses the current one + // If you have 'during scene' nodes, make sure to call it twice in the appropriate places + virtual void DrawPPEOnDemand( const int &index, const bool bInScene = false ) = 0; + virtual void DrawPPEOnDemand( const int &index, int x, int y, int w, int h, const bool bInScene = false ) = 0; + + // access a materialvar based on an incrementing token + // you don't need to cache the returned value, it's okay to call this each frame + // initialize the token with SHADEREDIT_MVAR_TOKEN_INVALID + virtual IMaterialVar *GetPPEMaterialVarFast( ShaderEditVarToken &token, + const char *pszPPEName, const char *pszNodeName, const char *pszVarName ) = 0; +}; + +#define SHADEREDIT_MVAR_TOKEN_INVALID 0 +#define SHADEREDIT_MVAR_TOKEN_FAILED 0xFFFFFFFF + +#define SHADEREDIT_INTERFACE_VERSION "ShaderEditor005" + +#ifdef SHADER_EDITOR_DLL +class ShaderEditorInterface; +extern ShaderEditorInterface *shaderEdit; +#else +extern IVShaderEditor *shaderEdit; +#endif // NOT SHADER_EDITOR_DLL + +#endif // NOT PROCSHADER_DLL + +#endif // NOT IV_SHADEREDITOR \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_base.cpp b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_base.cpp new file mode 100644 index 00000000..dfb21a5d --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_base.cpp @@ -0,0 +1,76 @@ + +#include "cbase.h" +#include "editorcommon.h" + +CNodePP_Base::CNodePP_Base( const char *opName, CNodeView *p ) : BaseClass( opName, p ) +{ + SetupVguiTex( m_iPreviewMaterial, "shadereditor/_rt_ppe" ); +} +CNodePP_Base::~CNodePP_Base() +{ +} +const int CNodePP_Base::GetAllowedFlowgraphTypes() +{ + return CNodeView::FLOWGRAPH_POSTPROC; +} +CNodePP_Base *CNodePP_Base::GetNextPPNode( int dir ) +{ + const bool bBack = dir < 0; + CJack *pJ = bBack ? (GetNumJacks_In()>0)?GetJack_In(0):NULL : (GetNumJacks_Out()>0)?GetJack_Out(0):NULL; + if ( !pJ ) + return NULL; + if ( pJ->GetNumBridgesConnected() <= 0 ) + return NULL; + + CNodePP_Base *pNode = dynamic_cast( pJ->GetBridge(0)->GetEndNode(this) ); + + return pNode; +} + + +CNodePP_Input::CNodePP_Input( CNodeView *p ) : BaseClass( "PP Input", p ) +{ + m_flMinSizeX = CRUCIALNODE_MIN_SIZE_X; + m_flMinSizeY = 0; + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "Chain master" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); +} +CNodePP_Input::~CNodePP_Input() +{ +} +bool CNodePP_Input::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_Start *solver = new CHLSL_Solver_PP_Start( GetUniqueIndex() ); + AddSolver( solver ); + return true; +} + + +CNodePP_Output::CNodePP_Output( CNodeView *p ) : BaseClass( "PP Output", p ) +{ + m_flMinSizeX = CRUCIALNODE_MIN_SIZE_X; + m_flMinSizeY = 0; + + GenerateJacks_Input( 1 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "Chain master" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + OnUpdateHierachy( NULL, NULL ); +} +CNodePP_Output::~CNodePP_Output() +{ +} +int CNodePP_Output::UpdateInputsValid() +{ + if ( GetNumJacks_In() > GetNumJacks_In_Connected() ) + return ERRORLEVEL_FAIL; + return BaseClass::UpdateInputsValid(); +} +bool CNodePP_Output::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_Base *solver = new CHLSL_Solver_PP_Base( GetUniqueIndex() ); + AddSolver( solver ); + return true; +} diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_base.h b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_base.h new file mode 100644 index 00000000..bf7b3775 --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_base.h @@ -0,0 +1,77 @@ +#ifndef CNODE_PP_BASE_H +#define CNODE_PP_BASE_H + +#include + +class CNodePP_Base : public CBaseNode +{ + DECLARE_CLASS( CNodePP_Base, CBaseNode ); +public: + + CNodePP_Base( const char *opName, CNodeView *p ); + ~CNodePP_Base(); + + virtual const int GetAllowedFlowgraphTypes(); + + virtual bool CanBeInContainer(){ return false; }; + //virtual bool IsPreviewVisible(){ return true; }; + + virtual int GetHierachyType(){return HLSLHIERACHY_POST_PROCESS;}; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_POST_PROCESS; }; + + CNodePP_Base *GetNextPPNode( int dir = 1 ); + virtual const bool IsSceneNode(){ return false; }; + +}; + + + +class CNodePP_Input : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_Input, CNodePP_Base ); +public: + + CNodePP_Input( CNodeView *p ); + ~CNodePP_Input(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_INPUT; }; + virtual const bool IsNodeCrucial(){ return true; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + virtual int UpdateInputsValid(){ return ERRORLEVEL_NONE; }; + + //virtual KeyValues *AllocateKeyValues( int NodeIndex ); + //virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +class CNodePP_Output : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_Output, CNodePP_Base ); +public: + + CNodePP_Output( CNodeView *p ); + ~CNodePP_Output(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_OUTPUT; }; + virtual const bool IsNodeCrucial(){ return true; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + virtual int UpdateInputsValid(); + + //virtual KeyValues *AllocateKeyValues( int NodeIndex ); + //virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_drawmat.cpp b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_drawmat.cpp new file mode 100644 index 00000000..986b2291 --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_drawmat.cpp @@ -0,0 +1,114 @@ + +#include "cbase.h" +#include "editorCommon.h" + + + +CNodePP_DrawMat::CNodePP_DrawMat( CNodeView *p ) : BaseClass( "Draw material", p ) +{ + m_bAllInputsRequired = false; + m_iSizingMode_Tg = VPSIZINGMODE_FULL_FB; + m_iSizingMode_Src = VPSIZINGMODE_FULL_FB; + m_bPushTarget = true; + Q_memset( &m_offsets, 0, sizeof( vp_offsets_t ) ); + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + GenerateJacks_Input( 4 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + LockJackInput_Flags( 1, HLSLVAR_PP_MATERIAL, "Material" ); + LockJackInput_Flags( 2, HLSLVAR_PP_RT, "Ref target (optional)" ); + LockJackInput_Flags( 3, HLSLVAR_PP_RT, "Ref source (optional)" ); +} + +CNodePP_DrawMat::~CNodePP_DrawMat() +{ +} + +KeyValues *CNodePP_DrawMat::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "iSizingMode_Tg", m_iSizingMode_Tg ); + pKV->SetInt( "iSizingMode_Src", m_iSizingMode_Src ); + pKV->SetInt( "iPushTg", m_bPushTarget ? 1 : 0 ); + + pKV->SetInt( "iSHEETHINT_enable_tg", GetJack_In(2)->GetNumBridgesConnected() ); + pKV->SetInt( "iSHEETHINT_enable_src", GetJack_In(3)->GetNumBridgesConnected() ); + + pKV->SetInt( "iDst_x", m_offsets.dst_x ); + pKV->SetInt( "iDst_y", m_offsets.dst_y ); + pKV->SetInt( "iDst_w", m_offsets.dst_w ); + pKV->SetInt( "iDst_h", m_offsets.dst_h ); + + pKV->SetFloat( "flSrcUV_x0", m_offsets.src_x0 ); + pKV->SetFloat( "flSrcUV_y0", m_offsets.src_y0 ); + pKV->SetFloat( "flSrcUV_x", m_offsets.src_x1 ); + pKV->SetFloat( "flSrcUV_y", m_offsets.src_y1 ); + + pKV->SetInt( "iSrc_w", m_offsets.src_w ); + pKV->SetInt( "iSrc_h", m_offsets.src_h ); + + return pKV; +} + +void CNodePP_DrawMat::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iSizingMode_Tg = pKV->GetInt( "iSizingMode_Tg" ); + m_iSizingMode_Src = pKV->GetInt( "iSizingMode_Src" ); + m_bPushTarget = !!pKV->GetInt( "iPushTg" ); + + m_offsets.dst_x = pKV->GetInt( "iDst_x" ); + m_offsets.dst_y = pKV->GetInt( "iDst_y" ); + m_offsets.dst_w = pKV->GetInt( "iDst_w" ); + m_offsets.dst_h = pKV->GetInt( "iDst_h" ); + + m_offsets.src_x0 = pKV->GetFloat( "flSrcUV_x0" ); + m_offsets.src_y0 = pKV->GetFloat( "flSrcUV_y0" ); + m_offsets.src_x1 = pKV->GetFloat( "flSrcUV_x" ); + m_offsets.src_y1 = pKV->GetFloat( "flSrcUV_y" ); + + m_offsets.src_w = pKV->GetInt( "iSrc_w" ); + m_offsets.src_h = pKV->GetInt( "iSrc_h" ); +} + +int CNodePP_DrawMat::UpdateInputsValid() +{ + int baseerror = BaseClass::UpdateInputsValid(); + + int localerror = ( GetJack_In(0)->GetNumBridgesConnected() < 1 ) ? ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE; + localerror = max( ( GetJack_In(1)->GetNumBridgesConnected() < 1 ) ? ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE, localerror ); + + return max( baseerror, localerror ); +} + +bool CNodePP_DrawMat::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_DrawMat *solver = new CHLSL_Solver_PP_DrawMat( GetUniqueIndex() ); + + int sizing_tg = m_iSizingMode_Tg; + int sizing_src = m_iSizingMode_Src; + + // mat + solver->AddSourceVar( GetJack_In(1)->GetTemporaryVarTarget_End() ); + // ref tg + if ( GetJack_In(2)->GetNumBridgesConnected() > 0 ) + { + solver->AddSourceVar( GetJack_In(2)->GetTemporaryVarTarget_End() ); + sizing_tg = VPSIZINGMODE_USE_RT; + } + // ref src + if ( GetJack_In(3)->GetNumBridgesConnected() > 0 ) + { + solver->AddSourceVar( GetJack_In(3)->GetTemporaryVarTarget_End() ); + sizing_src = VPSIZINGMODE_USE_RT; + } + + solver->Init( sizing_tg, sizing_src, m_bPushTarget, m_offsets ); + + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_drawmat.h b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_drawmat.h new file mode 100644 index 00000000..f9fb1292 --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_drawmat.h @@ -0,0 +1,39 @@ +#ifndef CNODE_PP_DRAWMAT_H +#define CNODE_PP_DRAWMAT_H + +#include + +class CNodePP_DrawMat : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_DrawMat, CNodePP_Base ); +public: + + enum + { + VPSIZINGMODE_USE_RT = -1, + VPSIZINGMODE_FULL_FB = 0, + VPSIZINGMODE_HALF_FB, + VPSIZINGMODE_QUARTER_FB, + }; + + CNodePP_DrawMat( CNodeView *p ); + ~CNodePP_DrawMat(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_DRAW_MATERIAL; }; + + virtual int UpdateInputsValid(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iSizingMode_Tg; + int m_iSizingMode_Src; + bool m_bPushTarget; + vp_offsets_t m_offsets; +}; + + +#endif diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_mat.cpp b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_mat.cpp new file mode 100644 index 00000000..9973eef5 --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_mat.cpp @@ -0,0 +1,82 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodePP_Mat::CNodePP_Mat( CNodeView *p ) : BaseClass( "Material", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MATERIAL, "Material" ); + + m_szMatPath[0] = '\0'; + m_pszInlineVMT = NULL; + m_bInline = true; + + OnUpdateHierachy( NULL, NULL ); +} + +CNodePP_Mat::~CNodePP_Mat() +{ + delete [] m_pszInlineVMT; +} + +KeyValues *CNodePP_Mat::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetString( "szVMTPath", m_szMatPath ); + pKV->SetInt( "iInline", m_bInline ? 1 : 0 ); + + if ( m_bInline && m_pszInlineVMT && Q_strlen(m_pszInlineVMT) > 0 ) + { + CKVPacker::KVPack( m_pszInlineVMT, "szVMTString", pKV ); + //pKV->SetString( "szVMTString", m_pszInlineVMT ); + } + + return pKV; +} + +void CNodePP_Mat::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + Q_snprintf( m_szMatPath, sizeof(m_szMatPath), "%s", pKV->GetString( "szVMTPath" ) ); + m_bInline = !!pKV->GetInt( "iInline" ); + + delete [] m_pszInlineVMT; + m_pszInlineVMT = NULL; + //const char *pszInlineCode = ( m_bInline ? pKV->GetString( "szVMTString" ) : NULL ); + + char *pszInlineCode = m_bInline ? CKVPacker::KVUnpack( pKV, "szVMTString" ) : NULL; + + if ( pszInlineCode && Q_strlen(pszInlineCode) > 0 ) + AutoCopyStringPtr( pszInlineCode, &m_pszInlineVMT ); + + delete [] pszInlineCode; + + OnUpdateHierachy(NULL,NULL); +} + +int CNodePP_Mat::UpdateInputsValid() +{ + if (m_bInline && (!m_pszInlineVMT || !*m_pszInlineVMT)) + return ERRORLEVEL_UNDEFINED; + + if (!m_bInline && (!*m_szMatPath || !g_pFullFileSystem->FileExists(m_szMatPath))) + return ERRORLEVEL_UNDEFINED; + + return ERRORLEVEL_NONE; +} + +bool CNodePP_Mat::CreateSolvers(GenericShaderData *ShaderData) +{ + const char *pszUserName = GetUserName(); + char *pUnsafeInline = CKVPacker::ConvertKVSafeString( m_pszInlineVMT, false ); + + CHLSL_Var *pVar = GetJack_Out(0)->AllocateVarFromSmartType(); //new CHLSL_Var( HLSLVAR_PP_RT ); + + CHLSL_Solver_PP_Mat *solver = new CHLSL_Solver_PP_Mat( GetUniqueIndex() ); + solver->AddTargetVar( pVar ); + solver->Init( m_bInline, m_szMatPath, pUnsafeInline, pszUserName ); + AddSolver( solver ); + + delete [] pUnsafeInline; + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_mat.h b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_mat.h new file mode 100644 index 00000000..3c286ae1 --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_mat.h @@ -0,0 +1,31 @@ +#ifndef CNODE_PP_MAT_H +#define CNODE_PP_MAT_H + +#include + +class CNodePP_Mat : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_Mat, CNodePP_Base ); +public: + + CNodePP_Mat( CNodeView *p ); + ~CNodePP_Mat(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_CREATE_MAT; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + virtual int UpdateInputsValid(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + char m_szMatPath[MAX_PATH*4]; + char *m_pszInlineVMT; + + bool m_bInline; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_operations.cpp b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_operations.cpp new file mode 100644 index 00000000..feef827a --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_operations.cpp @@ -0,0 +1,258 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodePP_ClearBuffers::CNodePP_ClearBuffers( CNodeView *p ) : BaseClass( "Clear buffers", p ) +{ + m_bAllInputsRequired = false; + + m_bClearColor = true; + m_bClearDepth = true; + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + GenerateJacks_Input( 2 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + LockJackInput_Flags( 1, HLSLVAR_PP_RT, "RT (optional)" ); + + + m_iChannelInfo.SetDefaultChannels(); + m_iChannelInfo.bAllowChars = false; + m_szConstantString[0] = '\0'; +} +CNodePP_ClearBuffers::~CNodePP_ClearBuffers() +{ +} +int CNodePP_ClearBuffers::UpdateInputsValid() +{ + int baseerror = BaseClass::UpdateInputsValid(); + + int localerror = ( GetJack_In(0)->GetNumBridgesConnected() < 1 ) ? ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE; + + return max( baseerror, localerror ); +} +KeyValues *CNodePP_ClearBuffers::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetString( "szConstantString", m_szConstantString ); + pKV->SetInt( "iClear_Color", m_bClearColor ? 1 : 0 ); + pKV->SetInt( "iClear_Depth", m_bClearDepth ? 1 : 0 ); + + return pKV; +} +void CNodePP_ClearBuffers::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + char tmp[MAX_PATH]; + Q_snprintf( tmp, sizeof(tmp), "%s", pKV->GetString( "szConstantString" ) ); + + m_iChannelInfo.Tokenize( tmp ); + m_iChannelInfo.PrintTargetString( m_szConstantString, MAX_PATH ); + + m_bClearColor = !!pKV->GetInt( "iClear_Color" ); + m_bClearDepth = !!pKV->GetInt( "iClear_Depth" ); +} +bool CNodePP_ClearBuffers::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_ClearBuffers *solver = new CHLSL_Solver_PP_ClearBuffers( GetUniqueIndex() ); + solver->Init( m_iChannelInfo, m_bClearColor, m_bClearDepth ); + + if ( GetNumJacks_In_Connected() > 1 ) + solver->AddSourceVar( GetJack_In(1)->GetTemporaryVarTarget_End() ); + + AddSolver( solver ); + return true; +} + + +CNodePP_VP_Push::CNodePP_VP_Push( CNodeView *p ) : BaseClass( "Push RT / viewport", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + GenerateJacks_Input( 2 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + LockJackInput_Flags( 1, HLSLVAR_PP_RT, "RT (optional)" ); +} +CNodePP_VP_Push::~CNodePP_VP_Push() +{ +} +int CNodePP_VP_Push::UpdateInputsValid() +{ + int pushCount = 1; + + CNodePP_Base *pSearchPop = GetNextPPNode(); + while ( pSearchPop != NULL && pushCount != 0 ) + { + if ( pSearchPop->GetNodeType() == HLSLNODE_POSTPROCESSING_PUSH_VP ) + pushCount++; + + else if ( pSearchPop->GetNodeType() == HLSLNODE_POSTPROCESSING_POP_VP ) + pushCount--; + + pSearchPop = pSearchPop->GetNextPPNode(); + } + + if ( pushCount != 0 ) + return ERRORLEVEL_FAIL; + + return BaseClass::UpdateInputsValid(); +} +bool CNodePP_VP_Push::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_VP_Push *solver = new CHLSL_Solver_PP_VP_Push( GetUniqueIndex() ); + if ( GetNumJacks_In_Connected() > 1 ) + solver->AddSourceVar( GetJack_In(1)->GetTemporaryVarTarget_End() ); + AddSolver( solver ); + return true; +} + + + +CNodePP_VP_Pop::CNodePP_VP_Pop( CNodeView *p ) : BaseClass( "Pop RT / viewport", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + GenerateJacks_Input( 1 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); +} +CNodePP_VP_Pop::~CNodePP_VP_Pop() +{ +} +int CNodePP_VP_Pop::UpdateInputsValid() +{ + int pushCount = -1; + + CNodePP_Base *pSearchPop = GetNextPPNode(-1); + while ( pSearchPop != NULL && pushCount != 0 ) + { + if ( pSearchPop->GetNodeType() == HLSLNODE_POSTPROCESSING_PUSH_VP ) + pushCount++; + + else if ( pSearchPop->GetNodeType() == HLSLNODE_POSTPROCESSING_POP_VP ) + pushCount--; + + pSearchPop = pSearchPop->GetNextPPNode(-1); + } + + if ( pushCount != 0 ) + return ERRORLEVEL_FAIL; + + return BaseClass::UpdateInputsValid(); +} +bool CNodePP_VP_Pop::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_VP_Pop *solver = new CHLSL_Solver_PP_VP_Pop( GetUniqueIndex() ); + AddSolver( solver ); + return true; +} + + + + +CNodePP_VP_SetRT::CNodePP_VP_SetRT( CNodeView *p ) : BaseClass( "Set RT / viewport", p ) +{ + m_bAllInputsRequired = false; + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + GenerateJacks_Input( 2 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + LockJackInput_Flags( 1, HLSLVAR_PP_RT, "RT (optional)" ); +} +CNodePP_VP_SetRT::~CNodePP_VP_SetRT() +{ +} +int CNodePP_VP_SetRT::UpdateInputsValid() +{ + int baseerror = BaseClass::UpdateInputsValid(); + + int localerror = ( GetJack_In(0)->GetNumBridgesConnected() < 1 ) ? ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE; + + return max( baseerror, localerror ); +} +bool CNodePP_VP_SetRT::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_VP_SetRT *solver = new CHLSL_Solver_PP_VP_SetRT( GetUniqueIndex() ); + + if ( GetNumJacks_In_Connected() > 1 ) + solver->AddSourceVar( GetJack_In(1)->GetTemporaryVarTarget_End() ); + + AddSolver( solver ); + return true; +} + + + + +CNodePP_CopyRT::CNodePP_CopyRT( CNodeView *p ) : BaseClass( "Copy RT", p ) +{ + m_bAllInputsRequired = false; + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + GenerateJacks_Input( 3 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + LockJackInput_Flags( 1, HLSLVAR_PP_RT, "RT source (optional)" ); + LockJackInput_Flags( 2, HLSLVAR_PP_RT, "RT target" ); +} +CNodePP_CopyRT::~CNodePP_CopyRT() +{ +} +int CNodePP_CopyRT::UpdateInputsValid() +{ + int baseerror = BaseClass::UpdateInputsValid(); + + int localerror = ( GetJack_In(0)->GetNumBridgesConnected() < 1 ) ? ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE; + localerror = max( localerror, ( GetJack_In(2)->GetNumBridgesConnected() < 1 ) ? ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE ); + + return max( baseerror, localerror ); +} +bool CNodePP_CopyRT::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_CopyRT *solver = new CHLSL_Solver_PP_CopyRT( GetUniqueIndex() ); + + solver->AddSourceVar( GetJack_In(2)->GetTemporaryVarTarget_End() ); + + if ( GetJack_In(1)->GetNumBridgesConnected() > 0 ) + solver->AddSourceVar( GetJack_In(1)->GetTemporaryVarTarget_End() ); + + AddSolver( solver ); + return true; +} + + + + +CNodePP_UpdateFB::CNodePP_UpdateFB( CNodeView *p ) : BaseClass( "Update FB copy", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + GenerateJacks_Input( 1 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); +} +CNodePP_UpdateFB::~CNodePP_UpdateFB() +{ +} +bool CNodePP_UpdateFB::CreateSolvers(GenericShaderData *ShaderData) +{ + CHLSL_Solver_PP_UpdateFB *solver = new CHLSL_Solver_PP_UpdateFB( GetUniqueIndex() ); + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_operations.h b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_operations.h new file mode 100644 index 00000000..a00923f2 --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_operations.h @@ -0,0 +1,115 @@ +#ifndef CNODE_PP_OPERATIONS_H +#define CNODE_PP_OPERATIONS_H + +#include + +class CNodePP_ClearBuffers : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_ClearBuffers, CNodePP_Base ); +public: + + CNodePP_ClearBuffers( CNodeView *p ); + ~CNodePP_ClearBuffers(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_CLEAR_BUFFERS; }; + virtual int UpdateInputsValid(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + TokenChannels_t m_iChannelInfo; + char m_szConstantString[MAX_PATH]; + + bool m_bClearColor; + bool m_bClearDepth; +}; + + +class CNodePP_VP_Push : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_VP_Push, CNodePP_Base ); +public: + + CNodePP_VP_Push( CNodeView *p ); + ~CNodePP_VP_Push(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_PUSH_VP; }; + virtual int UpdateInputsValid(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +class CNodePP_VP_Pop : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_VP_Pop, CNodePP_Base ); +public: + + CNodePP_VP_Pop( CNodeView *p ); + ~CNodePP_VP_Pop(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_POP_VP; }; + virtual int UpdateInputsValid(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +class CNodePP_VP_SetRT : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_VP_SetRT, CNodePP_Base ); +public: + + CNodePP_VP_SetRT( CNodeView *p ); + ~CNodePP_VP_SetRT(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_SET_RT; }; + virtual int UpdateInputsValid(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +class CNodePP_CopyRT : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_CopyRT, CNodePP_Base ); +public: + + CNodePP_CopyRT( CNodeView *p ); + ~CNodePP_CopyRT(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_COPY_RT; }; + virtual int UpdateInputsValid(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +class CNodePP_UpdateFB : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_UpdateFB, CNodePP_Base ); +public: + + CNodePP_UpdateFB( CNodeView *p ); + ~CNodePP_UpdateFB(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_UPDATE_FB; }; + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_renderview.cpp b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_renderview.cpp new file mode 100644 index 00000000..82efa7df --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_renderview.cpp @@ -0,0 +1,111 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodePP_RenderView::CNodePP_RenderView( CNodeView *p ) : BaseClass( "Render view", p ) +{ + m_bAllInputsRequired = false; + m_ViewRenderData = new EditorRenderViewCommand_Data(); + m_bSceneDraw = false; + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hOutputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + + GenerateJacks_Input( 3 ); + LockJackInput_Flags( 0, HLSLVAR_PP_MASTER, "" ); + m_hInputs[ 0 ]->SetJackColorCode( HLSLJACK_COLOR_PPMASTER ); + LockJackInput_Flags( 1, HLSLVAR_PP_RT, "RT target" ); + LockJackInput_Flags( 2, HLSLVAR_PP_MATERIAL, "Material override (optional)" ); + + OnUpdateHierachy(NULL,NULL); +} + +CNodePP_RenderView::~CNodePP_RenderView() +{ + delete m_ViewRenderData; +} + +KeyValues *CNodePP_RenderView::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + if ( m_ViewRenderData->GetName() != NULL ) + pKV->SetString( "szVRCName", m_ViewRenderData->GetName() ); + + pKV->SetInt( "options_bool_amt", m_ViewRenderData->GetNumBool() ); + pKV->SetInt( "options_int_amt", m_ViewRenderData->GetNumInt() ); + pKV->SetInt( "options_float_amt", m_ViewRenderData->GetNumFloat() ); + pKV->SetInt( "options_string_amt", m_ViewRenderData->GetNumString() ); + + for ( int i = 0; i < m_ViewRenderData->GetNumBool(); i++ ) + pKV->SetInt( VarArgs( "options_bool_%i", i ), m_ViewRenderData->GetBoolVal( i ) ? 1 : 0 ); + + for ( int i = 0; i < m_ViewRenderData->GetNumInt(); i++ ) + pKV->SetInt( VarArgs( "options_int_%i", i ), m_ViewRenderData->GetIntVal( i ) ); + + for ( int i = 0; i < m_ViewRenderData->GetNumFloat(); i++ ) + pKV->SetFloat( VarArgs( "options_float_%i", i ), m_ViewRenderData->GetFloatVal( i ) ); + + for ( int i = 0; i < m_ViewRenderData->GetNumString(); i++ ) + pKV->SetString( VarArgs( "options_string_%i", i ), m_ViewRenderData->GetStringVal( i ) ); + + pKV->SetInt( "iSceneDraw", m_bSceneDraw ? 1 : 0 ); + + return pKV; +} + +void CNodePP_RenderView::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_ViewRenderData->ClearAllValues(); + + m_ViewRenderData->SetName( pKV->GetString( "szVRCName" ) ); + + for ( int i = 0; i < pKV->GetInt( "options_bool_amt" ); i++ ) + m_ViewRenderData->AddBoolValue( !!pKV->GetInt( VarArgs( "options_bool_%i", i ) ) ); + + for ( int i = 0; i < pKV->GetInt( "options_int_amt" ); i++ ) + m_ViewRenderData->AddIntValue( pKV->GetInt( VarArgs( "options_int_%i", i ) ) ); + + for ( int i = 0; i < pKV->GetInt( "options_float_amt" ); i++ ) + m_ViewRenderData->AddFloatValue( pKV->GetFloat( VarArgs( "options_float_%i", i ) ) ); + + for ( int i = 0; i < pKV->GetInt( "options_string_amt" ); i++ ) + m_ViewRenderData->AddStringValue( pKV->GetString( VarArgs( "options_string_%i", i ) ) ); + + m_bSceneDraw = !!pKV->GetInt( "iSceneDraw" ); + + OnUpdateHierachy(NULL,NULL); +} + +int CNodePP_RenderView::UpdateInputsValid() +{ + const int baseerror = BaseClass::UpdateInputsValid(); + + int localerror = ( GetJack_In(0)->GetNumBridgesConnected() < 1 ) ? ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE; + localerror = max( localerror, ( GetJack_In(1)->GetNumBridgesConnected() < 1 ) ? ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE ); + localerror = max( localerror, + (m_ViewRenderData->GetName() == NULL || GetPPCache()->FindVrCallback( m_ViewRenderData->GetName() ) < 0) ? + ERRORLEVEL_UNDEFINED : ERRORLEVEL_NONE ); + + return max( localerror, baseerror ); +} + +bool CNodePP_RenderView::CreateSolvers(GenericShaderData *ShaderData) +{ + //if ( Q_strlen( m_szRTName ) < 1 ) + // Assert( 0 ); + + //CHLSL_Var *pVar = GetJack_Out(0)->AllocateVarFromSmartType(); + + CHLSL_Solver_PP_RenderView *solver = new CHLSL_Solver_PP_RenderView( GetUniqueIndex() ); + solver->Init( m_ViewRenderData, m_bSceneDraw ); + + solver->AddSourceVar( GetJack_In(1)->GetTemporaryVarTarget_End() ); + + if ( GetJack_In(2)->GetNumBridgesConnected() > 0 ) + solver->AddSourceVar( GetJack_In(2)->GetTemporaryVarTarget_End() ); + + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_renderview.h b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_renderview.h new file mode 100644 index 00000000..6ecaf8c8 --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_renderview.h @@ -0,0 +1,30 @@ +#ifndef CNODE_PP_RENDERVIEW_H +#define CNODE_PP_RENDERVIEW_H + +#include + +class CNodePP_RenderView : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_RenderView, CNodePP_Base ); +public: + + CNodePP_RenderView( CNodeView *p ); + ~CNodePP_RenderView(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_RENDER_VIEW; }; + virtual int UpdateInputsValid(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + virtual const bool IsSceneNode(){ return m_bSceneDraw; }; + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + EditorRenderViewCommand_Data *m_ViewRenderData; + bool m_bSceneDraw; + +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_rt.cpp b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_rt.cpp new file mode 100644 index 00000000..dafd2337 --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_rt.cpp @@ -0,0 +1,54 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodePP_RT::CNodePP_RT( CNodeView *p ) : BaseClass( "Rendertarget", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_PP_RT, "RT" ); + + m_szRTName[0] = '\0'; + + OnUpdateHierachy(NULL,NULL); +} + +CNodePP_RT::~CNodePP_RT() +{ +} + +KeyValues *CNodePP_RT::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetString( "szRTName", m_szRTName ); + + return pKV; +} + +void CNodePP_RT::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + Q_snprintf( m_szRTName, sizeof(m_szRTName), "%s", pKV->GetString( "szRTName" ) ); + + OnUpdateHierachy(NULL,NULL); +} + +int CNodePP_RT::UpdateInputsValid() +{ + if ( Q_strlen( m_szRTName ) < 1 ) + return ERRORLEVEL_UNDEFINED; + return ERRORLEVEL_NONE; +} + +bool CNodePP_RT::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( Q_strlen( m_szRTName ) < 1 ) + Assert( 0 ); + + CHLSL_Var *pVar = GetJack_Out(0)->AllocateVarFromSmartType(); + + CHLSL_Solver_PP_RT *solver = new CHLSL_Solver_PP_RT( GetUniqueIndex() ); + solver->AddTargetVar( pVar ); + solver->Init( m_szRTName ); + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/postprocessing/vnode_pp_rt.h b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_rt.h new file mode 100644 index 00000000..33d859ee --- /dev/null +++ b/sp/src/shadereditor/nodes/postprocessing/vnode_pp_rt.h @@ -0,0 +1,26 @@ +#ifndef CNODE_PP_RT_H +#define CNODE_PP_RT_H + +#include + +class CNodePP_RT : public CNodePP_Base +{ + DECLARE_CLASS( CNodePP_RT, CNodePP_Base ); +public: + + CNodePP_RT( CNodeView *p ); + ~CNodePP_RT(); + + virtual int GetNodeType(){ return HLSLNODE_POSTPROCESSING_CREATE_RT; }; + virtual int UpdateInputsValid(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + char m_szRTName[RT_NAME_MAX]; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vbasecontainer.cpp b/sp/src/shadereditor/nodes/vbasecontainer.cpp new file mode 100644 index 00000000..690dc971 --- /dev/null +++ b/sp/src/shadereditor/nodes/vbasecontainer.cpp @@ -0,0 +1,839 @@ + +#include "cbase.h" +#include "editorcommon.h" +#include + +//CBaseContainerNode::CBaseContainerNode( CNodeView *p ) : BaseClass( "BaseContainer", p ) +CBaseContainerNode::CBaseContainerNode( const char *opName, CNodeView *p ) : BaseClass( opName, p ) +{ + m_bAffectSolver = true; + + p->OnContainerAdded( this ); + m_vecContainerExtents.Init( 128, 384, -128 ); + + m_iActiveScalingMode = CBORDER_INVALID; + m_vecMouseStartPos.Init(); + Q_memset( m_vecAccumulatedExtent, 0, sizeof( m_vecAccumulatedExtent ) ); + bLastHierachyErrorTest = false; + + m_flMinSizeX = 50; + m_flMinSizeY = 30; + + SetupVguiTex( m_iGrabIcon, "shadereditor/grabicon" ); + +} +CBaseContainerNode::~CBaseContainerNode() +{ + RemoveAllChildren(); + pNodeView->OnContainerRemoved( this ); +} + +void CBaseContainerNode::Spawn() +{ + BaseClass::Spawn(); + + UpdateOnMove(); +} + +CBaseContainerNode *CBaseContainerNode::GetAsContainer() +{ + return this; +} +void CBaseContainerNode::UpdateContainerBounds() +{ + m_vecBounds.x = m_vecPosition.x - 30; + m_vecBounds.w = GetContainerMins().y - 30; + Vector2D maxs = GetContainerMaxs(); + m_vecBounds.z = maxs.x + 30; + m_vecBounds.y = maxs.y + 30; +} +void CBaseContainerNode::UpdateSize() +{ + int maxJacks = max( m_hInputs.Count(), m_hOutputs.Count() ); + float sizeMin = ( JACK_SIZE_Y + JACK_DELTA_Y ) * maxJacks + JACK_SIZE_Y; + sizeMin = max( m_flMinSizeY, sizeMin ); + m_vecBorderInfo.Init(); + m_vecSize.Init( max( m_flMinSizeX, 0 ), -sizeMin ); + TouchJacks(); + //UpdateSimpleObjectBounds( m_vecPosition, m_vecSize, m_vecBounds ); + UpdateContainerBounds(); +} +void CBaseContainerNode::SetPosition( Vector2D vec, bool bCenter ) +{ + BaseClass::SetPosition( vec, bCenter ); + UpdateContainerBounds(); + UpdateOnMove(); +} + +bool CBaseContainerNode::IsAffectingSolver() +{ + return m_bAffectSolver; +} + +void CBaseContainerNode::OnLeftClick( Vector2D &pos ) +{ + m_iActiveScalingMode = IsInBorderBounds( pos ); + m_vecMouseStartPos = pos; + Q_memset( m_vecAccumulatedExtent, 0, sizeof( m_vecAccumulatedExtent ) ); + + //if ( input()->IsKeyDown( KEY_RALT ) || input()->IsKeyDown( KEY_LALT ) ) + //{ + // for ( int i = 0; i < m_hChildren.Count(); i++ ) + // m_hChildren[i]->SetSelected( true ); + //} +} +void CBaseContainerNode::OnDrag( Vector2D &delta ) +{ + if ( m_iActiveScalingMode == CBORDER_INVALID ) + return BaseClass::OnDrag( delta ); + + //Vector2D pos = GetPosition(); + + Vector4D delta_NESW; + Vector2D pos_delta; + delta_NESW.Init(); + pos_delta.Init(); + + Vector2D half( delta.x * 0.5f, delta.y * 0.5f ); + + switch ( m_iActiveScalingMode ) + { + default: + Assert( 0 ); + case CBORDER_TOP_LEFT: + delta_NESW.x += half.y; + delta_NESW.z -= half.y; + delta_NESW.y -= delta.x; + pos_delta.x += delta.x; + pos_delta.y += half.y; + break; + case CBORDER_TOP: + delta_NESW.x += half.y; + delta_NESW.z -= half.y; + pos_delta.y += half.y; + break; + case CBORDER_TOP_RIGHT: + delta_NESW.x += half.y; + delta_NESW.z -= half.y; + delta_NESW.y += delta.x; + pos_delta.y += half.y; + break; + case CBORDER_RIGHT: + delta_NESW.y += delta.x; + break; + case CBORDER_BOTTOM_RIGHT: + delta_NESW.x -= half.y; + delta_NESW.z += half.y; + delta_NESW.y += delta.x; + pos_delta.y += half.y; + break; + case CBORDER_BOTTOM: + delta_NESW.x -= half.y; + delta_NESW.z += half.y; + pos_delta.y += half.y; + break; + case CBORDER_BOTTOM_LEFT: + delta_NESW.x -= half.y; + delta_NESW.z += half.y; + delta_NESW.y -= delta.x; + pos_delta.x += delta.x; + pos_delta.y += half.y; + break; + case CBORDER_LEFT: + delta_NESW.y -= delta.x; + pos_delta.x += delta.x; + break; + } + + for ( int i = 0; i < 5; i++ ) + { + if ( m_vecAccumulatedExtent[i] ) + { + float *target = NULL; + if ( i >= 3 ) + target = &pos_delta[ i - 3 ]; + else + target = &delta_NESW[ i ]; + + const bool bWasNeg = m_vecAccumulatedExtent[ i ] < 0; + m_vecAccumulatedExtent[ i ] += *target; + const bool bIsNeg = m_vecAccumulatedExtent[ i ] < 0; + if ( bWasNeg && bIsNeg || !bWasNeg && !bIsNeg ) + *target = 0; + else + { + *target = m_vecAccumulatedExtent[ i ] * 1; + m_vecAccumulatedExtent[ i ] = 0; + } + } + } + + Vector oldExtents = m_vecContainerExtents; + for ( int i = 0; i < 3; i++ ) + m_vecContainerExtents[i] += delta_NESW[i]; + + if ( m_vecContainerExtents[ 0 ] < m_flMinSizeY ) + { + m_vecAccumulatedExtent[ 0 ] += min( m_vecContainerExtents[ 0 ] - m_flMinSizeY, 0 ); + m_vecAccumulatedExtent[ 4 ] -= min( m_vecContainerExtents[ 0 ] - m_flMinSizeY, 0 ) * Sign( pos_delta.y ); + + float _save = oldExtents.x - m_flMinSizeY; + _save = max( _save, 0 ); + pos_delta.y = _save * Sign( pos_delta.y ); + m_vecContainerExtents[ 0 ] = m_flMinSizeY; + } + if ( m_vecContainerExtents[ 2 ] > -m_flMinSizeY ) + { + m_vecAccumulatedExtent[ 2 ] -= min( abs(m_vecContainerExtents[ 2 ]) - (m_flMinSizeY), 0 ); + m_vecContainerExtents[ 2 ] = -m_flMinSizeY; + } + if ( m_vecContainerExtents[ 1 ] < m_flMinSizeX ) + { + if ( pos_delta.x > 0 ) + { + float _save = oldExtents.y - m_flMinSizeX; + _save = max( _save, 0 ); + pos_delta.x = _save; + } + m_vecAccumulatedExtent[ 3 ] -= min( m_vecContainerExtents[ 1 ] - m_flMinSizeX, 0 ); + m_vecAccumulatedExtent[ 1 ] += min( m_vecContainerExtents[ 1 ] - m_flMinSizeX, 0 ); + m_vecContainerExtents[ 1 ] = m_flMinSizeX; + } + + m_vecContainerExtents[ 2 ] = -m_vecContainerExtents[ 0 ]; + + Vector2D posOld = GetPosition(); + SetPosition( posOld + pos_delta ); +} + +void CBaseContainerNode::OnDragEnd() +{ + BaseClass::OnDragEnd(); + + m_iActiveScalingMode = CBORDER_INVALID; +} + +void CBaseContainerNode::SelectAllInBounds( bool bSelected, CUtlVector *hNodes ) +{ + CUtlVector local; + CUtlVector *nodes = hNodes ? hNodes : &local; + + Assert( nodes ); + + int numNodes = pNodeView->GetNumNodes(); + for ( int i = 0; i < numNodes; i++ ) + { + CBaseNode *n = pNodeView->GetNode( i ); + if ( n == this ) + continue; + Vector2D nodePos = n->GetContainerSensitiveCenter(); + + bool bIsActive = IsInContainerBounds( nodePos ); + if ( !bIsActive ) + continue; + + if ( nodes->HasElement( n ) ) + continue; + + nodes->AddToTail( n ); + n->SetSelected( bSelected ); + if ( n->GetAsContainer() != NULL ) + n->GetAsContainer()->SelectAllInBounds( bSelected, nodes ); + } +} + +Vector2D CBaseContainerNode::GetContainerMins() +{ + Vector2D center = GetCenter(); + center.x = GetBoundsMaxNodeSpace().x; + //center.x += m_vecContainerExtents.y; + center.y += m_vecContainerExtents.z; + return center; +} +Vector2D CBaseContainerNode::GetContainerMaxs() +{ + Vector2D center = GetCenter(); + center.x = GetBoundsMaxNodeSpace().x; + center.x += m_vecContainerExtents.y; + center.y += m_vecContainerExtents.x; + return center; +} +bool CBaseContainerNode::IsInContainerBounds( const Vector2D &pos ) +{ + Vector2D bmin = GetContainerMins(); + Vector2D bmax = GetContainerMaxs(); + + if ( pos.x >= bmin.x && pos.x <= bmax.x && + pos.y >= bmin.y && pos.y <= bmax.y ) + return true; + return false; +} +int CBaseContainerNode::IsInBorderBounds( const Vector2D &pos ) +{ + for ( int i = CBORDER_FIRST; i <= CBORDER_LAST; i++ ) + { + Vector2D min = GetContainerBorderMin( i ); + Vector2D max = GetContainerBorderMax( i ); + if ( pos.x >= min.x && pos.x <= max.x && + pos.y >= min.y && pos.y <= max.y ) + return i; + } + return CBORDER_INVALID; +} + +void CBaseContainerNode::RemoveAllChildren() +{ + const bool bSolver = IsAffectingSolver(); + + for ( int i = 0; i < m_hChildren.Count() && bSolver; i++ ) + { + if ( m_hChildren[i]->RemoveFromContainer( this ) ) + m_hChildren[i]->OnUpdateHierachy( NULL, NULL ); + else + Assert( 0 ); + } + + m_hChildren.Purge(); +} +bool CBaseContainerNode::HasChild( CBaseNode *child ) +{ + return m_hChildren.IsValidIndex( m_hChildren.Find( child ) ); +} +bool CBaseContainerNode::HasAnyChildren() +{ + return m_hChildren.Count() > 0; +} +//bool CBaseContainerNode::IsSolvable( bool bHierachyUp, CBaseNode *pCaller, CUtlVector< CBaseNode* > *hTested ) +bool CBaseContainerNode::IsSolvable( bool bHierachyUp, CUtlVector< CBaseNode* > *hCallerList, CUtlVector< CBaseNode* > *hTested ) +{ + if ( !IsAffectingSolver() ) + return false; + + if ( !BaseClass::IsSolvable( bHierachyUp, hCallerList, hTested ) ) + return false; + + CUtlVector< CBaseNode* > hLocalTestList; + + CUtlVector< CBaseNode* > *hTestList = hTested ? hTested : &hLocalTestList; + + CUtlVector< CBaseContainerNode* > hChildrenContainer; + for ( int i = 0; i < m_hChildren.Count(); i++ ) + if ( m_hChildren[i]->GetAsContainer() != NULL ) + hChildrenContainer.AddToTail( m_hChildren[i]->GetAsContainer() ); + + //CBaseNode *pParentCaller = this; + //if ( pCaller && pCaller->GetAsContainer() != NULL + // && HasContainerParent( pCaller->GetAsContainer() ) ) + // pParentCaller = pCaller; + + CUtlVector< CBaseNode* > hLocalCallerList; + const bool bStoresCallerList = hCallerList == NULL; + if ( bStoresCallerList ) + hCallerList = &hLocalCallerList; + + if ( !hCallerList->HasElement( this ) ) + hCallerList->AddToTail( this ); + + for ( int i = 0; i < m_hChildren.Count(); i++ ) + { + bool bIgnore = false; + for ( int c = 0; c < hChildrenContainer.Count(); c++ ) + { + if ( hChildrenContainer[c]->HasChild( m_hChildren[i] ) ) + bIgnore = true; + } + + //if ( m_hChildren[i]->GetErrorLevel() == ERRORLEVEL_FAIL ) + // return false; + + if ( !bIgnore && + //!m_hChildren[i]->GetAsContainer() && + !m_hChildren[i]->IsSolvable( bHierachyUp, /*pParentCaller*/ hCallerList, hTestList ) ) + return false; + } + + if ( bStoresCallerList ) + hLocalCallerList.Purge(); + + hChildrenContainer.Purge(); + hLocalTestList.Purge(); + return true; +} +void CBaseContainerNode::UpdateOnMove() +{ + int numNodes = pNodeView->GetNumNodes(); + for ( int i = 0; i < numNodes; i++ ) + { + CBaseNode *n = pNodeView->GetNode( i ); + if ( n == this ) + continue; + Vector2D nodePos = n->GetContainerSensitiveCenter(); + + bool bIsActive = IsInContainerBounds( nodePos ); + if ( !bIsActive ) + RemoveChild( n ); + else + AddChild( n ); + } +} +void CBaseContainerNode::RemoveChild( CBaseNode *child ) +{ + if ( !IsAffectingSolver() ) + return; + + if ( !HasChild( child ) ) + return; + + child->RemoveFromContainer( this ); + m_hChildren.FindAndRemove( child ); + child->OnUpdateHierachy( NULL, NULL ); +} +void CBaseContainerNode::AddChild( CBaseNode *child ) +{ + if ( !IsAffectingSolver() ) + return; + + if ( HasChild( child ) ) + return; + + child->InsertToContainer( this ); + m_hChildren.AddToTail( child ); + child->OnUpdateHierachy( NULL, NULL ); +} +void CBaseContainerNode::Solve_ContainerEntered() +{ + AddSolver( new CHLSL_Solver_ContainerBasic( GetUniqueIndex() ) ); + AddSolver( new CHLSL_Solver_ContainerBasic( GetUniqueIndex() ) ); +} +void CBaseContainerNode::Solve_ContainerCreateVariables() +{ + Assert( 0 ); +} +void CBaseContainerNode::Solve_ContainerLeft() +{ + AddSolver( new CHLSL_Solver_ContainerBasic( GetUniqueIndex() ) ); +} + +bool CBaseContainerNode::MustDragAlone() +{ + return m_iActiveScalingMode != CBORDER_INVALID; +} + +void CBaseContainerNode::FullHierachyUpdate() +{ +#if 0 + CUtlVector< CBaseNode* > hListTopNodes; + for ( int i = 0; i < GetNumChildren(); i++ ) + { + CBaseNode *nChild = GetChild( i ); + nChild->Recursive_AddTailNodes( hListTopNodes, true, false, this ); + } + for ( int i = 0; i < hListTopNodes.Count(); i++ ) + { + hListTopNodes[ i ]->OnUpdateHierachy( NULL, NULL ); + } + hListTopNodes.Purge(); +#elif 0 + bool bHierachyError = ERRORLEVEL_NONE; + int CurrentHierachy = HLSLHIERACHY_NONE; + for ( int i = 0; i < GetNumChildren(); i++ ) + { + int NodeHierachy = GetChild( i )->GetHierachyTypeIterateFullyRecursive(); + if ( CurrentHierachy != HLSLHIERACHY_NONE && (NodeHierachy != CurrentHierachy || CurrentHierachy == HLSLHIERACHY_MULTIPLE) ) + bHierachyError = true; + else + CurrentHierachy = NodeHierachy; + if ( bHierachyError ) + break; + } + + + int iErrorLevel = ERRORLEVEL_NONE; + if ( bHierachyError ) + iErrorLevel = ERRORLEVEL_FAIL; + + for ( int i = 0; i < GetNumChildren(); i++ ) + iErrorLevel = max( iErrorLevel, GetChild( i )->GetErrorLevel() ); + if ( iErrorLevel != ERRORLEVEL_NONE ) + { + for ( int i = 0; i < GetNumChildren(); i++ ) + GetChild( i )->SetErrorLevel( iErrorLevel ); + } + + + for ( int i = 0; i < GetNumChildren(); i++ ) + { + GetChild( i )->OnUpdateHierachy( NULL, NULL ); + } +#else + + if ( !IsAffectingSolver() ) + return; + + for ( int i = 0; i < GetNumChildren(); i++ ) + { + GetChild( i )->OnUpdateHierachy( NULL, NULL ); + } +#endif +} +bool CBaseContainerNode::TestFullHierachyUpdate() +{ + if ( !IsAffectingSolver() ) + return false; + + bool bError = false; + int LastHierachy = HLSLHIERACHY_PENDING; + + for ( int i = 0; i < GetNumChildren(); i++ ) + { + CBaseNode *n = GetChild( i ); + if ( n->GetAsContainer() ) + continue; + + if ( !n->CanBeInContainer() ) + bError = true; + int tmpHierachy = n->GetTempHierachyType(); + if ( tmpHierachy == HLSLHIERACHY_PENDING ) + { + tmpHierachy = n->GetHierachyTypeIterateFullyRecursive(); + n->SetTempHierachyTypeFullyRecursive( tmpHierachy ); + } + + if ( LastHierachy > HLSLHIERACHY_PENDING && + LastHierachy != tmpHierachy ) + bError = true; + LastHierachy = tmpHierachy; + } + + pNodeView->ResetTempHierachy(); + if ( bLastHierachyErrorTest != bError ) + { + bLastHierachyErrorTest = bError; + FullHierachyUpdate(); + } + + if ( UpdateInputsValid() != ERRORLEVEL_NONE ) + bError = true; + + return bError; +} + +KeyValues *CBaseContainerNode::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetFloat( "container_extents_x", m_vecContainerExtents.x ); + pKV->SetFloat( "container_extents_y", m_vecContainerExtents.y ); + pKV->SetFloat( "container_extents_z", m_vecContainerExtents.z ); + + return pKV; +} +void CBaseContainerNode::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_vecContainerExtents.x = pKV->GetFloat( "container_extents_x", m_vecContainerExtents.x ); + m_vecContainerExtents.y = pKV->GetFloat( "container_extents_y", m_vecContainerExtents.y ); + m_vecContainerExtents.z = pKV->GetFloat( "container_extents_z", m_vecContainerExtents.z ); + + UpdateOnMove(); +} + +bool CBaseContainerNode::IsWithinBounds_Base( const Vector2D &pos ) +{ + bool bBaseTest = BaseClass::IsWithinBounds_Base( pos ); + if ( !bBaseTest ) + { + int BorderTest = IsInBorderBounds( pos ); + bBaseTest = BorderTest != CBORDER_INVALID; + } + return bBaseTest; +} +Vector2D CBaseContainerNode::GetContainerBorderMin( int mode ) +{ + Vector2D out; + Vector2D center = GetCenter(); + center.x = GetBoundsMaxNodeSpace().x; + const float bSize = GetBorderSize(); + + switch ( mode ) + { + default: + Assert( 0 ); + case CBORDER_TOP_LEFT: + out.x = center.x; + out.y = center.y + m_vecContainerExtents.x - bSize; + break; + case CBORDER_TOP: + out.x = center.x + bSize; + out.y = center.y + m_vecContainerExtents.x - bSize; + break; + case CBORDER_TOP_RIGHT: + out.x = center.x + m_vecContainerExtents.y - bSize; + out.y = center.y + m_vecContainerExtents.x - bSize; + break; + case CBORDER_RIGHT: + out.x = center.x + m_vecContainerExtents.y - bSize; + out.y = center.y + m_vecContainerExtents.z + bSize; + break; + case CBORDER_BOTTOM_RIGHT: + out.x = center.x + m_vecContainerExtents.y - bSize; + out.y = center.y + m_vecContainerExtents.z; + break; + case CBORDER_BOTTOM: + out.x = center.x + bSize; + out.y = center.y + m_vecContainerExtents.z; + break; + case CBORDER_BOTTOM_LEFT: + out.x = center.x; + out.y = center.y + m_vecContainerExtents.z; + break; + case CBORDER_LEFT: + out.x = center.x; + out.y = center.y + m_vecContainerExtents.z + bSize; + break; + } + + return out; +} +Vector2D CBaseContainerNode::GetContainerBorderMax( int mode ) +{ + Vector2D out; + Vector2D center = GetCenter(); + center.x = GetBoundsMaxNodeSpace().x; + const float bSize = GetBorderSize(); + + switch ( mode ) + { + default: + case CBORDER_TOP_LEFT: + out.x = center.x + bSize; + out.y = center.y + m_vecContainerExtents.x; + break; + case CBORDER_TOP: + out.x = center.x + m_vecContainerExtents.y - bSize; + out.y = center.y + m_vecContainerExtents.x; + break; + case CBORDER_TOP_RIGHT: + out.x = center.x + m_vecContainerExtents.y; + out.y = center.y + m_vecContainerExtents.x; + break; + case CBORDER_RIGHT: + out.x = center.x + m_vecContainerExtents.y; + out.y = center.y + m_vecContainerExtents.x - bSize; + break; + case CBORDER_BOTTOM_RIGHT: + out.x = center.x + m_vecContainerExtents.y; + out.y = center.y + m_vecContainerExtents.z + bSize; + break; + case CBORDER_BOTTOM: + out.x = center.x + m_vecContainerExtents.y - bSize; + out.y = center.y + m_vecContainerExtents.z + bSize; + break; + case CBORDER_BOTTOM_LEFT: + out.x = center.x + bSize; + out.y = center.y + m_vecContainerExtents.z + bSize; + break; + case CBORDER_LEFT: + out.x = center.x + bSize; + out.y = center.y + m_vecContainerExtents.x - bSize; + break; + } + + return out; +} + + +bool CBaseContainerNode::VguiDraw( bool bShadow ) +{ +#define TITEL_INSET_X NODE_DRAW_TITLE_SPACE + if ( !ShouldSimpleDrawObject( pNodeView, pNodeView, m_vecBounds ) ) + return false; + if ( !pNodeView ) + return false; + + Vector2D title_min = GetBoundsTitleMin(); + Vector2D title_max = GetBoundsTitleMax(); + title_max.x -= TITEL_INSET_X; + + Vector2D box_min = GetBoundsBoxMin(); + Vector2D box_max = GetBoundsBoxMax(); + + pNodeView->ToPanelSpace( title_min ); + pNodeView->ToPanelSpace( title_max ); + pNodeView->ToPanelSpace( box_min ); + pNodeView->ToPanelSpace( box_max ); + + float flZoom = pNodeView->GetZoomScalar(); + float flO = NODE_DRAW_SHADOW_DELTA * flZoom; + Vector2D offset( flO, flO ); + + if ( bShadow ) + { + title_min += offset; + title_max += offset; + box_min += offset; + box_max += offset; + } + + const bool bSelected = IsSelected(); + + if ( bShadow ) + surface()->DrawSetColor( NODE_DRAW_COLOR_SHADOW ); + else + { + Color colTitleNoShadow = NODE_DRAW_COLOR_TITLE; + if ( GetNumContainers() ) + colTitleNoShadow = NODE_DRAW_COLOR_HASCONTAINER_TITLE; + else if ( bSelected ) + colTitleNoShadow = NODE_DRAW_COLOR_SELECTED_TITLE; + surface()->DrawSetColor( colTitleNoShadow ); + } + + surface()->DrawFilledRect( title_min.x, title_min.y, title_max.x, title_max.y ); + + if ( !bShadow ) + { + Color boxNoShadow = NODE_DRAW_COLOR_BOX; + if ( bSelected ) + boxNoShadow = NODE_DRAW_COLOR_SELECTED_BOX; + else if ( GetNumSolvers() && !HasDummySolvers() ) + boxNoShadow = NODE_DRAW_COLOR_HASSOLVER_BOX; + + surface()->DrawSetColor( boxNoShadow ); + } + + surface()->DrawFilledRect( box_min.x, box_min.y, box_max.x, box_max.y ); + + //Vector2D r0_min = GetContainerBorderMin( CBORDER_TOP_LEFT ); + //Vector2D r0_max = GetContainerBorderMax( CBORDER_TOP_RIGHT ); + //Vector2D r1_min = GetContainerBorderMin( CBORDER_RIGHT ); + //Vector2D r1_max = GetContainerBorderMax( CBORDER_RIGHT ); + //Vector2D r2_min = GetContainerBorderMin( CBORDER_BOTTOM_LEFT ); + //Vector2D r2_max = GetContainerBorderMax( CBORDER_BOTTOM_RIGHT ); + //Vector2D r3_min = GetContainerBorderMin( CBORDER_RIGHT ); + //Vector2D r3_max = GetContainerBorderMax( CBORDER_RIGHT ); + Vector2D rects_[8] = { + GetContainerBorderMin( CBORDER_TOP_LEFT ), + GetContainerBorderMax( CBORDER_TOP_RIGHT ), + GetContainerBorderMin( CBORDER_RIGHT ), + GetContainerBorderMax( CBORDER_RIGHT ), + GetContainerBorderMin( CBORDER_BOTTOM_LEFT ), + GetContainerBorderMax( CBORDER_BOTTOM_RIGHT ), + GetContainerBorderMin( CBORDER_LEFT ), + GetContainerBorderMax( CBORDER_LEFT ), + }; + for ( int i = 0; i < 8; i++ ) + pNodeView->ToPanelSpace( rects_[i] ); + + if ( bShadow ) + { + for ( int i = 0; i < 8; i++ ) + rects_[i] += offset; + } + + for ( int i = 0; i < 4; i++ ) + surface()->DrawFilledRect( rects_[i*2].x, rects_[i*2+1].y, rects_[i*2+1].x, rects_[i*2].y ); + + + if ( bShadow ) + { + VguiDraw_Jacks( true ); + } + else + { + VguiDraw_Jacks( false ); + Color borderCol = NODE_DRAW_COLOR_BORDER; + if ( GetErrorLevel() == ERRORLEVEL_UNDEFINED ) + borderCol = DRAWCOLOR_ERRORLEVEL_UNDEFINED; + else if ( GetErrorLevel() == ERRORLEVEL_FAIL ) + borderCol = DRAWCOLOR_ERRORLEVEL_FAIL; + else if ( IsAllocating() ) + borderCol = NODE_DRAW_COLOR_HASSOLVER_BOX_ALLOC; + surface()->DrawSetColor( borderCol ); + + int borderSize = 1; + surface()->DrawFilledRect( title_min.x, title_min.y, title_max.x, title_min.y + borderSize ); + surface()->DrawFilledRect( title_min.x, title_max.y - borderSize, title_max.x, title_max.y ); + surface()->DrawFilledRect( title_min.x, title_min.y, title_min.x + borderSize, title_max.y ); + surface()->DrawFilledRect( title_max.x - borderSize, title_min.y, title_max.x, title_max.y ); + + surface()->DrawFilledRect( box_min.x, box_min.y, box_max.x, box_min.y + borderSize ); + surface()->DrawFilledRect( box_min.x, box_max.y - borderSize, box_max.x, box_max.y ); + surface()->DrawFilledRect( box_min.x, box_min.y, box_min.x + borderSize, box_max.y ); + //surface()->DrawFilledRect( box_max.x - borderSize, box_min.y, box_max.x, box_max.y ); + + surface()->DrawFilledRect( box_max.x, rects_[1].y, box_max.x + borderSize, box_min.y + borderSize ); + surface()->DrawFilledRect( box_max.x, box_max.y - borderSize, box_max.x + borderSize, rects_[4].y ); + surface()->DrawFilledRect( rects_[7].x-borderSize, rects_[7].y, rects_[7].x, rects_[6].y ); + + surface()->DrawFilledRect( rects_[2].x, rects_[3].y, rects_[2].x+borderSize, rects_[2].y ); + surface()->DrawFilledRect( rects_[3].x-borderSize, rects_[1].y, rects_[3].x, rects_[4].y ); + + surface()->DrawFilledRect( rects_[0].x, rects_[1].y, rects_[1].x, rects_[1].y+borderSize ); + surface()->DrawFilledRect( rects_[4].x, rects_[4].y-borderSize, rects_[5].x, rects_[4].y ); + + surface()->DrawFilledRect( rects_[7].x-borderSize, rects_[0].y-borderSize, rects_[2].x+borderSize, rects_[0].y ); + surface()->DrawFilledRect( rects_[7].x-borderSize, rects_[5].y, rects_[2].x+borderSize, rects_[5].y+borderSize ); + } + + Vector2D titleMid = ( title_max - title_min ) * 0.5f + title_min; + + wchar_t szconverted[ 1024 ]; + int fontWide, fontTall; + + if ( !bShadow ) + { + bool bDraw; + vgui::HFont hFont_Small = pNodeView->GetFontScaled(12,bDraw); + if ( bDraw ) + { + g_pVGuiLocalize->ConvertANSIToUnicode( szOpName, szconverted, sizeof(szconverted) ); + + surface()->DrawSetTextFont( hFont_Small ); + surface()->GetTextSize( hFont_Small, szconverted, fontWide, fontTall ); + surface()->DrawSetTextPos( titleMid.x - fontWide * 0.5f, titleMid.y - fontTall * 0.5f ); + + surface()->DrawSetTextColor( bSelected ? NODE_DRAW_COLOR_SELECTED_TEXT_OP : NODE_DRAW_COLOR_TEXT_OP ); + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } + + //VguiDraw_Preview(); + DrawGrabIcon(); + } + + + if ( Q_strlen( szNodeName ) > 1 ) + { + surface()->DrawSetTextColor( bShadow ? NODE_DRAW_COLOR_SHADOW : NODE_DRAW_COLOR_CUSTOMTITLE ); + + bool bDraw; + vgui::HFont hFont_Small = pNodeView->GetFontScaled(18,bDraw); + if ( bDraw ) + { + g_pVGuiLocalize->ConvertANSIToUnicode( szNodeName, szconverted, sizeof(szconverted) ); + + surface()->DrawSetTextFont( hFont_Small ); + surface()->GetTextSize( hFont_Small, szconverted, fontWide, fontTall ); + surface()->DrawSetTextPos( title_min.x, title_min.y - fontTall - 3 * pNodeView->GetZoomScalar() ); + + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } + } + + return true; +} +void CBaseContainerNode::DrawGrabIcon() +{ + const float bSize = GetBorderSize(); + + surface()->DrawSetColor( Color( 192, 192, 192, 255 ) ); + surface()->DrawSetTexture( m_iGrabIcon ); + + Vector2D icooffset( -GRABICO_OFFSET, GRABICO_OFFSET ); + Vector2D gi_max = Vector2D( GetContainerMaxs().x, GetContainerMins().y ) + icooffset; + Vector2D gi_min = gi_max + Vector2D( -bSize, bSize ); + + pNodeView->ToPanelSpace( gi_max ); + pNodeView->ToPanelSpace( gi_min ); + + surface()->DrawTexturedRect( gi_min.x, gi_min.y, gi_max.x, gi_max.y ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vbasecontainer.h b/sp/src/shadereditor/nodes/vbasecontainer.h new file mode 100644 index 00000000..9d32360e --- /dev/null +++ b/sp/src/shadereditor/nodes/vbasecontainer.h @@ -0,0 +1,111 @@ +#ifndef CCONTAINER_NODE_H +#define CCONTAINER_NODE_H + +#include "vBaseNode.h" + +#define CBORDER_SIZE 10.0f +#define CBORDER_SIZE_COMMENT 5.0f + +#define GRABICO_OFFSET 1.5f + +enum +{ + CBORDER_INVALID = 0, + CBORDER_TOP_LEFT, + CBORDER_TOP, + CBORDER_TOP_RIGHT, + CBORDER_RIGHT, + CBORDER_BOTTOM_RIGHT, + CBORDER_BOTTOM, + CBORDER_BOTTOM_LEFT, + CBORDER_LEFT, + + CBORDER_MAX, +}; + +#define CBORDER_FIRST CBORDER_TOP_LEFT +#define CBORDER_LAST CBORDER_LEFT + +class CBaseContainerNode : public CBaseNode +{ + DECLARE_CLASS( CBaseContainerNode, CBaseNode ); + +public: + CBaseContainerNode( const char *opName, CNodeView *p ); + //CBaseContainerNode( CNodeView *p ); + virtual ~CBaseContainerNode(); + virtual void Spawn(); + + virtual int GetNodeType(){ return HLSLNODE_INVALID; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + virtual void UpdateSize(); + virtual void UpdateContainerBounds(); + virtual void SetPosition( Vector2D vec, bool bCenter = false ); + virtual bool VguiDraw( bool bShadow = false ); + virtual void FullHierachyUpdate(); + virtual bool TestFullHierachyUpdate(); + + virtual void OnLeftClick( Vector2D &pos ); + virtual void OnDrag( Vector2D &delta ); + virtual void OnDragEnd(); + virtual bool ShouldSelectChildrenOnClick(){ return false; }; + void SelectAllInBounds( bool bSelected = true, CUtlVector*hNodes = NULL ); + + + virtual CBaseContainerNode *GetAsContainer(); + virtual bool HasAnyChildren(); + //virtual bool IsSolvable( bool bHierachyUp, CBaseNode *pCaller, CUtlVector< CBaseNode* > *hTested = NULL ); + virtual bool IsSolvable( bool bHierachyUp, + CUtlVector< CBaseNode* > *hCallerList = NULL, + CUtlVector< CBaseNode* > *hTested = NULL ); + + virtual bool IsWithinBounds_Base( const Vector2D &pos ); + virtual Vector2D GetContainerMins(); + virtual Vector2D GetContainerMaxs(); + virtual bool IsInContainerBounds( const Vector2D &pos ); + virtual Vector2D GetContainerBorderMin( int mode ); + virtual Vector2D GetContainerBorderMax( int mode ); + virtual int IsInBorderBounds( const Vector2D &pos ); + + virtual bool HasChild( CBaseNode *child ); + virtual void RemoveAllChildren(); + virtual void RemoveChild( CBaseNode *child ); + virtual void AddChild( CBaseNode *child ); + virtual int GetNumChildren(){ return m_hChildren.Count(); }; + virtual CBaseNode *GetChild( int i ){ Assert(m_hChildren.IsValidIndex(i)); return m_hChildren[i]; }; + virtual void UpdateOnMove(); + + virtual bool MustDragAlone(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + virtual void Solve_ContainerEntered(); + virtual void Solve_ContainerCreateVariables(); + virtual void Solve_ContainerLeft(); + +protected: + virtual float GetBorderSize(){ return CBORDER_SIZE; }; + + Vector m_vecContainerExtents; + bool m_bAffectSolver; + + void DrawGrabIcon(); + +private: + bool IsAffectingSolver(); + + bool bLastHierachyErrorTest; + CUtlVector< CBaseNode* > m_hChildren; + + int m_iActiveScalingMode; + int m_iGrabIcon; + Vector2D m_vecMouseStartPos; + float m_vecAccumulatedExtent[5]; + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vbasenode.cpp b/sp/src/shadereditor/nodes/vbasenode.cpp new file mode 100644 index 00000000..342affa6 --- /dev/null +++ b/sp/src/shadereditor/nodes/vbasenode.cpp @@ -0,0 +1,1946 @@ +#include "cbase.h" +#include +#include +#include "vgui/ISurface.h" +#include "ienginevgui.h" +#include +#include +#include + +#include "materialsystem/imesh.h" +#include "materialsystem/ITexture.h" +#include "materialsystem/IMaterial.h" +#include "materialsystem/IMaterialVar.h" +#include "materialsystem/imaterialsystem.h" + +#include "editorcommon.h" +#include "vBaseNode.h" + +HNODE CBaseNode::m_iUniqueIndexCount = HNODE(0); + +CBaseNode::CBaseNode( const char *opName, CNodeView *p ) +{ + szOpName[0] = '\0'; + szNodeName[0] = '\0'; + + m_vecPosition.Init(); + m_flMinSizeX = 80; + m_flMinSizeY = 80; + m_flMinSizeY_VS = 0; + m_flMinSizePREVIEW_X = PREVIEW_SIZE_NODE; + + m_bIsAllocating = false; + m_bMarkedForDeletion = false; + m_iTempHierachy = HLSLHIERACHY_PENDING; + bSelected = false; + m_bAllInputsRequired = true; + + m_bPreviewEnabled = true; + m_bAllowPreview = true; + m_iUniqueIndex = m_iUniqueIndexCount; + m_vecBorderInfo.Init(); + + SetErrorLevel( ERRORLEVEL_NONE ); + + pNodeView = p; + if ( pNodeView ) + pNodeView->OnHierachyChanged(); + + m_iUniqueIndexCount++; + + SetupVguiTex( m_iPreviewMaterial, "shadereditor/_rtdebug_pp0" ); + SetName( opName ); +} + +CBaseNode::~CBaseNode() +{ + RemoveSolvers( true ); + + //for ( int i = 0; i < GetNumContainers(); i++ ) + while( GetNumContainers() ) + GetContainer( 0 )->RemoveChild( this ); + Assert( !m_hParentContainers.Count() ); + //m_hParentContainers.Purge(); + //for ( int j = 0; j < m_hInputs.Count(); j++ ) + // m_hInputs[ j ]->DisconnectBridges(); + //for ( int j = 0; j < m_hOutputs.Count(); j++ ) + // m_hOutputs[ j ]->DisconnectBridges(); + + //SweepJackHlslCache(true); + + CUtlVector< CJack* >m_hTmpJacks; + m_hTmpJacks.AddVectorToTail( m_hInputs ); + m_hTmpJacks.AddVectorToTail( m_hOutputs ); + + m_hInputs.Purge(); + m_hOutputs.Purge(); + SaveDeleteVector( m_hTmpJacks ); + + //SaveDeleteVector( m_hInputs ); + //SaveDeleteVector( m_hOutputs ); + + if ( pNodeView ) + pNodeView->OnHierachyChanged(); +} +void CBaseNode::SetName( const char *opName ) +{ + Q_snprintf( szOpName, sizeof( szOpName ), "%s", opName ); + UpdateSize(); +} +const char *CBaseNode::GetName() +{ + return szOpName; +} +const char *CBaseNode::GetUserName() +{ + return szNodeName; +} +const int CBaseNode::GetAllowedFlowgraphTypes() +{ + return CNodeView::FLOWGRAPH_HLSL | CNodeView::FLOWGRAPH_HLSL_TEMPLATE; +} +int CBaseNode::GetFinalTextSize() +{ + int i = 0; + if ( Q_strlen(szOpName) >= 1 ) + { + float z = 1.5f; + bool bDraw; + HFont font = pNodeView->GetFontScaled( 9, bDraw, &z ); + Assert( bDraw ); + + wchar_t szconverted[ 1024 ]; + Q_memset( szconverted, 0, sizeof( szconverted ) ); + g_pVGuiLocalize->ConvertANSIToUnicode( szOpName, szconverted, sizeof(szconverted) ); + + int fontWide, fontTall; + surface()->DrawSetTextFont( font ); + surface()->GetTextSize( font, szconverted, fontWide, fontTall ); + + i = fontWide + 3; + } + return i; +} + +void CBaseNode::Spawn() +{ + UpdateSize(); +} + +//bool CBaseNode::IsNodeCrucial() +//{ +// int type = GetNodeType(); +// +// if ( type == HLSLNODE_VS_IN || +// type == HLSLNODE_VS_OUT || +// type == HLSLNODE_PS_IN || +// type == HLSLNODE_PS_OUT ) +// return true; +// return false; +//} + +void CBaseNode::AddSolver( CHLSL_SolverBase *solver ) +{ +#if SHOW_SEDIT_ERRORS + Assert( !m_hLocalSolvers.IsValidIndex( m_hLocalSolvers.Find(solver) ) ); +#endif + m_hLocalSolvers.AddToTail( solver ); +} +void CBaseNode::RemoveSolvers( bool bDelete ) +{ + if ( bDelete ) + SaveDeleteVector( m_hLocalSolvers ); + else + m_hLocalSolvers.Purge(); +} +const int CBaseNode::GetNumSolvers() +{ + return m_hLocalSolvers.Count(); +} +bool CBaseNode::HasDummySolvers() +{ + for ( int i = 0; i < m_hLocalSolvers.Count(); i++ ) + if ( m_hLocalSolvers[i]->IsDummy() ) + return true; + return false; +} +const CUtlVector< CHLSL_SolverBase* > *CBaseNode::GetSolvers() +{ + return &m_hLocalSolvers; +} +CHLSL_SolverBase *CBaseNode::GetSolver( int idx ) +{ +#if SHOW_SEDIT_ERRORS + Assert( m_hLocalSolvers.IsValidIndex( idx ) ); +#endif + return m_hLocalSolvers[ idx ]; +} +bool CBaseNode::InvokeCreateSolvers( GenericShaderData *ShaderData ) +{ + Assert( ShaderData || !( GetAllowedFlowgraphTypes() & CNodeView::FLOWGRAPH_HLSL ) ); + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + { + SmartCreateDummySolver(); + return true; + } + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + if ( GetJack_In(i)->GetNumBridges() ) + if ( GetJack_In(i)->GetBridge(0)->GetEndNode(this)->GetErrorLevel() != ERRORLEVEL_NONE ) + return false; + } + + bool bSuccess = CreateSolvers( ShaderData ); + if ( !bSuccess ) + { + SetErrorLevel( ERRORLEVEL_UNDEFINED ); + } + + if ( !bSuccess && !GetNumSolvers() ) + SmartCreateDummySolver(); + + return bSuccess; +} +bool CBaseNode::CreateSolvers( GenericShaderData *ShaderData ) +{ +#if SHOW_SEDIT_ERRORS + Warning( "NODETYPE %i HAS NO SOLVER IMPLEMENTED!!!\n", GetNodeType() ); +#endif + return false; +} +void CBaseNode::SmartCreateDummySolver() +{ + if ( GetNumSolvers() ) + return; + AddSolver( new CHLSL_Solver_Dummy( GetUniqueIndex() ) ); +} +void CBaseNode::SweepJackHlslCache() +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + GetJack_In( i )->ClearTemporaryVarTarget(); + + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + GetJack_Out( i )->ClearTemporaryVarTarget(); +} + +bool CBaseNode::InsertToContainer( CBaseContainerNode *container ) +{ + Assert( dynamic_cast( container ) == NULL ); + + if ( HasContainerParent( container ) ) + return false; + m_hParentContainers.AddToTail( container ); + return true; +} +bool CBaseNode::HasContainerParent( CBaseContainerNode *container ) +{ + if ( !container ) + return false; + return m_hParentContainers.HasElement( container ); +} +bool CBaseNode::RemoveFromContainer( CBaseContainerNode *container ) +{ + int idx = m_hParentContainers.Find( container ); + if ( !m_hParentContainers.IsValidIndex(idx) ) + return false; + m_hParentContainers.Remove( idx ); + Assert( !HasContainerParent( container ) ); + return true; +} +int CBaseNode::GetNumContainers() +{ + return m_hParentContainers.Count(); +} +CBaseContainerNode *CBaseNode::GetContainer( int idx ) +{ + Assert( m_hParentContainers.IsValidIndex( idx ) ); + return m_hParentContainers[ idx ]; +} +Vector2D CBaseNode::GetContainerSensitiveCenter() +{ + return GetPosition() + Vector2D( 45, - 30 ); +} +void CBaseNode::ListContainersChronologically_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, + CUtlVector< CBaseContainerNode* > &hList ) +{ + CBaseContainerNode *Self = GetAsContainer(); + int numContainerParents = GetNumContainers(); + + + //if ( !numContainerParents ) + { + if ( Self && !hList.IsValidIndex( hList.Find( Self ) ) ) + hList.AddToHead( Self ); + } + //else + { + for ( int i = 0; i < numContainerParents; i++ ) + { + CBaseContainerNode *c = m_hParentContainers[i]; + if ( m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( c ) ) ) + continue; + m_hNodesProcessed.AddToTail( c ); + c->ListContainersChronologically_Internal( m_hNodesProcessed, hList ); + } + } +} +int ContainerSort( CBaseContainerNode *const *c1, CBaseContainerNode *const *c2 ) +{ + if ( (*c1)->HasContainerParent( (*c2) ) ) + return 1; + else if ( (*c2)->HasContainerParent( (*c1) ) ) + return -1; + return 0; +} +void CBaseNode::ListContainersChronologically( CUtlVector< CBaseContainerNode* > &hList ) +{ + CUtlVector< CBaseNode* > hNodes; + ListContainersChronologically_Internal( hNodes, hList ); + hNodes.Purge(); + + hList.Sort( ContainerSort ); +} +bool CBaseNode::RecursiveTestContainerError_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, + bool &bLeftContainerOnce, const bool &bHierachyUp, CBaseContainerNode *container ) +{ + bool bError = false; + const bool bIsInContainer = HasContainerParent( container ); + if ( bLeftContainerOnce && bIsInContainer ) + bError = true; + //else if ( !bIsInContainer ) + // bLeftContainerOnce = true; + + const int numJacks = bHierachyUp ? GetNumJacks_In() : GetNumJacks_Out(); + for ( int i = 0; i < numJacks; i++ ) + { + CJack *j = bHierachyUp ? GetJack_In( i ) : GetJack_Out( i ); + for ( int b = 0; b < j->GetNumBridges(); b++ ) + { + CBridge *pBridge = j->GetBridge( b ); + CBaseNode *pNodeEnd = pBridge->GetEndNode( this ); + if ( !pNodeEnd ) + continue; + + if ( !bIsInContainer ) + bLeftContainerOnce = true; + bool bOtherInContainer = pNodeEnd->HasContainerParent( container ); + if ( bLeftContainerOnce && bOtherInContainer ) + bError = true; + + if ( m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( pNodeEnd ) ) ) + continue; + + m_hNodesProcessed.AddToTail( pNodeEnd ); + bError = bError || pNodeEnd->RecursiveTestContainerError_Internal( m_hNodesProcessed, + bLeftContainerOnce, bHierachyUp, container ); + } + } + bLeftContainerOnce = false; + return bError; +} +bool CBaseNode::RecursiveTestContainerError( const bool &bHierachyUp, CBaseContainerNode *container ) +{ + CUtlVector< CBaseNode* >m_hProcessed; + bool bLeftContainer = false; + bool bResult = RecursiveTestContainerError_Internal( m_hProcessed, bLeftContainer, bHierachyUp, container ); + m_hProcessed.Purge(); + return bResult; +} + +bool CBaseNode::IsSolvable( bool bHierachyUp, CUtlVector< CBaseNode* > *hCallerList, CUtlVector< CBaseNode* > *hTested ) +{ + if (hTested && !(hTested->HasElement(this))) + hTested->AddToTail( this ); + + const int numJacks = bHierachyUp ? GetNumJacks_In() : GetNumJacks_Out(); + for ( int i = 0; i < numJacks; i++ ) + { + CJack *j = bHierachyUp ? GetJack_In( i ) : GetJack_Out( i ); + for ( int b = 0; b < j->GetNumBridges(); b++ ) + { + CBridge *pBridge = j->GetBridge( b ); + CBaseNode *pNodeEnd = pBridge->GetEndNode( this ); + //if ( pCaller && ( pNodeEnd == pCaller || pNodeEnd->HasContainerParent( pCaller->GetAsContainer() ) ) ) + if ( hCallerList && hCallerList->HasElement( pNodeEnd ) ) + continue; + + bool bContinue = false; + for ( int c = 0; hCallerList && c < hCallerList->Count(); c++ ) + if ( pNodeEnd->HasContainerParent( hCallerList->Element( c )->GetAsContainer() ) ) + bContinue = true; + if ( bContinue ) + continue; + + if ( pNodeEnd->GetAsContainer() ) + continue; + if ( !pNodeEnd->GetNumSolvers() ) + return false; + } + } + if ( !GetAsContainer() ) + { + for ( int c = 0; c < GetNumContainers(); c++ ) + { + CBaseContainerNode *container = GetContainer( c ); + if ( hTested && hTested->HasElement(container) ) + continue; + //if ( pCaller != container && + // !container->IsSolvable( bHierachyUp, pCaller, hTested ) ) + if ( ( !hCallerList || !hCallerList->HasElement( container ) ) && + !container->IsSolvable( bHierachyUp, hCallerList, hTested ) ) + return false; + } + } + return true; +} +void CBaseNode::Recursive_AddTailNodes_Internal( CUtlVector< CBaseNode* > &m_hProcessedNodes, + CUtlVector< CBaseNode* > &m_hList, + bool bHierachyUp, bool bOnlyWithoutSolver, + CBaseContainerNode *pContainer, bool bAddContainers ) +{ + m_hProcessedNodes.AddToTail( this ); + Assert( !pContainer || HasContainerParent( pContainer ) ); + const int numJacks = bHierachyUp ? GetNumJacks_In() : GetNumJacks_Out(); + bool bEndOfContainer = pContainer != NULL; + const bool bIsContainer = GetAsContainer() != NULL; + + if ( bEndOfContainer ) + for ( int i = 0; i < numJacks; i++ ) + { + CJack *j = bHierachyUp ? GetJack_In( i ) : GetJack_Out( i ); + for ( int b = 0; b < j->GetNumBridges(); b++ ) + { + CBridge *pBridge = j->GetBridge( b ); + CBaseNode *pNodeEnd = pBridge->GetEndNode( this ); + if ( pNodeEnd && pNodeEnd->HasContainerParent( pContainer ) ) + bEndOfContainer = false; + } + } + + const bool bAnyConnected = bHierachyUp ? ( GetNumJacks_In_Connected() != 0 ) : ( GetNumJacks_Out_Connected() != 0 ); + if ( !numJacks || !bAnyConnected || bEndOfContainer ) + { + if ( !bOnlyWithoutSolver || !GetNumSolvers() ) + { + if ( m_hList.IsValidIndex( m_hList.Find( this ) ) ) + return; + if ( !bIsContainer || bAddContainers ) + m_hList.AddToTail( this ); + } + return; + } + + bool bCanBeSolved = !bOnlyWithoutSolver || IsSolvable( bHierachyUp ); + + for ( int i = 0; i < numJacks; i++ ) + { + CJack *j = bHierachyUp ? GetJack_In( i ) : GetJack_Out( i ); + const bool bSelfReady = ( !bOnlyWithoutSolver || !GetNumSolvers() ); + bool bOtherReady = !bAnyConnected && !j->GetNumBridgesConnected(); + if ( bOnlyWithoutSolver && j->GetNumBridges() ) + { + bool bOtherWithNoSolver = false; + for ( int b = 0; b < j->GetNumBridges(); b++ ) + { + CBridge *pBridge = j->GetBridge( b ); + CBaseNode *pNodeEnd = pBridge->GetEndNode( this ); + + // another container hack 7.2.2012 + if ( !pNodeEnd->GetNumSolvers() && !pNodeEnd->GetAsContainer() ) + bOtherWithNoSolver = true; + } + if ( !bOtherWithNoSolver ) + bOtherReady = true; + } + if ( bCanBeSolved && bOtherReady && bSelfReady ) + { + if ( m_hList.IsValidIndex( m_hList.Find( this ) ) ) + continue; + if ( !bIsContainer || bAddContainers ) + m_hList.AddToTail( this ); + continue; + } + + for ( int x = 0; x < j->GetNumBridges(); x++ ) + { + CBridge *b = j->GetBridge( x ); + CBaseNode *next = b->GetEndNode( j ); + if ( next && !m_hProcessedNodes.IsValidIndex( m_hProcessedNodes.Find( next ) ) && + (!pContainer || next->HasContainerParent( pContainer ) ) && + (!next->GetAsContainer() || bAddContainers) ) + next->Recursive_AddTailNodes_Internal( m_hProcessedNodes, m_hList, bHierachyUp, bOnlyWithoutSolver, pContainer, bAddContainers ); + } + } +} +void CBaseNode::Recursive_AddTailNodes( CUtlVector< CBaseNode* > &m_hList, bool bHierachyUp, bool bOnlyWithoutSolver, + CBaseContainerNode *pContainer, bool bAddContainers ) +{ + //if ( GetAsContainer() && !bAddContainers ) + // return; + CUtlVector< CBaseNode* >m_hProcessed; + + Recursive_AddTailNodes_Internal( m_hProcessed, m_hList, bHierachyUp, bOnlyWithoutSolver, pContainer, bAddContainers ); + + m_hProcessed.Purge(); +} + +void CBaseNode::MarkForDeletion() +{ + m_bMarkedForDeletion = true; +} +const bool CBaseNode::IsMarkedForDeletion() +{ + return m_bMarkedForDeletion; +} +//void CBaseNode::OnUpdateHierachy_Upwards( CBridge *pBridgeInitiator ) +//{ +// //if ( pBridgeInitiator ) +// { +// for ( int i = 0; i < GetNumJacks_In(); i++ ) +// { +// CJack *j = GetJack_In( i ); +// for ( int a = 0; a < j->GetNumBridges(); a++ ) +// { +// CBridge *b = j->GetBridge( a ); +// CBaseNode *next = b->GetInputNode(); +// CJack *nextJ = b->GetInputJack(); +// if ( next && nextJ ) +// next->OnUpdateHierachy_Upwards( b ); +// } +// } +// } +// +// UpdatePreviewAllowed(); +//} +void CBaseNode::OnUpdateHierachy_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed ) +//void CBaseNode::OnUpdateHierachy_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, +// CUtlVector< CBridge* > &m_hBridgesToUpdate, +// CUtlVector< CJack* > &m_hJacksToUpdate ) +//void CBaseNode::OnUpdateHierachy_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, CBridge *pBridgeInitiator, CJack *pCaller ) +{ + //for ( int __i = 0; __i < m_hJacksToUpdate.Count(); __i++ ) + /* + if ( !pCaller ) + { + UpdatePreviewAllowed(); + return; + } + */ + int oldLevel = GetErrorLevel(); + + if ( !m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( this ) ) ) + m_hNodesProcessed.AddToTail( this ); + + bool bContainerLinkError = false; + + int inputErrorLevel = ERRORLEVEL_NONE; + if ( m_bAllInputsRequired && !JacksAllConnected_In() ) + inputErrorLevel = ERRORLEVEL_UNDEFINED; + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJ = GetJack_In( i ); + for ( int a = 0; a < pJ->GetNumBridges(); a++ ) + { + CBridge *pB = pJ->GetBridge( a ); + CBaseNode *pN = pB->GetInputNode(); + if ( pB->GetInputJack() ) + pJ->SetSmartType( pB->GetInputJack()->GetSmartType() ); + if ( pN && pN->GetAsContainer() && !HasContainerParent( pN->GetAsContainer() ) ) + bContainerLinkError = true; + } + } + + for ( int i = 0; i < GetNumContainers(); i++ ) + { + if ( RecursiveTestContainerError( false, GetContainer(i) ) ) + inputErrorLevel = max( inputErrorLevel, ERRORLEVEL_FAIL ); + + CBaseContainerNode *ctr_A = GetContainer( i ); + if ( ctr_A->TestFullHierachyUpdate() ) + inputErrorLevel = max( inputErrorLevel, ERRORLEVEL_FAIL ); + + for ( int a = 0; a < GetNumContainers(); a++ ) + { + if ( a == i ) + continue; + CBaseContainerNode *ctr_B = GetContainer( a ); + if ( !ctr_A->HasContainerParent( ctr_B ) && + !ctr_B->HasContainerParent( ctr_A ) ) + inputErrorLevel = max( inputErrorLevel, ERRORLEVEL_FAIL ); + } + + int numContainerContainers = ctr_A->GetNumContainers(); + for ( int a = 0; a < numContainerContainers; a++ ) + { + CBaseContainerNode *ctr_A_A = ctr_A->GetContainer( a ); + if ( !HasContainerParent( ctr_A_A ) ) + inputErrorLevel = max( inputErrorLevel, ERRORLEVEL_FAIL ); + } + } + + if ( !CanBeInContainer() && GetNumContainers() ) + inputErrorLevel = max( inputErrorLevel, ERRORLEVEL_FAIL ); + + inputErrorLevel = max( inputErrorLevel, PerNodeErrorLevel() ); + + inputErrorLevel = max( inputErrorLevel, UpdateInputsValid() ); + + //if ( inputErrorLevel != ERRORLEVEL_UNDEFINED || GetErrorLevel() == ERRORLEVEL_FAIL ) + { + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *j = GetJack_In( i ); + for ( int a = 0; a < j->GetNumBridges(); a++ ) + { + CBridge *b = j->GetBridge(a); + UpdateBridgeValidity( b, b->GetDestinationJack(), inputErrorLevel ); + } + } + } + + if ( bContainerLinkError ) + inputErrorLevel = max( inputErrorLevel, ERRORLEVEL_FAIL ); + + SetErrorLevel( inputErrorLevel ); + bool bDeepUpdate = GetErrorLevel() != oldLevel; + + UpdateOutputs(); + + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *j = GetJack_Out( i ); + for ( int a = 0; a < j->GetNumBridges(); a++ ) + { + CBridge *b = j->GetBridge( a ); + CBaseNode *next = b->GetDestinationNode(); + CJack *nextJ = b->GetDestinationJack(); + + bool bTargetWithError = next && next->GetErrorLevel() != ERRORLEVEL_NONE; + + if ( next && nextJ && + (!m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( next ) ) || (bTargetWithError&&bDeepUpdate)) && + !next->IsMarkedForDeletion() ) + next->OnUpdateHierachy_Internal( m_hNodesProcessed ); + } + } +} +void CBaseNode::OnUpdateHierachy( CBridge *pBridgeInitiator, CJack *pCaller ) +{ + if ( !pCaller && pBridgeInitiator ) + { + UpdatePreviewAllowed(); + pNodeView->OnHierachyChanged(); + return; + } + + CUtlVector< CBaseNode* > m_hNodesProcessed; + + OnUpdateHierachy_Internal( m_hNodesProcessed ); + + m_hNodesProcessed.Purge(); + + pNodeView->OnHierachyChanged(); +} +void CBaseNode::UpdatePreviewAllowed() +{ + int hierachyType = GetHierachyTypeIterateFullyRecursive(); + CheckHierachyTypeFullyRecursive( hierachyType ); +} +void CBaseNode::CheckHierachyTypeFullyRecursive( int t ) +{ + CUtlVector< CBaseNode* > m_hNodesProcessed; + m_hNodesProcessed.AddToTail( this ); + CheckHierachyTypeFullyRecursive_Internal( t, m_hNodesProcessed ); + m_hNodesProcessed.Purge(); +} +void CBaseNode::CheckHierachyTypeFullyRecursive_Internal( int t, CUtlVector< CBaseNode* > &m_hNodesProcessed ) +{ + m_bAllowPreview = t != HLSLHIERACHY_VS; + UpdateSize(); + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJ = GetJack_In( i ); + for ( int b = 0; b < pJ->GetNumBridges(); b++ ) + { + CBridge *pBridge = pJ->GetBridge( b ); + CBaseNode *pOther = pBridge->GetEndNode( this ); + if ( !pOther || m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( pOther ) ) ) + continue; + m_hNodesProcessed.AddToTail( this ); + pOther->CheckHierachyTypeFullyRecursive_Internal( t, m_hNodesProcessed ); + } + } + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJ = GetJack_Out( i ); + for ( int b = 0; b < pJ->GetNumBridges(); b++ ) + { + CBridge *pBridge = pJ->GetBridge( b ); + CBaseNode *pOther = pBridge->GetEndNode( this ); + if ( !pOther || m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( pOther ) ) ) + continue; + m_hNodesProcessed.AddToTail( this ); + pOther->CheckHierachyTypeFullyRecursive_Internal( t, m_hNodesProcessed ); + } + } +} + +int CBaseNode::UpdateInputsValid() +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJIn = GetJack_In( i ); + for ( int a = 0; a < pJIn->GetNumBridges(); a++ ) + { + CBridge *b = pJIn->GetBridge(a); + CJack *pEnd = b ? b->GetEndJack(this) : NULL; + CBaseNode *pOtherNode = b->GetEndNode( this ); + if ( !pEnd || !pOtherNode ) + continue; + + int parentError = pOtherNode->GetErrorLevel(); + + bool bDefinedSmarttype_Local = pJIn->GetSmartType() >= 0; + bool bDefinedSmarttype_Remote = pEnd->GetSmartType() >= 0; + if ( bDefinedSmarttype_Local && + bDefinedSmarttype_Remote && + pJIn->GetSmartType() != pEnd->GetSmartType() ) + { + return ERRORLEVEL_FAIL; + } + else if ( parentError == ERRORLEVEL_FAIL ) + return ERRORLEVEL_UNDEFINED; + else if ( !bDefinedSmarttype_Local || !bDefinedSmarttype_Remote || + parentError == ERRORLEVEL_UNDEFINED ) + return ERRORLEVEL_UNDEFINED; + } + } + + if ( m_bAllInputsRequired && !JacksAllConnected_In() ) + return ERRORLEVEL_UNDEFINED; + return ERRORLEVEL_NONE; +} +void CBaseNode::UpdateBridgeValidity( CBridge *pBridge, CJack *pCaller, int inputErrorLevel ) +{ + CBaseNode *pNodeViewNode = pBridge->GetInputNode(); + CJack *pOther = pBridge->GetInputJack(); + + int iOther_SmartType = pOther ? pOther->GetSmartType() : -1; + int iLocal_SmartType = pCaller->GetSmartType(); + + bool bDefined_Other = iOther_SmartType > -1; + bool bDefined_Local = iLocal_SmartType > -1; + //bool bLocked_Other = pOther->IsSmartTypeLocked(); + bool bLocked_Local = pCaller->IsSmartTypeLocked(); + + int iParentErrorLevel = pNodeViewNode ? pNodeViewNode->GetErrorLevel() : ERRORLEVEL_UNDEFINED; + int iGoalErrorLevel = inputErrorLevel; + + bool bCorrectType = iOther_SmartType == iLocal_SmartType; + + // something isn't defined at all + if ( !bDefined_Local || !bDefined_Other || iParentErrorLevel != ERRORLEVEL_NONE ) + iGoalErrorLevel = ERRORLEVEL_UNDEFINED; + // wrong type, fail for sure + else if ( !bCorrectType ) + iGoalErrorLevel = ERRORLEVEL_FAIL; + else if ( pNodeViewNode && pNodeViewNode->GetAsContainer() && !HasContainerParent( pNodeViewNode->GetAsContainer() ) ) + iGoalErrorLevel = ERRORLEVEL_FAIL; + else if ( inputErrorLevel == ERRORLEVEL_UNDEFINED ) + { + // Our parent is ready but we failed locally, nothing wrong with the bridge after all + if ( iParentErrorLevel == ERRORLEVEL_NONE ) + iGoalErrorLevel = ERRORLEVEL_NONE; + } + else if ( inputErrorLevel == ERRORLEVEL_FAIL ) + { + // we failed although our parent is ready and the target input is static and correct + if ( iParentErrorLevel == ERRORLEVEL_NONE && bLocked_Local ) + iGoalErrorLevel = ERRORLEVEL_NONE; + } + + pBridge->SetErrorLevel( iGoalErrorLevel ); +} +void CBaseNode::UpdateOutputs() +{ +} +void CBaseNode::SetOutputsUndefined() +{ + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJack = GetJack_Out( i ); + pJack->SetSmartType( -1 ); + } +} +void CBaseNode::OnShowSolverErrored() +{ + CUtlVector< CBaseNode* >hList; + for ( int j = 0; j < GetNumJacks_Out(); j++ ) + { + CJack *pJ_Out = GetJack_Out(j); + for ( int i = 0; pJ_Out && i < pJ_Out->GetNumBridges(); i++ ) + { + CBridge *pB = pJ_Out->GetBridge(i); + CBaseNode *pN = pB->GetEndNode( this ); + if ( !pN || hList.HasElement( pN ) ) + continue; + pN->OnUpdateHierachy( NULL, NULL ); + hList.AddToTail( pN ); + } + } + hList.Purge(); +} +const int CBaseNode::GetErrorLevel() +{ + if ( ShouldErrorOnUndefined() && iErrorLevel == ERRORLEVEL_UNDEFINED ) + return ERRORLEVEL_FAIL; + return iErrorLevel; +} +void CBaseNode::SetErrorLevel( const int e ) +{ + iErrorLevel = e; +} + +int CBaseNode::GetHierachyType() +{ + return HLSLHIERACHY_NONE; +} +int CBaseNode::GetAllowedHierachiesAsFlags() +{ + return HLSLHIERACHY_VS | HLSLHIERACHY_PS; // | HLSLHIERACHY_TEMPLATE_VS | HLSLHIERACHY_TEMPLATE_PS; +} +int CBaseNode::GetHierachyTypeIterateFullyRecursive_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, int *iAllowances ) +{ + int tmp = GetHierachyType(); + if ( tmp > HLSLHIERACHY_NONE ) + return tmp; + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJ = GetJack_In( i ); + for ( int b = 0; b < pJ->GetNumBridges(); b++ ) + { + CBridge *pBridge = pJ->GetBridge( b ); + CBaseNode *pOther = pBridge->GetInputNode(); + if ( !pOther || m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( pOther ) ) ) + continue; + + m_hNodesProcessed.AddToTail( pOther ); + //m_hNodesProcessed.AddToTail( this ); + if ( iAllowances ) + *iAllowances &= pOther->GetAllowedHierachiesAsFlags(); + + int otherHType = pOther->GetHierachyTypeIterateFullyRecursive_Internal( m_hNodesProcessed, iAllowances ); + + if ( otherHType == HLSLHIERACHY_NONE ) + continue; + if ( tmp > HLSLHIERACHY_NONE && tmp == otherHType ) + continue; + if ( tmp > HLSLHIERACHY_NONE && tmp != otherHType ) + return HLSLHIERACHY_MULTIPLE; + tmp = otherHType; + } + } + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJ = GetJack_Out( i ); + for ( int b = 0; b < pJ->GetNumBridges(); b++ ) + { + CBridge *pBridge = pJ->GetBridge( b ); + CBaseNode *pOther = pBridge->GetDestinationNode(); + if ( !pOther || m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( pOther ) ) ) + continue; + + m_hNodesProcessed.AddToTail( pOther ); + //m_hNodesProcessed.AddToTail( this ); + if ( iAllowances ) + *iAllowances &= pOther->GetAllowedHierachiesAsFlags(); + + int otherHType = pOther->GetHierachyTypeIterateFullyRecursive_Internal( m_hNodesProcessed, iAllowances ); + + if ( otherHType == HLSLHIERACHY_NONE ) + continue; + if ( tmp > HLSLHIERACHY_NONE && tmp == otherHType ) + continue; + if ( tmp > HLSLHIERACHY_NONE && tmp != otherHType ) + return HLSLHIERACHY_MULTIPLE; + tmp = otherHType; + } + } + + return tmp; +} +int CBaseNode::GetHierachyTypeIterateFullyRecursive( int *iAllowances ) +{ + if ( iAllowances ) + *iAllowances = GetAllowedHierachiesAsFlags(); + if ( GetHierachyType() > HLSLHIERACHY_NONE ) + return GetHierachyType(); + + CUtlVector< CBaseNode* > m_hIgnore; + m_hIgnore.AddToTail( this ); + + //CFastTimer timer_; + //timer_.Start(); + + int hSearch = GetHierachyTypeIterateFullyRecursive_Internal( m_hIgnore, iAllowances ); + + //timer_.End(); + //Msg( "recursive search took %f seconds\n", timer_.GetDuration() ); + + m_hIgnore.Purge(); + return hSearch; +} + + +void CBaseNode::SetTempHierachyTypeFullyRecursive_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, int t ) +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJ = GetJack_In( i ); + for ( int b = 0; b < pJ->GetNumBridges(); b++ ) + { + CBridge *pBridge = pJ->GetBridge( b ); + CBaseNode *pOther = pBridge->GetInputNode(); + if ( !pOther || m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( pOther ) ) ) + continue; + + m_hNodesProcessed.AddToTail( pOther ); + pOther->SetTempHierachyType( t ); + pOther->SetTempHierachyTypeFullyRecursive_Internal( m_hNodesProcessed, t ); + } + } + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJ = GetJack_Out( i ); + for ( int b = 0; b < pJ->GetNumBridges(); b++ ) + { + CBridge *pBridge = pJ->GetBridge( b ); + CBaseNode *pOther = pBridge->GetDestinationNode(); + if ( !pOther || m_hNodesProcessed.IsValidIndex( m_hNodesProcessed.Find( pOther ) ) ) + continue; + + m_hNodesProcessed.AddToTail( pOther ); + pOther->SetTempHierachyType( t ); + pOther->SetTempHierachyTypeFullyRecursive_Internal( m_hNodesProcessed, t ); + } + } +} +const int CBaseNode::GetTempHierachyType() +{ + return m_iTempHierachy; +} +void CBaseNode::SetTempHierachyTypeFullyRecursive( const int t ) +{ + CUtlVector< CBaseNode* > m_hIgnore; + m_hIgnore.AddToTail( this ); + + SetTempHierachyType( t ); + SetTempHierachyTypeFullyRecursive_Internal( m_hIgnore, t ); + + m_hIgnore.Purge(); +} +void CBaseNode::SetTempHierachyType( const int t ) +{ + m_iTempHierachy = t; +} + +/* +int CBaseNode::GetHierachyTypeIterate( bool bUp, int *iAllowances ) +{ + int tmp = GetHierachyType(); + if ( tmp > HLSLHIERACHY_NONE ) + return tmp; + + int numJacks = bUp ? GetNumJacks_In() : GetNumJacks_Out(); + + for ( int i = 0; i < numJacks; i++ ) + { + CJack *pJack = bUp ? GetJack_In( i ) : GetJack_Out( i ); + for ( int b = 0; b < pJack->GetNumBridges(); b++ ) + { + CBridge *pBridge = pJack->GetBridge( b ); + CBaseNode *pOther = bUp ? pBridge->GetInputNode() : pBridge->GetDestinationNode(); + if ( !pOther ) + continue; + + if ( iAllowances ) + *iAllowances &= pOther->GetAllowedHierachiesAsFlags(); + + int otherHType = pOther->GetHierachyTypeIterate( bUp, iAllowances ); + if ( otherHType == HLSLHIERACHY_NONE ) + continue; + + if ( tmp > HLSLHIERACHY_NONE && tmp == otherHType ) + continue; + + if ( tmp > HLSLHIERACHY_NONE && tmp != otherHType ) + return HLSLHIERACHY_MULTIPLE; + + tmp = otherHType; + } + } + + return tmp; +} +*/ +/* +int CBaseNode::GetHierachyTypeIterate( int *iAllowances ) +{ + //return GetHierachyTypeIterateFullyRecursive( iAllowances ); + + if ( iAllowances ) + *iAllowances = GetAllowedHierachiesAsFlags(); + if ( GetHierachyType() > HLSLHIERACHY_NONE ) + return GetHierachyType(); + + int hUp = GetHierachyTypeIterate( true, iAllowances ); + int hDown = GetHierachyTypeIterate( false, iAllowances ); + + if ( hUp == HLSLHIERACHY_MULTIPLE || + hDown == HLSLHIERACHY_MULTIPLE ) + return HLSLHIERACHY_MULTIPLE; + + if ( hUp == HLSLHIERACHY_NONE && + hDown == HLSLHIERACHY_NONE ) + return HLSLHIERACHY_NONE; + + if ( hUp != HLSLHIERACHY_NONE && + hDown != HLSLHIERACHY_NONE && + hUp != hDown ) + return HLSLHIERACHY_MULTIPLE; + + return max( hUp, hDown ); +} +*/ +bool CBaseNode::IsPreviewVisible() +{ + return m_bAllowPreview && m_bPreviewEnabled; +} + +void CBaseNode::UpdateSize() +{ + int maxJacks = max( m_hInputs.Count(), m_hOutputs.Count() ); + float sizeMin = ( JACK_SIZE_Y + JACK_DELTA_Y ) * maxJacks + JACK_SIZE_Y; + sizeMin = max( sizeMin, m_flMinSizeY_VS ); + + //if ( GetHierachyType() == HLSLHIERACHY_PS ) + if ( IsPreviewVisible() ) + sizeMin = max( m_flMinSizeY, sizeMin ); + + m_vecBorderInfo.Init(); + + for ( int i = 0; i < m_hInputs.Count(); i++ ) + m_vecBorderInfo.x = max( m_vecBorderInfo.x, GetJack_In(i)->GetFinalTextInset() ); + for ( int i = 0; i < m_hOutputs.Count(); i++ ) + m_vecBorderInfo.y = max( m_vecBorderInfo.y, GetJack_Out(i)->GetFinalTextInset() ); + + float addSize = IsPreviewVisible() ? m_flMinSizePREVIEW_X : 0; + + float localminX = max( GetFinalTextSize(), m_flMinSizeX ); + m_vecSize.Init( max( localminX, addSize + m_vecBorderInfo.x + m_vecBorderInfo.y ), -sizeMin ); + + TouchJacks(); + + UpdateSimpleObjectBounds( m_vecPosition, m_vecSize, m_vecBounds ); +} +void CBaseNode::GenerateJacks_Input( int num ) +{ + if ( num ) + SetErrorLevel( ERRORLEVEL_UNDEFINED ); + else + SetErrorLevel( ERRORLEVEL_NONE ); + + SaveDeleteVector( m_hInputs ); + + for ( int i = 0; i < num; i++ ) + { + CJack *p = new CJack( this, i, true ); + m_hInputs.AddToTail( p ); + } + + UpdateSize(); +} +void CBaseNode::GenerateJacks_Output( int num ) +{ + SaveDeleteVector( m_hOutputs ); + + for ( int i = 0; i < num; i++ ) + { + CJack *p = new CJack( this, i, false ); + m_hOutputs.AddToTail( p ); + } + + UpdateSize(); +} +void CBaseNode::TouchJacks() +{ + for ( int i = 0; i < m_hInputs.Count(); i++ ) + m_hInputs[i]->UpdatePosition(); + for ( int i = 0; i < m_hOutputs.Count(); i++ ) + m_hOutputs[i]->UpdatePosition(); +} +int CBaseNode::GetNumJacks_Out() +{ + return m_hOutputs.Count(); +} +int CBaseNode::GetNumJacks_In() +{ + return m_hInputs.Count(); +} +int CBaseNode::GetNumJacks_Out_Connected() +{ + int o = 0; + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + if ( GetJack_Out( i )->GetNumBridgesConnected() ) + o++; + } + return o; +} +int CBaseNode::GetNumJacks_In_Connected() +{ + int o = 0; + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + if ( GetJack_In( i )->GetNumBridgesConnected() ) + o++; + } + return o; +} +CJack* CBaseNode::GetJack_Out( int i ) +{ + return m_hOutputs[ i ]; +} +CJack* CBaseNode::GetJack_In( int i ) +{ + return m_hInputs[ i ]; +} +CJack *CBaseNode::GetJackByName_Out( const char *name ) +{ + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + if ( !Q_stricmp( GetJack_Out( i )->GetName(), name ) ) + return GetJack_Out( i ); + return NULL; +} +CJack *CBaseNode::GetJackByName_In( const char *name ) +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + if ( !Q_stricmp( GetJack_In( i )->GetName(), name ) ) + return GetJack_In( i ); + return NULL; +} +CJack *CBaseNode::GetJackByResType_Out( int restype ) +{ + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + if ( restype == GetJack_Out(i)->GetResourceType() ) + return GetJack_Out( i ); + return NULL; +} +CJack *CBaseNode::GetJackByResType_In( int restype ) +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + if ( restype == GetJack_In(i)->GetResourceType() ) + return GetJack_In( i ); + return NULL; +} +bool CBaseNode::JacksAllConnected_Out() +{ + return GetNumJacks_Out_Connected() == GetNumJacks_Out(); +} +bool CBaseNode::JacksAllConnected_In() +{ + return GetNumJacks_In_Connected() == GetNumJacks_In(); +} +void CBaseNode::JackHierachyUpdate_Out() +{ + for ( int j = 0; j < GetNumJacks_Out(); j++ ) + { + CJack *pJack = GetJack_Out( j ); + for ( int b = 0; b < pJack->GetNumBridges(); b++ ) + { + CBridge *pBridge = pJack->GetBridge( b ); + CJack *pJackNeedsUpdate = pBridge->GetEndJack( this ); + CBaseNode *pNodeNeedsUpdate = pBridge->GetEndNode( this ); + if ( !pJackNeedsUpdate || !pNodeNeedsUpdate ) + continue; + pJack->UpdateSmartType( pBridge ); + pNodeNeedsUpdate->OnUpdateHierachy( pBridge, pJackNeedsUpdate ); + } + } +} +CHLSL_Var *CBaseNode::GetInputToWriteTo( int varTypes ) +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJIn = GetJack_In( i ); + CHLSL_Var *potentialVar = pJIn->GetTemporaryVarTarget_End_Smart( varTypes ); + if ( !potentialVar ) + continue; + if ( !potentialVar->CanBeOverwritten() ) + continue; + if ( !( potentialVar->GetType() & varTypes ) ) + continue; + return potentialVar; + } + return NULL; +} + +void CBaseNode::SetJackFlags_MinFloatRequirement( CJack *j, int components ) +{ + j->ClearVarFlags(); + switch ( components ) + { + case 1: + j->AddVarFlags( HLSLVAR_FLOAT1 ); + case 2: + j->AddVarFlags( HLSLVAR_FLOAT2 ); + case 3: + j->AddVarFlags( HLSLVAR_FLOAT3 ); + case 4: + j->AddVarFlags( HLSLVAR_FLOAT4 ); + } +} +void CBaseNode::SetJackFlags( CJack *j, HLSLJackVarCluster mode ) +{ + j->ClearVarFlags(); + + switch (mode) + { + case HLSLJACKFLAGS_F1: + j->AddVarFlags( HLSLVAR_FLOAT1 ); + break; + case HLSLJACKFLAGS_F2: + case HLSLJACKFLAGS_UV: + j->AddVarFlags( HLSLVAR_FLOAT2 ); + break; + case HLSLJACKFLAGS_F3: + j->AddVarFlags( HLSLVAR_FLOAT3 ); + break; + case HLSLJACKFLAGS_F4: + j->AddVarFlags( HLSLVAR_FLOAT4 ); + break; + case HLSLJACKFLAGS_F1_TO_F4: + j->AddVarFlags( HLSLVAR_FLOAT1 | HLSLVAR_FLOAT2 | HLSLVAR_FLOAT3 | HLSLVAR_FLOAT4 ); + break; + case HLSLJACKFLAGS_VECTOR: + j->AddVarFlags( HLSLVAR_FLOAT3 | HLSLVAR_FLOAT4 ); + break; + case HLSLJACKFLAGS_MATRIX: + j->AddVarFlags( HLSLVAR_MATRIX3X3 | HLSLVAR_MATRIX4X3 | HLSLVAR_MATRIX4X4 ); + break; + case HLSLJACKFLAGS_ALL: + j->AddVarFlags( HLSLVAR_FLOAT1 | HLSLVAR_FLOAT2 | HLSLVAR_FLOAT3 | HLSLVAR_FLOAT4 ); + j->AddVarFlags( HLSLVAR_MATRIX3X3 | HLSLVAR_MATRIX4X3 | HLSLVAR_MATRIX4X4 ); + break; + } +} +void CBaseNode::SetJackFlags_Input( int idx, HLSLJackVarCluster mode ) +{ + SetJackFlags( GetJack_In( idx ), mode ); +} +void CBaseNode::SetJackFlags_Output( int idx, HLSLJackVarCluster mode ) +{ + SetJackFlags( GetJack_Out( idx ), mode ); +} +void CBaseNode::SetJackFlags_Input_Flags( int idx, int Flags ) +{ + CJack *j = GetJack_In( idx ); + j->ClearVarFlags(); + j->AddVarFlags(Flags); +} +void CBaseNode::SetJackFlags_Output_Flags( int idx, int Flags ) +{ + CJack *j = GetJack_Out( idx ); + j->ClearVarFlags(); + j->AddVarFlags(Flags); +} +void CBaseNode::SetupJackOutput( int idx, HLSLJackVarCluster mode, const char *name ) +{ + GetJack_Out( idx )->SetName( name ); + SetJackFlags( GetJack_Out( idx ), mode ); +} +void CBaseNode::SetupJackInput( int idx, HLSLJackVarCluster mode, const char *name ) +{ + GetJack_In( idx )->SetName( name ); + SetJackFlags( GetJack_In( idx ), mode ); +} +void CBaseNode::LockJackOutput_Flags( int idx, int Flag, const char *name ) +{ + CJack *j = GetJack_Out( idx ); + if ( name ) + j->SetName( name ); + j->ClearVarFlags(); + j->AddVarFlags(Flag); + + j->SetSmartTypeLocked( false ); + j->SetSmartType( Flag ); + j->SetSmartTypeLocked( true ); +} +void CBaseNode::LockJackInput_Flags( int idx, int Flag, const char *name ) +{ + CJack *j = GetJack_In( idx ); + if ( name ) + j->SetName( name ); + j->ClearVarFlags(); + j->AddVarFlags(Flag); + + j->SetSmartTypeLocked( false ); + j->SetSmartType( Flag ); + j->SetSmartTypeLocked( true ); +} +int CBaseNode::TestJackFlags_In() +{ + bool bError = false; + bool bUndefined = false; + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *j = GetJack_In( i ); + int type = j->GetSmartType(); + if ( type < 0 ) + bUndefined = true; + else if ( !j->HasVarFlag( type ) ) + bError = true; + } + if ( bError ) + return ERRORLEVEL_FAIL; + if ( bUndefined ) + return ERRORLEVEL_UNDEFINED; + return ERRORLEVEL_NONE; +} +void CBaseNode::PurgeBridges( bool bInputs, bool bOutputs ) +{ + if ( bInputs ) + for ( int i = 0; i < GetNumJacks_In(); i++ ) + GetJack_In( i )->PurgeBridges(); + if ( bOutputs ) + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + GetJack_Out( i )->PurgeBridges(); +} +void CBaseNode::CreateBridgeRestoreData_Out( BridgeRestoreMode mode, CUtlVector< BridgeRestoreInfo* > &m_hList ) +{ + int iJacksInUse = 0; + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *cur = GetJack_Out(i); + for ( int b = 0; b < cur->GetNumBridges(); b++ ) + { + CBridge *pB = cur->GetBridge(b); + + if ( pB->GetEndJack( cur ) ) + { + BridgeRestoreInfo *restore = new BridgeRestoreInfo(); + restore->iMode = mode; + restore->pJackOther = pB->GetEndJack( cur ); + + if ( mode == BY_NAME ) + Q_snprintf( restore->jackSelfName, sizeof(restore->jackSelfName), "%s", cur->GetName() ); + else if ( mode == BY_RESTYPE ) + restore->resType = cur->GetResourceType(); + else if ( mode == BY_COUNT ) + restore->idx = iJacksInUse; + else + restore->idx = i; + + m_hList.AddToTail( restore ); + } + } + + if ( cur->GetNumBridges() > 0 || + ( GetNumJacks_In() > i && GetJack_In( i )->GetNumBridges() > 0 ) ) + { + iJacksInUse++; + } + } +} +void CBaseNode::CreateBridgeRestoreData_In( BridgeRestoreMode mode, CUtlVector< BridgeRestoreInfo* > &m_hList ) +{ + int iJacksInUse = 0; + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *cur = GetJack_In(i); + for ( int b = 0; b < cur->GetNumBridges(); b++ ) + { + CBridge *pB = cur->GetBridge(b); + + if ( pB->GetEndJack( cur ) ) + { + BridgeRestoreInfo *restore = new BridgeRestoreInfo(); + restore->iMode = mode; + restore->pJackOther = pB->GetEndJack( cur ); + + if ( mode == BY_NAME ) + Q_snprintf( restore->jackSelfName, sizeof(restore->jackSelfName), "%s", cur->GetName() ); + else if ( mode == BY_RESTYPE ) + restore->resType = cur->GetResourceType(); + else if ( mode == BY_COUNT ) + restore->idx = iJacksInUse; + else + restore->idx = i; + + m_hList.AddToTail( restore ); + } + } + + if ( cur->GetNumBridges() > 0 || + ( GetNumJacks_Out() > i && GetJack_Out( i )->GetNumBridges() > 0 ) ) + { + iJacksInUse++; + } + } +} +void CBaseNode::RestoreBridgesFromList_Out( CUtlVector< BridgeRestoreInfo* > &m_hList ) +{ + for ( int i = 0; i < m_hList.Count(); i++ ) + { + BridgeRestoreInfo *inf = m_hList[i]; + CJack *localJack = NULL; + switch ( inf->iMode ) + { + default: + Assert(0); + break; + case BY_INDEX: + localJack = inf->idx < GetNumJacks_Out() ? GetJack_Out( inf->idx ) : NULL; + break; + case BY_NAME: + localJack = GetJackByName_Out( inf->jackSelfName ); + break; + case BY_RESTYPE: + localJack = GetJackByResType_Out( inf->resType ); + break; + case BY_COUNT: + if ( inf->idx < GetNumJacks_Out() ) + localJack = GetJack_Out( inf->idx ); + break; + } + + if ( !localJack ) + continue; + m_hList[i]->pJackOther->BridgeEndBuild( localJack->BridgeBeginBuild() ); + } + SaveDeleteVector( m_hList ); +} +void CBaseNode::RestoreBridgesFromList_In( CUtlVector< BridgeRestoreInfo* > &m_hList ) +{ + for ( int i = 0; i < m_hList.Count(); i++ ) + { + BridgeRestoreInfo *inf = m_hList[i]; + CJack *localJack = NULL; + switch ( inf->iMode ) + { + default: + Assert(0); + break; + case BY_INDEX: + localJack = inf->idx < GetNumJacks_In() ? GetJack_In( inf->idx ) : NULL; + break; + case BY_NAME: + localJack = GetJackByName_In( inf->jackSelfName ); + break; + case BY_RESTYPE: + localJack = GetJackByResType_In( inf->resType ); + break; + case BY_COUNT: + if ( inf->idx < GetNumJacks_In() ) + localJack = GetJack_In( inf->idx ); + break; + } + + if ( !localJack ) + continue; + m_hList[i]->pJackOther->BridgeEndBuild( localJack->BridgeBeginBuild() ); + } + SaveDeleteVector( m_hList ); +} + +bool CBaseNode::RecursiveFindNode_Internal( CUtlVector< CBaseNode* > &m_hList, CBaseNode *n, bool bHierachyUp ) +{ + m_hList.AddToTail( this ); + bool bFound = false; + const int numJacks = bHierachyUp ? GetNumJacks_In() : GetNumJacks_Out(); + for ( int i = 0; i < numJacks && !bFound; i++ ) + { + CJack *j = bHierachyUp ? GetJack_In( i ) : GetJack_Out( i ); + for ( int x = 0; x < j->GetNumBridges() && !bFound; x++ ) + { + CBridge *b = j->GetBridge( x ); + CBaseNode *next = bHierachyUp ? b->GetInputNode() : b->GetDestinationNode(); + if ( next == NULL ) + continue; + if ( next == n ) + return true; + else if ( !m_hList.IsValidIndex( m_hList.Find( next ) ) ) + bFound = bFound || next->RecursiveFindNode_Internal( m_hList, n, bHierachyUp ); + } + } + return bFound; +} +bool CBaseNode::RecursiveFindNode( CBaseNode *n, bool bHierachyUp ) +{ + CUtlVector< CBaseNode* > m_hList; + bool bResult = RecursiveFindNode_Internal( m_hList, n, bHierachyUp ); + m_hList.Purge(); + return bResult; +} + +Vector2D CBaseNode::GetBoundsMin() +{ + return GetBoundsTitleMin(); +} +Vector2D CBaseNode::GetBoundsMax() +{ + return GetBoundsBoxMax(); +} +Vector2D CBaseNode::GetBoundsMinNodeSpace() +{ + Vector2D _min = GetBoundsMin(); + Vector2D _max = GetBoundsMax(); + Vector2D out( min( _min.x, _max.x ), + min( _min.y, _max.y ) ); + return out; +} +Vector2D CBaseNode::GetBoundsMaxNodeSpace() +{ + Vector2D _min = GetBoundsMin(); + Vector2D _max = GetBoundsMax(); + Vector2D out( max( _min.x, _max.x ), + max( _min.y, _max.y ) ); + return out; +} +Vector2D CBaseNode::GetSelectionBoundsMinNodeSpace() +{ + return GetBoundsMinNodeSpace(); +} +Vector2D CBaseNode::GetSelectionBoundsMaxNodeSpace() +{ + return GetBoundsMaxNodeSpace(); +} +Vector2D CBaseNode::GetCenter() +{ + Vector2D _min = GetBoundsMinNodeSpace(); + Vector2D _max = GetBoundsMaxNodeSpace(); + return _min + ( _max - _min ) * 0.5f; +} +Vector2D CBaseNode::GetBoundsTitleMin() +{ + return m_vecPosition; +} +Vector2D CBaseNode::GetBoundsTitleMax() +{ + return Vector2D( m_vecPosition + Vector2D( m_vecSize.x, -NODE_DRAW_TITLE_Y ) ); +} +Vector2D CBaseNode::GetBoundsBoxMin() +{ + return Vector2D( m_vecPosition - Vector2D( 0, NODE_DRAW_TITLE_Y + NODE_DRAW_TITLE_SPACE ) ); +} +Vector2D CBaseNode::GetBoundsBoxMax() +{ + return Vector2D( GetBoundsBoxMin() + m_vecSize ); +} +bool CBaseNode::IsWithinBounds_Base( const Vector2D &pos ) +{ + Vector2D _min, _max; + _min = GetBoundsMin(); + _max = GetBoundsMax(); + + if ( pos.x >= _min.x && pos.y <= _min.y && + pos.x <= _max.x && pos.y >= _max.y ) + return true; + return false; +} + +void CBaseNode::OnLeftClick( Vector2D &pos ) +{ +} +void CBaseNode::OnDragStart() +{ +} +void CBaseNode::OnDrag( Vector2D &delta ) +{ + Vector2D pos = GetPosition(); + pos += delta; + SetPosition( pos ); +} +void CBaseNode::OnDragEnd() +{ +} +bool CBaseNode::MustDragAlone() +{ + return false; +} + +void CBaseNode::UpdateParentContainers() +{ + Vector2D center = GetContainerSensitiveCenter(); + CUtlVector< CBaseContainerNode* > hContainers_Add; + CUtlVector< CBaseContainerNode* > hContainers_Remove; + pNodeView->ListContainerAtPos( center, hContainers_Add ); + + for ( int i = 0; i < GetNumContainers(); i++ ) + { + CBaseContainerNode *c = GetContainer( i ); + if ( hContainers_Add.IsValidIndex( hContainers_Add.Find( c ) ) ) + hContainers_Add.FindAndRemove( c ); + else + hContainers_Remove.AddToTail( c ); + } + + for ( int i = 0; i < hContainers_Remove.Count(); i++ ) + hContainers_Remove[ i ]->RemoveChild( this ); + for ( int i = 0; i < hContainers_Add.Count(); i++ ) + hContainers_Add[ i ]->AddChild( this ); + + hContainers_Add.Purge(); + hContainers_Remove.Purge(); +} + +void CBaseNode::SetPosition( Vector2D vec, bool bCenter ) +{ + if ( bCenter ) + { + Vector2D delta = GetBoundsMin() + ( GetBoundsMax() - GetBoundsMin() ) * 0.5f; + vec -= delta; + } + m_vecPosition = vec; + + TouchJacks(); + + UpdateSimpleObjectBounds( m_vecPosition, m_vecSize, m_vecBounds ); + + UpdateParentContainers(); +} +Vector2D CBaseNode::GetPosition() +{ + return m_vecPosition; +} +Vector2D CBaseNode::GetSize() +{ + return m_vecSize; +} +const Vector4D &CBaseNode::GetBoundsFast() +{ + return m_vecBounds; +} + +void CBaseNode::SetAllocating( const bool &a ) +{ + m_bIsAllocating = a; +} +bool CBaseNode::IsAllocating() +{ + if ( !GetNumSolvers() || HasDummySolvers() ) + return false; + return m_bIsAllocating; +} +bool CBaseNode::VguiDraw( bool bShadow ) +{ + if ( !ShouldSimpleDrawObject( pNodeView, pNodeView, m_vecBounds ) ) + return false; + if ( !pNodeView ) + return false; + + Vector2D title_min = GetBoundsTitleMin(); + Vector2D title_max = GetBoundsTitleMax(); + Vector2D box_min = GetBoundsBoxMin(); + Vector2D box_max = GetBoundsBoxMax(); + + pNodeView->ToPanelSpace( title_min ); + pNodeView->ToPanelSpace( title_max ); + pNodeView->ToPanelSpace( box_min ); + pNodeView->ToPanelSpace( box_max ); + + float flZoom = pNodeView->GetZoomScalar(); + if ( bShadow ) + { + float flO = NODE_DRAW_SHADOW_DELTA * flZoom; + Vector2D offset( flO, flO ); + title_min += offset; + title_max += offset; + box_min += offset; + box_max += offset; + } + + const bool bSelected = IsSelected(); + + if ( bShadow ) + surface()->DrawSetColor( NODE_DRAW_COLOR_SHADOW ); + else + { + Color colTitleNoShadow = NODE_DRAW_COLOR_TITLE; + if ( GetNumContainers() ) + colTitleNoShadow = NODE_DRAW_COLOR_HASCONTAINER_TITLE; + else if ( bSelected ) + colTitleNoShadow = NODE_DRAW_COLOR_SELECTED_TITLE; + surface()->DrawSetColor( colTitleNoShadow ); + } + + surface()->DrawFilledRect( title_min.x, title_min.y, title_max.x, title_max.y ); + + if ( !bShadow ) + { + Color boxNoShadow = NODE_DRAW_COLOR_BOX; + if ( bSelected ) + boxNoShadow = NODE_DRAW_COLOR_SELECTED_BOX; + else if ( GetNumSolvers() && !HasDummySolvers() ) + boxNoShadow = NODE_DRAW_COLOR_HASSOLVER_BOX; + else if ( GetNumContainers() ) + boxNoShadow = NODE_DRAW_COLOR_HASCONTAINER_BOX; + + surface()->DrawSetColor( boxNoShadow ); + } + + surface()->DrawFilledRect( box_min.x, box_min.y, box_max.x, box_max.y ); + + if ( bShadow ) + { + VguiDraw_Jacks( true ); + } + else + { + VguiDraw_Jacks( false ); + Color borderCol = NODE_DRAW_COLOR_BORDER; + if ( GetErrorLevel() == ERRORLEVEL_UNDEFINED ) + borderCol = DRAWCOLOR_ERRORLEVEL_UNDEFINED; + else if ( GetErrorLevel() == ERRORLEVEL_FAIL ) + borderCol = DRAWCOLOR_ERRORLEVEL_FAIL; + else if ( IsAllocating() ) + borderCol = NODE_DRAW_COLOR_HASSOLVER_BOX_ALLOC; + surface()->DrawSetColor( borderCol ); + + int borderSize = 1; + surface()->DrawFilledRect( title_min.x, title_min.y, title_max.x, title_min.y + borderSize ); + surface()->DrawFilledRect( title_min.x, title_max.y - borderSize, title_max.x, title_max.y ); + surface()->DrawFilledRect( title_min.x, title_min.y, title_min.x + borderSize, title_max.y ); + surface()->DrawFilledRect( title_max.x - borderSize, title_min.y, title_max.x, title_max.y ); + + surface()->DrawFilledRect( box_min.x, box_min.y, box_max.x, box_min.y + borderSize ); + surface()->DrawFilledRect( box_min.x, box_max.y - borderSize, box_max.x, box_max.y ); + surface()->DrawFilledRect( box_min.x, box_min.y, box_min.x + borderSize, box_max.y ); + surface()->DrawFilledRect( box_max.x - borderSize, box_min.y, box_max.x, box_max.y ); + + //float offsetTextBorder = m_vecSize.x - m_flMinSizeX; + + //if ( m_vecBorderInfo.x > 1 || m_vecBorderInfo.y IsPreviewEnabled() ) + if ( m_vecBorderInfo.x > 1 && ( IsPreviewVisible() ) ) + { + Vector2D DivideStart( m_vecPosition.x + m_vecBorderInfo.x, m_vecPosition.y ); + pNodeView->ToPanelSpace( DivideStart ); + surface()->DrawFilledRect( DivideStart.x, box_min.y, DivideStart.x + borderSize, box_max.y ); + } + if ( m_vecBorderInfo.y > 1 && ( m_vecBorderInfo.x > 1 || IsPreviewVisible() ) ) + { + Vector2D DivideStart( m_vecPosition.x + m_vecSize.x - m_vecBorderInfo.y, m_vecPosition.y ); + pNodeView->ToPanelSpace( DivideStart ); + surface()->DrawFilledRect( DivideStart.x, box_min.y, DivideStart.x + borderSize, box_max.y ); + } + } + + Vector2D titleMid = ( title_max - title_min ) * 0.5f + title_min; + + wchar_t szconverted[ 256 ]; + int fontWide, fontTall; + + if ( !bShadow ) + { + bool bDraw; + vgui::HFont hFont_Small = pNodeView->GetFontScaled(12,bDraw); + if ( bDraw ) + { + g_pVGuiLocalize->ConvertANSIToUnicode( szOpName, szconverted, sizeof(szconverted) ); + + surface()->DrawSetTextFont( hFont_Small ); + surface()->GetTextSize( hFont_Small, szconverted, fontWide, fontTall ); + surface()->DrawSetTextPos( titleMid.x - fontWide * 0.5f, titleMid.y - fontTall * 0.5f ); + + surface()->DrawSetTextColor( bSelected ? NODE_DRAW_COLOR_SELECTED_TEXT_OP : NODE_DRAW_COLOR_TEXT_OP ); + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } + + VguiDraw_Preview(); + } + + + if ( Q_strlen( szNodeName ) > 1 ) + { + surface()->DrawSetTextColor( bShadow ? NODE_DRAW_COLOR_SHADOW : NODE_DRAW_COLOR_CUSTOMTITLE ); + + bool bDraw; + vgui::HFont hFont_Small = pNodeView->GetFontScaled(18,bDraw); + if ( bDraw ) + { + g_pVGuiLocalize->ConvertANSIToUnicode( szNodeName, szconverted, sizeof(szconverted) ); + + surface()->DrawSetTextFont( hFont_Small ); + surface()->GetTextSize( hFont_Small, szconverted, fontWide, fontTall ); + surface()->DrawSetTextPos( title_min.x, title_min.y - fontTall - 3 * pNodeView->GetZoomScalar() ); + + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } + } + return true; +} +void CBaseNode::VguiDraw_Jacks( bool bShadow ) +{ + for ( int i = 0; i < m_hInputs.Count(); i++ ) + m_hInputs[ i ]->VguiDraw(bShadow); + for ( int i = 0; i < m_hOutputs.Count(); i++ ) + m_hOutputs[ i ]->VguiDraw(bShadow); +} +void CBaseNode::VguiDraw_Preview() +{ + if ( !IsPreviewVisible() ) + return; + + CUtlVector< CUtlVector< CHLSL_SolverBase* >* > hStackList; + hStackList.AddToTail( &pNodeView->AccessSolverStack_PS() ); + hStackList.AddToTail( &pNodeView->AccessSolverStack_UNDEFINED() ); + hStackList.AddToTail( &pNodeView->AccessSolverStack_POSTPROC() ); + + int puzzleIdx = -1; + for ( int i = 0; i < hStackList.Count() && puzzleIdx < 0; i++ ) + { + for ( int s = 0; s < hStackList[i]->Count() && puzzleIdx < 0; s++ ) + { + if ( hStackList[i]->Element(s)->GetData().iNodeIndex == GetUniqueIndex() ) + { + puzzleIdx = hStackList[i]->Element(s)->GetMapIndex(); + break; + } + } + } + + //if ( puzzleIdx < 0 ) + // return; + //Msg("own idx: %u - puzzle: %i\n",GetUniqueIndex(),puzzleIdx); + + float preview_inset = PREVIEWINSET; + + + Vector2D prev_min( m_vecPosition.x + m_vecBorderInfo.x + preview_inset, GetBoundsBoxMin().y - preview_inset ); + Vector2D prev_max( m_vecPosition.x + m_vecSize.x - m_vecBorderInfo.y - preview_inset, GetBoundsBoxMax().y + preview_inset ); + + float deltax = prev_max.x - prev_min.x; + float deltay = prev_min.y - prev_max.y; + float deltamin = min ( deltay, deltax ); + prev_min.y = prev_max.y + deltamin; + + Vector2D _mid = prev_min + ( prev_max - prev_min ) * 0.5f; + deltamin *= 0.5f; + prev_min = _mid - Vector2D( deltamin, -deltamin ); + prev_max = _mid + Vector2D( deltamin, -deltamin ); + + pNodeView->ToPanelSpace( prev_min ); + pNodeView->ToPanelSpace( prev_max ); + + if ( GetErrorLevel() == ERRORLEVEL_NONE && GetNumSolvers() && !GetSolver(0)->IsDummy() && sedit_2dprev_Enable.GetInt() ) + { + Vector2D a,b; + GetUVsForPuzzle(puzzleIdx,a,b,true); + surface()->DrawSetTexture( m_iPreviewMaterial ); + surface()->DrawSetColor( Color( 255,255,255,255 ) ); + surface()->DrawTexturedSubRect(prev_min.x,prev_min.y, + prev_max.x,prev_max.y, + a.x,a.y, + b.x,b.y ); + } + else + { + surface()->DrawSetColor( Color( 0,0,0,64 ) ); + surface()->DrawFilledRect( prev_min.x,prev_min.y, + prev_max.x,prev_max.y ); + } +} + +KeyValues *CBaseNode::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = new KeyValues( VarArgs("Node_%03i", NodeIndex) ); + + pKV->SetInt( "iType", GetNodeType() ); + if ( Q_strlen(szNodeName) ) + pKV->SetString( "szName", szNodeName ); + + pKV->SetFloat( "pos_x", m_vecPosition.x ); + pKV->SetFloat( "pos_y", m_vecPosition.y ); + pKV->SetFloat( "size_x", m_vecSize.x ); + pKV->SetFloat( "size_y", m_vecSize.y ); + pKV->SetInt( "iPreview", IsPreviewEnabled() ? 1 : 0 ); + + KeyValues *pKV_Bridges = new KeyValues( "bridges" ); + pKV->AddSubKey( pKV_Bridges ); + + for ( int i = 0; i < m_hInputs.Count(); i++ ) + { + CJack *j = m_hInputs[ i ]; + if ( j->GetNumBridges() ) + { + for ( int b = 0; b < j->GetNumBridges(); b++ ) + { + CBridge *pBridge = j->GetBridge( b ); + + KeyValues *pKV_Jack = new KeyValues( VarArgs( "jackIn_%02i", i ) ); + pKV_Bridges->AddSubKey( pKV_Jack ); + + CBaseNode *pTargetNode = pBridge->GetEndNode( this ); + CJack *pTargetJack = pBridge->GetEndJack( this ); + if ( pTargetJack && pTargetNode ) + { + int targetIndex_Node = pNodeView->GetNodeIndex( pTargetNode ); + int targetIndex_Jack = pTargetJack->GetSlot(); + + pKV_Jack->SetInt( "iTarget_node", targetIndex_Node ); + pKV_Jack->SetInt( "iTarget_jack", targetIndex_Jack ); + } + } + } + } + + return pKV; +} + +void CBaseNode::RestoreFromKeyValues( KeyValues *pKV ) +{ +// m_iType = pKV->GetInt( "iType" ); + Q_snprintf( szNodeName, sizeof(szNodeName), "%s", pKV->GetString( "szName" ) ); + + SetPosition( Vector2D( pKV->GetFloat( "pos_x" ), pKV->GetFloat( "pos_y" ) ) ); + m_vecSize.x = pKV->GetFloat( "size_x" ); + m_vecSize.y = pKV->GetFloat( "size_y" ); + m_bPreviewEnabled = !!pKV->GetInt( "iPreview" ); + + RestoreFromKeyValues_Specific( pKV ); + + //UpdatePreviewAllowed(); + UpdateSize(); +} +void CBaseNode::RestoreFromKeyValues_CreateBridges( KeyValues *pKV ) +{ + PurgeBridges( true, false ); + + KeyValues *pKV_Bridges = pKV->FindKey( "bridges" ); + if ( pKV_Bridges ) + { + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + KeyValues *pKV_Jack = pKV_Bridges->FindKey( VarArgs( "jackIn_%02i", i ) ); + if ( pKV_Jack ) + { + CJack *localJack = GetJack_In( i ); + + int iTGNode = pKV_Jack->GetInt( "iTarget_node" ); + int iTGJack = pKV_Jack->GetInt( "iTarget_jack" ); + + CBaseNode *tgNode = pNodeView->GetNodeFromIndex( iTGNode ); + CJack *tgJack = ( tgNode && tgNode->GetNumJacks_Out() > iTGJack ) ? tgNode->GetJack_Out( iTGJack ) : NULL; + + if ( tgNode && tgJack && localJack ) + { + tgJack->BridgeEndBuild( localJack->BridgeBeginBuild() ); + } + } + } + } +} diff --git a/sp/src/shadereditor/nodes/vbasenode.h b/sp/src/shadereditor/nodes/vbasenode.h new file mode 100644 index 00000000..95ad1402 --- /dev/null +++ b/sp/src/shadereditor/nodes/vbasenode.h @@ -0,0 +1,299 @@ +#ifndef CBASENODE_H +#define CBASENODE_H + +#include +#include +#include +#include +#include "ienginevgui.h" +#include "vgui_controls/Controls.h" + +class CJack; +class CBaseNode; +class CBaseContainerNode; +class CNodeView; + +#include "hlsl_solver.h" + +#define NODEDEFSIZE_SMALL 50.0f + +#define NODE_DRAW_TITLE_Y 15 +#define NODE_DRAW_TITLE_SPACE 3 +#define PREVIEWINSET 3.5f + +#define NODE_DRAW_COLOR_TITLE Color( 60, 60, 70, 255 ) +#define NODE_DRAW_COLOR_BOX Color( 110, 110, 110, 255 ) +#define NODE_DRAW_COLOR_BOX_COMMENT Color( 18, 18, 18, 255 ) +#define NODE_DRAW_COLOR_BORDER Color( 10, 10, 10, 255 ) +#define NODE_DRAW_COLOR_TEXT_OP Color( 150, 150, 100, 255 ) + +#define NODE_DRAW_COLOR_SELECTED_TITLE Color( 75, 75, 90, 255 ) +#define NODE_DRAW_COLOR_SELECTED_BOX Color( 220, 150, 110, 255 ) +#define NODE_DRAW_COLOR_SELECTED_BORDER Color( 10, 10, 10, 255 ) +#define NODE_DRAW_COLOR_SELECTED_TEXT_OP Color( 170, 170, 120, 255 ) + +#define NODE_DRAW_COLOR_HASSOLVER_BOX Color( 110, 118, 110, 255 ) +#define NODE_DRAW_COLOR_HASSOLVER_BOX_ALLOC Color( 110, 196, 110, 255 ) + +#define NODE_DRAW_COLOR_HASCONTAINER_TITLE Color( 70, 70, 100, 255 ) +#define NODE_DRAW_COLOR_HASCONTAINER_BOX Color( 110, 110, 148, 255 ) + +#define NODE_DRAW_COLOR_CUSTOMTITLE Color( 160, 150, 180, 255 ) // Color( 120, 110, 140, 255 ) + +class CBaseNode +{ + friend class CBaseContainerNode; + +public: + DECLARE_CLASS_NOBASE(CBaseNode); + + CBaseNode( const char *opName, CNodeView *p ); + virtual ~CBaseNode(); + + virtual void SetName( const char *opName ); + virtual const char *GetName(); + virtual const char *GetUserName(); + virtual int GetFinalTextSize(); + + virtual void Spawn(); + + const HNODE GetUniqueIndex(){ return m_iUniqueIndex; }; + + CNodeView *GetParent(){ return pNodeView; }; + + virtual CBaseContainerNode *GetAsContainer(){ return NULL; }; + virtual bool IsSolvable( bool bHierachyUp, + CUtlVector< CBaseNode* > *hCallerList = NULL, + CUtlVector< CBaseNode* > *hTested = NULL ); + + virtual const int GetAllowedFlowgraphTypes(); + +private: + CUtlVector< CBaseContainerNode* > m_hParentContainers; + bool RecursiveTestContainerError_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, + bool &bLeftContainerOnce, const bool &bHierachyUp, CBaseContainerNode *container ); + void ListContainersChronologically_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, + CUtlVector< CBaseContainerNode* > &hList ); + +protected: + virtual bool InsertToContainer( CBaseContainerNode *container ); // don't call directly + virtual bool RemoveFromContainer( CBaseContainerNode *container ); // don't call directly + +public: + bool RecursiveTestContainerError( const bool &bHierachyUp, CBaseContainerNode *container ); // true on error + virtual bool HasContainerParent( CBaseContainerNode *container ); + + virtual int GetNumContainers(); + virtual CBaseContainerNode *GetContainer( int idx ); + + virtual Vector2D GetContainerSensitiveCenter(); + virtual void ListContainersChronologically( CUtlVector< CBaseContainerNode* > &hList ); + + virtual bool CanBeInContainer(){ return true; }; + virtual void UpdateParentContainers(); + + virtual int GetNodeType(){ return HLSLNODE_INVALID; }; + virtual const bool IsNodeCrucial(){ return false; }; + virtual bool ShouldErrorOnUndefined(){ return false; }; + + virtual int PerNodeErrorLevel(){ return ERRORLEVEL_NONE; }; + virtual int TestJackFlags_In(); + + virtual bool VguiDraw( bool bShadow = false ); + virtual void VguiDraw_Jacks( bool bShadow = false ); + virtual void VguiDraw_Preview(); + + virtual void OnLeftClick( Vector2D &pos ); + virtual void OnDragStart(); + virtual void OnDrag( Vector2D &delta ); + virtual void OnDragEnd(); + virtual bool MustDragAlone(); + virtual bool IsWithinBounds_Base( const Vector2D &pos ); + + virtual Vector2D GetBoundsMin(); + virtual Vector2D GetBoundsMax(); + virtual Vector2D GetBoundsMinNodeSpace(); + virtual Vector2D GetBoundsMaxNodeSpace(); + virtual Vector2D GetSelectionBoundsMinNodeSpace(); + virtual Vector2D GetSelectionBoundsMaxNodeSpace(); + virtual Vector2D GetCenter(); + const virtual Vector4D &GetBoundsFast(); + + virtual Vector2D GetBoundsTitleMin(); + virtual Vector2D GetBoundsTitleMax(); + virtual Vector2D GetBoundsBoxMin(); + virtual Vector2D GetBoundsBoxMax(); + + virtual void SetPosition( Vector2D vec, bool bCenter = false ); + virtual Vector2D GetPosition(); + virtual Vector2D GetSize(); + + virtual void SetSelected( const bool b ){ bSelected = b; }; + virtual void ToggleSelection(){ bSelected = !bSelected; }; + virtual const bool IsSelected(){ return bSelected; }; + + virtual int GetHierachyType(); +private: + virtual int GetHierachyTypeIterateFullyRecursive_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, int *iAllowances = NULL ); + virtual void CheckHierachyTypeFullyRecursive_Internal( int t, CUtlVector< CBaseNode* > &m_hNodesProcessed ); + //virtual void OnUpdateHierachy_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, CBridge *pBridgeInitiator, CJack *pCaller ); + virtual void OnUpdateHierachy_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed ); + //CUtlVector< CBridge* > &m_hBridgesToUpdate, + //CUtlVector< CJack* > &m_hJacksToUpdate ); + virtual void SetTempHierachyTypeFullyRecursive_Internal( CUtlVector< CBaseNode* > &m_hNodesProcessed, int t ); + + int m_iTempHierachy; +protected: + bool m_bAllInputsRequired; +public: + virtual void OnUpdateHierachy( CBridge *pBridgeInitiator, CJack *pCaller ); + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + virtual void SetOutputsUndefined(); + virtual void OnShowSolverErrored(); + + virtual void PreSolverUpdated(){}; + virtual void PostSolverUpdated(){}; + + virtual int GetHierachyTypeIterateFullyRecursive( int *iAllowances = NULL ); + virtual void CheckHierachyTypeFullyRecursive( int t ); + virtual int GetAllowedHierachiesAsFlags(); + + virtual void UpdateBridgeValidity( CBridge *pBridge, CJack *pCaller, int inputErrorLevel ); + + virtual const int GetTempHierachyType(); + virtual void SetTempHierachyType( const int t ); + virtual void SetTempHierachyTypeFullyRecursive( const int t ); + + //virtual void OnBridgeConnect + virtual void GenerateJacks_Input( int num ); + virtual void GenerateJacks_Output( int num ); + virtual int GetNumJacks_Out(); + virtual int GetNumJacks_In(); + virtual CJack* GetJack_Out( int i ); + virtual CJack* GetJack_In( int i ); + virtual int GetNumJacks_Out_Connected(); + virtual int GetNumJacks_In_Connected(); + CJack *GetJackByName_Out( const char *name ); + CJack *GetJackByName_In( const char *name ); + CJack *GetJackByResType_Out( int restype ); + CJack *GetJackByResType_In( int restype ); + virtual bool JacksAllConnected_Out(); + virtual bool JacksAllConnected_In(); + virtual void JackHierachyUpdate_Out(); + virtual CHLSL_Var *GetInputToWriteTo( int varTypes ); + + virtual void PurgeBridges( bool bInputs = true, bool bOutputs = true ); + enum BridgeRestoreMode + { + BY_INDEX = 0, + BY_NAME, + BY_RESTYPE, + BY_COUNT, + }; + void CreateBridgeRestoreData_Out( BridgeRestoreMode mode, CUtlVector< BridgeRestoreInfo* > &m_hList ); + void CreateBridgeRestoreData_In( BridgeRestoreMode mode, CUtlVector< BridgeRestoreInfo* > &m_hList ); + void RestoreBridgesFromList_Out( CUtlVector< BridgeRestoreInfo* > &m_hList ); + void RestoreBridgesFromList_In( CUtlVector< BridgeRestoreInfo* > &m_hList ); + + virtual void UpdateSize(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues( KeyValues *pKV ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ){}; + virtual void RestoreFromKeyValues_CreateBridges( KeyValues *pKV ); + +private: + bool RecursiveFindNode_Internal( CUtlVector< CBaseNode* > &m_hList, CBaseNode *n, bool bHierachyUp ); + void Recursive_AddTailNodes_Internal( CUtlVector< CBaseNode* > &m_hProcessedNodes, + CUtlVector< CBaseNode* > &m_hList, + bool bHierachyUp, bool bOnlyWithoutSolver, CBaseContainerNode *pContainer, bool bAddContainers ); +public: + bool RecursiveFindNode( CBaseNode *n, bool bHierachyUp ); + void Recursive_AddTailNodes( CUtlVector< CBaseNode* > &m_hList, bool bHierachyUp, + bool bOnlyWithoutSolver = false, CBaseContainerNode *pContainer = NULL, bool bAddContainers = false ); + + const int GetErrorLevel(); + void SetErrorLevel( const int e ); + + virtual const bool IsPreviewEnabled(){ return m_bPreviewEnabled; }; + virtual bool IsPreviewVisible(); + void UpdatePreviewAllowed(); + + void SetAllocating( const bool &a ); + bool IsAllocating(); + +protected: + bool m_bIsAllocating; + + bool m_bAllowPreview; + bool m_bPreviewEnabled; + float m_flMinSizeX; + float m_flMinSizeY; + float m_flMinSizeY_VS; + float m_flMinSizePREVIEW_X; + + HNODE m_iUniqueIndex; + static HNODE m_iUniqueIndexCount; + + Vector2D m_vecBorderInfo; + Vector2D m_vecPosition; + Vector2D m_vecSize; + Vector4D m_vecBounds; + + char szOpName[MAX_PATH]; + char szNodeName[MAX_PATH]; + + CNodeView *pNodeView; + + bool bSelected; + int iErrorLevel; + + CUtlVector< CJack* >m_hInputs; + CUtlVector< CJack* >m_hOutputs; + void TouchJacks(); + + void SetJackFlags( CJack *j, HLSLJackVarCluster mode ); + void SetJackFlags_Input( int idx, HLSLJackVarCluster mode ); + void SetJackFlags_Output( int idx, HLSLJackVarCluster mode ); + void SetJackFlags_MinFloatRequirement( CJack *j, int components ); + void SetJackFlags_Input_Flags( int idx, int Flags ); + void SetJackFlags_Output_Flags( int idx, int Flags ); + + void SetupJackOutput( int idx, HLSLJackVarCluster mode, const char *name ); + void SetupJackInput( int idx, HLSLJackVarCluster mode, const char *name ); + + // these lock smarttype!!! + void LockJackOutput_Flags( int idx, int Flag, const char *name = NULL ); + void LockJackInput_Flags( int idx, int Flag, const char *name = NULL ); + +public: + void AddSolver( CHLSL_SolverBase *solver ); + virtual void RemoveSolvers( bool bDelete = true ); + bool InvokeCreateSolvers( GenericShaderData *ShaderData ); + virtual void SmartCreateDummySolver(); + + const CUtlVector< CHLSL_SolverBase* > *GetSolvers(); + CHLSL_SolverBase *GetSolver( int idx ); + const int GetNumSolvers(); + bool HasDummySolvers(); + + void SweepJackHlslCache(); + + void MarkForDeletion(); + const bool IsMarkedForDeletion(); + +protected: + virtual bool CreateSolvers( GenericShaderData *ShaderData ); + CUtlVector< CHLSL_SolverBase* > m_hLocalSolvers; + + int m_iPreviewMaterial; + +private: + + bool m_bMarkedForDeletion; +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_add.cpp b/sp/src/shadereditor/nodes/vnode_add.cpp new file mode 100644 index 00000000..eef0b78c --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_add.cpp @@ -0,0 +1,93 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeAdd::CNodeAdd( CNodeView *p ) : BaseClass( "Add", p ) +{ + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "A" ); + GetJack_In( 1 )->SetName( "B" ); +} + +CNodeAdd::~CNodeAdd() +{ +} + +int CNodeAdd::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + locallevel = ERRORLEVEL_FAIL; + } + else if ( vartype_jack_0 >= HLSLVAR_MATRIX3X3 || + vartype_jack_1 >= HLSLVAR_MATRIX3X3 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeAdd::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( max( GetJack_In(0)->GetSmartType(), GetJack_In(1)->GetSmartType() ) ); +} +bool CNodeAdd::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type1 = pJ1->GetSmartType(); + int type2 = pJ2->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + //if ( type1 != type2 && + // type1 != HLSLVAR_FLOAT1 && + // type2 != HLSLVAR_FLOAT1 ) + // return false; + + CHLSL_Var *tg = GetInputToWriteTo( max( type1, type2 ) ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Add *solver = new CHLSL_Solver_Add( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + //Msg("add solver has %i src vars\n", solver->GetNumSourceVars()); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_add.h b/sp/src/shadereditor/nodes/vnode_add.h new file mode 100644 index 00000000..2066d478 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_add.h @@ -0,0 +1,26 @@ +#ifndef CNODEADD_H +#define CNODEADD_H + +#include "vBaseNode.h" + +class CNodeAdd : public CBaseNode +{ + DECLARE_CLASS( CNodeAdd, CBaseNode ); + +public: + + CNodeAdd( CNodeView *p ); + ~CNodeAdd(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_ADD; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_array.cpp b/sp/src/shadereditor/nodes/vnode_array.cpp new file mode 100644 index 00000000..0cc19fd4 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_array.cpp @@ -0,0 +1,132 @@ + +#include "cbase.h" +#include "editorcommon.h" + +CNodeArray::CNodeArray( CNodeView *p ) : BaseClass( "Array", p ) +{ + m_iSize_X = 6; + m_iSize_Y = 1; + + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + m_iDataTypeFlag = HLSLVAR_FLOAT1; + m_vecValues = new Vector4D[ m_iSize_X * m_iSize_Y ]; + Q_memset( m_vecValues, 0, sizeof( Vector4D ) * ( m_iSize_X * m_iSize_Y ) ); + + GenerateJacks_Output( 1 ); + + UpdateNode(); +} + +//CNodeArray::CNodeArray( const CNodeArray &other ) : BaseClass( other ) +//{ +// m_iSize_X = other.m_iSize_X; +// m_iSize_Y = other.m_iSize_Y; +// +// m_iDataTypeFlag = other.m_iDataTypeFlag; +// m_vecValues = NULL; +// +// if ( other.m_vecValues ) +// { +// int vecSize = m_iSize_X * m_iSize_Y; +// m_vecValues = new Vector4D[ vecSize ]; +// Q_memcpy( m_vecValues, other.m_vecValues, sizeof( Vector4D ) * vecSize ); +// } +//} + +CNodeArray::~CNodeArray() +{ + delete [] m_vecValues; +} + +void CNodeArray::UpdateNode() +{ + const bool bIs2D = m_iSize_Y > 1; + + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_INDEX, m_hRestoreBridges ); + + GenerateJacks_Input( bIs2D ? 2 : 1 ); + + if ( bIs2D ) + { + LockJackInput_Flags( 0, HLSLVAR_FLOAT1, "X" ); + LockJackInput_Flags( 1, HLSLVAR_FLOAT1, "Y" ); + } + else + LockJackInput_Flags( 0, HLSLVAR_FLOAT1, "X" ); + + RestoreBridgesFromList_In( m_hRestoreBridges ); + + LockJackOutput_Flags( 0, m_iDataTypeFlag, "Var" ); +} + +KeyValues *CNodeArray::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "i_array_size_x", m_iSize_X ); + pKV->SetInt( "i_array_size_y", m_iSize_Y ); + pKV->SetInt( "i_array_datatype", m_iDataTypeFlag ); + + const int arraySize = m_iSize_X * m_iSize_Y; + char tmp[ MAX_PATH ]; + for ( int i = 0; i < arraySize; i++ ) + { + const Vector4D &vec = m_vecValues[ i ]; + Q_snprintf( tmp, sizeof( tmp ), "%f %f %f %f", vec[0], vec[1], vec[2], vec[3] ); + pKV->SetString( VarArgs( "pfl_arraydata_%03i", i ), tmp ); + } + + return pKV; +} +void CNodeArray::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iSize_X = pKV->GetInt( "i_array_size_x", m_iSize_X ); + m_iSize_Y = pKV->GetInt( "i_array_size_y", m_iSize_Y ); + m_iDataTypeFlag = pKV->GetInt( "i_array_datatype", m_iDataTypeFlag ); + + delete [] m_vecValues; + const int arraySize = m_iSize_X * m_iSize_Y; + m_vecValues = new Vector4D[ arraySize ]; + ::SimpleTokenize tokens; + for ( int i = 0; i < arraySize; i++ ) + { + const char *szData = pKV->GetString( VarArgs( "pfl_arraydata_%03i", i ) ); + tokens.Tokenize( szData ); + m_vecValues[i].Init(); + for ( int t = 0; t < tokens.Count() && t < 4; t++ ) + { + float flVal = atof( tokens.GetToken( t ) ); + m_vecValues[i][t] = flVal; + } + } + + UpdateNode(); + OnUpdateHierachy( NULL, NULL ); +} + +bool CNodeArray::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + if ( m_iSize_X < 1 || m_iSize_Y < 1 || m_vecValues == NULL ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_Array *solver = new CHLSL_Solver_Array( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( ::GetVarFlagsVarValue( m_iDataTypeFlag ), m_iSize_X, m_iSize_Y, m_vecValues ); + solver->AddTargetVar( tg ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In( i )->GetTemporaryVarTarget_End() ); + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_array.h b/sp/src/shadereditor/nodes/vnode_array.h new file mode 100644 index 00000000..9d926ea6 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_array.h @@ -0,0 +1,37 @@ +#ifndef CNODEARRAY_H +#define CNODEARRAY_H + +#include "vBaseNode.h" + +class CNodeArray : public CBaseNode +{ + DECLARE_CLASS( CNodeArray, CBaseNode ); + +public: + CNodeArray( CNodeView *p ); + ~CNodeArray(); + + void UpdateNode(); + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_ARRAY; }; + + //virtual int UpdateInputsValid(); + //virtual void UpdateOutputs(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + //CNodeArray( const CNodeArray &other ){}; + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iSize_X; + int m_iSize_Y; + + int m_iDataTypeFlag; + + Vector4D *m_vecValues; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_baseevaluate.cpp b/sp/src/shadereditor/nodes/vnode_baseevaluate.cpp new file mode 100644 index 00000000..062c0196 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_baseevaluate.cpp @@ -0,0 +1,114 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeBaseEvaluate::CNodeBaseEvaluate( const char *name, CNodeView *p, int LockOutput, int numInputs, bool bSmall, int LockInput ) : BaseClass( name, p ) +{ + if ( bSmall ) + { + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + } + GenerateJacks_Input( numInputs ); + GenerateJacks_Output( 1 ); + + if ( LockOutput > 0 ) + LockJackOutput_Flags( 0, LockOutput ); + else + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + HLSLJackVarCluster LockInType = (HLSLJackVarCluster)(( LockInput < 0 ) ? HLSLJACKFLAGS_ALL : LockInput); + Assert( LockInType >= HLSLJACKFLAGS_F1 && LockInType < HLSLJACKFLAGS_ ); + + for ( int i = 0; i < numInputs; i++ ) + { + SetJackFlags_Input( i, LockInType ); + } + + if ( numInputs == 1 ) + GetJack_In( 0 )->SetName( "In" ); + else + { + int start = (int)'A'; + for ( int i = 0; i < numInputs; i++ ) + { + char tmp[2]; + Q_snprintf( tmp, 2, "%c", start ); + GetJack_In( i )->SetName( tmp ); + start++; + } + } +} + +CNodeBaseEvaluate::~CNodeBaseEvaluate() +{ +} + +int CNodeBaseEvaluate::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = TestJackFlags_In(); + + if ( GetNumJacks_In() > 1 && locallevel == ERRORLEVEL_NONE ) + { + int typeTest = GetJack_In(0)->GetSmartType(); + for ( int i = 1; i < GetNumJacks_In(); i++ ) + { + int curType = GetJack_In(i)->GetSmartType(); + if ( typeTest != HLSLVAR_FLOAT1 && + curType != HLSLVAR_FLOAT1 && + typeTest != curType ) + locallevel = ERRORLEVEL_FAIL; + + if ( typeTest > HLSLVAR_FLOAT4 || + curType > HLSLVAR_FLOAT4 ) + locallevel = ERRORLEVEL_FAIL; + + if ( typeTest == HLSLVAR_FLOAT1 ) + typeTest = curType; + } + } + + return max( locallevel, baseLevel ); +} +void CNodeBaseEvaluate::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() || GetJack_Out(0)->IsSmartTypeLocked() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + int maxType = GetJack_In(0)->GetSmartType(); + for ( int i = 1; i < GetNumJacks_In(); i++ ) + maxType = max( maxType, GetJack_In(i)->GetSmartType() ); + GetJack_Out( 0 )->SetSmartType( maxType ); +} +bool CNodeBaseEvaluate::CreateSolvers(GenericShaderData *ShaderData) +{ + int numIn = GetNumJacks_In(); + if ( GetNumJacks_In_Connected() < numIn ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + + int targettype = pJ_Out->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( targettype ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_SolverBase *solver = AllocRangeSolver(); + solver->SetResourceType( res ); + for ( int i = 0; i < numIn; i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} diff --git a/sp/src/shadereditor/nodes/vnode_baseevaluate.h b/sp/src/shadereditor/nodes/vnode_baseevaluate.h new file mode 100644 index 00000000..03492ef6 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_baseevaluate.h @@ -0,0 +1,86 @@ +#ifndef CNODE_NORMALIZE_H +#define CNODE_NORMALIZE_H + +#include "vBaseNode.h" + +class CNodeBaseEvaluate : public CBaseNode +{ + DECLARE_CLASS( CNodeBaseEvaluate, CBaseNode ); + +public: + + CNodeBaseEvaluate( const char *name, CNodeView *p, int LockOutput, int numInputs = 1, bool bSmall = false, int LockInput = -1 ); + ~CNodeBaseEvaluate(); + + virtual int GetNodeType(){ Assert(0); return HLSLNODE_MATH_NORMALIZE; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); +protected: + virtual CHLSL_SolverBase *AllocRangeSolver(){ Assert(0); return NULL; }; + +}; + +#define CREATE_EVALUATE_NODE( className, nodeName, nodeType, solverclassName, lockType, numIn, isSmall, lockTypeIn ) class className : public CNodeBaseEvaluate\ +{\ + DECLARE_CLASS( className, CNodeBaseEvaluate );\ +public:\ + className( CNodeView *p ) : BaseClass( #nodeName, p, lockType, numIn, isSmall, lockTypeIn ){};\ + virtual int GetNodeType(){ return nodeType; };\ +protected:\ + virtual CHLSL_SolverBase *AllocRangeSolver(){ return new solverclassName( GetUniqueIndex() ); };\ +} +#define CREATE_EVALUATE_NODE_FAST( name, nodeType, lockType ) CREATE_EVALUATE_NODE( CNode##name, name, nodeType, CHLSL_Solver_##name, lockType, 1, false, -1 ) +#define CREATE_EVALUATE_NODE_FAST_SETIN( name, nodeType, lockType, numIn ) CREATE_EVALUATE_NODE( CNode##name, name, nodeType, CHLSL_Solver_##name, lockType, numIn, false, -1 ) + +#define CREATE_EVALUATE_NODE_FAST_SMALL( name, nodeType, lockType ) CREATE_EVALUATE_NODE( CNode##name, name, nodeType, CHLSL_Solver_##name, lockType, 1, true, -1 ) +#define CREATE_EVALUATE_NODE_FAST_SETIN_SMALL( name, nodeType, lockType, numIn ) CREATE_EVALUATE_NODE( CNode##name, name, nodeType, CHLSL_Solver_##name, lockType, numIn, true, -1 ) + +#define CREATE_EVALUATE_NODE_FAST_SETIN_SMALL_LOCKIN( name, nodeType, lockType, numIn, lockTypeIn ) CREATE_EVALUATE_NODE( CNode##name, name, nodeType, CHLSL_Solver_##name, lockType, numIn, true, lockTypeIn ) + +//CREATE_EVALUATE_NODE( CNodeNormalize, Normalize, HLSLNODE_MATH_NORMALIZE, CHLSL_Solver_Normalize, 0 ); + +CREATE_EVALUATE_NODE_FAST( Normalize, HLSLNODE_MATH_NORMALIZE, 0 ); +CREATE_EVALUATE_NODE_FAST( Length, HLSLNODE_MATH_LENGTH, HLSLVAR_FLOAT1 ); +CREATE_EVALUATE_NODE_FAST( Round, HLSLNODE_MATH_ROUND, 0 ); +CREATE_EVALUATE_NODE_FAST( Fraction, HLSLNODE_MATH_FRAC, 0 ); +CREATE_EVALUATE_NODE_FAST( Floor, HLSLNODE_MATH_FLOOR, 0 ); +CREATE_EVALUATE_NODE_FAST( Ceil, HLSLNODE_MATH_CEIL, 0 ); +CREATE_EVALUATE_NODE_FAST( Abs, HLSLNODE_MATH_ABS, 0 ); +CREATE_EVALUATE_NODE_FAST( Saturate, HLSLNODE_MATH_SATURATE, 0 ); +CREATE_EVALUATE_NODE_FAST( Root, HLSLNODE_MATH_SQRT, 0 ); + +CREATE_EVALUATE_NODE_FAST_SMALL( Degrees, HLSLNODE_MATH_DEGREES, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( Radians, HLSLNODE_MATH_RADIANS, 0 ); +CREATE_EVALUATE_NODE_FAST( Sign, HLSLNODE_MATH_SIGN, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( Log, HLSLNODE_MATH_LOG, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( Log2, HLSLNODE_MATH_LOG2, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( Log10, HLSLNODE_MATH_LOG10, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( Exp, HLSLNODE_MATH_EXP, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( Exp2, HLSLNODE_MATH_EXP2, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( ddx, HLSLNODE_MATH_DDX, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( ddy, HLSLNODE_MATH_DDY, 0 ); + +CREATE_EVALUATE_NODE_FAST_SETIN( Power, HLSLNODE_MATH_POW, 0, 2 ); +CREATE_EVALUATE_NODE_FAST_SETIN( Step, HLSLNODE_MATH_STEP, 0, 2 ); +CREATE_EVALUATE_NODE_FAST_SETIN( Min, HLSLNODE_MATH_MIN, 0, 2 ); +CREATE_EVALUATE_NODE_FAST_SETIN( Max, HLSLNODE_MATH_MAX, 0, 2 ); +CREATE_EVALUATE_NODE_FAST_SETIN( FMod, HLSLNODE_MATH_FMOD, 0, 2 ); + +CREATE_EVALUATE_NODE_FAST_SMALL( Sin, HLSLNODE_MATH_SIN, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( ASin, HLSLNODE_MATH_ASIN, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( SinH, HLSLNODE_MATH_SINH, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( Cos, HLSLNODE_MATH_COS, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( ACos, HLSLNODE_MATH_ACOS, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( CosH, HLSLNODE_MATH_COSH, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( Tan, HLSLNODE_MATH_TAN, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( ATan, HLSLNODE_MATH_ATAN, 0 ); +CREATE_EVALUATE_NODE_FAST_SMALL( TanH, HLSLNODE_MATH_TANH, 0 ); +CREATE_EVALUATE_NODE_FAST_SETIN_SMALL( ATan2, HLSLNODE_MATH_ATAN2, 0, 2 ); + +CREATE_EVALUATE_NODE_FAST_SETIN_SMALL_LOCKIN( Distance, HLSLNODE_VECTOR_DISTANCE, HLSLVAR_FLOAT1, 2, HLSLJACKFLAGS_F1_TO_F4 ); + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_baserange.cpp b/sp/src/shadereditor/nodes/vnode_baserange.cpp new file mode 100644 index 00000000..b090b8c5 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_baserange.cpp @@ -0,0 +1,102 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeBaseRange::CNodeBaseRange( const char *name, CNodeView *p ) : BaseClass( name, p ) +{ + GenerateJacks_Input( 3 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 2, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "min" ); + GetJack_In( 1 )->SetName( "max" ); + GetJack_In( 2 )->SetName( "value" ); +} + +CNodeBaseRange::~CNodeBaseRange() +{ +} + +int CNodeBaseRange::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + int vartype_jack_2 = GetJack_In( 2 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != HLSLVAR_FLOAT1 && + vartype_jack_0 != vartype_jack_2 ) + locallevel = ERRORLEVEL_FAIL; + if ( vartype_jack_1 != HLSLVAR_FLOAT1 && + vartype_jack_1 != vartype_jack_2 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeBaseRange::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( GetJack_In(2)->GetSmartType() ); +} +bool CNodeBaseRange::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 3 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ3 = GetJack_In( 2 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type3 = pJ3->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( type3 ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_SolverBase *solver = AllocRangeSolver(); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ3->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} + + +CNodeSmoothstep::CNodeSmoothstep( CNodeView *p ) : BaseClass( "Smooth step", p ) +{ +} +CHLSL_SolverBase *CNodeSmoothstep::AllocRangeSolver() +{ + return new CHLSL_Solver_Smoothstep( GetUniqueIndex() ); +} +CNodeClamp::CNodeClamp( CNodeView *p ) : BaseClass( "Clamp", p ) +{ +} +CHLSL_SolverBase *CNodeClamp::AllocRangeSolver() +{ + return new CHLSL_Solver_Clamp( GetUniqueIndex() ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_baserange.h b/sp/src/shadereditor/nodes/vnode_baserange.h new file mode 100644 index 00000000..d9d48e10 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_baserange.h @@ -0,0 +1,48 @@ +#ifndef CNODE_BASERANGE_H +#define CNODE_BASERANGE_H + +#include "vBaseNode.h" + +class CNodeBaseRange : public CBaseNode +{ + DECLARE_CLASS( CNodeBaseRange, CBaseNode ); + +public: + + CNodeBaseRange( const char *name, CNodeView *p ); + ~CNodeBaseRange(); + + virtual int GetNodeType(){ return HLSLNODE_INVALID; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +protected: + virtual CHLSL_SolverBase *AllocRangeSolver(){ Assert(0); return NULL; }; + +}; + + +class CNodeSmoothstep : public CNodeBaseRange +{ + DECLARE_CLASS( CNodeSmoothstep, CNodeBaseRange ); +public: + CNodeSmoothstep( CNodeView *p ); + virtual int GetNodeType(){ return HLSLNODE_MATH_SMOOTHSTEP; }; +protected: + virtual CHLSL_SolverBase *AllocRangeSolver(); +}; +class CNodeClamp : public CNodeBaseRange +{ + DECLARE_CLASS( CNodeClamp, CNodeBaseRange ); +public: + CNodeClamp( CNodeView *p ); + virtual int GetNodeType(){ return HLSLNODE_MATH_CLAMP; }; +protected: + virtual CHLSL_SolverBase *AllocRangeSolver(); +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_break.cpp b/sp/src/shadereditor/nodes/vnode_break.cpp new file mode 100644 index 00000000..7ea0bf9c --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_break.cpp @@ -0,0 +1,151 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeBreak::CNodeBreak( CNodeView *p ) : BaseClass( "Break", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = 0; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + m_bAllInputsRequired = false; + + GenerateJacks_Input( 1 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_ALL ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_ALL ); +} + +CNodeBreak::~CNodeBreak() +{ +} + +void CNodeBreak::UpdateNode() +{ + int iJacksRequired = 1; + for ( int i = 0; i < max( GetNumJacks_In(), GetNumJacks_Out() ); i++ ) + { + const bool bJackInValid = i < GetNumJacks_In(); + const bool bJackOutValid = i < GetNumJacks_Out(); + if ( bJackInValid && GetJack_In( i )->GetNumBridgesConnected() ) + iJacksRequired++; + else if ( bJackOutValid && GetJack_Out( i )->GetNumBridgesConnected() ) + iJacksRequired++; + } + + //CUtlVector< int >hSmartTypes_Out; + //for ( int i = 0; i < GetNumJacks_Out(); i++ ) + // hSmartTypes_Out.AddToTail( GetJack_Out(i)->GetSmartType() ); + + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges_In; + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges_Out; + CreateBridgeRestoreData_In( CBaseNode::BY_COUNT, m_hRestoreBridges_In ); + CreateBridgeRestoreData_Out( CBaseNode::BY_COUNT, m_hRestoreBridges_Out ); + + GenerateJacks_Input( iJacksRequired ); + GenerateJacks_Output( iJacksRequired ); + + RestoreBridgesFromList_In( m_hRestoreBridges_In ); + RestoreBridgesFromList_Out( m_hRestoreBridges_Out ); + + //for ( int i = 0; i < GetNumJacks_Out(); i++ ) + // GetJack_Out( i )->SetSmartType( hSmartTypes_Out[i] ); + //hSmartTypes_Out.Purge(); + + OnUpdateHierachy( NULL, NULL ); +} + +void CNodeBreak::PreSolverUpdated() +{ + UpdateNode(); +} +void CNodeBreak::PostSolverUpdated() +{ +} +int CNodeBreak::UpdateInputsValid() +{ + return BaseClass::UpdateInputsValid(); +} +void CNodeBreak::UpdateOutputs() +{ + if ( GetNumJacks_Out() != GetNumJacks_In() ) + return SetOutputsUndefined(); + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + if ( GetJack_In( i )->GetNumBridgesConnected() < 1 ) + break; + int iSmartTypeIn = GetJack_In( i )->GetSmartType(); + if ( iSmartTypeIn < 0 ) + return SetOutputsUndefined(); + GetJack_Out( i )->SetSmartType( iSmartTypeIn ); + } +} +bool CNodeBreak::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_Out() != GetNumJacks_In() ) + return false; + + CHLSL_Solver_Break *solver = new CHLSL_Solver_Break( GetUniqueIndex() ); + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJ_In = GetJack_In( i ); + if ( pJ_In->GetNumBridgesConnected() < 1 ) + break; + GetJack_Out( i )->SetTemporaryVarTarget( pJ_In->GetTemporaryVarTarget_End() ); + } + + AddSolver( solver ); + return true; +} + + + + +CNodeClip::CNodeClip( CNodeView *p ) : BaseClass( "Clip", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = 0; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Input( 1 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_ALL ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_ALL ); +} +CNodeClip::~CNodeClip() +{ +} +void CNodeClip::UpdateOutputs() +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + if ( GetJack_In( i )->GetNumBridgesConnected() < 1 ) + break; + int iSmartTypeIn = GetJack_In( i )->GetSmartType(); + if ( iSmartTypeIn < 0 ) + return SetOutputsUndefined(); + GetJack_Out( i )->SetSmartType( iSmartTypeIn ); + } +} +bool CNodeClip::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_In_0 = GetJack_In( 0 ); + CJack *pJ_Out_0 = GetJack_Out( 0 ); + + CHLSL_Var *pt = pJ_In_0->GetTemporaryVarTarget_End(); + + pJ_Out_0->SetTemporaryVarTarget( pt ); + + CHLSL_Solver_Clip *solver = new CHLSL_Solver_Clip( GetUniqueIndex() ); + solver->AddSourceVar( pt ); + solver->AddTargetVar( pt ); + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_break.h b/sp/src/shadereditor/nodes/vnode_break.h new file mode 100644 index 00000000..041c4321 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_break.h @@ -0,0 +1,60 @@ +#ifndef CNODE_BREAK_H +#define CNODE_BREAK_H + +#include "vBaseNode.h" + +class CNodeBreak : public CBaseNode +{ + DECLARE_CLASS( CNodeBreak, CBaseNode ); + +public: + + CNodeBreak( CNodeView *p ); + ~CNodeBreak(); + + virtual int GetNodeType(){ return HLSLNODE_CONTROLFLOW_BREAK; }; + + virtual void UpdateNode(); + + //virtual void OnUpdateHierachy( CBridge *pBridgeInitiator, CJack *pCaller ); + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + virtual void PreSolverUpdated(); + virtual void PostSolverUpdated(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + +class CNodeClip : public CBaseNode +{ + DECLARE_CLASS( CNodeClip, CBaseNode ); + +public: + + CNodeClip( CNodeView *p ); + ~CNodeClip(); + + virtual int GetNodeType(){ return HLSLNODE_CONTROLFLOW_CLIP; }; + + //virtual void UpdateNode(); + + //virtual void OnUpdateHierachy( CBridge *pBridgeInitiator, CJack *pCaller ); + //virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_callback.cpp b/sp/src/shadereditor/nodes/vnode_callback.cpp new file mode 100644 index 00000000..4e5d7295 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_callback.cpp @@ -0,0 +1,100 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeCallback::CNodeCallback( CNodeView *p ) : BaseClass( "Callback", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + szCallbackName = NULL; + iNumComponents = 1; + + UpdateNode(); +} + +CNodeCallback::~CNodeCallback() +{ + delete [] szCallbackName; +} + +void CNodeCallback::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_Out( CBaseNode::BY_INDEX, m_hRestoreBridges ); + + if ( !szCallbackName ) + { + GenerateJacks_Output( 0 ); + + SaveDeleteVector( m_hRestoreBridges ); + return; + } + + GenerateJacks_Output( 1 ); + int flag = ::GetVarTypeFlag( iNumComponents - 1 ); + LockJackOutput_Flags( 0, flag, szCallbackName ); + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} + +KeyValues *CNodeCallback::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetString( "sz_callbackname", szCallbackName ); + pKV->SetInt( "i_numc", iNumComponents ); + return pKV; +} +void CNodeCallback::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + const char *cbname = pKV->GetString( "sz_callbackname" ); + + if ( Q_strlen( cbname ) ) + { + delete [] szCallbackName; + szCallbackName = new char [ Q_strlen( cbname ) + 1 ]; + Q_strcpy( szCallbackName, cbname ); + } + + iNumComponents = pKV->GetInt( "i_numc", iNumComponents ); + + UpdateNode(); + OnUpdateHierachy( NULL, NULL ); +} + +int CNodeCallback::UpdateInputsValid() +{ + if ( !szCallbackName || !Q_strlen( szCallbackName ) ) + return ERRORLEVEL_UNDEFINED; + if ( shaderEdit->FindCallback( szCallbackName ) < 0 ) + return ERRORLEVEL_UNDEFINED; + + return BaseClass::UpdateInputsValid(); +} + +bool CNodeCallback::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( !szCallbackName || !Q_strlen( szCallbackName ) || !iNumComponents ) + return false; + int target = shaderEdit->FindCallback( szCallbackName ); + if ( target < 0 ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + + const int res = pJ_Out->GetResourceType(); + + SetAllocating( true ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_Callback *solver = new CHLSL_Solver_Callback( GetUniqueIndex() ); + solver->SetState( target, szCallbackName, iNumComponents ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_callback.h b/sp/src/shadereditor/nodes/vnode_callback.h new file mode 100644 index 00000000..7ea3e46c --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_callback.h @@ -0,0 +1,31 @@ +#ifndef CNODE_CALLBACK_H +#define CNODE_CALLBACK_H + +#include "vBaseNode.h" + +class CNodeCallback : public CBaseNode +{ + DECLARE_CLASS( CNodeCallback, CBaseNode ); + +public: + + CNodeCallback( CNodeView *p ); + ~CNodeCallback(); + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_CALLBACK; }; + + void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + virtual int UpdateInputsValid(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + char *szCallbackName; + int iNumComponents; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_combo.cpp b/sp/src/shadereditor/nodes/vnode_combo.cpp new file mode 100644 index 00000000..37786def --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_combo.cpp @@ -0,0 +1,98 @@ + +#include "cbase.h" +#include "editorcommon.h" + + +CNodeCombo::CNodeCombo( CNodeView *p ) : BaseClass( "Combo", p ) +{ + m_iCondition = ITERATORCOND_EQUAL; + m_iValue_Compare = 0; + m_bStatic = false; + + const char *defname = "UNKNOWNCOMBO"; + m_szComboName = new char [Q_strlen( defname ) + 1]; + Q_strcpy( m_szComboName, defname ); +} + +CNodeCombo::~CNodeCombo() +{ + delete [] m_szComboName; +} + +void CNodeCombo::Solve_ContainerEntered() +{ + CHLSL_Solver_ComboIntro *solver_intro = new CHLSL_Solver_ComboIntro( GetUniqueIndex() ); + solver_intro->SetState( m_iCondition, m_szComboName, m_iValue_Compare, m_bStatic ); + AddSolver( solver_intro ); + + CHLSL_Solver_ContainerBasic *solver_dummy = new CHLSL_Solver_ContainerBasic( GetUniqueIndex() ); + AddSolver( solver_dummy ); +} +void CNodeCombo::Solve_ContainerLeft() +{ + CHLSL_Solver_ComboOutro *solver_outro = new CHLSL_Solver_ComboOutro( GetUniqueIndex() ); + AddSolver( solver_outro ); +} + +KeyValues *CNodeCombo::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "i_combo_condition", m_iCondition ); + pKV->SetInt( "i_combo_value", m_iValue_Compare ); + pKV->SetInt( "i_combo_static", m_bStatic ? 1 : 0 ); + if ( Q_stricmp( "UNKNOWNCOMBO", m_szComboName ) ) + pKV->SetString( "sz_cname", m_szComboName ); + + return pKV; +} +void CNodeCombo::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + BaseClass::RestoreFromKeyValues_Specific( pKV ); + + m_iCondition = pKV->GetInt( "i_combo_condition", m_iCondition ); + m_iValue_Compare = pKV->GetInt( "i_combo_value", m_iValue_Compare ); + m_bStatic = !!pKV->GetInt( "i_combo_static", m_bStatic ); + const char *name = pKV->GetString( "sz_cname" ); + + if ( name && Q_strlen( name ) ) + { + delete [] m_szComboName; + m_szComboName = new char[Q_strlen( name ) + 1]; + Q_strcpy( m_szComboName, name ); + } + + pNodeView->MakeSolversDirty(); +} +bool CNodeCombo::VguiDraw( bool bShadow ) +{ + if ( !BaseClass::VguiDraw( bShadow ) ) + return false; + + if ( !m_szComboName || !Q_strlen( m_szComboName ) ) + return false; + + bool bVis = false; + HFont _font = pNodeView->GetFontScaled( 10.0f, bVis ); + if ( !bVis ) + return false; + + const Vector2D bmin = GetBoundsBoxMin(); + const Vector2D bmax = GetBoundsBoxMax(); + const float _offset = PREVIEWINSET + 0.5f; + Vector2D text_pos( bmin.x + _offset, bmax.y + _offset + 10.0f ); + pNodeView->ToPanelSpace( text_pos ); + + char szraw[MAX_PATH]; + wchar_t szconverted[ MAX_PATH ]; + + Q_snprintf( szraw, MAX_PATH, "%s", m_szComboName ); + g_pVGuiLocalize->ConvertANSIToUnicode( szraw, szconverted, sizeof(szconverted) ); + + surface()->DrawSetTextFont( _font ); + surface()->DrawSetTextPos( text_pos.x, text_pos.y ); + + surface()->DrawSetTextColor( NODE_DRAW_COLOR_TEXT_OP ); + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_combo.h b/sp/src/shadereditor/nodes/vnode_combo.h new file mode 100644 index 00000000..d28c0d18 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_combo.h @@ -0,0 +1,34 @@ +#ifndef CNODE_COMBO_H +#define CNODE_COMBO_H + +#include "vBaseContainer.h" + +class CNodeCombo : public CBaseContainerNode +{ + DECLARE_CLASS( CNodeCombo, CBaseContainerNode ); + +public: + + CNodeCombo( CNodeView *p ); + ~CNodeCombo(); + + virtual int GetNodeType(){ return HLSLNODE_CONTROLFLOW_COMBO; }; + + virtual void Solve_ContainerEntered(); + virtual void Solve_ContainerLeft(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + bool VguiDraw( bool bShadow = false ); + +private: + + int m_iCondition; + int m_iValue_Compare; + bool m_bStatic; + char *m_szComboName; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_comment.cpp b/sp/src/shadereditor/nodes/vnode_comment.cpp new file mode 100644 index 00000000..dd34d02b --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_comment.cpp @@ -0,0 +1,273 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeComment::CNodeComment( CNodeView *p ) : BaseClass( "Group", p ) +{ + m_bAffectSolver = false; + + m_flMinSizeX = 64 + CBORDER_SIZE * 2; + + m_iChannelInfo.SetDefaultChannels(); + m_iChannelInfo.bAllowChars = false; + m_iChannelInfo.bHasAnyValues = true; + m_iChannelInfo.iActiveChannels = 3; + + for ( int i = 0; i < 3; i++ ) + { + m_iChannelInfo.flValue[i] = RandomFloat( 0, 1 ); + m_iChannelInfo.bChannelAsValue[i] = true; + } + + m_iChannelInfo.PrintTargetString( m_szConstantString, sizeof( m_szConstantString ) ); +} + +CNodeComment::~CNodeComment() +{ +} + +const int CNodeComment::GetAllowedFlowgraphTypes() +{ + return CNodeView::FLOWGRAPH_POSTPROC | CNodeView::FLOWGRAPH_HLSL | CNodeView::FLOWGRAPH_HLSL_TEMPLATE; +} + +KeyValues *CNodeComment::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetString( "szConstantString", m_szConstantString ); + + return pKV; +} + +void CNodeComment::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + BaseClass::RestoreFromKeyValues_Specific( pKV ); + + char tmp[MAX_PATH]; + Q_snprintf( tmp, sizeof(tmp), "%s", pKV->GetString( "szConstantString" ) ); + + m_iChannelInfo.Tokenize( tmp ); + if ( m_iChannelInfo.iActiveChannels >= 3 ) + m_iChannelInfo.flValue[3] = max( 0.1f, m_iChannelInfo.flValue[3] ); + + m_iChannelInfo.PrintTargetString( m_szConstantString, MAX_PATH ); +} + +void CNodeComment::UpdateSize() +{ + BaseClass::UpdateSize(); + + //m_vecSize.Init( 0, 60 ); + //UpdateContainerBounds(); +} + +Vector2D CNodeComment::GetSelectionBoundsMinNodeSpace() +{ + return GetContainerBorderMin( CBORDER_TOP_LEFT ) + Vector2D( CBORDER_SIZE, 0 ); +} +Vector2D CNodeComment::GetSelectionBoundsMaxNodeSpace() +{ + return GetContainerBorderMin( CBORDER_TOP_LEFT ) + Vector2D( CBORDER_SIZE + 64, GetBorderSize() + CBORDER_SIZE ); +} + +bool CNodeComment::IsWithinBounds_Base( const Vector2D &pos ) +{ + return IsInBounds_DragMove( pos ) || BaseClass::IsInBorderBounds( pos ) != CBORDER_INVALID; // BaseClass::IsWithinBounds_Base( pos ); +} + +int CNodeComment::IsInBorderBounds( const Vector2D &pos ) +{ + if ( IsInBounds_DragMove( pos ) ) + return CBORDER_INVALID; + + return BaseClass::IsInBorderBounds( pos ); +} + +bool CNodeComment::IsInBounds_DragMove( const Vector2D &pos ) +{ + Vector2D _min, _max; + _min = GetSelectionBoundsMinNodeSpace(); + _max = GetSelectionBoundsMaxNodeSpace(); + + if ( pos.x >= _min.x && pos.y >= _min.y && + pos.x <= _max.x && pos.y <= _max.y ) + return true; + return false; +} + +Vector2D CNodeComment::GetContainerSensitiveCenter() +{ + Vector2D sMin = GetSelectionBoundsMinNodeSpace() + Vector2D( 0, GetBorderSize() ); + Vector2D sMax = GetSelectionBoundsMaxNodeSpace(); + + return sMin + ( sMax - sMin ) * 0.5f; +} + +bool CNodeComment::VguiDraw( bool bShadow ) +{ +#define TITEL_INSET_X NODE_DRAW_TITLE_SPACE + if ( !ShouldSimpleDrawObject( pNodeView, pNodeView, m_vecBounds ) ) + return false; + if ( !pNodeView ) + return false; + + //Vector2D title_min = GetBoundsTitleMin(); + //Vector2D title_max = GetBoundsTitleMax(); + //title_max.x -= TITEL_INSET_X; + + Vector2D box_min = GetBoundsBoxMin(); + Vector2D box_max = GetBoundsBoxMax(); + + //pNodeView->ToPanelSpace( title_min ); + //pNodeView->ToPanelSpace( title_max ); + pNodeView->ToPanelSpace( box_min ); + pNodeView->ToPanelSpace( box_max ); + + float flZoom = pNodeView->GetZoomScalar(); + float flO = NODE_DRAW_SHADOW_DELTA * flZoom; + Vector2D offset( flO, flO ); + + if ( bShadow ) + { + //title_min += offset; + //title_max += offset; + box_min += offset; + box_max += offset; + } + + const bool bSelected = IsSelected(); + + //else + //{ + // Color colTitleNoShadow = NODE_DRAW_COLOR_TITLE; + // if ( GetNumContainers() ) + // colTitleNoShadow = NODE_DRAW_COLOR_HASCONTAINER_TITLE; + // else if ( bSelected ) + // colTitleNoShadow = NODE_DRAW_COLOR_SELECTED_TITLE; + // surface()->DrawSetColor( colTitleNoShadow ); + //} + + //surface()->DrawFilledRect( title_min.x, title_min.y, title_max.x, title_max.y ); + + + + if ( !bShadow ) + { + Color boxNoShadow = NODE_DRAW_COLOR_BOX_COMMENT; + + if ( bSelected ) + boxNoShadow = NODE_DRAW_COLOR_SELECTED_BOX; + else if ( GetNumSolvers() && !HasDummySolvers() ) + boxNoShadow = NODE_DRAW_COLOR_HASSOLVER_BOX; + else + { + for ( int i = 0; i < m_iChannelInfo.iActiveChannels; i++ ) + boxNoShadow[i] = m_iChannelInfo.flValue[i] * 255.0f; + } + + surface()->DrawSetColor( boxNoShadow ); + } + else + surface()->DrawSetColor( NODE_DRAW_COLOR_SHADOW ); + + //surface()->DrawFilledRect( box_min.x, box_min.y, box_max.x, box_max.y ); + + //Vector2D r0_min = GetContainerBorderMin( CBORDER_TOP_LEFT ); + //Vector2D r0_max = GetContainerBorderMax( CBORDER_TOP_RIGHT ); + //Vector2D r1_min = GetContainerBorderMin( CBORDER_RIGHT ); + //Vector2D r1_max = GetContainerBorderMax( CBORDER_RIGHT ); + //Vector2D r2_min = GetContainerBorderMin( CBORDER_BOTTOM_LEFT ); + //Vector2D r2_max = GetContainerBorderMax( CBORDER_BOTTOM_RIGHT ); + //Vector2D r3_min = GetContainerBorderMin( CBORDER_RIGHT ); + //Vector2D r3_max = GetContainerBorderMax( CBORDER_RIGHT ); + Vector2D rects_[8] = { + GetContainerBorderMin( CBORDER_TOP_LEFT ), + GetContainerBorderMax( CBORDER_TOP_RIGHT ), + GetContainerBorderMin( CBORDER_RIGHT ), + GetContainerBorderMax( CBORDER_RIGHT ), + GetContainerBorderMin( CBORDER_BOTTOM_LEFT ), + GetContainerBorderMax( CBORDER_BOTTOM_RIGHT ), + GetContainerBorderMin( CBORDER_LEFT ), + GetContainerBorderMax( CBORDER_LEFT ), + }; + for ( int i = 0; i < 8; i++ ) + pNodeView->ToPanelSpace( rects_[i] ); + + Vector2D sMin = GetSelectionBoundsMinNodeSpace() + Vector2D( 0, GetBorderSize() ); + Vector2D sMax = GetSelectionBoundsMaxNodeSpace(); + + pNodeView->ToPanelSpace( sMin ); + pNodeView->ToPanelSpace( sMax ); + + if ( bShadow ) + { + for ( int i = 0; i < 8; i++ ) + rects_[i] += offset; + + sMin += offset; + sMax += offset; + } + + for ( int i = 0; i < 4; i++ ) + surface()->DrawFilledRect( rects_[i*2].x, rects_[i*2+1].y, rects_[i*2+1].x, rects_[i*2].y ); + + surface()->DrawFilledRect( sMin.x, sMax.y, sMax.x, sMin.y ); + +#if 0 + if ( bShadow ) + { + VguiDraw_Jacks( true ); + } + else + { + VguiDraw_Jacks( false ); + Color borderCol = NODE_DRAW_COLOR_BORDER; + if ( GetErrorLevel() == ERRORLEVEL_UNDEFINED ) + borderCol = DRAWCOLOR_ERRORLEVEL_UNDEFINED; + else if ( GetErrorLevel() == ERRORLEVEL_FAIL ) + borderCol = DRAWCOLOR_ERRORLEVEL_FAIL; + else if ( IsAllocating() ) + borderCol = NODE_DRAW_COLOR_HASSOLVER_BOX_ALLOC; + surface()->DrawSetColor( borderCol ); + + int borderSize = 1; + surface()->DrawFilledRect( rects_[0].x-borderSize, rects_[1].y, rects_[0].x, rects_[4].y ); + surface()->DrawFilledRect( rects_[7].x-borderSize, rects_[7].y, rects_[7].x, rects_[6].y ); + + surface()->DrawFilledRect( rects_[2].x, rects_[3].y, rects_[2].x+borderSize, rects_[2].y ); + surface()->DrawFilledRect( rects_[3].x-borderSize, rects_[1].y, rects_[3].x, rects_[4].y ); + + surface()->DrawFilledRect( rects_[0].x, rects_[1].y, rects_[1].x, rects_[1].y+borderSize ); + surface()->DrawFilledRect( rects_[4].x, rects_[4].y-borderSize, rects_[5].x, rects_[4].y ); + + surface()->DrawFilledRect( rects_[7].x-borderSize, rects_[0].y-borderSize, rects_[2].x+borderSize, rects_[0].y ); + surface()->DrawFilledRect( rects_[7].x-borderSize, rects_[5].y, rects_[2].x+borderSize, rects_[5].y+borderSize ); + } +#endif + if ( !bShadow ) + DrawGrabIcon(); + + if ( Q_strlen( szNodeName ) > 1 ) + { + wchar_t szconverted[ 1024 ]; + int fontWide, fontTall; + + surface()->DrawSetTextColor( bShadow ? NODE_DRAW_COLOR_SHADOW : NODE_DRAW_COLOR_CUSTOMTITLE ); + + bool bDraw; + vgui::HFont hFont_Small = pNodeView->GetFontScaled(18,bDraw); + if ( bDraw ) + { + g_pVGuiLocalize->ConvertANSIToUnicode( szNodeName, szconverted, sizeof(szconverted) ); + + surface()->DrawSetTextFont( hFont_Small ); + surface()->GetTextSize( hFont_Small, szconverted, fontWide, fontTall ); + surface()->DrawSetTextPos( sMin.x, sMax.y - fontTall - 3 * pNodeView->GetZoomScalar() ); + + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } + } + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_comment.h b/sp/src/shadereditor/nodes/vnode_comment.h new file mode 100644 index 00000000..f7110da0 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_comment.h @@ -0,0 +1,48 @@ +#ifndef CNODE_COMMENT_H +#define CNODE_COMMENT_H + +#include "vBaseContainer.h" + +class CNodeComment : public CBaseContainerNode +{ + DECLARE_CLASS( CNodeComment, CBaseContainerNode ); + +public: + + CNodeComment( CNodeView *p ); + ~CNodeComment(); + + virtual Vector2D GetContainerSensitiveCenter(); + + virtual const int GetAllowedFlowgraphTypes(); + virtual int GetNodeType(){ return HLSLNODE_OTHER_COMMENT; }; + + virtual bool ShouldSelectChildrenOnClick(){ return true; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + virtual Vector2D GetSelectionBoundsMinNodeSpace(); + virtual Vector2D GetSelectionBoundsMaxNodeSpace(); + + virtual int IsInBorderBounds( const Vector2D &pos ); + virtual bool IsWithinBounds_Base( const Vector2D &pos ); + virtual void UpdateSize(); + + bool VguiDraw( bool bShadow = false ); + + int GetErrorLevel(){ return ERRORLEVEL_NONE; }; + +protected: + virtual float GetBorderSize(){ return CBORDER_SIZE_COMMENT; }; + + virtual bool IsInBounds_DragMove( const Vector2D &pos ); + +private: + + TokenChannels_t m_iChannelInfo; + char m_szConstantString[MAX_PATH]; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_condition.cpp b/sp/src/shadereditor/nodes/vnode_condition.cpp new file mode 100644 index 00000000..e127625c --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_condition.cpp @@ -0,0 +1,82 @@ + +#include "cbase.h" +#include "editorcommon.h" + + +CNodeCondition::CNodeCondition( CNodeView *p ) : BaseClass( "Condition", p ) +{ + m_iCondition = ITERATORCOND_EQUAL; + + GenerateJacks_Input( 2 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "A" ); + GetJack_In( 1 )->SetName( "B" ); +} + +CNodeCondition::~CNodeCondition() +{ +} + +int CNodeCondition::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + locallevel = ERRORLEVEL_FAIL; + } + } + + return max( locallevel, baseLevel ); +} + +void CNodeCondition::Solve_ContainerEntered() +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return; + + CHLSL_Solver_ConditionIntro *solver_intro = new CHLSL_Solver_ConditionIntro( GetUniqueIndex() ); + solver_intro->m_iCondition = m_iCondition; + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver_intro->AddSourceVar( GetJack_In( i )->GetTemporaryVarTarget_End() ); + AddSolver( solver_intro ); + + CHLSL_Solver_ContainerBasic *solver_dummy = new CHLSL_Solver_ContainerBasic( GetUniqueIndex() ); + AddSolver( solver_dummy ); +} +void CNodeCondition::Solve_ContainerLeft() +{ + CHLSL_Solver_LoopOutro *solver_outro = new CHLSL_Solver_LoopOutro( GetUniqueIndex() ); + AddSolver( solver_outro ); +} + +KeyValues *CNodeCondition::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "i_combo_condition", m_iCondition ); + + return pKV; +} +void CNodeCondition::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + BaseClass::RestoreFromKeyValues_Specific( pKV ); + + m_iCondition = pKV->GetInt( "i_combo_condition", m_iCondition ); + + pNodeView->MakeSolversDirty(); +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_condition.h b/sp/src/shadereditor/nodes/vnode_condition.h new file mode 100644 index 00000000..71d10f19 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_condition.h @@ -0,0 +1,33 @@ +#ifndef CNODE_CONDITION_H +#define CNODE_CONDITION_H + +#include "vBaseContainer.h" + +class CNodeCondition : public CBaseContainerNode +{ + DECLARE_CLASS( CNodeCondition, CBaseContainerNode ); + +public: + + CNodeCondition( CNodeView *p ); + ~CNodeCondition(); + + virtual int GetNodeType(){ return HLSLNODE_CONTROLFLOW_CONDITION; }; + + virtual int UpdateInputsValid(); + + virtual void Solve_ContainerEntered(); + virtual void Solve_ContainerLeft(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + //void VguiDraw( bool bShadow = false ); + +private: + + int m_iCondition; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_constant.cpp b/sp/src/shadereditor/nodes/vnode_constant.cpp new file mode 100644 index 00000000..70bfa267 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_constant.cpp @@ -0,0 +1,219 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeConstant::CNodeConstant( CNodeView *p ) : BaseClass( "Constant", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + m_iChannelInfo.SetDefaultChannels(); + m_iChannelInfo.bAllowChars = false; + m_szConstantString[0] = '\0'; + + UpdateNode(); +} + +CNodeConstant::~CNodeConstant() +{ +} + +KeyValues *CNodeConstant::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetString( "szConstantString", m_szConstantString ); + + return pKV; +} +void CNodeConstant::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + char tmp[MAX_PATH]; + Q_snprintf( tmp, sizeof(tmp), "%s", pKV->GetString( "szConstantString" ) ); + + m_iChannelInfo.Tokenize( tmp ); + m_iChannelInfo.PrintTargetString( m_szConstantString, MAX_PATH ); + + m_flMinSizeY_VS = 0; + if ( m_iChannelInfo.iActiveChannels >= 2 ) + { + m_flMinSizeY_VS = 28; + m_flMinSizeY_VS += 10 * (m_iChannelInfo.iActiveChannels - 2); + } + + UpdateNode(); +} + +void CNodeConstant::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_Out( CBaseNode::BY_INDEX, m_hRestoreBridges ); + + GenerateJacks_Output( 1 ); + + if ( !m_iChannelInfo.IsActive() ) + m_iChannelInfo.Tokenize( "0" ); + + Assert(m_iChannelInfo.IsActive()); + + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1 ); + LockJackOutput_Flags( 0, GetTypeFlagFromEnum(m_iChannelInfo.iActiveChannels) ); + + // HLSLVAR_FLOAT1 - HLSLVAR_FLOAT4 + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} + +bool CNodeConstant::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_Constant *solver = new CHLSL_Solver_Constant( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + solver->SetComponentInfo( m_iChannelInfo ); + AddSolver( solver ); + + return true; +} + +bool CNodeConstant::VguiDraw( bool bShadow ) +{ + if ( !BaseClass::VguiDraw( bShadow ) ) + return false; + + if ( !m_iChannelInfo.IsActive() || bShadow ) + return false; + + bool bVis = false; + HFont _font = pNodeView->GetFontScaled( 10.0f, bVis ); + if ( !bVis ) + return false; + + char szraw[32]; + wchar_t szconverted[ 32 ]; + + const Vector2D bmin = GetBoundsBoxMin(); + const Vector2D bmax = GetBoundsBoxMax(); + const float _offset = PREVIEWINSET + 0.5f; + const Vector2D text_pos( bmin.x + _offset, bmax.y + _offset ); + + for ( int i = 0; i < m_iChannelInfo.iActiveChannels; i++ ) + { + Assert( m_iChannelInfo.bChannelAsValue[i] ); + + Vector2D curpos = text_pos; + curpos.y += 10.0f * (m_iChannelInfo.iActiveChannels - i); + pNodeView->ToPanelSpace( curpos ); + + Q_snprintf( szraw, 32, "%f", m_iChannelInfo.flValue[i] ); + g_pVGuiLocalize->ConvertANSIToUnicode( szraw, szconverted, sizeof(szconverted) ); + + surface()->DrawSetTextFont( _font ); + surface()->DrawSetTextPos( curpos.x, curpos.y ); + + surface()->DrawSetTextColor( NODE_DRAW_COLOR_TEXT_OP ); + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } + + return true; +} + + + + + +CNodeRandom::CNodeRandom( CNodeView *p ) : BaseClass( "Random", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Output( 1 ); + m_iNumComponents = 3; + m_flValue_Min = 0; + m_flValue_Max = 1; + UpdateNode(); +} +CNodeRandom::~CNodeRandom() +{ +} +KeyValues *CNodeRandom::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_num_comps", m_iNumComponents ); + pKV->SetFloat( "fl_value_min", m_flValue_Min ); + pKV->SetFloat( "fl_value_max", m_flValue_Max ); + + return pKV; +} +void CNodeRandom::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iNumComponents = pKV->GetInt( "i_num_comps", m_iNumComponents ); + m_flValue_Min = pKV->GetFloat( "fl_value_min", m_flValue_Min ); + m_flValue_Max = pKV->GetFloat( "fl_value_max", m_flValue_Max ); + UpdateNode(); +} +void CNodeRandom::UpdateNode() +{ + LockJackOutput_Flags( 0, ::GetVarTypeFlag( m_iNumComponents ) ); +} +bool CNodeRandom::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_Random *solver = new CHLSL_Solver_Random( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + solver->SetState( m_iNumComponents, m_flValue_Min, m_flValue_Max ); + AddSolver( solver ); + + return true; +} + + +CNodeBumpBasis::CNodeBumpBasis( CNodeView *p ) : BaseClass( "Bump basis", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Output( 3 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "1" ); + LockJackOutput_Flags( 1, HLSLVAR_FLOAT3, "2" ); + LockJackOutput_Flags( 2, HLSLVAR_FLOAT3, "3" ); +} +CNodeBumpBasis::~CNodeBumpBasis() +{ +} +bool CNodeBumpBasis::CreateSolvers(GenericShaderData *ShaderData) +{ + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJCur = GetJack_Out(i); + if ( !pJCur->GetNumBridgesConnected() && i != 0 ) + continue; + + const int res = pJCur->GetResourceType(); + + CHLSL_Var *tg = pJCur->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_BumpBasis *solver = new CHLSL_Solver_BumpBasis( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + solver->SetState( i ); + AddSolver( solver ); + } + + return !!GetNumSolvers(); +} diff --git a/sp/src/shadereditor/nodes/vnode_constant.h b/sp/src/shadereditor/nodes/vnode_constant.h new file mode 100644 index 00000000..399ce9e8 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_constant.h @@ -0,0 +1,71 @@ +#ifndef CNODE_CONSTANT_H +#define CNODE_CONSTANT_H + +#include "vBaseNode.h" + +class CNodeConstant : public CBaseNode +{ + DECLARE_CLASS( CNodeConstant, CBaseNode ); + +public: + + CNodeConstant( CNodeView *p ); + ~CNodeConstant(); + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_LOCAL; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + bool VguiDraw( bool bShadow = false ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + TokenChannels_t m_iChannelInfo; + char m_szConstantString[MAX_PATH]; + + void UpdateNode(); +}; + + +class CNodeRandom : public CBaseNode +{ + DECLARE_CLASS( CNodeRandom, CBaseNode ); + +public: + CNodeRandom( CNodeView *p ); + ~CNodeRandom(); + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_RANDOM; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iNumComponents; + float m_flValue_Min; + float m_flValue_Max; + void UpdateNode(); +}; + + +class CNodeBumpBasis : public CBaseNode +{ + DECLARE_CLASS( CNodeBumpBasis, CBaseNode ); + +public: + CNodeBumpBasis( CNodeView *p ); + ~CNodeBumpBasis(); + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_BUMPBASIS; }; + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_cross.cpp b/sp/src/shadereditor/nodes/vnode_cross.cpp new file mode 100644 index 00000000..f09eef94 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_cross.cpp @@ -0,0 +1,53 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeCross::CNodeCross( CNodeView *p ) : BaseClass( "Crossproduct", p ) +{ + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + LockJackInput_Flags( 0, HLSLVAR_FLOAT3, "A" ); + LockJackInput_Flags( 1, HLSLVAR_FLOAT3, "B" ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3 ); +} + +CNodeCross::~CNodeCross() +{ +} + +int CNodeCross::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = TestJackFlags_In(); + + return max( locallevel, baseLevel ); +} + +bool CNodeCross::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( HLSLVAR_FLOAT3 ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Cross *solver = new CHLSL_Solver_Cross( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_cross.h b/sp/src/shadereditor/nodes/vnode_cross.h new file mode 100644 index 00000000..0f1c3c08 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_cross.h @@ -0,0 +1,25 @@ +#ifndef CNODE_CROSS_H +#define CNODE_CROSS_H + +#include "vBaseNode.h" + +class CNodeCross : public CBaseNode +{ + DECLARE_CLASS( CNodeCross, CBaseNode ); + +public: + + CNodeCross( CNodeView *p ); + ~CNodeCross(); + + virtual int GetNodeType(){ return HLSLNODE_VECTOR_CROSS; }; + + virtual int UpdateInputsValid(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_custom.cpp b/sp/src/shadereditor/nodes/vnode_custom.cpp new file mode 100644 index 00000000..42afa0c4 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_custom.cpp @@ -0,0 +1,311 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodeCustom::CNodeCustom( CNodeView *p ) : BaseClass( "Custom code", p ) +{ + m_szFunctionName[0] = 0; + m_szFilePath[0] = 0; + + m_pCode_Global = NULL; + m_pCode_Function = NULL; + + m_bInline = true; + m_iEnvFlags = 0; + + UpdateNode(); +} + +CNodeCustom::~CNodeCustom() +{ + delete [] m_pCode_Global; + delete [] m_pCode_Function; + + PurgeNameVectors(); +} + +void CNodeCustom::PurgeNameVectors() +{ + m_hszVarNames_In.PurgeAndDeleteElements(); + m_hszVarNames_Out.PurgeAndDeleteElements(); +} + +char *CNodeCustom::GenerateDefaultName( int idx, bool bOut ) +{ + const char *ref = bOut ? "out_%02i" : "in_%02i"; + static char tmp[32]; + + Q_snprintf( tmp, sizeof(tmp), ref, idx ); + return tmp; + + //char *out = new char[ Q_strlen( tmp ) ]; + //Q_strcpy( out, tmp ); + //return out; +} + +KeyValues *CNodeCustom::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + WriteJackDataFromKV( pKV, m_hszVarNames_In, m_hszVarNames_Out, + GetNumJacks_In(), GetNumJacks_Out() ); + + pKV->SetString( "szFunctionName", m_szFunctionName ); + pKV->SetString( "szFilePath", m_szFilePath ); + pKV->SetInt( "iInline", m_bInline ? 1 : 0 ); + + CKVPacker::KVPack( m_pCode_Global, "szcode_global", pKV ); + CKVPacker::KVPack( m_pCode_Function, "szcode_body", pKV ); + //pKV->SetString( "szcode_global", m_pCode_Global ); + //pKV->SetString( "szcode_body", m_pCode_Function ); + pKV->SetInt( "iEnvFlags", m_iEnvFlags ); + + return pKV; +} + +void CNodeCustom::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + RestoreInternal( pKV ); + + if ( !IsUsingInlineCode() ) + UpdateFromFile(); + + UpdateNode(); +} + +void CNodeCustom::RestoreInternal( KeyValues *pKV ) +{ + PurgeNameVectors(); + + FillJackDataFromKV( pKV, m_hszVarNames_In, m_hszVarNames_Out ); + + Q_snprintf( m_szFunctionName, sizeof(m_szFunctionName), "%s", pKV->GetString( "szFunctionName" ) ); + Q_snprintf( m_szFilePath, sizeof(m_szFilePath), "%s", pKV->GetString( "szFilePath" ) ); + m_bInline = !!pKV->GetInt( "iInline" ); + m_iEnvFlags = pKV->GetInt( "iEnvFlags" ); + + delete [] m_pCode_Global; + delete [] m_pCode_Function; + m_pCode_Global = NULL; + m_pCode_Function = NULL; + + m_pCode_Global = CKVPacker::KVUnpack( pKV, "szcode_global" ); + m_pCode_Function = CKVPacker::KVUnpack( pKV, "szcode_body" ); +} + +void CNodeCustom::UpdateFromFile() +{ + if ( IsUsingInlineCode() ) + return; + + if ( Q_strlen( GetFilePath() ) < 1 ) + return; + + //g_pFullFileSystem->RelativePathToFullPath( GetFilePath + KeyValues *pData = new KeyValues(""); + pData->LoadFromFile( g_pFullFileSystem, GetFilePath(), "MOD" ); + RestoreInternal( pData ); + pData->deleteThis(); +} + +const char *CNodeCustom::GetFilePath() +{ + return m_szFilePath; +} + +bool CNodeCustom::IsUsingInlineCode() +{ + return m_bInline; +} + +void CNodeCustom::WriteJackDataFromKV( KeyValues *pKV, CUtlVector< __funcParamSetup* > &m_hIn, CUtlVector< __funcParamSetup* > &m_hOut, + int maxIn, int maxOut ) +{ + for ( int i = 0; i < maxIn; i++ ) + { + const char *pName = VarArgs( "varName_In_%i", i ); + if ( i < m_hIn.Count() ) + pKV->SetString( pName, m_hIn[ i ]->pszName ); + else + pKV->SetString( pName, "" ); + + pName = VarArgs( "varType_In_%i", i ); + if ( i < m_hIn.Count() ) + pKV->SetInt( pName, m_hIn[ i ]->iFlag ); + else + pKV->SetInt( pName, HLSLVAR_FLOAT1 ); + } + + for ( int i = 0; i < maxOut; i++ ) + { + const char *pName = VarArgs( "varName_Out_%i", i ); + if ( i < m_hOut.Count() ) + pKV->SetString( pName, m_hOut[ i ]->pszName ); + else + pKV->SetString( pName, "" ); + + pName = VarArgs( "varType_Out_%i", i ); + if ( i < m_hOut.Count() ) + pKV->SetInt( pName, m_hOut[ i ]->iFlag ); + else + pKV->SetInt( pName, HLSLVAR_FLOAT1 ); + } +} +void CNodeCustom::FillJackDataFromKV( KeyValues *pKV, CUtlVector< __funcParamSetup* > &m_hIn, CUtlVector< __funcParamSetup* > &m_hOut ) +{ + Assert( m_hIn.Count() == 0 ); + Assert( m_hOut.Count() == 0 ); + + const char *nullString = ""; + int itr = 0; + + for (;;) + { + const char *read_name = pKV->GetString( VarArgs( "varName_In_%i", itr ), nullString ); + const int read_type = pKV->GetInt( VarArgs( "varType_In_%i", itr ), 0 ); + + if ( read_type == 0 ) + break; + + m_hIn.AddToTail( AllocOutputSetup( false, read_name, read_type ) ); + itr++; + } + + itr = 0; + + for (;;) + { + const char *read_name = pKV->GetString( VarArgs( "varName_Out_%i", itr ), nullString ); + const int read_type = pKV->GetInt( VarArgs( "varType_Out_%i", itr ), 0 ); + + if ( read_type == 0 ) + break; + + m_hOut.AddToTail( AllocOutputSetup( true, read_name, read_type ) ); + itr++; + } +} +__funcParamSetup *CNodeCustom::AllocOutputSetup( bool bOutput, const char *name, int type ) +{ + __funcParamSetup *p = new __funcParamSetup(); + AutoCopyStringPtr( name, &p->pszName ); + p->iFlag = type; + p->bOutput = bOutput; + + char *pszFixSpaces = p->pszName; + while ( pszFixSpaces && *pszFixSpaces ) + { + if ( *pszFixSpaces == ' ' ) + *pszFixSpaces = '_'; + pszFixSpaces++; + } + + return p; +} + +void CNodeCustom::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges_In; + CreateBridgeRestoreData_In( CBaseNode::BY_INDEX, m_hRestoreBridges_In ); + GenerateJacks_Input( m_hszVarNames_In.Count() ); + //GenerateJacks_Input( numJacksIn ); + + + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges_Out; + CreateBridgeRestoreData_Out( CBaseNode::BY_INDEX, m_hRestoreBridges_Out ); + GenerateJacks_Output( m_hszVarNames_Out.Count() ); + + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + char *name = NULL; + + if ( m_hszVarNames_In.Count() > i && m_hszVarNames_In[ i ]->pszName != NULL && + Q_strlen( m_hszVarNames_In[ i ]->pszName ) > 0 ) + name = m_hszVarNames_In[ i ]->pszName; + else + name = GenerateDefaultName( i ); + + LockJackInput_Flags( i, m_hszVarNames_In[ i ]->iFlag, name ); + } + + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + char *name = NULL; + + if ( m_hszVarNames_Out.Count() > i && m_hszVarNames_Out[ i ]->pszName != NULL && + Q_strlen( m_hszVarNames_Out[ i ]->pszName ) > 0 ) + name = m_hszVarNames_Out[ i ]->pszName; + else + name = GenerateDefaultName( i, true ); + + LockJackOutput_Flags( i, m_hszVarNames_Out[ i ]->iFlag, name ); + } + + RestoreBridgesFromList_In( m_hRestoreBridges_In ); + RestoreBridgesFromList_Out( m_hRestoreBridges_Out ); + + + OnUpdateHierachy( NULL, NULL ); +} + +void CNodeCustom::PreSolverUpdated() +{ + //UpdateNode(); +} + +int CNodeCustom::UpdateInputsValid() +{ + int base = BaseClass::UpdateInputsValid(); + int local = (/*(m_pCode_Global && Q_strlen(m_pCode_Global)) &&*/ + (m_pCode_Function && Q_strlen(m_pCode_Function)) && + (m_bInline || Q_strlen(m_szFilePath))) ? ERRORLEVEL_NONE : ERRORLEVEL_UNDEFINED; + + return max( base, local ); +} + +bool CNodeCustom::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + Assert( m_pCode_Function && Q_strlen( m_pCode_Function ) ); + Assert( m_bInline || Q_strlen(m_szFilePath) ); + + SetAllocating( true ); + + char *pszFuncString = CKVPacker::ConvertKVSafeString( m_pCode_Function, false ); + char *pszGlobalString = CKVPacker::ConvertKVSafeString( m_pCode_Global, false ); + + int iHierachyType = GetHierachyTypeIterateFullyRecursive(); + int envflags = m_iEnvFlags; + if ( iHierachyType & HLSLHIERACHY_PS ) + envflags &= ~NODECUSTOM_ADDENV_LIGHTING_VS; + + if ( iHierachyType & HLSLHIERACHY_VS ) + envflags &= ~NODECUSTOM_ADDENV_LIGHTING_PS; + + CHLSL_Solver_Custom *solver = new CHLSL_Solver_Custom( GetUniqueIndex() ); + solver->SetResourceType( RESOURCETYPE_VARIABLE ); + solver->Init( pszGlobalString, pszFuncString, envflags, + m_szFunctionName, m_szFilePath, + m_hszVarNames_In, m_hszVarNames_Out, + this ); + + delete [] pszFuncString; + delete [] pszGlobalString; + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In( i )->GetTemporaryVarTarget_End() ); + + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJ = GetJack_Out( i ); + CHLSL_Var *pTg = pJ->AllocateVarFromSmartType(); + solver->AddTargetVar( pTg ); + } + + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_custom.h b/sp/src/shadereditor/nodes/vnode_custom.h new file mode 100644 index 00000000..ae3bd24d --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_custom.h @@ -0,0 +1,66 @@ +#ifndef CNODECUSTOM_H +#define CNODECUSTOM_H + +#include "vBaseNode.h" + +enum +{ + NODECUSTOM_ADDENV_LIGHTING_PS = ( 1 << 0 ), + NODECUSTOM_ADDENV_LIGHTING_VS = ( 1 << 1 ), +}; + +class CNodeCustom : public CBaseNode +{ + DECLARE_CLASS( CNodeCustom, CBaseNode ); + +public: + + CNodeCustom( CNodeView *p ); + ~CNodeCustom(); + + virtual int GetNodeType(){ return HLSLNODE_UTILITY_CUSTOMCODE; }; + + //virtual int UpdateInputsValid(); + //virtual void UpdateOutputs(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + virtual void PreSolverUpdated(); + virtual int UpdateInputsValid(); + + static void WriteJackDataFromKV( KeyValues *pKV, CUtlVector< __funcParamSetup* > &m_hIn, CUtlVector< __funcParamSetup* > &m_hOut, + int maxIn, int maxOut ); + static void FillJackDataFromKV( KeyValues *pKV, CUtlVector< __funcParamSetup* > &m_hIn, CUtlVector< __funcParamSetup* > &m_hOut ); + static __funcParamSetup *AllocOutputSetup( bool bOutput, const char *name, int type = HLSLVAR_FLOAT1 ); + + + void UpdateFromFile(); + const char *GetFilePath(); + bool IsUsingInlineCode(); + +private: + void RestoreInternal( KeyValues *pKV ); + + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + void UpdateNode(); + + CUtlVector< __funcParamSetup* >m_hszVarNames_In; + CUtlVector< __funcParamSetup* >m_hszVarNames_Out; + + char *m_pCode_Global; + char *m_pCode_Function; + + char m_szFunctionName[MAX_PATH]; + char m_szFilePath[MAX_PATH*4]; + bool m_bInline; + int m_iEnvFlags; + + void PurgeNameVectors(); + + char *GenerateDefaultName( int idx, bool bOut = false ); +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_divide.cpp b/sp/src/shadereditor/nodes/vnode_divide.cpp new file mode 100644 index 00000000..23638a9d --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_divide.cpp @@ -0,0 +1,86 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeDivide::CNodeDivide( CNodeView *p ) : BaseClass( "Divide", p ) +{ + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "A" ); + GetJack_In( 1 )->SetName( "B" ); +} + +CNodeDivide::~CNodeDivide() +{ +} + +int CNodeDivide::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + locallevel = ERRORLEVEL_FAIL; + } + else if ( vartype_jack_0 >= HLSLVAR_MATRIX3X3 || + vartype_jack_1 >= HLSLVAR_MATRIX3X3 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeDivide::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( max( GetJack_In(0)->GetSmartType(), GetJack_In(1)->GetSmartType() ) ); +} +bool CNodeDivide::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type1 = pJ1->GetSmartType(); + int type2 = pJ2->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( max( type1, type2 ) ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Divide *solver = new CHLSL_Solver_Divide( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_divide.h b/sp/src/shadereditor/nodes/vnode_divide.h new file mode 100644 index 00000000..3f11929d --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_divide.h @@ -0,0 +1,26 @@ +#ifndef CNODE_DIVIDE_H +#define CNODE_DIVIDE_H + +#include "vBaseNode.h" + +class CNodeDivide : public CBaseNode +{ + DECLARE_CLASS( CNodeDivide, CBaseNode ); + +public: + + CNodeDivide( CNodeView *p ); + ~CNodeDivide(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_DIVIDE; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_dot.cpp b/sp/src/shadereditor/nodes/vnode_dot.cpp new file mode 100644 index 00000000..49df5590 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_dot.cpp @@ -0,0 +1,91 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeDot::CNodeDot( CNodeView *p ) : BaseClass( "Dotproduct", p ) +{ + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + //SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT1 ); + + GetJack_In( 0 )->SetName( "A" ); + GetJack_In( 1 )->SetName( "B" ); +} + +CNodeDot::~CNodeDot() +{ +} + +int CNodeDot::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + locallevel = ERRORLEVEL_FAIL; + } + else if ( vartype_jack_0 >= HLSLVAR_MATRIX3X3 || + vartype_jack_1 >= HLSLVAR_MATRIX3X3 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeDot::UpdateOutputs() +{ + //if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + // return; + + //if ( GetErrorLevel() != ERRORLEVEL_NONE ) + // return SetOutputsUndefined(); + + //GetJack_Out( 0 )->SetSmartType( max( GetJack_In(0)->GetSmartType(), GetJack_In(1)->GetSmartType() ) ); +} +bool CNodeDot::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type0 = pJ_Out->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + if ( pJ2->GetSmartType() == HLSLVAR_FLOAT1 ) + swap( pJ1, pJ2 ); + + CHLSL_Var *tg = GetInputToWriteTo( type0 ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Dot *solver = new CHLSL_Solver_Dot( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + //Msg("add solver has %i src vars\n", solver->GetNumSourceVars()); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_dot.h b/sp/src/shadereditor/nodes/vnode_dot.h new file mode 100644 index 00000000..064176f3 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_dot.h @@ -0,0 +1,26 @@ +#ifndef CNODEDOT_H +#define CNODEDOT_H + +#include "vBaseNode.h" + +class CNodeDot : public CBaseNode +{ + DECLARE_CLASS( CNodeDot, CBaseNode ); + +public: + + CNodeDot( CNodeView *p ); + ~CNodeDot(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_DOT; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_envc.cpp b/sp/src/shadereditor/nodes/vnode_envc.cpp new file mode 100644 index 00000000..5e14ecad --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_envc.cpp @@ -0,0 +1,71 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeEnvC::CNodeEnvC( CNodeView *p, float defaultSmartVal ) : BaseClass( "UNKNOWN ENVC", p ) +{ + m_iNodeType = HLSLNODE_CONSTANT_TIME; + m_iEnvCIndex = 0; + + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + m_flSmartVal = m_flDefaultSmartVal = defaultSmartVal; +} +CNodeEnvC::~CNodeEnvC() +{ +} +int CNodeEnvC::GetAllowedHierachiesAsFlags() +{ + switch ( m_iEnvCIndex ) + { + case HLSLENV_FOG_PARAMS: + return HLSLHIERACHY_PS; + break; + } + + return BaseClass::GetAllowedHierachiesAsFlags(); +} + +KeyValues *CNodeEnvC::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetFloat( "flSmartVal0", m_flSmartVal ); + + return pKV; +} +void CNodeEnvC::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_flSmartVal = pKV->GetFloat( "flSmartVal0" ); +} + +void CNodeEnvC::SetEnvCType( int type ) +{ + m_iEnvCIndex = type; + m_iNodeType = EConstant_GetData(type)->nodetype; + + SetName( EConstant_GetData(type)->nodename ); + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, EConstant_GetData(type)->varflag, EConstant_GetData(type)->jackname ); +} +bool CNodeEnvC::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_EnvC *solver = new CHLSL_Solver_EnvC( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + solver->SetEnvironmentConstantIndex( m_iEnvCIndex, m_flSmartVal ); + AddSolver( solver ); + + return true; +} diff --git a/sp/src/shadereditor/nodes/vnode_envc.h b/sp/src/shadereditor/nodes/vnode_envc.h new file mode 100644 index 00000000..dee89885 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_envc.h @@ -0,0 +1,40 @@ +#ifndef CNODE_TIME_H +#define CNODE_TIME_H + +#include "vBaseNode.h" + +class CNodeEnvC : public CBaseNode +{ + DECLARE_CLASS( CNodeEnvC, CBaseNode ); + +public: + CNodeEnvC( CNodeView *p, float defaultSmartVal ); + ~CNodeEnvC(); + + enum + { + ENVC_FBSCALE_FULL = 0, + ENVC_FBSCALE_HALF, + ENVC_FBSCALE_QUARTER, + }; + + void SetEnvCType( int type ); + virtual int GetNodeType(){ return m_iNodeType; }; + + virtual int GetAllowedHierachiesAsFlags(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iNodeType; + int m_iEnvCIndex; + + float m_flDefaultSmartVal; + float m_flSmartVal; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_final.cpp b/sp/src/shadereditor/nodes/vnode_final.cpp new file mode 100644 index 00000000..4d20142c --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_final.cpp @@ -0,0 +1,78 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeFinal::CNodeFinal( CNodeView *p ) : BaseClass( "Final output", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT4, "Color" ); + + i_tonemaptype = 1; + b_writedepth = true; + + UpdateNode(); +} + +CNodeFinal::~CNodeFinal() +{ +} + +void CNodeFinal::SetState( int t, bool wd ) +{ + i_tonemaptype = t; + b_writedepth = wd; +} + +KeyValues *CNodeFinal::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_final_tonemap", i_tonemaptype ); + pKV->SetInt( "i_final_wdepth", b_writedepth ? 1 : 0 ); + return pKV; +} +void CNodeFinal::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + i_tonemaptype = pKV->GetInt( "i_final_tonemap", i_tonemaptype ); + b_writedepth = !!pKV->GetInt( "i_final_wdepth", b_writedepth ); + UpdateNode(); +} + +void CNodeFinal::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + GenerateJacks_Input( b_writedepth ? 3 : 2 ); + LockJackInput_Flags( 0, HLSLVAR_FLOAT4, "Color" ); + LockJackInput_Flags( 1, HLSLVAR_FLOAT1, "Fog" ); + if ( b_writedepth ) + LockJackInput_Flags( 2, HLSLVAR_FLOAT1, "Proj z" ); + + RestoreBridgesFromList_In( m_hRestoreBridges ); +} + +bool CNodeFinal::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( pJ_Out->GetSmartType() ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Final *solver = new CHLSL_Solver_Final( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( i_tonemaptype, b_writedepth ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_final.h b/sp/src/shadereditor/nodes/vnode_final.h new file mode 100644 index 00000000..b5ecdb6d --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_final.h @@ -0,0 +1,32 @@ +#ifndef CNODE_FINAL_H +#define CNODE_FINAL_H + +#include "vBaseNode.h" + +class CNodeFinal : public CBaseNode +{ + DECLARE_CLASS( CNodeFinal, CBaseNode ); + +public: + + CNodeFinal( CNodeView *p ); + ~CNodeFinal(); + + virtual int GetNodeType(){ return HLSLNODE_UTILITY_FINAL; }; + + virtual void UpdateNode(); + + virtual void SetState( int t, bool wd ); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int i_tonemaptype; + bool b_writedepth; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_flashlight.cpp b/sp/src/shadereditor/nodes/vnode_flashlight.cpp new file mode 100644 index 00000000..f498ffbb --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_flashlight.cpp @@ -0,0 +1,123 @@ + +#include "cbase.h" +#include "editorcommon.h" + + +CNodeFlashlight::CNodeFlashlight( CNodeView *p ) : BaseClass( "Flashlight", p ) +{ + m_bSpecular = false; + UpdateNode(); +} +CNodeFlashlight::~CNodeFlashlight() +{ +} + +void CNodeFlashlight::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + GenerateJacks_Input( m_bSpecular ? 7 : 4 ); + LockJackInput_Flags( 0, HLSLVAR_FLOAT3, "World pos" ); + LockJackInput_Flags( 1, HLSLVAR_FLOAT3, "World normal" ); + LockJackInput_Flags( 2, HLSLVAR_FLOAT4, "FVP pos" ); + LockJackInput_Flags( 3, HLSLVAR_FLOAT2, "Screen pos" ); + if ( m_bSpecular ) + { + LockJackInput_Flags( 4, HLSLVAR_FLOAT3, "Eye dir" ); + LockJackInput_Flags( 5, HLSLVAR_FLOAT1, "Spec exp" ); + LockJackInput_Flags( 6, HLSLVAR_FLOAT1, "Fresnel" ); + } + + RestoreBridgesFromList_In( m_hRestoreBridges ); + + + + CreateBridgeRestoreData_Out( CBaseNode::BY_NAME, m_hRestoreBridges ); + + GenerateJacks_Output( m_bSpecular ? 2 : 1 ); + + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "diffuse" ); + if ( m_bSpecular ) + LockJackOutput_Flags( 1, HLSLVAR_FLOAT3, "specular" ); + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} + +KeyValues *CNodeFlashlight::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_flashlight_Spec", m_bSpecular ? 1 : 0 ); + return pKV; +} +void CNodeFlashlight::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_bSpecular = !!pKV->GetInt( "i_flashlight_Spec", m_bSpecular ); + UpdateNode(); +} + +bool CNodeFlashlight::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out_0 = GetJack_Out( 0 ); + CJack *pJ_Out_1 = m_bSpecular ? GetJack_Out( 1 ) : NULL; + + CHLSL_Var *tg_0 = NULL; + CHLSL_Var *tg_1 = NULL; + + tg_0 = GetInputToWriteTo( pJ_Out_0->GetSmartType() ); + if ( m_bSpecular ) + tg_1 = GetInputToWriteTo( pJ_Out_1->GetSmartType() ); + + SetAllocating( !(m_bSpecular ? (tg_0 != NULL) : (tg_0 && tg_1)) ); + + if ( !tg_0 ) + tg_0 = pJ_Out_0->AllocateVarFromSmartType(); + pJ_Out_0->SetTemporaryVarTarget( tg_0 ); + if ( m_bSpecular ) + { + if ( !tg_1 ) + tg_1 = pJ_Out_1->AllocateVarFromSmartType(); + pJ_Out_1->SetTemporaryVarTarget( tg_1 ); + } + + CHLSL_Solver_Flashlight *solver = new CHLSL_Solver_Flashlight( GetUniqueIndex() ); + solver->SetState( m_bSpecular ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + solver->AddTargetVar( GetJack_Out(i)->GetTemporaryVarTarget() ); + AddSolver( solver ); + + return true; +} + + +CNodeFlashlight_Position::CNodeFlashlight_Position( CNodeView *p ) : BaseClass( "FL Pos", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "pos" ); +} +CNodeFlashlight_Position::~CNodeFlashlight_Position() +{ +} +bool CNodeFlashlight_Position::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out_0 = GetJack_Out( 0 ); + CHLSL_Var *tg_0 = pJ_Out_0->AllocateVarFromSmartType(); + tg_0->MakeConstantOnly(); + + SetAllocating( false ); + + CHLSL_Solver_Flashlight_Pos *solver = new CHLSL_Solver_Flashlight_Pos( GetUniqueIndex() ); + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + solver->AddTargetVar( GetJack_Out(i)->GetTemporaryVarTarget() ); + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_flashlight.h b/sp/src/shadereditor/nodes/vnode_flashlight.h new file mode 100644 index 00000000..c66c6e1a --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_flashlight.h @@ -0,0 +1,48 @@ +#ifndef CNODE_FLASHLIGHT_H +#define CNODE_FLASHLIGHT_H + +#include "vBaseNode.h" + +class CNodeFlashlight : public CBaseNode +{ + DECLARE_CLASS( CNodeFlashlight, CBaseNode ); + +public: + + CNodeFlashlight( CNodeView *p ); + ~CNodeFlashlight(); + + virtual int GetNodeType(){ return HLSLNODE_UTILITY_FLASHLIGHT; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + void UpdateNode(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + bool m_bSpecular; +}; + + + +class CNodeFlashlight_Position : public CBaseNode +{ + DECLARE_CLASS( CNodeFlashlight_Position, CBaseNode ); + +public: + + CNodeFlashlight_Position( CNodeView *p ); + ~CNodeFlashlight_Position(); + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_FLASHLIGHTPOS; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_fog.cpp b/sp/src/shadereditor/nodes/vnode_fog.cpp new file mode 100644 index 00000000..71eb5d98 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_fog.cpp @@ -0,0 +1,66 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeFog::CNodeFog( CNodeView *p ) : BaseClass( "Fog factor", p ) +{ +#ifdef SHADER_EDITOR_DLL_SWARM + GenerateJacks_Input( 3 ); +#else + GenerateJacks_Input( 4 ); +#endif + GenerateJacks_Output( 1 ); + + LockJackInput_Flags( 0, HLSLVAR_FLOAT4, "Fog params" ); +#ifdef SHADER_EDITOR_DLL_SWARM + LockJackInput_Flags( 1, HLSLVAR_FLOAT3, "View pos" ); + LockJackInput_Flags( 2, HLSLVAR_FLOAT3, "World pos" ); +#else + LockJackInput_Flags( 1, HLSLVAR_FLOAT1, "View pos z" ); + LockJackInput_Flags( 2, HLSLVAR_FLOAT1, "World pos z" ); + LockJackInput_Flags( 3, HLSLVAR_FLOAT1, "Proj pos z" ); +#endif + + LockJackOutput_Flags( 0, HLSLVAR_FLOAT1, "Fog factor" ); +} + +CNodeFog::~CNodeFog() +{ +} + + +bool CNodeFog::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ3 = GetJack_In( 2 ); +#ifndef SHADER_EDITOR_DLL_SWARM + CJack *pJ4 = GetJack_In( 3 ); +#endif + CJack *pJ_Out = GetJack_Out( 0 ); + + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( pJ_Out->GetSmartType() ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Fog *solver = new CHLSL_Solver_Fog( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ3->GetTemporaryVarTarget_End() ); +#ifndef SHADER_EDITOR_DLL_SWARM + solver->AddSourceVar( pJ4->GetTemporaryVarTarget_End() ); +#endif + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_fog.h b/sp/src/shadereditor/nodes/vnode_fog.h new file mode 100644 index 00000000..15efd389 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_fog.h @@ -0,0 +1,23 @@ +#ifndef CNODE_FOG_H +#define CNODE_FOG_H + +#include "vBaseNode.h" + +class CNodeFog : public CBaseNode +{ + DECLARE_CLASS( CNodeFog, CBaseNode ); + +public: + + CNodeFog( CNodeView *p ); + ~CNodeFog(); + + virtual int GetNodeType(){ return HLSLNODE_UTILITY_FOG; }; + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_lerp.cpp b/sp/src/shadereditor/nodes/vnode_lerp.cpp new file mode 100644 index 00000000..3bd54ed7 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_lerp.cpp @@ -0,0 +1,101 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeLerp::CNodeLerp( CNodeView *p ) : BaseClass( "Lerp", p ) +{ + GenerateJacks_Input( 3 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 2, HLSLJACKFLAGS_F1_TO_F4 ); + //LockJackInput_Flags( 2, HLSLVAR_FLOAT1, "frac" ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "A" ); + GetJack_In( 1 )->SetName( "B" ); + GetJack_In( 2 )->SetName( "frac" ); +} + +CNodeLerp::~CNodeLerp() +{ +} + +int CNodeLerp::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + int vartype_jack_2 = GetJack_In( 2 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_2 > vartype_jack_0 && + vartype_jack_2 > vartype_jack_1 ) + locallevel = ERRORLEVEL_FAIL; + else if ( vartype_jack_2 != vartype_jack_0 && + vartype_jack_2 != vartype_jack_1 && + vartype_jack_2 != HLSLVAR_FLOAT1 ) + locallevel = ERRORLEVEL_FAIL; + + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + locallevel = ERRORLEVEL_FAIL; + } + else if ( vartype_jack_0 >= HLSLVAR_MATRIX3X3 || + vartype_jack_1 >= HLSLVAR_MATRIX3X3 || + vartype_jack_2 >= HLSLVAR_MATRIX3X3 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeLerp::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( max( GetJack_In(0)->GetSmartType(), GetJack_In(1)->GetSmartType() ) ); +} +bool CNodeLerp::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 3 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ3 = GetJack_In( 2 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type1 = pJ1->GetSmartType(); + int type2 = pJ2->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( max( type1, type2 ) ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Lerp *solver = new CHLSL_Solver_Lerp( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ3->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_lerp.h b/sp/src/shadereditor/nodes/vnode_lerp.h new file mode 100644 index 00000000..e3efe2db --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_lerp.h @@ -0,0 +1,26 @@ +#ifndef CNODE_LERP_H +#define CNODE_LERP_H + +#include "vBaseNode.h" + +class CNodeLerp : public CBaseNode +{ + DECLARE_CLASS( CNodeLerp, CBaseNode ); + +public: + + CNodeLerp( CNodeView *p ); + ~CNodeLerp(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_LERP; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_lightscale.cpp b/sp/src/shadereditor/nodes/vnode_lightscale.cpp new file mode 100644 index 00000000..354d221d --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_lightscale.cpp @@ -0,0 +1,55 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeLightscale::CNodeLightscale( CNodeView *p ) : BaseClass( "Lightscale", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT1, "" ); + m_iLightScale = LSCALE_LINEAR; + UpdateNode(); +} + +CNodeLightscale::~CNodeLightscale() +{ +} + +void CNodeLightscale::UpdateNode() +{ + GetJack_Out( 0 )->SetName( GetLightscaleGameString( m_iLightScale ) ); +} + + +KeyValues *CNodeLightscale::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_lscale_type", m_iLightScale ); + return pKV; +} +void CNodeLightscale::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iLightScale = pKV->GetInt( "i_lscale_type", m_iLightScale ); + UpdateNode(); +} + +bool CNodeLightscale::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_Lightscale *solver = new CHLSL_Solver_Lightscale( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + solver->SetState( m_iLightScale ); + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_lightscale.h b/sp/src/shadereditor/nodes/vnode_lightscale.h new file mode 100644 index 00000000..dcad0e2f --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_lightscale.h @@ -0,0 +1,30 @@ +#ifndef CNODE_LIGHTSCALE_H +#define CNODE_LIGHTSCALE_H + +#include "vBaseNode.h" + +class CNodeLightscale : public CBaseNode +{ + DECLARE_CLASS( CNodeLightscale, CBaseNode ); + +public: + + CNodeLightscale( CNodeView *p ); + ~CNodeLightscale(); + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_LIGHTSCALE; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + void UpdateNode(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iLightScale; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_loop.cpp b/sp/src/shadereditor/nodes/vnode_loop.cpp new file mode 100644 index 00000000..51fed5bf --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_loop.cpp @@ -0,0 +1,66 @@ + +#include "cbase.h" +#include "editorcommon.h" + + +CNodeLoop::CNodeLoop( CNodeView *p ) : BaseClass( "Loop", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT1, "Iteration" ); + + m_iCondition = ITERATORCOND_SMALLER; + m_iValue_Start = 0; + m_iValue_End = 1; + bDecrement = false; +} + +CNodeLoop::~CNodeLoop() +{ +} + +void CNodeLoop::Solve_ContainerEntered() +{ + CJack *pJO = GetJack_Out( 0 ); + CHLSL_Var *varIterator = pJO->AllocateVarFromSmartType(); + varIterator->MakeConstantOnly(); + + CHLSL_Solver_LoopIntro *solver_intro = new CHLSL_Solver_LoopIntro( GetUniqueIndex() ); + CHLSL_Solver_Iterator *solver_iterator = new CHLSL_Solver_Iterator( GetUniqueIndex() ); + + solver_intro->m_iCondition = m_iCondition; + solver_intro->m_iValue_Start = m_iValue_Start; + solver_intro->m_iValue_End = m_iValue_End; + solver_intro->bDecrement = bDecrement; + solver_intro->AddTargetVar( varIterator ); + AddSolver( solver_intro ); + + solver_iterator->AddTargetVar( varIterator ); + AddSolver( solver_iterator ); +} +void CNodeLoop::Solve_ContainerLeft() +{ + CHLSL_Solver_LoopOutro *solver_outro = new CHLSL_Solver_LoopOutro( GetUniqueIndex() ); + AddSolver( solver_outro ); +} + +KeyValues *CNodeLoop::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "loop_condition", m_iCondition ); + pKV->SetInt( "loop_value_min", m_iValue_Start ); + pKV->SetInt( "loop_value_max", m_iValue_End ); + + return pKV; +} +void CNodeLoop::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + BaseClass::RestoreFromKeyValues_Specific( pKV ); + + m_iCondition = pKV->GetInt( "loop_condition", m_iCondition ); + m_iValue_Start = pKV->GetInt( "loop_value_min", m_iValue_Start ); + m_iValue_End = pKV->GetInt( "loop_value_max", m_iValue_End ); + + bDecrement = m_iValue_Start > m_iValue_End; + pNodeView->MakeSolversDirty(); +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_loop.h b/sp/src/shadereditor/nodes/vnode_loop.h new file mode 100644 index 00000000..b9908119 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_loop.h @@ -0,0 +1,32 @@ +#ifndef CNODELOOP_H +#define CNODELOOP_H + +#include "vBaseContainer.h" + +class CNodeLoop : public CBaseContainerNode +{ + DECLARE_CLASS( CNodeLoop, CBaseContainerNode ); + +public: + + CNodeLoop( CNodeView *p ); + ~CNodeLoop(); + + virtual int GetNodeType(){ return HLSLNODE_CONTROLFLOW_LOOP; }; + + virtual void Solve_ContainerEntered(); + virtual void Solve_ContainerLeft(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + + int m_iCondition; + int m_iValue_Start; + int m_iValue_End; + bool bDecrement; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_matrices.cpp b/sp/src/shadereditor/nodes/vnode_matrices.cpp new file mode 100644 index 00000000..ad4b01b0 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_matrices.cpp @@ -0,0 +1,162 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeMatrix_MVP::CNodeMatrix_MVP( CNodeView *p ) : BaseClass( "Matrix MVP", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_MATRIX4X4, "Model View Projection" ); +} +bool CNodeMatrix_MVP::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_MVP *solver = new CHLSL_Solver_MVP( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + return true; +} + + +CNodeMatrix_VP::CNodeMatrix_VP( CNodeView *p ) : BaseClass( "Matrix VP", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_MATRIX4X4, "View Projection" ); +} +bool CNodeMatrix_VP::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_VP *solver = new CHLSL_Solver_VP( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + return true; +} + + + +CNodeMatrix_M::CNodeMatrix_M( CNodeView *p ) : BaseClass( "Matrix Model", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_MATRIX4X3, "Model transform" ); +} +bool CNodeMatrix_M::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_M *solver = new CHLSL_Solver_M( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + return true; +} + + + + + + +CNodeMatrix_VM::CNodeMatrix_VM( CNodeView *p ) : BaseClass( "Matrix VP", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_MATRIX4X4, "View Model" ); +} +bool CNodeMatrix_VM::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_VM *solver = new CHLSL_Solver_VM( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + return true; +} + + + + + +CNodeMatrix_FVP::CNodeMatrix_FVP( CNodeView *p ) : BaseClass( "Flashlight VP", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_MATRIX4X4, "Flashlight View Proj" ); +} +bool CNodeMatrix_FVP::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_FVP *solver = new CHLSL_Solver_FVP( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + return true; +} + + + +CNodeMatrix_Custom::CNodeMatrix_Custom( CNodeView *p ) : BaseClass( "Custom matrix", p ) +{ + m_iCustomID = CMATRIX_VIEW; + GenerateJacks_Output( 1 ); + UpdateNode(); +} +void CNodeMatrix_Custom::UpdateNode() +{ + const customMatrix_t *data = GetCMatrixInfo( m_iCustomID ); + LockJackOutput_Flags( 0, data->iHLSLVarFlag, data->szCanvasName ); +} +KeyValues *CNodeMatrix_Custom::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_c_matrix", m_iCustomID ); + return pKV; +} +void CNodeMatrix_Custom::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iCustomID = pKV->GetInt( "i_c_matrix" ); + UpdateNode(); +} +bool CNodeMatrix_Custom::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_CMatrix *solver = new CHLSL_Solver_CMatrix( GetUniqueIndex() ); + solver->SetMatrixID( m_iCustomID ); + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_matrices.h b/sp/src/shadereditor/nodes/vnode_matrices.h new file mode 100644 index 00000000..086e7a64 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_matrices.h @@ -0,0 +1,98 @@ +#ifndef CNODEMATRICES_H +#define CNODEMATRICES_H + +#include "vBaseNode.h" + +class CNodeMatrix_MVP : public CBaseNode +{ + DECLARE_CLASS( CNodeMatrix_MVP, CBaseNode ); +public: + CNodeMatrix_MVP( CNodeView *p ); + virtual int GetNodeType(){ return HLSLNODE_MATRIX_MODELVIEWPROJ; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); +}; + + +class CNodeMatrix_VP : public CBaseNode +{ + DECLARE_CLASS( CNodeMatrix_VP, CBaseNode ); +public: + CNodeMatrix_VP( CNodeView *p ); + virtual int GetNodeType(){ return HLSLNODE_MATRIX_VIEWPROJ; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); +}; + + +class CNodeMatrix_M : public CBaseNode +{ + DECLARE_CLASS( CNodeMatrix_M, CBaseNode ); +public: + CNodeMatrix_M( CNodeView *p ); + virtual int GetNodeType(){ return HLSLNODE_MATRIX_MODEL; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); +}; + + + +class CNodeMatrix_VM : public CBaseNode +{ + DECLARE_CLASS( CNodeMatrix_VM, CBaseNode ); +public: + CNodeMatrix_VM( CNodeView *p ); + virtual int GetNodeType(){ return HLSLNODE_MATRIX_VIEWMODEL; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); +}; + + + + +class CNodeMatrix_FVP : public CBaseNode +{ + DECLARE_CLASS( CNodeMatrix_FVP, CBaseNode ); +public: + CNodeMatrix_FVP( CNodeView *p ); + virtual int GetNodeType(){ return HLSLNODE_MATRIX_FLASHLIGHT; }; + //virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); +}; + + +class CNodeMatrix_Custom : public CBaseNode +{ + DECLARE_CLASS( CNodeMatrix_Custom, CBaseNode ); +public: + CNodeMatrix_Custom( CNodeView *p ); + virtual int GetNodeType(){ return HLSLNODE_MATRIX_CUSTOM; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + void UpdateNode(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iCustomID; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_mcompose.cpp b/sp/src/shadereditor/nodes/vnode_mcompose.cpp new file mode 100644 index 00000000..7b132bbd --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_mcompose.cpp @@ -0,0 +1,86 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeMCompose::CNodeMCompose( CNodeView *p ) : BaseClass( "MCompose", p ) +{ + GenerateJacks_Output( 1 ); + + iTargetMatrix = HLSLVAR_MATRIX3X3; + bColumns = false; + UpdateNode(); +} + +CNodeMCompose::~CNodeMCompose() +{ +} + +void CNodeMCompose::SetTargetMatrix( int flag, bool docolumns ) +{ + iTargetMatrix = flag; + bColumns = docolumns; +} + +void CNodeMCompose::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + int numInputs = 3; + if ( iTargetMatrix == HLSLVAR_MATRIX4X4 || + (iTargetMatrix == HLSLVAR_MATRIX4X3 && bColumns) ) + numInputs = 4; + + GenerateJacks_Input( numInputs ); + + int type = HLSLVAR_FLOAT3; + if ( iTargetMatrix == HLSLVAR_MATRIX4X4 || + (iTargetMatrix == HLSLVAR_MATRIX4X3 && !bColumns) ) + type = HLSLVAR_FLOAT4; + + for ( int i = 0; i < numInputs; i++ ) + LockJackInput_Flags( i, type, VarArgs( "%c", (((int)'A')+i) ) ); + + LockJackOutput_Flags( 0, iTargetMatrix ); + + RestoreBridgesFromList_In( m_hRestoreBridges ); +} + +KeyValues *CNodeMCompose::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_mcomp_matrix", iTargetMatrix ); + pKV->SetInt( "i_mcomp_c", bColumns ? 1 : 0 ); + return pKV; +} +void CNodeMCompose::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + BaseClass::RestoreFromKeyValues_Specific( pKV ); + iTargetMatrix = pKV->GetInt( "i_mcomp_matrix", iTargetMatrix ); + bColumns = !!pKV->GetInt( "i_mcomp_c", bColumns ); + UpdateNode(); +} + +bool CNodeMCompose::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + SetAllocating( true ); + + CHLSL_Solver_MComp *solver = new CHLSL_Solver_MComp( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( iTargetMatrix, bColumns ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_mcompose.h b/sp/src/shadereditor/nodes/vnode_mcompose.h new file mode 100644 index 00000000..2eff103e --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_mcompose.h @@ -0,0 +1,31 @@ +#ifndef CNODE_MCOMPOSE_H +#define CNODE_MCOMPOSE_H + +#include "vBaseNode.h" + +class CNodeMCompose : public CBaseNode +{ + DECLARE_CLASS( CNodeMCompose, CBaseNode ); + +public: + + CNodeMCompose( CNodeView *p ); + ~CNodeMCompose(); + + virtual int GetNodeType(){ return HLSLNODE_MATRIX_COMPOSE; }; + + void SetTargetMatrix( int flag, bool docolumns ); + void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int iTargetMatrix; + bool bColumns; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_multiply.cpp b/sp/src/shadereditor/nodes/vnode_multiply.cpp new file mode 100644 index 00000000..93eb923b --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_multiply.cpp @@ -0,0 +1,175 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeMultiply::CNodeMultiply( CNodeView *p ) : BaseClass( "Multiply", p ) +{ + m_bMatrixRotation = false; + + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_ALL ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_ALL ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_ALL ); + + GetJack_In( 0 )->SetName( "A" ); + GetJack_In( 1 )->SetName( "B" ); +} + +CNodeMultiply::~CNodeMultiply() +{ +} + +KeyValues *CNodeMultiply::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_mat_rotation", m_bMatrixRotation ? 1 : 0 ); + return pKV; +} +void CNodeMultiply::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_bMatrixRotation = pKV->GetInt( "i_mat_rotation" ) != 0; + + OnUpdateHierachy( NULL, NULL ); +} + +int CNodeMultiply::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + { + // unequal types && none is float1 + // 3 * 3x3 -> float3 + // 3 * 4x3 - append 1 -> float3 + // 4 * 4x3 -> float3 + // 3 * 4x4 - append 1 -> float4 + // 4 * 4x4 -> float4 + if ( vartype_jack_0 != HLSLVAR_FLOAT3 && + vartype_jack_0 != HLSLVAR_FLOAT4 && + vartype_jack_0 != HLSLVAR_MATRIX3X3 && + vartype_jack_0 != HLSLVAR_MATRIX4X3 ) + locallevel = ERRORLEVEL_FAIL; + else if ( vartype_jack_0 == HLSLVAR_FLOAT3 && + vartype_jack_1 != HLSLVAR_MATRIX3X3 && + vartype_jack_1 != HLSLVAR_MATRIX4X3 && + vartype_jack_1 != HLSLVAR_MATRIX4X4 ) + locallevel = ERRORLEVEL_FAIL; + else if ( vartype_jack_0 == HLSLVAR_FLOAT4 && + vartype_jack_1 != HLSLVAR_MATRIX4X3 && + vartype_jack_1 != HLSLVAR_MATRIX4X4 ) + locallevel = ERRORLEVEL_FAIL; + else if ( vartype_jack_0 == HLSLVAR_MATRIX3X3 && + vartype_jack_1 != HLSLVAR_FLOAT3 ) + locallevel = ERRORLEVEL_FAIL; + } + } + else + { + // equal types: + // 1 * 1 + // 2 * 2 + // 3 * 3 + // 4 * 4 + // 3x3 * 3x3 + // 4x4 * 4x4 + if ( vartype_jack_0 == HLSLVAR_MATRIX4X3 ) + locallevel = ERRORLEVEL_FAIL; + } + } + + return max( locallevel, baseLevel ); +} +void CNodeMultiply::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + CJack *pJO = GetJack_Out( 0 ); + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int iGoalSmarttype = HLSLVAR_FLOAT4; + + // matrices out + if ( vartype_jack_0 == HLSLVAR_MATRIX3X3 && vartype_jack_1 == HLSLVAR_MATRIX3X3 ) + iGoalSmarttype = HLSLVAR_MATRIX3X3; + else if ( vartype_jack_0 == HLSLVAR_MATRIX4X4 && vartype_jack_1 == HLSLVAR_MATRIX4X4 ) + iGoalSmarttype = HLSLVAR_MATRIX4X4; + else if ( vartype_jack_0 == HLSLVAR_MATRIX4X3 && vartype_jack_1 == HLSLVAR_MATRIX4X4 ) + iGoalSmarttype = HLSLVAR_MATRIX4X4; + // vector out + else if ( vartype_jack_0 == HLSLVAR_FLOAT1 || vartype_jack_1 == HLSLVAR_FLOAT1 ) + iGoalSmarttype = max( vartype_jack_0, vartype_jack_1 ); + else if ( vartype_jack_0 == vartype_jack_1 ) + iGoalSmarttype = vartype_jack_0; + // vector transform out + else if ( vartype_jack_1 == HLSLVAR_MATRIX3X3 || + vartype_jack_0 == HLSLVAR_MATRIX3X3 || + vartype_jack_1 == HLSLVAR_MATRIX4X3 || + ( vartype_jack_1 == HLSLVAR_MATRIX4X4 && m_bMatrixRotation ) ) + iGoalSmarttype = HLSLVAR_FLOAT3; + + return pJO->SetSmartType( iGoalSmarttype ); + //GetJack_Out( 0 )->SetSmartType( max( GetJack_In(0)->GetSmartType(), GetJack_In(1)->GetSmartType() ) ); +} +bool CNodeMultiply::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type1 = pJ1->GetSmartType(); + int type2 = pJ2->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = NULL; + + if ( type1 == type2 || type1 == HLSLVAR_FLOAT1 || type2 == HLSLVAR_FLOAT1 ) + tg = GetInputToWriteTo( max( type1, type2 ) ); + else if ( type1 == HLSLVAR_FLOAT3 && type2 == HLSLVAR_MATRIX3X3 ) + tg = GetInputToWriteTo( HLSLVAR_FLOAT3 ); + else if ( type1 == HLSLVAR_FLOAT3 && type2 == HLSLVAR_MATRIX4X3 ) + tg = GetInputToWriteTo( HLSLVAR_FLOAT3 ); + else if ( type1 == HLSLVAR_FLOAT4 && type2 == HLSLVAR_MATRIX4X4 ) + tg = GetInputToWriteTo( HLSLVAR_FLOAT4 ); + else if ( type1 == HLSLVAR_MATRIX3X3 && type2 == HLSLVAR_FLOAT3 ) + tg = GetInputToWriteTo( HLSLVAR_FLOAT3 ); + + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Multiply *solver = new CHLSL_Solver_Multiply( GetUniqueIndex() ); + solver->SetMatrixRotationOnly( m_bMatrixRotation ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + //Msg("add solver has %i src vars\n", solver->GetNumSourceVars()); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_multiply.h b/sp/src/shadereditor/nodes/vnode_multiply.h new file mode 100644 index 00000000..d0d4054a --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_multiply.h @@ -0,0 +1,31 @@ +#ifndef CNODEMULTIPLY_H +#define CNODEMULTIPLY_H + +#include "vBaseNode.h" + +class CNodeMultiply : public CBaseNode +{ + DECLARE_CLASS( CNodeMultiply, CBaseNode ); + +public: + + CNodeMultiply( CNodeView *p ); + ~CNodeMultiply(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_MULTIPLY; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + bool m_bMatrixRotation; + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_parallax.cpp b/sp/src/shadereditor/nodes/vnode_parallax.cpp new file mode 100644 index 00000000..beef3fc3 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_parallax.cpp @@ -0,0 +1,160 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeParallax::CNodeParallax( CNodeView *p ) : BaseClass( "Parallax UV", p ) +{ + UpdateNode(); +} + +CNodeParallax::~CNodeParallax() +{ +} + +void CNodeParallax::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges_I, m_hRestoreBridges_O; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges_I ); + CreateBridgeRestoreData_Out( CBaseNode::BY_NAME, m_hRestoreBridges_O ); + + const bool bDepthTest = m_PSetup.bGetOffset; + //GenerateJacks_Input( bDepthTest ? 7 : 6 ); + GenerateJacks_Input( 7 ); + GenerateJacks_Output( bDepthTest ? 2 : 1 ); + + int iCurJack = 0; + + LockJackInput_Flags( iCurJack, HLSLVAR_FLOAT2, "UV" );iCurJack++; + LockJackInput_Flags( iCurJack, HLSLVAR_FLOAT3, "View TSpace" );iCurJack++; + LockJackInput_Flags( iCurJack, HLSLVAR_FLOAT1, "Parallax Amt" );iCurJack++; + //if ( bDepthTest ) + { + LockJackInput_Flags( iCurJack, HLSLVAR_FLOAT3, "World pos" );iCurJack++; + } + LockJackInput_Flags( iCurJack, HLSLVAR_FLOAT3, "World normal" );iCurJack++; + LockJackInput_Flags( iCurJack, HLSLVAR_FLOAT3, "Eye dir" );iCurJack++; + LockJackInput_Flags( iCurJack, HLSLVAR_SAMPLER, "Heightmap" );iCurJack++; + + LockJackOutput_Flags( 0, HLSLVAR_FLOAT2, "UV" ); + if ( bDepthTest ) + LockJackOutput_Flags( 1, HLSLVAR_FLOAT3, "Tan offset" ); + + + RestoreBridgesFromList_In( m_hRestoreBridges_I ); + RestoreBridgesFromList_Out( m_hRestoreBridges_O ); +} + +KeyValues *CNodeParallax::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_samples_min", m_PSetup.iSamplesMin ); + pKV->SetInt( "i_samples_max", m_PSetup.iSamplesMax ); + pKV->SetInt( "i_samples_binary", m_PSetup.iBinaryMax ); + pKV->SetInt( "i_dtest", m_PSetup.bGetOffset ? 1 : 0 ); + pKV->SetInt( "i_gradient", m_PSetup.bGradientLookup ? 1 : 0 ); + pKV->SetInt( "i_prlx_mode", m_PSetup.iParallaxMode ); + return pKV; +} +void CNodeParallax::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_PSetup.iSamplesMin = pKV->GetInt( "i_samples_min" ); + m_PSetup.iSamplesMax = pKV->GetInt( "i_samples_max" ); + m_PSetup.iBinaryMax = pKV->GetInt( "i_samples_binary" ); + m_PSetup.bGetOffset = !!pKV->GetInt( "i_dtest" ); + m_PSetup.bGradientLookup = !!pKV->GetInt( "i_gradient" ); + m_PSetup.iParallaxMode = pKV->GetInt( "i_prlx_mode" ); + + UpdateNode(); +} + +bool CNodeParallax::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out_0 = GetJack_Out( 0 ); + CJack *pJ_Out_1 = m_PSetup.bGetOffset ? GetJack_Out( 1 ) : NULL; + + const int res = pJ_Out_0->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( pJ_Out_0->GetSmartType() ); + CHLSL_Var *tg2 = pJ_Out_1 ? GetInputToWriteTo( pJ_Out_1->GetSmartType() ) : NULL; + if ( tg2 == tg ) + tg2 = NULL; + + SetAllocating( !tg || (pJ_Out_1 && !tg2) ); + + if ( !tg ) + tg = pJ_Out_0->AllocateVarFromSmartType(); + pJ_Out_0->SetTemporaryVarTarget( tg ); + + if ( pJ_Out_1 ) + { + if ( !tg2 ) + tg2 = pJ_Out_1->AllocateVarFromSmartType(); + pJ_Out_1->SetTemporaryVarTarget( tg2 ); + } + + CHLSL_Solver_Parallax *solver = new CHLSL_Solver_Parallax( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( m_PSetup ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + if ( pJ_Out_1 ) + solver->AddTargetVar( tg2 ); + else + solver->AddTargetVar( new CHLSL_Var( HLSLVAR_FLOAT3 ) ); + AddSolver( solver ); + return true; +} + + + +CNodeParallax_StdShadow::CNodeParallax_StdShadow( CNodeView *p ) : BaseClass( "Parallax shadow", p ) +{ + GenerateJacks_Input( 7 ); + GenerateJacks_Output( 1 ); + + LockJackInput_Flags( 0, HLSLVAR_FLOAT2, "UV" ); + LockJackInput_Flags( 1, HLSLVAR_FLOAT2, "Parallax UV" ); + LockJackInput_Flags( 2, HLSLVAR_FLOAT3, "Light TSpace" ); + LockJackInput_Flags( 3, HLSLVAR_FLOAT1, "Parallax Amt" ); + LockJackInput_Flags( 4, HLSLVAR_FLOAT3, "World pos" ); + LockJackInput_Flags( 5, HLSLVAR_FLOAT1, "Softening" ); + LockJackInput_Flags( 6, HLSLVAR_SAMPLER, "Heightmap" ); + + LockJackOutput_Flags( 0, HLSLVAR_FLOAT1, "Light" ); +} + +CNodeParallax_StdShadow::~CNodeParallax_StdShadow() +{ +} + +bool CNodeParallax_StdShadow::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out_0 = GetJack_Out( 0 ); + + const int res = pJ_Out_0->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( pJ_Out_0->GetSmartType() ); + + SetAllocating( !tg ); + + if ( !tg ) + tg = pJ_Out_0->AllocateVarFromSmartType(); + pJ_Out_0->SetTemporaryVarTarget( tg ); + + + CHLSL_Solver_Parallax_StdShadow *solver = new CHLSL_Solver_Parallax_StdShadow( GetUniqueIndex() ); + solver->SetResourceType( res ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_parallax.h b/sp/src/shadereditor/nodes/vnode_parallax.h new file mode 100644 index 00000000..72df6260 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_parallax.h @@ -0,0 +1,49 @@ +#ifndef CNODE_PARALLAX_H +#define CNODE_PARALLAX_H + +#include "vBaseNode.h" +#include "editorcommon.h" + +class CNodeParallax : public CBaseNode +{ + DECLARE_CLASS( CNodeParallax, CBaseNode ); + +public: + + CNodeParallax( CNodeView *p ); + ~CNodeParallax(); + + virtual int GetNodeType(){ return HLSLNODE_TEXTURE_PARALLAX; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + void UpdateNode(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + //int iSamp_Min; + //int iSamp_Max; + //bool bDepthTest; + ParallaxConfig_t m_PSetup; +}; + +class CNodeParallax_StdShadow : public CBaseNode +{ + DECLARE_CLASS( CNodeParallax_StdShadow, CBaseNode ); +public: + + CNodeParallax_StdShadow( CNodeView *p ); + ~CNodeParallax_StdShadow(); + + virtual int GetNodeType(){ return HLSLNODE_TEXTURE_PARALLAX_SHADOW; }; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_psinput.cpp b/sp/src/shadereditor/nodes/vnode_psinput.cpp new file mode 100644 index 00000000..b2e56547 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_psinput.cpp @@ -0,0 +1,181 @@ + +#include "cbase.h" +#include "editorCommon.h" +#include "vSheets.h" + + +CNodePSInput::CNodePSInput( CNodeView *p ) : BaseClass( "PS Input", p ) +{ + m_flMinSizeX = CRUCIALNODE_MIN_SIZE_X; + m_flMinSizeY = 0; + m_bPreviewEnabled = false; + + SETUP_HLSL_VS_Output_PS_Input defaultInfo; + Setup( defaultInfo ); +} + +CNodePSInput::~CNodePSInput() +{ +} + +void CNodePSInput::Setup( SETUP_HLSL_VS_Output_PS_Input info ) +{ + int numInputs = 0; + numInputs += info.iTexcoords_num; + numInputs += info.iVertexcolor_num; + + int extraRows = 0; + for ( int i = 0; i < info.iTexcoords_num; i++ ) + { + int rows = max(0,GetVarFlagsRowsRequired( info.iTexCoordFlag[i] ) - 1); + extraRows += rows; + } + + numInputs -= extraRows; + + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_Out( CBaseNode::BY_RESTYPE, m_hRestoreBridges ); + + GenerateJacks_Output( numInputs ); + + int curInput = 0; + int texCoordNameOffset = 0; + //int texCoordLookupOffset = 0; + + for ( int i = 0; i < info.iTexcoords_num - extraRows; i++ ) + { + GetJack_Out( curInput )->SetResourceType( RESOURCETYPE_TEXCOORD_0 + i ); + LockJackOutput_Flags( curInput, info.iTexCoordFlag[texCoordNameOffset], VarArgs("TexCoords %i", texCoordNameOffset) ); + int localRows = GetVarFlagsRowsRequired( info.iTexCoordFlag[ texCoordNameOffset ] ); + texCoordNameOffset += localRows; + curInput++; + } + + for ( int i = 0; i < info.iVertexcolor_num; i++ ) + { + GetJack_Out( curInput )->SetResourceType( RESOURCETYPE_COLOR_0 + i ); + LockJackOutput_Flags( curInput, info.iColorFlag[i], VarArgs("Color %i",i) ); + curInput++; + } + curSetup = info; + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} +void CNodePSInput::LoadNames() +{ + int numInputs = 0; + numInputs += curSetup.iTexcoords_num; + numInputs += curSetup.iVertexcolor_num; + + int extraRows = 0; + for ( int i = 0; i < curSetup.iTexcoords_num; i++ ) + { + int rows = max(0,GetVarFlagsRowsRequired( curSetup.iTexCoordFlag[i] ) - 1); + extraRows += rows; + } + + numInputs -= extraRows; + + int curInput = 0; + int texCoordNameOffset = 0; + + for ( int i = 0; i < curSetup.iTexcoords_num - extraRows; i++ ) + { + GetJack_Out(curInput)->SetResourceType( RESOURCETYPE_TEXCOORD_0 + texCoordNameOffset ); + if ( Q_strlen( curNames.names_texcoords[ texCoordNameOffset ] ) ) + GetJack_Out( curInput )->SetName( curNames.names_texcoords[ texCoordNameOffset ] ); + int localRows = GetVarFlagsRowsRequired( curSetup.iTexCoordFlag[ texCoordNameOffset ] ); + texCoordNameOffset += localRows; + curInput++; + } + for ( int i = 0; i < curSetup.iVertexcolor_num; i++ ) + { + if ( Q_strlen( curNames.names_colors[ i ] ) ) + GetJack_Out( curInput )->SetName( curNames.names_colors[ i ] ); + curInput++; + } +} +KeyValues *CNodePSInput::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "numTexcoords", curSetup.iTexcoords_num ); + pKV->SetInt( "numColor", curSetup.iVertexcolor_num ); + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + pKV->SetInt( VarArgs( "numTexcoord_Flag_%i", i ), curSetup.iTexCoordFlag[ i ] ); + pKV->SetString( VarArgs( "numTexcoord_Name_%i", i ), curNames.names_texcoords[ i ] ); + } + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + { + pKV->SetInt( VarArgs( "numColor_Flag_%i", i ), curSetup.iColorFlag[ i ] ); + pKV->SetString( VarArgs( "numColor_Name_%i", i ), curNames.names_colors[ i ] ); + } + return pKV; +} +void CNodePSInput::RestoreFromKeyValues( KeyValues *pKV ) +{ + BaseClass::RestoreFromKeyValues( pKV ); + + CBaseNode *pPartner = pNodeView->GetNodeFromType( HLSLNODE_VS_OUT ); + if ( pPartner ) + pPartner->RestoreFromKeyValues_Specific( pKV ); +} +void CNodePSInput::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + SETUP_HLSL_VS_Output_PS_Input info; + + info.iTexcoords_num = pKV->GetInt( "numTexcoords" ); + info.iVertexcolor_num = pKV->GetInt( "numColor" ); + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + info.iTexCoordFlag[ i ] = pKV->GetInt( VarArgs( "numTexcoord_Flag_%i", i ) ); + Q_snprintf( curNames.names_texcoords[ i ], sizeof(curNames.names_texcoords[ i ]), "%s", pKV->GetString( VarArgs( "numTexcoord_Name_%i", i ) ) ); + } + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + { + info.iColorFlag[ i ] = pKV->GetInt( VarArgs( "numColor_Flag_%i", i ) ); + Q_snprintf( curNames.names_colors[ i ], sizeof(curNames.names_colors[ i ]), "%s", pKV->GetString( VarArgs( "numColor_Name_%i", i ) ) ); + } + + Setup( info ); + LoadNames(); +} +int CNodePSInput::PerNodeErrorLevel() +{ +#if PSIN_ERROR_WHEN_VSOUT_ERROR + CNodeView *pView = GetParent(); + CBaseNode *pVS_Out = pView ? pView->GetNodeFromType( HLSLNODE_VS_OUT ) : NULL; + if ( !pVS_Out ) + return ERRORLEVEL_NONE; + if ( pVS_Out->GetErrorLevel() != ERRORLEVEL_NONE ) + return ERRORLEVEL_FAIL; +#endif + return BaseClass::PerNodeErrorLevel(); +} + +bool CNodePSInput::CreateSolvers(GenericShaderData *ShaderData) +{ + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJ = GetJack_Out( i ); + if ( !pJ->GetNumBridgesConnected() ) + continue; + + const int res = pJ->GetResourceType(); + CHLSL_Var *var = pJ->AllocateVarFromSmartType(); + var->MakeConstantOnly(); + + CHLSL_Solver_ReadSemantics *solver = new CHLSL_Solver_ReadSemantics( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddTargetVar( var ); + solver->GetData()._IntValue_0 = pJ->GetSmartType(); + //if ( pJ->GetSmartType() < 0 ) + // Warning("smarttype error!!\n"); + + AddSolver( solver ); + } + + SmartCreateDummySolver(); + return true; +} diff --git a/sp/src/shadereditor/nodes/vnode_psinput.h b/sp/src/shadereditor/nodes/vnode_psinput.h new file mode 100644 index 00000000..bf402e36 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_psinput.h @@ -0,0 +1,42 @@ +#ifndef CNODEPSINPUT_H +#define CNODEPSINPUT_H + +#include + +class CNodePSInput : public CBaseNode +{ + DECLARE_CLASS( CNodePSInput, CBaseNode ); + +public: + + CNodePSInput( CNodeView *p ); + ~CNodePSInput(); + + virtual bool CanBeInContainer(){ return false; }; + virtual int GetNodeType(){ return HLSLNODE_PS_IN; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsNodeCrucial(){ return true; }; + virtual int PerNodeErrorLevel(); + + virtual int GetHierachyType(){return HLSLHIERACHY_PS;}; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + virtual int UpdateInputsValid(){ return ERRORLEVEL_NONE; }; + + void Setup( SETUP_HLSL_VS_Output_PS_Input info ); + SETUP_HLSL_VS_Output_PS_Input &GetSetup(){ return curSetup; }; + + void LoadNames(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues( KeyValues *pKV ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + SETUP_HLSL_VS_Output_PS_Input curSetup; + SETUP_VSOUTPSIN_CustomNames curNames; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_psoutput.cpp b/sp/src/shadereditor/nodes/vnode_psoutput.cpp new file mode 100644 index 00000000..ea38d840 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_psoutput.cpp @@ -0,0 +1,95 @@ + +#include "cbase.h" +#include "editorCommon.h" +#include "vSheets.h" + + +CNodePSOutput::CNodePSOutput( CNodeView *p ) : BaseClass( "PS Output", p ) +{ + m_flMinSizeX = CRUCIALNODE_MIN_SIZE_X; + m_flMinSizeY = 0; + m_bPreviewEnabled = false; + + SETUP_HLSL_PS_Output defaultInfo; + Setup( defaultInfo ); +} + +CNodePSOutput::~CNodePSOutput() +{ +} + +void CNodePSOutput::Setup( SETUP_HLSL_PS_Output info ) +{ + int numInputs = 0; + numInputs += info.iNumRTs; + if ( info.bDepth ) + numInputs += 1; + + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_RESTYPE, m_hRestoreBridges ); + + GenerateJacks_Input( numInputs ); + + int curInput = 0; + + for ( int i = 0; i < info.iNumRTs; i++ ) + { + GetJack_In( curInput )->SetResourceType( RESOURCETYPE_COLOR_0 + i ); + LockJackInput_Flags( curInput, HLSLVAR_FLOAT4, VarArgs("Color %i",i) ); + curInput++; + } + if ( info.bDepth ) + { + GetJack_In( curInput )->SetResourceType( RESOURCETYPE_DEPTH ); + LockJackInput_Flags( curInput, HLSLVAR_FLOAT1, "Depth" ); + curInput++; + } + + curSetup = info; + RestoreBridgesFromList_In( m_hRestoreBridges ); +} +KeyValues *CNodePSOutput::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "numColors", curSetup.iNumRTs ); + pKV->SetInt( "enable_Depth", ( curSetup.bDepth ? 1 : 0 ) ); + + return pKV; +} +void CNodePSOutput::RestoreFromKeyValues( KeyValues *pKV ) +{ + BaseClass::RestoreFromKeyValues( pKV ); +} +void CNodePSOutput::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + SETUP_HLSL_PS_Output info; + + info.iNumRTs = pKV->GetInt( "numColors" ); + info.bDepth = !!pKV->GetInt( "enable_Depth" ); + + Setup( info ); +} + +bool CNodePSOutput::CreateSolvers(GenericShaderData *ShaderData) +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJ = GetJack_In( i ); + if ( !pJ->GetNumBridgesConnected() ) + continue; + + CJack *sourceJack = pJ->GetBridge( 0 )->GetInputJack(); + CHLSL_Var *src = sourceJack->GetTemporaryVarTarget(); + const int res = pJ->GetResourceType(); + + CHLSL_Solver_WriteSemantics *solver = new CHLSL_Solver_WriteSemantics( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( src ); + + AddSolver( solver ); + } + + SmartCreateDummySolver(); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_psoutput.h b/sp/src/shadereditor/nodes/vnode_psoutput.h new file mode 100644 index 00000000..fde27072 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_psoutput.h @@ -0,0 +1,39 @@ +#ifndef CNODEPSOUTPUT_H +#define CNODEPSOUTPUT_H + +#include + +class CNodePSOutput : public CBaseNode +{ + DECLARE_CLASS( CNodePSOutput, CBaseNode ); + +public: + + CNodePSOutput( CNodeView *p ); + ~CNodePSOutput(); + + virtual bool CanBeInContainer(){ return false; }; + virtual int GetNodeType(){ return HLSLNODE_PS_OUT; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsNodeCrucial(){ return true; }; + + virtual int GetHierachyType(){return HLSLHIERACHY_PS;}; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + virtual bool ShouldErrorOnUndefined(){ return true; }; + + void Setup( SETUP_HLSL_PS_Output info ); + SETUP_HLSL_PS_Output &GetSetup(){ return curSetup; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues( KeyValues *pKV ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + SETUP_HLSL_PS_Output curSetup; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_sampler.cpp b/sp/src/shadereditor/nodes/vnode_sampler.cpp new file mode 100644 index 00000000..42d2365c --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_sampler.cpp @@ -0,0 +1,82 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodeSampler::CNodeSampler( CNodeView *p ) : BaseClass( "Sampler object", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_SAMPLER, "Sampler" ); + + szParamName[0] = '\0'; + m_szDemoTexturePath[0] = '\0'; + bIs3DTexture = false; + iTexType = HLSLTEX_BASETEXTURE; + + iFallbackType = 0; + m_szFallbackTexturePath[0] = '\0'; +} + +CNodeSampler::~CNodeSampler() +{ +} + +KeyValues *CNodeSampler::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetString( "szParamname", szParamName ); + pKV->SetInt( "iTextureType", iTexType ); + pKV->SetInt( "IsCubemap", bIs3DTexture ? 1: 0 ); + + pKV->SetString( "szDemoTexturePath", m_szDemoTexturePath ); + pKV->SetString( "szFallbackTexturePath", m_szFallbackTexturePath ); + pKV->SetInt( "iFallbackMode", iFallbackType ); + return pKV; +} +void CNodeSampler::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + Q_snprintf( szParamName, MAX_PATH, "%s", pKV->GetString( "szParamname" ) ); + iTexType = pKV->GetInt( "iTextureType" ); + bIs3DTexture = !!pKV->GetInt( "IsCubemap" ); + + Q_StripExtension( pKV->GetString("szDemoTexturePath"), m_szDemoTexturePath, sizeof( m_szDemoTexturePath ) ); + Q_StripExtension( pKV->GetString("szFallbackTexturePath"), m_szFallbackTexturePath, sizeof( m_szFallbackTexturePath ) ); + + iFallbackType = pKV->GetInt( "iFallbackMode" ); +} + +void CNodeSampler::UpdateOutputs() +{ +} + +bool CNodeSampler::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + pJ_Out->SetTemporaryVarTarget( tg ); + SetAllocating( false ); + + const int res = pJ_Out->GetResourceType(); + + CHLSL_Solver_TextureSample *solver = new CHLSL_Solver_TextureSample( GetUniqueIndex() ); + solver->MakeSamplerObject(); + solver->SetCubemap( bIs3DTexture ); + solver->SetTextureMode( iTexType ); + solver->SetLookupMode( 0 ); + solver->SetTextureName( m_szDemoTexturePath ); + solver->SetFallbackName( m_szFallbackTexturePath ); + solver->SetParamName( szParamName ); + solver->SetSrgb( false ); + solver->SetFunction( TEXSAMP_AUTO ); + + solver->SetResourceType( res ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_sampler.h b/sp/src/shadereditor/nodes/vnode_sampler.h new file mode 100644 index 00000000..90ed2b4d --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_sampler.h @@ -0,0 +1,38 @@ +#ifndef CNODE_SAMPLEROBJECT_H +#define CNODE_SAMPLEROBJECT_H + +#include "vBaseNode.h" + +class CNodeSampler : public CBaseNode +{ + DECLARE_CLASS( CNodeSampler, CBaseNode ); + +public: + CNodeSampler( CNodeView *p ); + ~CNodeSampler(); + + virtual int GetNodeType(){ return HLSLNODE_TEXTURE_SAMPLEROBJECT; }; + //virtual bool IsPreviewVisible(){ return false; }; + //virtual const bool IsPreviewEnabled(){ return false; }; + + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + virtual void UpdateOutputs(); + +private: + char m_szDemoTexturePath[ MAX_PATH ]; + char m_szFallbackTexturePath[ MAX_PATH ]; + + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + char szParamName[MAX_PATH]; + bool bIs3DTexture; + int iTexType; + int iFallbackType; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_std_plight.cpp b/sp/src/shadereditor/nodes/vnode_std_plight.cpp new file mode 100644 index 00000000..dcddc0a1 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_std_plight.cpp @@ -0,0 +1,190 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeStdPLight::CNodeStdPLight( CNodeView *p ) : BaseClass( "PS lighting", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "Light" ); + + m_bStaticLighting = false; + m_bAOTerm = false; + m_bHalfLambert = false; + + UpdateNode(); +} + +CNodeStdPLight::~CNodeStdPLight() +{ +} + +KeyValues *CNodeStdPLight::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_plight_static", m_bStaticLighting ? 1 : 0 ); + pKV->SetInt( "i_plight_ao", m_bAOTerm ? 1 : 0 ); + pKV->SetInt( "i_plight_hl", m_bHalfLambert ? 1 : 0 ); + return pKV; +} +void CNodeStdPLight::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_bStaticLighting = !!pKV->GetInt( "i_plight_static", m_bStaticLighting ); + m_bAOTerm = !!pKV->GetInt( "i_plight_ao", m_bAOTerm ); + m_bHalfLambert = !!pKV->GetInt( "i_plight_hl", m_bHalfLambert ); + UpdateNode(); +} + +void CNodeStdPLight::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + // pos, normal, attn + // static col + // ao + int numIn = 3; + if ( m_bStaticLighting ) + numIn += 1; + if ( m_bAOTerm ) + numIn += 1; + + GenerateJacks_Input( numIn ); + int curIn = 0; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT3, "World pos" ); + curIn++; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT3, "World normal" ); + curIn++; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT4, "Light attn" ); + curIn++; + + if ( m_bStaticLighting ) + { + LockJackInput_Flags( curIn, HLSLVAR_FLOAT3, "Static light" ); + curIn++; + } + if ( m_bAOTerm ) + { + LockJackInput_Flags( curIn, HLSLVAR_FLOAT1, "AO term" ); + } + + RestoreBridgesFromList_In( m_hRestoreBridges ); +} + +bool CNodeStdPLight::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( pJ_Out->GetSmartType() ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_StdPLight *solver = new CHLSL_Solver_StdPLight( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( m_bStaticLighting, m_bHalfLambert, m_bAOTerm ); + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} + + + + + + +CNodeStdPSpecLight::CNodeStdPSpecLight( CNodeView *p ) : BaseClass( "PS specular", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "Spec" ); + + m_bAOTerm = false; + + UpdateNode(); +} + +CNodeStdPSpecLight::~CNodeStdPSpecLight() +{ +} + +KeyValues *CNodeStdPSpecLight::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_plight_ao", m_bAOTerm ? 1 : 0 ); + return pKV; +} +void CNodeStdPSpecLight::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_bAOTerm = !!pKV->GetInt( "i_plight_ao", m_bAOTerm ); + UpdateNode(); +} + +void CNodeStdPSpecLight::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + // pos, normal, attn + // ao + int numIn = 6; + if ( m_bAOTerm ) + numIn += 1; + + GenerateJacks_Input( numIn ); + int curIn = 0; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT3, "World pos" ); + curIn++; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT3, "World normal" ); + curIn++; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT3, "Eye dir" ); + curIn++; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT1, "Spec exp" ); + curIn++; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT1, "Fresnel" ); + curIn++; + LockJackInput_Flags( curIn, HLSLVAR_FLOAT4, "Light attn" ); + curIn++; + + if ( m_bAOTerm ) + { + LockJackInput_Flags( curIn, HLSLVAR_FLOAT1, "AO term" ); + } + + RestoreBridgesFromList_In( m_hRestoreBridges ); +} +bool CNodeStdPSpecLight::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( pJ_Out->GetSmartType() ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_StdPSpecLight *solver = new CHLSL_Solver_StdPSpecLight( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( m_bAOTerm ); + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_std_plight.h b/sp/src/shadereditor/nodes/vnode_std_plight.h new file mode 100644 index 00000000..179eeb15 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_std_plight.h @@ -0,0 +1,59 @@ +#ifndef CNODE_STD_PLIGHT_H +#define CNODE_STD_PLIGHT_H + +#include "vBaseNode.h" + +class CNodeStdPLight : public CBaseNode +{ + DECLARE_CLASS( CNodeStdPLight, CBaseNode ); + +public: + + CNodeStdPLight( CNodeView *p ); + ~CNodeStdPLight(); + + virtual int GetNodeType(){ return HLSLNODE_STUDIO_PIXELSHADER_LIGHTING; }; + + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + + virtual void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + bool m_bStaticLighting; + bool m_bAOTerm; + bool m_bHalfLambert; +}; + + + +class CNodeStdPSpecLight : public CBaseNode +{ + DECLARE_CLASS( CNodeStdPSpecLight, CBaseNode ); + +public: + + CNodeStdPSpecLight( CNodeView *p ); + ~CNodeStdPSpecLight(); + + virtual int GetNodeType(){ return HLSLNODE_STUDIO_PIXELSHADER_SPECLIGHTING; }; + + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; + + virtual void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + bool m_bAOTerm; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_std_skinning.cpp b/sp/src/shadereditor/nodes/vnode_std_skinning.cpp new file mode 100644 index 00000000..9b14dff3 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_std_skinning.cpp @@ -0,0 +1,227 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeStdSkinning::CNodeStdSkinning( CNodeView *p ) : BaseClass( "Skinning", p ) +{ + m_iSkinMode = STD_SKINNING_MODE_POS; + UpdateNode(); +} + +CNodeStdSkinning::~CNodeStdSkinning() +{ +} + +void CNodeStdSkinning::SetState( int m ) +{ + m_iSkinMode = m; +} + +KeyValues *CNodeStdSkinning::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_vskinning_mode", m_iSkinMode ); + return pKV; +} +void CNodeStdSkinning::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iSkinMode = pKV->GetInt( "i_vskinning_mode", m_iSkinMode ); + UpdateNode(); +} + +void CNodeStdSkinning::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + int numInputs = 3; + if ( m_iSkinMode == STD_SKINNING_MODE_POS_NORMAL ) + numInputs = 4; + else if ( m_iSkinMode == STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + numInputs = 5; + GenerateJacks_Input( numInputs ); + + LockJackInput_Flags( 0, HLSLVAR_FLOAT4, "Bone indices" ); + LockJackInput_Flags( 1, HLSLVAR_FLOAT4, "Bone weights" ); + LockJackInput_Flags( 2, HLSLVAR_FLOAT3, "Obj pos" ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL ) + LockJackInput_Flags( 3, HLSLVAR_FLOAT3, "Obj normal" ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + LockJackInput_Flags( 4, HLSLVAR_FLOAT4, "Obj tangent s" ); + + RestoreBridgesFromList_In( m_hRestoreBridges ); + + + + + CreateBridgeRestoreData_Out( CBaseNode::BY_NAME, m_hRestoreBridges ); + + int numOutputs = 1; + if ( m_iSkinMode == STD_SKINNING_MODE_POS_NORMAL ) + numOutputs = 2; + else if ( m_iSkinMode == STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + numOutputs = 4; + GenerateJacks_Output( numOutputs ); + + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "World pos" ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL ) + LockJackOutput_Flags( 1, HLSLVAR_FLOAT3, "World normal" ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + { + LockJackOutput_Flags( 2, HLSLVAR_FLOAT3, "World tangent s" ); + LockJackOutput_Flags( 3, HLSLVAR_FLOAT3, "World tangent t" ); + } + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} + +bool CNodeStdSkinning::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + SetAllocating( true ); + + CHLSL_Solver_StdSkinning *solver = new CHLSL_Solver_StdSkinning( GetUniqueIndex() ); + + solver->SetState( m_iSkinMode ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + solver->AddTargetVar( GetJack_Out(i)->AllocateVarFromSmartType() ); + + AddSolver( solver ); + + return true; +} + + + + + + + + + + +CNodeStdMorph::CNodeStdMorph( CNodeView *p ) : BaseClass( "Morph", p ) +{ + m_iSkinMode = STD_SKINNING_MODE_POS; + UpdateNode(); +} + +CNodeStdMorph::~CNodeStdMorph() +{ +} + +void CNodeStdMorph::SetState( int m ) +{ + m_iSkinMode = m; +} + +KeyValues *CNodeStdMorph::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_vskinning_mode", m_iSkinMode ); + return pKV; +} +void CNodeStdMorph::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iSkinMode = pKV->GetInt( "i_vskinning_mode", m_iSkinMode ); + UpdateNode(); +} + +void CNodeStdMorph::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + int numInputs = 2; + if ( m_iSkinMode == STD_SKINNING_MODE_POS_NORMAL ) + numInputs = 4; + else if ( m_iSkinMode == STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + numInputs = 5; + GenerateJacks_Input( numInputs ); + + LockJackInput_Flags( 0, HLSLVAR_FLOAT3, "Obj pos" ); + LockJackInput_Flags( 1, HLSLVAR_FLOAT3, "Flex delta" ); + //LockJackInput_Flags( 2, HLSLVAR_FLOAT2, "Morph coords" ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL ) + { + LockJackInput_Flags( 2, HLSLVAR_FLOAT3, "Obj normal" ); + LockJackInput_Flags( 3, HLSLVAR_FLOAT3, "Flex normal" ); + } + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + LockJackInput_Flags( 4, HLSLVAR_FLOAT3, "Tangent s" ); + + RestoreBridgesFromList_In( m_hRestoreBridges ); + + + + + CreateBridgeRestoreData_Out( CBaseNode::BY_NAME, m_hRestoreBridges ); + + int numOutputs = 1; + if ( m_iSkinMode == STD_SKINNING_MODE_POS_NORMAL ) + numOutputs = 2; + else if ( m_iSkinMode == STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + numOutputs = 3; + GenerateJacks_Output( numOutputs ); + + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "Obj pos" ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL ) + LockJackOutput_Flags( 1, HLSLVAR_FLOAT3, "Obj normal" ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + LockJackOutput_Flags( 2, HLSLVAR_FLOAT3, "Obj tangent s" ); + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} + +bool CNodeStdMorph::CreateSolvers(GenericShaderData *ShaderData) +{ + const int numJacksIn = GetNumJacks_In(); + if ( GetNumJacks_In_Connected() < numJacksIn ) + return false; + +#define __ALLOCVARONOVERWRITEFAIL( _in, _out ) CHLSL_Var *tg##_out = NULL;\ + if ( _in + 1 > GetNumJacks_In() || _out + 1 > GetNumJacks_Out() )\ + {}\ + else if ( GetJack_In( _in )->GetTemporaryVarTarget_End()->CanBeOverwritten() )\ + {\ + tg##_out = GetJack_In( _in )->GetTemporaryVarTarget_End();\ + GetJack_Out( _out )->SetTemporaryVarTarget( tg##_out );\ + }\ + else\ + {\ + tg##_out = GetJack_Out( _out )->AllocateVarFromSmartType();\ + } + + bool bWillAlloc = !GetJack_In( 0 )->GetTemporaryVarTarget_End()->CanBeOverwritten(); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL && !GetJack_In( 2 )->GetTemporaryVarTarget_End()->CanBeOverwritten() ) + bWillAlloc = true; + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL_TANGENT && !GetJack_In( 4 )->GetTemporaryVarTarget_End()->CanBeOverwritten() ) + bWillAlloc = true; + + SetAllocating( bWillAlloc ); + + CHLSL_Solver_StdMorph *solver = new CHLSL_Solver_StdMorph( GetUniqueIndex() ); + + solver->SetState( m_iSkinMode ); + for ( int i = 0; i < numJacksIn; i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + + __ALLOCVARONOVERWRITEFAIL( 0, 0 ) + __ALLOCVARONOVERWRITEFAIL( 2, 1 ) + __ALLOCVARONOVERWRITEFAIL( 4, 2 ) + + solver->AddTargetVar( tg0 ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL ) + solver->AddTargetVar( tg1 ); + if ( m_iSkinMode >= STD_SKINNING_MODE_POS_NORMAL_TANGENT ) + solver->AddTargetVar( tg2 ); + + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_std_skinning.h b/sp/src/shadereditor/nodes/vnode_std_skinning.h new file mode 100644 index 00000000..bbd14506 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_std_skinning.h @@ -0,0 +1,72 @@ +#ifndef CNODE_STD_SKINNING_H +#define CNODE_STD_SKINNING_H + +#include "vBaseNode.h" + + +enum +{ + STD_SKINNING_MODE_POS = 0, + STD_SKINNING_MODE_POS_NORMAL, + STD_SKINNING_MODE_POS_NORMAL_TANGENT, +}; + +class CNodeStdSkinning : public CBaseNode +{ + DECLARE_CLASS( CNodeStdSkinning, CBaseNode ); + +public: + + CNodeStdSkinning( CNodeView *p ); + ~CNodeStdSkinning(); + + virtual int GetNodeType(){ return HLSLNODE_STUDIO_SKINNING; }; + + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + virtual void SetState( int m ); + + virtual void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iSkinMode; +}; + + +class CNodeStdMorph : public CBaseNode +{ + DECLARE_CLASS( CNodeStdMorph, CBaseNode ); + +public: + + CNodeStdMorph( CNodeView *p ); + ~CNodeStdMorph(); + + virtual int GetNodeType(){ return HLSLNODE_STUDIO_MORPH; }; + + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + virtual void SetState( int m ); + + virtual void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iSkinMode; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_std_vlight.cpp b/sp/src/shadereditor/nodes/vnode_std_vlight.cpp new file mode 100644 index 00000000..2689607c --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_std_vlight.cpp @@ -0,0 +1,87 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeStdVLight::CNodeStdVLight( CNodeView *p ) : BaseClass( "Vertex lighting", p ) +{ + m_bStaticLighting = false; + m_bHalfLambert = false; + + UpdateNode(); +} + +CNodeStdVLight::~CNodeStdVLight() +{ +} + +KeyValues *CNodeStdVLight::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "i_vlight_static", m_bStaticLighting ? 1 : 0 ); + pKV->SetInt( "i_vlight_hl", m_bHalfLambert ? 1 : 0 ); + return pKV; +} +void CNodeStdVLight::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_bStaticLighting = !!pKV->GetInt( "i_vlight_static", m_bStaticLighting ); + m_bHalfLambert = !!pKV->GetInt( "i_vlight_hl", m_bHalfLambert ); + UpdateNode(); +} + +void CNodeStdVLight::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + GenerateJacks_Input( m_bStaticLighting ? 3 : 1 ); + if ( m_bStaticLighting ) + { + LockJackInput_Flags( 0, HLSLVAR_FLOAT3, "World pos" ); + LockJackInput_Flags( 1, HLSLVAR_FLOAT3, "World normal" ); + LockJackInput_Flags( 2, HLSLVAR_FLOAT3, "Static light" ); + } + else + { + LockJackInput_Flags( 0, HLSLVAR_FLOAT3, "World pos" ); + } + + RestoreBridgesFromList_In( m_hRestoreBridges ); + + CreateBridgeRestoreData_Out( CBaseNode::BY_NAME, m_hRestoreBridges ); + + GenerateJacks_Output( 1 ); + if ( m_bStaticLighting ) + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "Lighting" ); + else + LockJackOutput_Flags( 0, HLSLVAR_FLOAT4, "VAttn" ); + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} + +bool CNodeStdVLight::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( pJ_Out->GetSmartType() ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_StdVLight *solver = new CHLSL_Solver_StdVLight( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( m_bStaticLighting, m_bHalfLambert ); + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_std_vlight.h b/sp/src/shadereditor/nodes/vnode_std_vlight.h new file mode 100644 index 00000000..28d078bd --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_std_vlight.h @@ -0,0 +1,34 @@ +#ifndef CNODE_STD_VLIGHT_H +#define CNODE_STD_VLIGHT_H + +#include "vBaseNode.h" + +class CNodeStdVLight : public CBaseNode +{ + DECLARE_CLASS( CNodeStdVLight, CBaseNode ); + +public: + + CNodeStdVLight( CNodeView *p ); + ~CNodeStdVLight(); + + virtual int GetNodeType(){ return HLSLNODE_STUDIO_VERTEXLIGHTING; }; + + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + virtual void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + bool m_bStaticLighting; + bool m_bHalfLambert; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_subtract.cpp b/sp/src/shadereditor/nodes/vnode_subtract.cpp new file mode 100644 index 00000000..fb04376d --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_subtract.cpp @@ -0,0 +1,150 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeSubtract::CNodeSubtract( CNodeView *p ) : BaseClass( "Subtract", p ) +{ + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "A" ); + GetJack_In( 1 )->SetName( "B" ); +} + +CNodeSubtract::~CNodeSubtract() +{ +} + +int CNodeSubtract::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + locallevel = ERRORLEVEL_FAIL; + } + else if ( vartype_jack_0 >= HLSLVAR_MATRIX3X3 || + vartype_jack_1 >= HLSLVAR_MATRIX3X3 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeSubtract::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( max( GetJack_In(0)->GetSmartType(), GetJack_In(1)->GetSmartType() ) ); +} +bool CNodeSubtract::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type1 = pJ1->GetSmartType(); + int type2 = pJ2->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( max( type1, type2 ) ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Subtract *solver = new CHLSL_Solver_Subtract( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} + + + + + + + +CNodeInvert::CNodeInvert( CNodeView *p ) : BaseClass( "Invert", p ) +{ + GenerateJacks_Input( 1 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "In" ); +} + +CNodeInvert::~CNodeInvert() +{ +} + +int CNodeInvert::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = TestJackFlags_In(); + + return max( locallevel, baseLevel ); +} +void CNodeInvert::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( GetJack_In(0)->GetSmartType() ); +} +bool CNodeInvert::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 1 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type1 = pJ1->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( type1 ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Invert *solver = new CHLSL_Solver_Invert( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_subtract.h b/sp/src/shadereditor/nodes/vnode_subtract.h new file mode 100644 index 00000000..d3fbe015 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_subtract.h @@ -0,0 +1,47 @@ +#ifndef CNODE_SUBTRACT_H +#define CNODE_SUBTRACT_H + +#include "vBaseNode.h" + +class CNodeSubtract : public CBaseNode +{ + DECLARE_CLASS( CNodeSubtract, CBaseNode ); + +public: + + CNodeSubtract( CNodeView *p ); + ~CNodeSubtract(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_SUBTRACT; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + + +class CNodeInvert : public CBaseNode +{ + DECLARE_CLASS( CNodeInvert, CBaseNode ); + +public: + + CNodeInvert( CNodeView *p ); + ~CNodeInvert(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_INVERT; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_swizzle.cpp b/sp/src/shadereditor/nodes/vnode_swizzle.cpp new file mode 100644 index 00000000..bf0a4efd --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_swizzle.cpp @@ -0,0 +1,127 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeSwizzle::CNodeSwizzle( CNodeView *p ) : BaseClass( "Swizzle", p ) +{ + GenerateJacks_Input( 1 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "In" ); + + m_SwizzleInfo.SetDefaultChannels(); + szSwizzle[ 0 ] = '\0'; +} + +CNodeSwizzle::~CNodeSwizzle() +{ +} + +void CNodeSwizzle::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_Out( CBaseNode::BY_INDEX, m_hRestoreBridges ); + + GenerateJacks_Output( 1 ); + + if ( !m_SwizzleInfo.IsActive() ) + { + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_Out( 0 )->SetSmartTypeLocked( false ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + } + else + { + Assert( m_SwizzleInfo.IsActive() ); + int minComps = GetSwizzleMinComponents(); + SetJackFlags_MinFloatRequirement( GetJack_In(0), minComps ); + LockJackOutput_Flags( 0, GetTypeFlagFromEnum(m_SwizzleInfo.iActiveChannels), szSwizzle ); + } + + // HLSLVAR_FLOAT1 - HLSLVAR_FLOAT4 + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} +int CNodeSwizzle::GetSwizzleMinComponents() +{ + Assert( m_SwizzleInfo.IsActive() ); + return m_SwizzleInfo.iChannelDepth; +} +int CNodeSwizzle::GetSwizzleTargetComponents() +{ + return m_SwizzleInfo.iActiveChannels; +} + +int CNodeSwizzle::PerNodeErrorLevel() +{ + return BaseClass::PerNodeErrorLevel(); // TestJackFlags_In(); +} + +KeyValues *CNodeSwizzle::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetString( "swizzleString", szSwizzle ); + return pKV; +} +void CNodeSwizzle::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_SwizzleInfo.Tokenize( pKV->GetString( "swizzleString" ) ); + m_SwizzleInfo.PrintTargetString( szSwizzle, sizeof(szSwizzle) ); + UpdateNode(); +} + +int CNodeSwizzle::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + return max( baseLevel, TestJackFlags_In() ); +} +void CNodeSwizzle::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( m_SwizzleInfo.IsActive() ) + return GetJack_Out( 0 )->SetSmartType( GetTypeFlagFromEnum(m_SwizzleInfo.iActiveChannels) ); + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( GetJack_In(0)->GetSmartType() ); +} +bool CNodeSwizzle::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 1 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int numTargetComponents = GetSwizzleTargetComponents(); + if ( !m_SwizzleInfo.IsActive() ) + numTargetComponents = GetSlotsFromTypeFlag( pJ1->GetSmartType() ); + + int typeMin = GetTypeFlagFromEnum( numTargetComponents ); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( typeMin ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Swizzle *solver = new CHLSL_Solver_Swizzle( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + //solver->SetTargetSize( numTargetComponents ); + //for ( int i = 0; i < numTargetComponents; i++ ) + // solver->SetComponentInfo( i, GetTargetComponentInSlot( i ) ); + solver->SetComponentInfo( m_SwizzleInfo ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_swizzle.h b/sp/src/shadereditor/nodes/vnode_swizzle.h new file mode 100644 index 00000000..dffeb2d1 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_swizzle.h @@ -0,0 +1,40 @@ +#ifndef CNODE_SWIZZLE_H +#define CNODE_SWIZZLE_H + +#include "vBaseNode.h" + +class CNodeSwizzle : public CBaseNode +{ + DECLARE_CLASS( CNodeSwizzle, CBaseNode ); + +public: + + CNodeSwizzle( CNodeView *p ); + ~CNodeSwizzle(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_SWIZZLE; }; + virtual int PerNodeErrorLevel(); + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + // reading from w or a? must be 4 comps input... + int GetSwizzleMinComponents(); + // vector targetlength required + int GetSwizzleTargetComponents(); + //int GetTargetComponentInSlot( int slot ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + TokenChannels_t m_SwizzleInfo; + char szSwizzle[MAX_PATH]; + + void UpdateNode(); +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_texsample.cpp b/sp/src/shadereditor/nodes/vnode_texsample.cpp new file mode 100644 index 00000000..8d61395a --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_texsample.cpp @@ -0,0 +1,185 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodeTexSample::CNodeTexSample( CNodeView *p ) : BaseClass( "Texture sample", p ) +{ + GenerateJacks_Output( 6 ); + + m_hOutputs[ 1 ]->SetJackColorCode( HLSLJACK_COLOR_RGB ); + m_hOutputs[ 2 ]->SetJackColorCode( HLSLJACK_COLOR_R ); + m_hOutputs[ 3 ]->SetJackColorCode( HLSLJACK_COLOR_G ); + m_hOutputs[ 4 ]->SetJackColorCode( HLSLJACK_COLOR_B ); + m_hOutputs[ 5 ]->SetJackColorCode( HLSLJACK_COLOR_A ); + + LockJackOutput_Flags( 0, HLSLVAR_FLOAT4, "RGBA" ); + LockJackOutput_Flags( 1, HLSLVAR_FLOAT3, "RGB" ); + LockJackOutput_Flags( 2, HLSLVAR_FLOAT1, "R" ); + LockJackOutput_Flags( 3, HLSLVAR_FLOAT1, "G" ); + LockJackOutput_Flags( 4, HLSLVAR_FLOAT1, "B" ); + LockJackOutput_Flags( 5, HLSLVAR_FLOAT1, "A" ); + + szParamName[0] = '\0'; + m_szDemoTexturePath[0] = '\0'; + bSRGBRead = false; + bIs3DTexture = false; + iTexType = HLSLTEX_BASETEXTURE; + + iFallbackType = 0; + m_szFallbackTexturePath[0] = '\0'; + + iLookupOverride = TEXSAMP_AUTO; + + UpdateInput(); +} + +CNodeTexSample::~CNodeTexSample() +{ +} + +void CNodeTexSample::UpdateInput() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_INDEX, m_hRestoreBridges ); + + int numIn = 1; + const bool bHasDerivative = iLookupOverride != TEXSAMP_AUTO && GetSamplerData_UseDerivative( iLookupOverride ); + int Flag = HLSLVAR_FLOAT2; + const char *jackname = "UV"; + + if ( bIs3DTexture ) + { + Flag = HLSLVAR_FLOAT3; + jackname = "Dir"; + } + if ( iLookupOverride != TEXSAMP_AUTO ) + { + Flag = ::GetVarTypeFlag( GetSampleData_ComponentSize( iLookupOverride ) ); + jackname = GetSamplerData_JackName( iLookupOverride ); + } + if ( bHasDerivative ) + numIn = 3; + + GenerateJacks_Input( numIn ); + LockJackInput_Flags( 0, Flag, jackname ); + if ( bHasDerivative ) + { + LockJackInput_Flags( 1, Flag, "ddx" ); + LockJackInput_Flags( 2, Flag, "ddy" ); + } + + RestoreBridgesFromList_In( m_hRestoreBridges ); +} + +KeyValues *CNodeTexSample::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetString( "szParamname", szParamName ); + pKV->SetInt( "iSRGB", bSRGBRead ? 1 : 0 ); + pKV->SetInt( "iTextureType", iTexType ); + pKV->SetInt( "IsCubemap", bIs3DTexture ? 1: 0 ); + pKV->SetInt( "iLookupoverride", iLookupOverride ); + + pKV->SetString( "szDemoTexturePath", m_szDemoTexturePath ); + pKV->SetString( "szFallbackTexturePath", m_szFallbackTexturePath ); + pKV->SetInt( "iFallbackMode", iFallbackType ); + return pKV; +} +void CNodeTexSample::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + Q_snprintf( szParamName, MAX_PATH, "%s", pKV->GetString( "szParamname" ) ); + bSRGBRead = !!pKV->GetInt( "iSRGB" ); + iTexType = pKV->GetInt( "iTextureType" ); + bIs3DTexture = !!pKV->GetInt( "IsCubemap" ); + iLookupOverride = pKV->GetInt( "iLookupoverride" ); + + Q_StripExtension( pKV->GetString("szDemoTexturePath"), m_szDemoTexturePath, sizeof( m_szDemoTexturePath ) ); + Q_StripExtension( pKV->GetString("szFallbackTexturePath"), m_szFallbackTexturePath, sizeof( m_szFallbackTexturePath ) ); + +// Q_snprintf( m_szDemoTexturePath, sizeof( m_szDemoTexturePath ), "%s", pKV->GetString("szDemoTexturePath") ); +// Q_snprintf( m_szFallbackTexturePath, sizeof( m_szFallbackTexturePath ), "%s", pKV->GetString("szFallbackTexturePath") ); + iFallbackType = pKV->GetInt( "iFallbackMode" ); + + UpdateInput(); +} + +int CNodeTexSample::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int autoTest = TestJackFlags_In(); + + if ( Q_strlen( szParamName ) < 1 && iTexType == HLSLTEX_CUSTOMPARAM ) + autoTest = ERRORLEVEL_FAIL; + + return max( baseLevel, autoTest ); +} +void CNodeTexSample::UpdateOutputs() +{ +} + +bool CNodeTexSample::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + if ( GetNumJacks_Out_Connected() ) + { + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJ_Out = GetJack_Out( i ); + if ( !pJ_Out->GetNumBridgesConnected() ) + continue; + + int mode = i; + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + SetAllocating( true ); + + CHLSL_Solver_TextureSample *solver = new CHLSL_Solver_TextureSample( GetUniqueIndex() ); + solver->SetCubemap( bIs3DTexture ); + solver->SetLookupMode( mode ); + solver->SetTextureMode( iTexType ); + solver->SetTextureName( m_szDemoTexturePath ); + solver->SetFallbackName( m_szFallbackTexturePath ); + solver->SetParamName( szParamName ); + solver->SetSrgb( bSRGBRead ); + solver->SetFunction( iLookupOverride ); + + solver->SetResourceType( res ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + } + } + else + { + CJack *pJ_Out = GetJack_Out( 0 ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + SetAllocating( true ); + + const int res = pJ_Out->GetResourceType(); + + CHLSL_Solver_TextureSample *solver = new CHLSL_Solver_TextureSample( GetUniqueIndex() ); + solver->SetCubemap( bIs3DTexture ); + solver->SetTextureMode( iTexType ); + solver->SetLookupMode( 0 ); + solver->SetTextureName( m_szDemoTexturePath ); + solver->SetFallbackName( m_szFallbackTexturePath ); + solver->SetParamName( szParamName ); + solver->SetSrgb( bSRGBRead ); + solver->SetFunction( iLookupOverride ); + + solver->SetResourceType( res ); + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In(i)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + } + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_texsample.h b/sp/src/shadereditor/nodes/vnode_texsample.h new file mode 100644 index 00000000..e45cbb6f --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_texsample.h @@ -0,0 +1,41 @@ +#ifndef CNODETEXTURESAMPLE_H +#define CNODETEXTURESAMPLE_H + +#include "vBaseNode.h" + +class CNodeTexSample : public CBaseNode +{ + DECLARE_CLASS( CNodeTexSample, CBaseNode ); + +public: + CNodeTexSample( CNodeView *p ); + ~CNodeTexSample(); + + virtual int GetNodeType(){ return HLSLNODE_TEXTURE_SAMPLER; }; +#ifndef SHADER_EDITOR_DLL_SWARM + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_PS; }; +#endif + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + char m_szDemoTexturePath[ MAX_PATH ]; + char m_szFallbackTexturePath[ MAX_PATH ]; + + void UpdateInput(); + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + char szParamName[MAX_PATH]; + bool bSRGBRead; + bool bIs3DTexture; + int iTexType; + int iFallbackType; + int iLookupOverride; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_textransform.cpp b/sp/src/shadereditor/nodes/vnode_textransform.cpp new file mode 100644 index 00000000..986008a3 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_textransform.cpp @@ -0,0 +1,112 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeTexTransform::CNodeTexTransform( CNodeView *p ) : BaseClass( "Texture transform", p ) +{ + GenerateJacks_Output( 1 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT2, "UV" ); + + bEnable_Center = false; + bEnable_Rot = true; + bEnable_Scale = true; + bEnable_Trans = true; + + UpdateNode(); +} + +CNodeTexTransform::~CNodeTexTransform() +{ +} + +void CNodeTexTransform::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + int numIn = bEnable_Center + bEnable_Rot + bEnable_Scale + bEnable_Trans + 1; + GenerateJacks_Input( numIn ); + + int curIn = 0; + + LockJackInput_Flags( curIn, HLSLVAR_FLOAT2, "UV" ); + curIn++; + if ( bEnable_Center ) + { + LockJackInput_Flags( curIn, HLSLVAR_FLOAT2, "Center" ); + curIn++; + } + if ( bEnable_Rot ) + { + LockJackInput_Flags( curIn, HLSLVAR_FLOAT1, "Rot" ); + curIn++; + } + if ( bEnable_Scale ) + { + LockJackInput_Flags( curIn, HLSLVAR_FLOAT2, "Scale" ); + curIn++; + } + if ( bEnable_Trans ) + { + LockJackInput_Flags( curIn, HLSLVAR_FLOAT2, "Trans" ); + curIn++; + } + + RestoreBridgesFromList_In( m_hRestoreBridges ); +} + +KeyValues *CNodeTexTransform::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "iTexTrans_center", bEnable_Center ? 1 : 0 ); + pKV->SetInt( "iTexTrans_rot", bEnable_Rot ? 1 : 0 ); + pKV->SetInt( "iTexTrans_scale", bEnable_Scale ? 1 : 0 ); + pKV->SetInt( "iTexTrans_trans", bEnable_Trans ? 1 : 0 ); + + return pKV; +} +void CNodeTexTransform::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + bEnable_Center = !!pKV->GetInt( "iTexTrans_center", bEnable_Center ? 1 : 0 ); + bEnable_Rot = !!pKV->GetInt( "iTexTrans_rot", bEnable_Rot ? 1 : 0 ); + bEnable_Scale = !!pKV->GetInt( "iTexTrans_scale", bEnable_Scale ? 1 : 0 ); + bEnable_Trans = !!pKV->GetInt( "iTexTrans_trans", bEnable_Trans ? 1 : 0 ); + + UpdateNode(); +} + +int CNodeTexTransform::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int autoTest = TestJackFlags_In(); + return max( autoTest, baseLevel ); +} +bool CNodeTexTransform::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < GetNumJacks_In() ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + + CHLSL_Var *tg = GetInputToWriteTo( pJ_Out->GetSmartType() ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_TexTransform *solver = new CHLSL_Solver_TexTransform( GetUniqueIndex() ); + + for ( int i = 0; i < GetNumJacks_In(); i++ ) + solver->AddSourceVar( GetJack_In( i )->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + + solver->bEnable_Center = bEnable_Center; + solver->bEnable_Rot = bEnable_Rot; + solver->bEnable_Scale = bEnable_Scale; + solver->bEnable_Trans = bEnable_Trans; + + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_textransform.h b/sp/src/shadereditor/nodes/vnode_textransform.h new file mode 100644 index 00000000..d3741ce2 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_textransform.h @@ -0,0 +1,33 @@ +#ifndef CNODE_TEXTRANSFORM_H +#define CNODE_TEXTRANSFORM_H + +#include "vBaseNode.h" + +class CNodeTexTransform : public CBaseNode +{ + DECLARE_CLASS( CNodeTexTransform, CBaseNode ); + +public: + + CNodeTexTransform( CNodeView *p ); + ~CNodeTexTransform(); + + virtual int GetNodeType(){ return HLSLNODE_TEXTURE_TRANSFORM; }; + + void UpdateNode(); + virtual int UpdateInputsValid(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + bool bEnable_Center; + bool bEnable_Rot; + bool bEnable_Scale; + bool bEnable_Trans; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_utility.cpp b/sp/src/shadereditor/nodes/vnode_utility.cpp new file mode 100644 index 00000000..46f67286 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_utility.cpp @@ -0,0 +1,136 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodeUtility_Declare::CNodeUtility_Declare( CNodeView *p ) : BaseClass( "Declare", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Input( 1 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_ALL ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_ALL ); +} +CNodeUtility_Declare::~CNodeUtility_Declare() +{ +} +int CNodeUtility_Declare::UpdateInputsValid() +{ + return BaseClass::UpdateInputsValid(); +} +void CNodeUtility_Declare::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( GetJack_In(0)->GetSmartType() ); +} +bool CNodeUtility_Declare::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 1 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + const int res = pJ_Out->GetResourceType(); + + SetAllocating( true ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + + CHLSL_Solver_Utility_Declare *solver = new CHLSL_Solver_Utility_Declare( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} + + + +CNodeUtility_Assign::CNodeUtility_Assign( CNodeView *p ) : BaseClass( "Assign", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_ALL ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_ALL ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_ALL ); +} +CNodeUtility_Assign::~CNodeUtility_Assign() +{ +} +int CNodeUtility_Assign::UpdateInputsValid() +{ + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + return ERRORLEVEL_FAIL; + } + + return max( autoTest, BaseClass::UpdateInputsValid() ); +} +void CNodeUtility_Assign::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( GetJack_In(0)->GetSmartType() ); +} +bool CNodeUtility_Assign::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + if ( !pJ1->GetTemporaryVarTarget_End()->CanBeOverwritten() ) + { + SetOutputsUndefined(); + OnShowSolverErrored(); + return false; + } + + + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = pJ1->GetTemporaryVarTarget_End_Smart( pJ1->GetSmartType(), true ); + Assert( tg ); + if ( !tg->CanBeOverwritten() ) + tg = NULL; + if ( !( tg->GetType() & pJ1->GetSmartType() ) ) + tg = NULL; + + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Utility_Assign *solver = new CHLSL_Solver_Utility_Assign( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_utility.h b/sp/src/shadereditor/nodes/vnode_utility.h new file mode 100644 index 00000000..14318a78 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_utility.h @@ -0,0 +1,46 @@ +#ifndef CNODE_UTILITY_H +#define CNODE_UTILITY_H + +#include "vBaseNode.h" + +class CNodeUtility_Declare : public CBaseNode +{ + DECLARE_CLASS( CNodeUtility_Declare, CBaseNode ); + +public: + + CNodeUtility_Declare( CNodeView *p ); + ~CNodeUtility_Declare(); + + virtual int GetNodeType(){ return HLSLNODE_UTILITY_DECLARE; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +class CNodeUtility_Assign : public CBaseNode +{ + DECLARE_CLASS( CNodeUtility_Assign, CBaseNode ); + +public: + + CNodeUtility_Assign( CNodeView *p ); + ~CNodeUtility_Assign(); + + virtual int GetNodeType(){ return HLSLNODE_UTILITY_ASSIGN; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vcompression.cpp b/sp/src/shadereditor/nodes/vnode_vcompression.cpp new file mode 100644 index 00000000..fbecaa86 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vcompression.cpp @@ -0,0 +1,74 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CNodeVCompression::CNodeVCompression( CNodeView *p ) : BaseClass( "Vertex decompress", p ) +{ + m_iCompressionMode = COMPRESSION_MODE_NORMAL; + UpdateNode(); +} + +CNodeVCompression::~CNodeVCompression() +{ +} + +void CNodeVCompression::UpdateNode() +{ + bool bUseTangent = m_iCompressionMode == COMPRESSION_MODE_NORMAL_TANGENT; + + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_NAME, m_hRestoreBridges ); + + GenerateJacks_Input( bUseTangent ? 2 : 1 ); + LockJackInput_Flags( 0, HLSLVAR_FLOAT4, "Normal" ); + if ( bUseTangent ) + LockJackInput_Flags( 1, HLSLVAR_FLOAT4, "Tangent" ); + + RestoreBridgesFromList_In( m_hRestoreBridges ); + + + CreateBridgeRestoreData_Out( CBaseNode::BY_NAME, m_hRestoreBridges ); + + GenerateJacks_Output( bUseTangent ? 2 : 1 ); + LockJackOutput_Flags( 0, HLSLVAR_FLOAT3, "Normal" ); + if ( bUseTangent ) + LockJackOutput_Flags( 1, HLSLVAR_FLOAT4, "Tangent" ); + + RestoreBridgesFromList_Out( m_hRestoreBridges ); + + OnUpdateHierachy( NULL, NULL ); +} + +KeyValues *CNodeVCompression::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + pKV->SetInt( "iCompMode", m_iCompressionMode ); + return pKV; +} + +void CNodeVCompression::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iCompressionMode = pKV->GetInt( "iCompMode" ); + UpdateNode(); +} + +bool CNodeVCompression::CreateSolvers(GenericShaderData *ShaderData) +{ + const bool bUseTangent = m_iCompressionMode == COMPRESSION_MODE_NORMAL_TANGENT; + + SetAllocating( true ); + CHLSL_Solver_VCompression *solver = new CHLSL_Solver_VCompression( GetUniqueIndex() ); + solver->SetCompressionType( m_iCompressionMode ); + + solver->AddSourceVar( GetJack_In(0)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( GetJack_Out(0)->AllocateVarFromSmartType() ); + + if ( bUseTangent ) + { + solver->AddSourceVar( GetJack_In(1)->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( GetJack_Out(1)->AllocateVarFromSmartType() ); + } + + AddSolver( solver ); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vcompression.h b/sp/src/shadereditor/nodes/vnode_vcompression.h new file mode 100644 index 00000000..e6029753 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vcompression.h @@ -0,0 +1,44 @@ +#ifndef CNODE_VCOMPRESSION_H +#define CNODE_VCOMPRESSION_H + +#include "vBaseNode.h" + +class CNodeVCompression : public CBaseNode +{ + DECLARE_CLASS( CNodeVCompression, CBaseNode ); + +public: + + enum + { + COMPRESSION_MODE_NORMAL = 0, + COMPRESSION_MODE_NORMAL_TANGENT, + + COMPRESSION_MODE_COUNT, + }; + + CNodeVCompression( CNodeView *p ); + ~CNodeVCompression(); + + virtual int GetNodeType(){ return HLSLNODE_STUDIO_VCOMPRESSION; }; + + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsPreviewEnabled(){ return false; }; + + //virtual int UpdateInputsValid(); + //virtual void UpdateOutputs(); + + virtual void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iCompressionMode; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vecappend.cpp b/sp/src/shadereditor/nodes/vnode_vecappend.cpp new file mode 100644 index 00000000..4631d1ca --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vecappend.cpp @@ -0,0 +1,80 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeAppend::CNodeAppend( CNodeView *p ) : BaseClass( "Append", p ) +{ + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "A" ); + GetJack_In( 1 )->SetName( "B" ); +} + +CNodeAppend::~CNodeAppend() +{ +} + +int CNodeAppend::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = TestJackFlags_In(); + + if ( locallevel == ERRORLEVEL_NONE ) + { + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int numComps_0 = ::GetSlotsFromTypeFlag( vartype_jack_0 ); + int numComps_1 = ::GetSlotsFromTypeFlag( vartype_jack_1 ); + + if ( (numComps_0 + numComps_1) > 4 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeAppend::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE || GetNumJacks_In_Connected() < GetNumJacks_In() ) + return SetOutputsUndefined(); + + int numComps_0 = ::GetSlotsFromTypeFlag( GetJack_In( 0 )->GetSmartType() ); + int numComps_1 = ::GetSlotsFromTypeFlag( GetJack_In( 1 )->GetSmartType() ); + int typeO = ::GetTypeFlagFromEnum( numComps_0 + numComps_1 ); + + GetJack_Out( 0 )->SetSmartType( typeO ); +} +bool CNodeAppend::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + const int res = pJ_Out->GetResourceType(); + CHLSL_Var *tg = NULL; //GetInputToWriteTo( pJ_Out->GetSmartType() ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_Append *solver = new CHLSL_Solver_Append( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vecappend.h b/sp/src/shadereditor/nodes/vnode_vecappend.h new file mode 100644 index 00000000..2424dcfa --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vecappend.h @@ -0,0 +1,26 @@ +#ifndef CNODE_APPEND_H +#define CNODE_APPEND_H + +#include "vBaseNode.h" + +class CNodeAppend : public CBaseNode +{ + DECLARE_CLASS( CNodeAppend, CBaseNode ); + +public: + + CNodeAppend( CNodeView *p ); + ~CNodeAppend(); + + virtual int GetNodeType(){ return HLSLNODE_MATH_APPEND; }; + + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vectorref.cpp b/sp/src/shadereditor/nodes/vnode_vectorref.cpp new file mode 100644 index 00000000..bf788be4 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vectorref.cpp @@ -0,0 +1,175 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeVectorReflect::CNodeVectorReflect( CNodeView *p ) : BaseClass( "Reflect", p ) +{ + GenerateJacks_Input( 2 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "Ray" ); + GetJack_In( 1 )->SetName( "Normal" ); +} + +CNodeVectorReflect::~CNodeVectorReflect() +{ +} + +int CNodeVectorReflect::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + locallevel = ERRORLEVEL_FAIL; + } + else if ( vartype_jack_0 >= HLSLVAR_MATRIX3X3 || + vartype_jack_1 >= HLSLVAR_MATRIX3X3 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeVectorReflect::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( max( GetJack_In(0)->GetSmartType(), GetJack_In(1)->GetSmartType() ) ); +} +bool CNodeVectorReflect::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type1 = pJ1->GetSmartType(); + int type2 = pJ2->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( max( type1, type2 ) ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_VectorReflect *solver = new CHLSL_Solver_VectorReflect( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} + + + + + +CNodeVectorRefract::CNodeVectorRefract( CNodeView *p ) : BaseClass( "Refract", p ) +{ + GenerateJacks_Input( 3 ); + GenerateJacks_Output( 1 ); + + SetJackFlags_Input( 0, HLSLJACKFLAGS_F1_TO_F4 ); + SetJackFlags_Input( 1, HLSLJACKFLAGS_F1_TO_F4 ); + LockJackInput_Flags( 2, HLSLVAR_FLOAT1, "Ref Index" ); + SetJackFlags_Output( 0, HLSLJACKFLAGS_F1_TO_F4 ); + + GetJack_In( 0 )->SetName( "Ray" ); + GetJack_In( 1 )->SetName( "Normal" ); +} + +CNodeVectorRefract::~CNodeVectorRefract() +{ +} + +int CNodeVectorRefract::UpdateInputsValid() +{ + int baseLevel = BaseClass::UpdateInputsValid(); + int locallevel = ERRORLEVEL_NONE; + + int vartype_jack_0 = GetJack_In( 0 )->GetSmartType(); + int vartype_jack_1 = GetJack_In( 1 )->GetSmartType(); + + int autoTest = TestJackFlags_In(); + + if ( autoTest == ERRORLEVEL_NONE ) + { + if ( vartype_jack_0 != vartype_jack_1 ) + { + bool bOneIsF1 = ( vartype_jack_0 == HLSLVAR_FLOAT1 ) || + ( vartype_jack_1 == HLSLVAR_FLOAT1 ); + if ( !bOneIsF1 ) + locallevel = ERRORLEVEL_FAIL; + } + else if ( vartype_jack_0 >= HLSLVAR_MATRIX3X3 || + vartype_jack_1 >= HLSLVAR_MATRIX3X3 ) + locallevel = ERRORLEVEL_FAIL; + } + + return max( locallevel, baseLevel ); +} +void CNodeVectorRefract::UpdateOutputs() +{ + if ( !GetNumJacks_Out() || !GetNumJacks_In() ) + return; + + if ( GetErrorLevel() != ERRORLEVEL_NONE ) + return SetOutputsUndefined(); + + GetJack_Out( 0 )->SetSmartType( max( GetJack_In(0)->GetSmartType(), GetJack_In(1)->GetSmartType() ) ); +} +bool CNodeVectorRefract::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( GetNumJacks_In_Connected() < 2 ) + return false; + + CJack *pJ1 = GetJack_In( 0 ); + CJack *pJ2 = GetJack_In( 1 ); + CJack *pJ3 = GetJack_In( 2 ); + CJack *pJ_Out = GetJack_Out( 0 ); + + int type1 = pJ1->GetSmartType(); + int type2 = pJ2->GetSmartType(); + const int res = pJ_Out->GetResourceType(); + + CHLSL_Var *tg = GetInputToWriteTo( max( type1, type2 ) ); + SetAllocating( !tg ); + if ( !tg ) + tg = pJ_Out->AllocateVarFromSmartType(); + pJ_Out->SetTemporaryVarTarget( tg ); + + CHLSL_Solver_VectorRefract *solver = new CHLSL_Solver_VectorRefract( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( pJ1->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ2->GetTemporaryVarTarget_End() ); + solver->AddSourceVar( pJ3->GetTemporaryVarTarget_End() ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vectorref.h b/sp/src/shadereditor/nodes/vnode_vectorref.h new file mode 100644 index 00000000..d81bf542 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vectorref.h @@ -0,0 +1,39 @@ +#ifndef CNODE_VECTORREF_H +#define CNODE_VECTORREF_H + +#include "vBaseNode.h" + +class CNodeVectorReflect : public CBaseNode +{ + DECLARE_CLASS( CNodeVectorReflect, CBaseNode ); + +public: + CNodeVectorReflect( CNodeView *p ); + ~CNodeVectorReflect(); + virtual int GetNodeType(){ return HLSLNODE_VECTOR_REFLECT; }; + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + +class CNodeVectorRefract : public CBaseNode +{ + DECLARE_CLASS( CNodeVectorRefract, CBaseNode ); + +public: + CNodeVectorRefract( CNodeView *p ); + ~CNodeVectorRefract(); + virtual int GetNodeType(){ return HLSLNODE_VECTOR_REFRACT; }; + virtual int UpdateInputsValid(); + virtual void UpdateOutputs(); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vmtparam.cpp b/sp/src/shadereditor/nodes/vnode_vmtparam.cpp new file mode 100644 index 00000000..3e3cd094 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vmtparam.cpp @@ -0,0 +1,156 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CNodeVmtParam_Mutable::CNodeVmtParam_Mutable( CNodeView *p ) : BaseClass( "VParam mutable", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + GenerateJacks_Output( 1 ); + + m_iParamIndex = 0; + m_iNumComponents = 3; + m_iChannelInfo.SetDefaultChannels(); + m_iChannelInfo.bAllowChars = false; + m_szConstantString[0] = '\0'; + + UpdateNode(); +} +void CNodeVmtParam_Mutable::UpdateNode() +{ + LockJackOutput_Flags( 0, ::GetVarTypeFlag( m_iNumComponents ), VarArgs( "Idx %02i", m_iParamIndex + 1 ) ); + + OnUpdateHierachy( NULL, NULL ); +} +KeyValues *CNodeVmtParam_Mutable::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "i_vp_mutable_param", m_iParamIndex ); + pKV->SetInt( "i_vp_mutable_nc", m_iNumComponents ); + pKV->SetString( "szConstantString", m_szConstantString ); + + return pKV; +} +void CNodeVmtParam_Mutable::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + m_iParamIndex = pKV->GetInt( "i_vp_mutable_param", m_iParamIndex ); + m_iNumComponents = pKV->GetInt( "i_vp_mutable_nc", m_iNumComponents ); + + char tmp[MAX_PATH]; + Q_snprintf( tmp, sizeof(tmp), "%s", pKV->GetString( "szConstantString" ) ); + m_iChannelInfo.Tokenize( tmp ); + m_iChannelInfo.PrintTargetString( m_szConstantString, MAX_PATH ); + + UpdateNode(); +} +bool CNodeVmtParam_Mutable::CreateSolvers(GenericShaderData *ShaderData) +{ + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_VParam_Mutable *solver = new CHLSL_Solver_VParam_Mutable( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( m_iParamIndex, m_iNumComponents ); + solver->SetComponentInfo( m_iChannelInfo ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} + + + + + + +CNodeVmtParam_Static::CNodeVmtParam_Static( CNodeView *p ) : BaseClass( "VParam static", p ) +{ + m_flMinSizeX = NODEDEFSIZE_SMALL; + m_flMinSizeY = NODEDEFSIZE_SMALL; + m_flMinSizePREVIEW_X = NODEDEFSIZE_SMALL; + + m_iNumComponents = 3; + m_szName = NULL; + m_iChannelInfo.SetDefaultChannels(); + m_iChannelInfo.bAllowChars = false; + m_szConstantString[0] = '\0'; + + UpdateNode(); +} +CNodeVmtParam_Static::~CNodeVmtParam_Static() +{ + delete [] m_szName; +} +void CNodeVmtParam_Static::UpdateNode() +{ + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_Out( CBaseNode::BY_INDEX, m_hRestoreBridges ); + + const bool bValid = m_szName && Q_strlen( m_szName ); + GenerateJacks_Output( bValid ? 1 : 0 ); + + if ( bValid ) + { + LockJackOutput_Flags( 0, ::GetVarTypeFlag( m_iNumComponents ), VarArgs( "%s", m_szName ) ); + } + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} +KeyValues *CNodeVmtParam_Static::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetString( "i_vp_static_name", m_szName ); + pKV->SetInt( "i_vp_static_nc", m_iNumComponents ); + pKV->SetString( "szConstantString", m_szConstantString ); + + return pKV; +} +void CNodeVmtParam_Static::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + const char *name = pKV->GetString( "i_vp_static_name" ); + if ( name && Q_strlen( name ) ) + { + delete [] m_szName; + m_szName = new char[ Q_strlen( name ) + 1 ]; + Q_strcpy( m_szName, name ); + } + m_iNumComponents = pKV->GetInt( "i_vp_static_nc", m_iNumComponents ); + + char tmp[MAX_PATH]; + Q_snprintf( tmp, sizeof(tmp), "%s", pKV->GetString( "szConstantString" ) ); + m_iChannelInfo.Tokenize( tmp ); + m_iChannelInfo.PrintTargetString( m_szConstantString, MAX_PATH ); + + UpdateNode(); + OnUpdateHierachy( NULL, NULL ); +} +bool CNodeVmtParam_Static::CreateSolvers(GenericShaderData *ShaderData) +{ + if ( !m_szName || !Q_strlen( m_szName ) ) + return false; + + CJack *pJ_Out = GetJack_Out( 0 ); + const int res = pJ_Out->GetResourceType(); + + SetAllocating( false ); + CHLSL_Var *tg = pJ_Out->AllocateVarFromSmartType(); + tg->MakeConstantOnly(); + + CHLSL_Solver_VParam_Static *solver = new CHLSL_Solver_VParam_Static( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->SetState( m_szName, m_iNumComponents ); + solver->SetComponentInfo( m_iChannelInfo ); + solver->AddTargetVar( tg ); + AddSolver( solver ); + + return true; +} diff --git a/sp/src/shadereditor/nodes/vnode_vmtparam.h b/sp/src/shadereditor/nodes/vnode_vmtparam.h new file mode 100644 index 00000000..cf0e9436 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vmtparam.h @@ -0,0 +1,59 @@ +#ifndef CNODE_VMTPARAM_H +#define CNODE_VMTPARAM_H + +#include "vBaseNode.h" + +class CNodeVmtParam_Mutable : public CBaseNode +{ + DECLARE_CLASS( CNodeVmtParam_Mutable, CBaseNode ); + +public: + CNodeVmtParam_Mutable( CNodeView *p ); + ~CNodeVmtParam_Mutable(){}; + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_VP_MUTABLE; }; + + void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + int m_iParamIndex; + int m_iNumComponents; + + char m_szConstantString[MAX_PATH]; + TokenChannels_t m_iChannelInfo; +}; + + + +class CNodeVmtParam_Static : public CBaseNode +{ + DECLARE_CLASS( CNodeVmtParam_Static, CBaseNode ); + +public: + CNodeVmtParam_Static( CNodeView *p ); + ~CNodeVmtParam_Static(); + + virtual int GetNodeType(){ return HLSLNODE_CONSTANT_VP_STATIC; }; + + void UpdateNode(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + char *m_szName; + int m_iNumComponents; + + char m_szConstantString[MAX_PATH]; + TokenChannels_t m_iChannelInfo; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vsinput.cpp b/sp/src/shadereditor/nodes/vnode_vsinput.cpp new file mode 100644 index 00000000..6a38f0cd --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vsinput.cpp @@ -0,0 +1,160 @@ + +#include "cbase.h" +#include "editorCommon.h" +#include "vSheets.h" + + +CNodeVSInput::CNodeVSInput( CNodeView *p ) : BaseClass( "VS Input", p ) +{ + m_flMinSizeX = CRUCIALNODE_MIN_SIZE_X; + m_flMinSizeY = 0; + m_bPreviewEnabled = false; + + SETUP_HLSL_VS_Input defaultInfo; + Setup( defaultInfo ); + //curSetup = defaultInfo; + + //GenerateJacks_Output( 2 ); + //SetupJackOutput( 0, HLSLJACKFLAGS_F3, "Position" ); +} + +CNodeVSInput::~CNodeVSInput() +{ +} + +void CNodeVSInput::Setup( SETUP_HLSL_VS_Input info ) +{ + int numOutputs = 1; + if ( info.bFlexDelta_enabled ) + numOutputs += 2; + if ( info.bBlendweights_enabled ) + numOutputs += 2; + if ( info.bNormal_enabled ) + numOutputs += 1; + if ( info.bTangentspace_enabled ) + numOutputs += 2; + numOutputs += info.iTexcoords_num; + numOutputs += info.iVertexcolor_num; + + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_Out( CBaseNode::BY_NAME, m_hRestoreBridges ); + + GenerateJacks_Output( numOutputs ); + + int curOutput = 0; + + GetJack_Out( curOutput )->SetResourceType( RESOURCETYPE_POS_3 ); + LockJackOutput_Flags( curOutput, HLSLVAR_FLOAT3, "Position" );curOutput++; + + if ( info.bFlexDelta_enabled ) + { + GetJack_Out( curOutput )->SetResourceType( RESOURCETYPE_FLEXDELTA ); + LockJackOutput_Flags( curOutput, HLSLVAR_FLOAT3, "Flex offset" );curOutput++; + GetJack_Out( curOutput )->SetResourceType( RESOURCETYPE_FLEXDELTA_NORMAL ); + LockJackOutput_Flags( curOutput, HLSLVAR_FLOAT3, "Flex normal" );curOutput++; + } + if ( info.bBlendweights_enabled ) + { + GetJack_Out( curOutput )->SetResourceType( RESOURCETYPE_BONE_WEIGHTS ); + LockJackOutput_Flags( curOutput, HLSLVAR_FLOAT4, "Bone weights" );curOutput++; + GetJack_Out( curOutput )->SetResourceType( RESOURCETYPE_BONE_INDICES ); + LockJackOutput_Flags( curOutput, HLSLVAR_FLOAT4, "Bone indices" );curOutput++; + } + if ( info.bNormal_enabled ) + { + int normalFlag = info.bNormal_enabled_compression ? HLSLVAR_FLOAT4 : HLSLVAR_FLOAT3; + GetJack_Out( curOutput )->SetResourceType( info.bNormal_enabled_compression ? RESOURCETYPE_NORMAL_4 : RESOURCETYPE_NORMAL ); + LockJackOutput_Flags( curOutput, normalFlag, "Normal" );curOutput++; + } + if ( info.bTangentspace_enabled ) + { + int tangentStype = info.bTangentspace_enabled_skinning ? HLSLVAR_FLOAT4 : HLSLVAR_FLOAT3; + int tangentSRestype = info.bTangentspace_enabled_skinning ? RESOURCETYPE_TANGENTS_4 : RESOURCETYPE_TANGENTS_3; + + GetJack_Out( curOutput )->SetResourceType( tangentSRestype ); + LockJackOutput_Flags( curOutput, tangentStype, "Tangent S" );curOutput++; + GetJack_Out( curOutput )->SetResourceType( RESOURCETYPE_TANGENTT ); + LockJackOutput_Flags( curOutput, HLSLVAR_FLOAT3, "Tangent T" );curOutput++; + } + + for ( int i = 0; i < info.iTexcoords_num; i++ ) + { + Assert( i < 3 ); + GetJack_Out( curOutput )->SetResourceType( RESOURCETYPE_TEXCOORD_0 + i ); + LockJackOutput_Flags( curOutput, info.iDataTypeFlag_TexCoords[i], VarArgs("TexCoords %i",i) );curOutput++; + } + for ( int i = 0; i < info.iVertexcolor_num; i++ ) + { + Assert( i < 2 ); + GetJack_Out( curOutput )->SetResourceType( RESOURCETYPE_COLOR_0 + i ); + LockJackOutput_Flags( curOutput, info.iDataTypeFlag_Color[i], VarArgs("Color %i",i) );curOutput++; + } + curSetup = info; + + RestoreBridgesFromList_Out( m_hRestoreBridges ); +} +KeyValues *CNodeVSInput::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "enable_flex", curSetup.bFlexDelta_enabled ); + pKV->SetInt( "enable_normal", curSetup.bNormal_enabled ); + pKV->SetInt( "enable_normal_compression", curSetup.bNormal_enabled_compression ); + pKV->SetInt( "enable_blendweights", curSetup.bBlendweights_enabled ); + pKV->SetInt( "enable_tangentspace", curSetup.bTangentspace_enabled ); + pKV->SetInt( "enable_tangentspace_skinning", curSetup.bTangentspace_enabled_skinning ); + + pKV->SetInt( "numTexcoords", curSetup.iTexcoords_num ); + pKV->SetInt( "numColor", curSetup.iVertexcolor_num ); + + for ( int i = 0; i < 3; i++ ) + pKV->SetInt( VarArgs( "dTFlag_Texcoords_%i", i ), curSetup.iDataTypeFlag_TexCoords[i] ); + + for ( int i = 0; i < 2; i++ ) + pKV->SetInt( VarArgs( "dTFlag_Color_%i", i ), curSetup.iDataTypeFlag_Color[i] ); + + return pKV; +} +void CNodeVSInput::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + SETUP_HLSL_VS_Input info; + + info.bFlexDelta_enabled = !!pKV->GetInt( "enable_flex" ); + info.bNormal_enabled = !!pKV->GetInt( "enable_normal" ); + info.bNormal_enabled_compression = !!pKV->GetInt( "enable_normal_compression" ); + info.bBlendweights_enabled = !!pKV->GetInt( "enable_blendweights" ); + info.bTangentspace_enabled = !!pKV->GetInt( "enable_tangentspace" ); + info.bTangentspace_enabled_skinning = !!pKV->GetInt( "enable_tangentspace_skinning" ); + + info.iTexcoords_num = pKV->GetInt( "numTexcoords" ); + info.iVertexcolor_num = pKV->GetInt( "numColor" ); + + for ( int i = 0; i < 3; i++ ) + info.iDataTypeFlag_TexCoords[i] = pKV->GetInt( VarArgs( "dTFlag_Texcoords_%i", i ), HLSLVAR_FLOAT2 ); + for ( int i = 0; i < 2; i++ ) + info.iDataTypeFlag_Color[i] = pKV->GetInt( VarArgs( "dTFlag_Color_%i", i ), HLSLVAR_FLOAT4 ); + + Setup( info ); +} +bool CNodeVSInput::CreateSolvers(GenericShaderData *ShaderData) +{ + for ( int i = 0; i < GetNumJacks_Out(); i++ ) + { + CJack *pJ = GetJack_Out( i ); + if ( !pJ->GetNumBridgesConnected() ) + continue; + + const int res = pJ->GetResourceType(); + CHLSL_Var *var = pJ->AllocateVarFromSmartType(); + var->MakeConstantOnly(); + + CHLSL_Solver_ReadSemantics *solver = new CHLSL_Solver_ReadSemantics( GetUniqueIndex() ); + solver->SendVSSetup( curSetup ); + solver->SetResourceType( res ); + solver->AddTargetVar( var ); + AddSolver( solver ); + } + + SmartCreateDummySolver(); + return true; +} diff --git a/sp/src/shadereditor/nodes/vnode_vsinput.h b/sp/src/shadereditor/nodes/vnode_vsinput.h new file mode 100644 index 00000000..9f0a1fca --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vsinput.h @@ -0,0 +1,37 @@ +#ifndef CNODEVSINPUT_H +#define CNODEVSINPUT_H + +#include + +class CNodeVSInput : public CBaseNode +{ + DECLARE_CLASS( CNodeVSInput, CBaseNode ); + +public: + + CNodeVSInput( CNodeView *p ); + ~CNodeVSInput(); + + virtual bool CanBeInContainer(){ return false; }; + virtual int GetNodeType(){ return HLSLNODE_VS_IN; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsNodeCrucial(){ return true; }; + + virtual int GetHierachyType(){return HLSLHIERACHY_VS;}; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual int UpdateInputsValid(){ return ERRORLEVEL_NONE; }; + + void Setup( SETUP_HLSL_VS_Input info ); + SETUP_HLSL_VS_Input &GetSetup(){ return curSetup; }; + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + SETUP_HLSL_VS_Input curSetup; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vsoutput.cpp b/sp/src/shadereditor/nodes/vnode_vsoutput.cpp new file mode 100644 index 00000000..0efe1e59 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vsoutput.cpp @@ -0,0 +1,169 @@ + +#include "cbase.h" +#include "editorCommon.h" +#include "vSheets.h" + + +CNodeVSOutput::CNodeVSOutput( CNodeView *p ) : BaseClass( "VS Output", p ) +{ + m_flMinSizeX = CRUCIALNODE_MIN_SIZE_X; + m_flMinSizeY = 0; + m_bPreviewEnabled = false; + + SETUP_HLSL_VS_Output_PS_Input defaultInfo; + Setup( defaultInfo ); +} + +CNodeVSOutput::~CNodeVSOutput() +{ +} + +void CNodeVSOutput::Setup( SETUP_HLSL_VS_Output_PS_Input info ) +{ + int numInputs = 1; + numInputs += info.iTexcoords_num; + numInputs += info.iVertexcolor_num; + + int extraRows = 0; + for ( int i = 0; i < info.iTexcoords_num; i++ ) + { + int rows = max(0,GetVarFlagsRowsRequired( info.iTexCoordFlag[i] ) - 1); + extraRows += rows; + } + + numInputs -= extraRows; + + CUtlVector< BridgeRestoreInfo* >m_hRestoreBridges; + CreateBridgeRestoreData_In( CBaseNode::BY_RESTYPE, m_hRestoreBridges ); + + GenerateJacks_Input( numInputs ); + + int curInput = 0; + int texCoordNameOffset = 0; + + GetJack_In(curInput)->SetResourceType( RESOURCETYPE_POS_4 ); + LockJackInput_Flags( curInput, HLSLVAR_FLOAT4, "ProjPosition" );curInput++; + + for ( int i = 0; i < info.iTexcoords_num - extraRows; i++ ) + { + GetJack_In(curInput)->SetResourceType( RESOURCETYPE_TEXCOORD_0 + texCoordNameOffset ); + LockJackInput_Flags( curInput, info.iTexCoordFlag[texCoordNameOffset], VarArgs("TexCoords %i", texCoordNameOffset) ); + int localRows = GetVarFlagsRowsRequired( info.iTexCoordFlag[ texCoordNameOffset ] ); + texCoordNameOffset += localRows; + curInput++; + } + for ( int i = 0; i < info.iVertexcolor_num; i++ ) + { + GetJack_In(curInput)->SetResourceType( RESOURCETYPE_COLOR_0 + i ); + LockJackInput_Flags( curInput, info.iColorFlag[i], VarArgs("Color %i",i) ); + curInput++; + } + curSetup = info; + + RestoreBridgesFromList_In( m_hRestoreBridges ); +} +void CNodeVSOutput::LoadNames() +{ + int numInputs = 0; + numInputs += curSetup.iTexcoords_num; + numInputs += curSetup.iVertexcolor_num; + + int extraRows = 0; + for ( int i = 0; i < curSetup.iTexcoords_num; i++ ) + { + int rows = max(0,GetVarFlagsRowsRequired( curSetup.iTexCoordFlag[i] ) - 1); + extraRows += rows; + } + + numInputs -= extraRows; + + int curInput = 1; + int texCoordNameOffset = 0; + + for ( int i = 0; i < curSetup.iTexcoords_num - extraRows; i++ ) + { + if ( Q_strlen( curNames.names_texcoords[ texCoordNameOffset ] ) ) + GetJack_In( curInput )->SetName( curNames.names_texcoords[ texCoordNameOffset ] ); + int localRows = GetVarFlagsRowsRequired( curSetup.iTexCoordFlag[ texCoordNameOffset ] ); + texCoordNameOffset += localRows; + curInput++; + } + for ( int i = 0; i < curSetup.iVertexcolor_num; i++ ) + { + if ( Q_strlen( curNames.names_colors[ i ] ) ) + GetJack_In( curInput )->SetName( curNames.names_colors[ i ] ); + curInput++; + } +} +KeyValues *CNodeVSOutput::AllocateKeyValues( int NodeIndex ) +{ + KeyValues *pKV = BaseClass::AllocateKeyValues( NodeIndex ); + + pKV->SetInt( "numTexcoords", curSetup.iTexcoords_num ); + pKV->SetInt( "numColor", curSetup.iVertexcolor_num ); + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + pKV->SetInt( VarArgs( "numTexcoord_Flag_%i", i ), curSetup.iTexCoordFlag[ i ] ); + pKV->SetString( VarArgs( "numTexcoord_Name_%i", i ), curNames.names_texcoords[ i ] ); + } + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + { + pKV->SetInt( VarArgs( "numColor_Flag_%i", i ), curSetup.iColorFlag[ i ] ); + pKV->SetString( VarArgs( "numColor_Name_%i", i ), curNames.names_colors[ i ] ); + } + return pKV; +} +void CNodeVSOutput::RestoreFromKeyValues( KeyValues *pKV ) +{ + BaseClass::RestoreFromKeyValues( pKV ); + + CBaseNode *pPartner = pNodeView->GetNodeFromType( HLSLNODE_PS_IN ); + if ( pPartner ) + pPartner->RestoreFromKeyValues_Specific( pKV ); +} +void CNodeVSOutput::RestoreFromKeyValues_Specific( KeyValues *pKV ) +{ + SETUP_HLSL_VS_Output_PS_Input info; + + info.iTexcoords_num = pKV->GetInt( "numTexcoords" ); + info.iVertexcolor_num = pKV->GetInt( "numColor" ); + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + info.iTexCoordFlag[ i ] = pKV->GetInt( VarArgs( "numTexcoord_Flag_%i", i ) ); + Q_snprintf( curNames.names_texcoords[ i ], sizeof(curNames.names_texcoords[ i ]), "%s", pKV->GetString( VarArgs( "numTexcoord_Name_%i", i ) ) ); + } + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + { + info.iColorFlag[ i ] = pKV->GetInt( VarArgs( "numColor_Flag_%i", i ) ); + Q_snprintf( curNames.names_colors[ i ], sizeof(curNames.names_colors[ i ]), "%s", pKV->GetString( VarArgs( "numColor_Name_%i", i ) ) ); + } + + Setup( info ); + LoadNames(); +} + +bool CNodeVSOutput::CreateSolvers(GenericShaderData *ShaderData) +{ + for ( int i = 0; i < GetNumJacks_In(); i++ ) + { + CJack *pJ = GetJack_In( i ); + if ( !pJ->GetNumBridgesConnected() ) + continue; + + CJack *sourceJack = pJ->GetBridge( 0 )->GetInputJack(); + CHLSL_Var *src = sourceJack->GetTemporaryVarTarget(); + const int res = pJ->GetResourceType(); + + CHLSL_Solver_WriteSemantics *solver = new CHLSL_Solver_WriteSemantics( GetUniqueIndex() ); + solver->SetResourceType( res ); + solver->AddSourceVar( src ); + solver->GetData()._IntValue_0 = pJ->GetSmartType(); + //if ( pJ->GetSmartType() < 0 ) + // Warning("smarttype error!!\n"); + + AddSolver( solver ); + } + + SmartCreateDummySolver(); + return true; +} \ No newline at end of file diff --git a/sp/src/shadereditor/nodes/vnode_vsoutput.h b/sp/src/shadereditor/nodes/vnode_vsoutput.h new file mode 100644 index 00000000..1ff39168 --- /dev/null +++ b/sp/src/shadereditor/nodes/vnode_vsoutput.h @@ -0,0 +1,41 @@ +#ifndef CNODEVSOUTPUT_H +#define CNODEVSOUTPUT_H + +#include + +class CNodeVSOutput : public CBaseNode +{ + DECLARE_CLASS( CNodeVSOutput, CBaseNode ); + +public: + + CNodeVSOutput( CNodeView *p ); + ~CNodeVSOutput(); + + virtual bool CanBeInContainer(){ return false; }; + virtual int GetNodeType(){ return HLSLNODE_VS_OUT; }; + virtual bool IsPreviewVisible(){ return false; }; + virtual const bool IsNodeCrucial(){ return true; }; + + virtual int GetHierachyType(){return HLSLHIERACHY_VS;}; + virtual int GetAllowedHierachiesAsFlags(){ return HLSLHIERACHY_VS; }; + virtual bool ShouldErrorOnUndefined(){ return true; }; + + void Setup( SETUP_HLSL_VS_Output_PS_Input info ); + SETUP_HLSL_VS_Output_PS_Input &GetSetup(){ return curSetup; }; + + void LoadNames(); + + virtual KeyValues *AllocateKeyValues( int NodeIndex ); + virtual void RestoreFromKeyValues( KeyValues *pKV ); + virtual void RestoreFromKeyValues_Specific( KeyValues *pKV ); + +private: + virtual bool CreateSolvers(GenericShaderData *ShaderData); + + SETUP_HLSL_VS_Output_PS_Input curSetup; + SETUP_VSOUTPSIN_CustomNames curNames; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_drawmat.cpp b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_drawmat.cpp new file mode 100644 index 00000000..a8a964c1 --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_drawmat.cpp @@ -0,0 +1,106 @@ + +#include "cbase.h" +#include "vSheets.h" + +static const char *pszSizingModes[] = { + "Full frame buffer", + "Half frame buffer", + "Quarter frame buffer", +}; +static const int iSizingModes = ARRAYSIZE( pszSizingModes ); + +CSheet_PP_DrawMat::CSheet_PP_DrawMat(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_SizingTg = new ComboBox( this, "cbox_sizingrt", 20, true ); + m_pCBox_SizingSrc = new ComboBox( this, "cbox_sizingsrc", 20, true ); + m_pCheck_PushTarget = new CheckButton( this, "checkpushtg", "Push target for rendering" ); + + m_pTE_Destx = new TextEntry( this, "compensate_dest_x" ); + m_pTE_Desty = new TextEntry( this, "compensate_dest_y" ); + m_pTE_Destw = new TextEntry( this, "compensate_dest_w" ); + m_pTE_Desth = new TextEntry( this, "compensate_dest_h" ); + + m_pTE_Srcx0 = new TextEntry( this, "compensate_src_x0" ); + m_pTE_Srcy0 = new TextEntry( this, "compensate_src_y0" ); + m_pTE_Srcx1 = new TextEntry( this, "compensate_sourceuv_x" ); + m_pTE_Srcy1 = new TextEntry( this, "compensate_sourceuv_y" ); + + m_pTE_Srcw = new TextEntry( this, "compensate_src_w" ); + m_pTE_Srch = new TextEntry( this, "compensate_src_h" ); + + for ( int i = 0; i < iSizingModes; i++ ) + { + m_pCBox_SizingTg->AddItem( pszSizingModes[i], NULL ); + m_pCBox_SizingSrc->AddItem( pszSizingModes[i], NULL ); + } + + LoadControlSettings( "shadereditorui/vgui/sheet_pp_drawmat.res" ); +} + +CSheet_PP_DrawMat::~CSheet_PP_DrawMat() +{ +} + +void CSheet_PP_DrawMat::OnResetData() +{ + int iTg = pData->GetInt( "iSizingMode_Tg" ); + int iSrc = pData->GetInt( "iSizingMode_Src" ); + + Assert( iTg >= 0 && iTg < iSizingModes ); + Assert( iSrc >= 0 && iSrc < iSizingModes ); + + m_pCBox_SizingTg->ActivateItem( iTg ); + m_pCBox_SizingSrc->ActivateItem( iSrc ); + + m_pCBox_SizingTg->SetEnabled( !pData->GetInt( "iSHEETHINT_enable_tg" ) ); + m_pCBox_SizingSrc->SetEnabled( !pData->GetInt( "iSHEETHINT_enable_src" ) ); + + m_pCheck_PushTarget->SetSelected( !!pData->GetInt( "iPushTg" ) ); + + m_pTE_Destx->SetText( VarArgs( "%i", pData->GetInt( "iDst_x" ) ) ); + m_pTE_Desty->SetText( VarArgs( "%i", pData->GetInt( "iDst_y" ) ) ); + m_pTE_Destw->SetText( VarArgs( "%i", pData->GetInt( "iDst_w" ) ) ); + m_pTE_Desth->SetText( VarArgs( "%i", pData->GetInt( "iDst_h" ) ) ); + + m_pTE_Srcx0->SetText( VarArgs( "%f", pData->GetFloat( "flSrcUV_x0" ) ) ); + m_pTE_Srcy0->SetText( VarArgs( "%f", pData->GetFloat( "flSrcUV_y0" ) ) ); + m_pTE_Srcx1->SetText( VarArgs( "%f", pData->GetFloat( "flSrcUV_x" ) ) ); + m_pTE_Srcy1->SetText( VarArgs( "%f", pData->GetFloat( "flSrcUV_y" ) ) ); + + m_pTE_Srcw->SetText( VarArgs( "%i", pData->GetInt( "iSrc_w" ) ) ); + m_pTE_Srch->SetText( VarArgs( "%i", pData->GetInt( "iSrc_h" ) ) ); +} + +void CSheet_PP_DrawMat::OnApplyChanges() +{ + pData->SetInt( "iSizingMode_Tg", m_pCBox_SizingTg->GetActiveItem() ); + pData->SetInt( "iSizingMode_Src", m_pCBox_SizingSrc->GetActiveItem() ); + pData->SetInt( "iPushTg", m_pCheck_PushTarget->IsSelected() ? 1 : 0 ); + + char tmp[MAX_PATH]; + m_pTE_Destx->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "iDst_x", atoi( tmp ) ); + m_pTE_Desty->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "iDst_y", atoi( tmp ) ); + m_pTE_Destw->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "iDst_w", atoi( tmp ) ); + m_pTE_Desth->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "iDst_h", atoi( tmp ) ); + + m_pTE_Srcx0->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "flSrcUV_x0", atof( tmp ) ); + m_pTE_Srcy0->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "flSrcUV_y0", atof( tmp ) ); + m_pTE_Srcx1->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "flSrcUV_x", atof( tmp ) ); + m_pTE_Srcy1->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "flSrcUV_y", atof( tmp ) ); + + m_pTE_Srcw->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "iSrc_w", atoi( tmp ) ); + m_pTE_Srch->GetText( tmp, sizeof(tmp) ); + pData->SetFloat( "iSrc_h", atoi( tmp ) ); +} diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_drawmat.h b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_drawmat.h new file mode 100644 index 00000000..55a8fe63 --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_drawmat.h @@ -0,0 +1,42 @@ +#ifndef CSHEET_PP_DRAWMAT_H +#define CSHEET_PP_DRAWMAT_H + +#include "vSheets.h" + +class CSheet_PP_DrawMat : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_PP_DrawMat, CSheet_Base ); + + CSheet_PP_DrawMat(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_PP_DrawMat(); + + virtual const char *GetSheetTitle(){return"Draw material";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_SizingTg; + ComboBox *m_pCBox_SizingSrc; + CheckButton *m_pCheck_PushTarget; + + //TextEntry *m_pManualSourceUV_x; + //TextEntry *m_pManualSourceUV_y; + + TextEntry *m_pTE_Destx; + TextEntry *m_pTE_Desty; + TextEntry *m_pTE_Destw; + TextEntry *m_pTE_Desth; + + TextEntry *m_pTE_Srcx0; + TextEntry *m_pTE_Srcy0; + TextEntry *m_pTE_Srcx1; + TextEntry *m_pTE_Srcy1; + + TextEntry *m_pTE_Srcw; + TextEntry *m_pTE_Srch; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_mat.cpp b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_mat.cpp new file mode 100644 index 00000000..7792565e --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_mat.cpp @@ -0,0 +1,245 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CSheet_PP_Mat::CSheet_PP_Mat(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_szMatPath[0] = '\0'; + m_pVMTBuffer = new KeyValues("vmtbuffer"); + + m_bPerformedInjection = false; + + m_pCheck_Inline = new CheckButton( this, "check_inline", "Inline material" ); + + m_pLoadMaterial = new Button( this, "button_load", "Load material", this, "mat_load" ); + m_pSaveMaterial = new Button( this, "button_save", "Save material", this, "mat_save" ); + m_pLabel_MatPath = new Label( this, "label_matpath", "-" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_pp_mat.res" ); +} + +CSheet_PP_Mat::~CSheet_PP_Mat() +{ + m_pVMTBuffer->deleteThis(); +} + +void CSheet_PP_Mat::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( "mat_load", cmd ) ) + { + OpenFiledialog( false ); + } + else if ( !Q_stricmp( "mat_save", cmd ) ) + { + OpenFiledialog( true ); + } + else if ( !Q_stricmp( "edit_vmt", cmd ) ) + { + char *pszSafe = CKVPacker::KVUnpack( m_pVMTBuffer, "szVMTString" ); + const char *pEditorVmt = CKVPacker::ConvertKVSafeString( pszSafe, false ); + delete [] pszSafe; + + CCode_Editor *pCEdit = new CCode_Editor( this, "ceditinstance", CSmartText::CODEEDITMODE_VMT ); + pCEdit->AddActionSignalTarget( this ); + pCEdit->MoveToFront(); + + const char *pszEditorInput = ( pEditorVmt && Q_strlen(pEditorVmt) > 0 ) ? pEditorVmt : DEFAULT_VMT_CONTENT; + + pCEdit->InitVMT( pszEditorInput ); + + delete [] pEditorVmt; + } + else + BaseClass::OnCommand( cmd ); +} + +void CSheet_PP_Mat::OnCodeUpdate( KeyValues *pKV ) +{ + char *pUnsafe = CKVPacker::KVUnpack( pKV, "szVMTString" ); + char *pSafeVmt = CKVPacker::ConvertKVSafeString( pUnsafe, true ); + delete [] pUnsafe; + CKVPacker::KVPack( pSafeVmt, "szVMTString", m_pVMTBuffer ); + //m_pVMTBuffer->SetString( "szVMTString", pSafeVmt ); + delete [] pSafeVmt; + + const bool bDoInjection = pKV->GetInt( "doinject" ) != 0; + + m_bPerformedInjection = m_bPerformedInjection || bDoInjection; + + if ( bDoInjection ) + { + KeyValues *pInject = pData->MakeCopy(); + WriteDataToKV( pInject ); + + n->RestoreFromKeyValues_Specific( pInject ); + pView->MakeSolversDirty(); + + pInject->deleteThis(); + } +} + +void CSheet_PP_Mat::OnResetData() +{ + const bool bInline = !!pData->GetInt( "iInline" ); + m_pCheck_Inline->SetSelected( bInline ); + + CKVPacker::KVCopyPacked( pData, m_pVMTBuffer, "szVMTString" ); + //m_pVMTBuffer->SetString( "szVMTString", pData->GetString("szVMTString")); + + if ( !bInline ) + { + Q_snprintf( m_szMatPath, sizeof(m_szMatPath), "%s", pData->GetString("szVMTPath") ); + m_pLabel_MatPath->SetText( m_szMatPath ); + + DoLoad(); + } +} + +void CSheet_PP_Mat::OnApplyChanges() +{ + WriteDataToKV( pData ); +} + +void CSheet_PP_Mat::OnRestoreNode() +{ + if ( !pData->GetInt( "iInline" ) ) + { + DoSave(); + } +} + +void CSheet_PP_Mat::WriteDataToKV( KeyValues *pKV ) +{ + const bool bInline = m_pCheck_Inline->IsSelected() || Q_strlen( m_szMatPath ) < 1; + pKV->SetInt( "iInline", bInline ? 1 : 0 ); + + if ( bInline ) + { + pKV->SetString( "szVMTPath", "" ); + CKVPacker::KVCopyPacked( m_pVMTBuffer, pKV, "szVMTString" ); + //pKV->SetString( "szVMTString", m_pVMTBuffer->GetString("szVMTString") ); + } + else + { + pKV->SetString( "szVMTString", "" ); + pKV->SetString( "szVMTPath", m_szMatPath ); + } +} + +void CSheet_PP_Mat::CheckButtonChecked( KeyValues *pKV ) +{ + const bool bChecked = !!pKV->GetInt( "state" ); + + m_pLoadMaterial->SetEnabled( !bChecked ); + m_pSaveMaterial->SetEnabled( !bChecked ); + m_pLabel_MatPath->SetVisible( !bChecked ); +} + +void CSheet_PP_Mat::OnFileSelected( KeyValues *pKV ) +{ + KeyValues *pContext = pKV->FindKey( "FileOpenContext" ); + if ( !pContext ) + return; + + const char *__c = pContext->GetString( "context" ); + bool bSaving = true; + if ( !Q_stricmp( __c, "openc" ) ) + bSaving = false; + + const char *pathIn = pKV->GetString( "fullpath" ); + if ( Q_strlen( pathIn ) <= 1 ) + return; + + if ( !g_pFullFileSystem->FullPathToRelativePath( pathIn, m_szMatPath, sizeof(m_szMatPath) ) ) + { + Q_snprintf( m_szMatPath, sizeof(m_szMatPath), "%s", pathIn ); + + vgui::PromptSimple *prompt = new vgui::PromptSimple( this, "ERROR" ); + prompt->MoveToCenterOfScreen(); + prompt->SetText( "The selected file is not located in the game directory!" ); + prompt->AddButton( "Ok" ); + prompt->MakeReadyForUse(); + prompt->InvalidateLayout( true, true ); + } + + m_pLabel_MatPath->SetText( m_szMatPath ); + + if ( !bSaving ) + { + DoLoad(); + } + else + { + DoSave(); + } +} + +void CSheet_PP_Mat::DoSave() +{ + if ( Q_strlen(m_szMatPath) < 1 ) + return; + + char *pszVmt_Unpacked = CKVPacker::KVUnpack( m_pVMTBuffer, "szVMTString" ); + const char *pszVmt = pszVmt_Unpacked; + //const char *pszVmt = m_pVMTBuffer->GetString( "szVMTString" ); + char *pConverted = NULL; + + if ( Q_strlen( pszVmt ) > 0 ) + pszVmt = pConverted = CKVPacker::ConvertKVSafeString( pszVmt, false ); + else + pszVmt = DEFAULT_VMT_CONTENT; + + CUtlBuffer buf; + buf.EnsureCapacity( Q_strlen( pszVmt ) + 1 ); + buf.Put( pszVmt, Q_strlen( pszVmt ) ); + g_pFullFileSystem->WriteFile( m_szMatPath, NULL, buf ); + buf.Clear(); + + delete [] pszVmt_Unpacked; + delete [] pConverted; +} + +void CSheet_PP_Mat::DoLoad() +{ + CUtlBuffer buf; + if ( g_pFullFileSystem->ReadFile( m_szMatPath, NULL, buf ) ) // && buf.TellPut() > 0 ) + { + int size = buf.TellPut(); + char *pszString = new char[ size + 1 ]; + buf.SeekGet( CUtlBuffer::SEEK_HEAD, 0 ); + buf.Get( pszString, size ); + pszString[size] = '\0'; + + char *pszSafeString = CKVPacker::ConvertKVSafeString( pszString, true ); + CKVPacker::KVPack( pszSafeString, "szVMTString", m_pVMTBuffer ); + //m_pVMTBuffer->SetString( "szVMTString", pszSafeString ); + + delete [] pszSafeString; + delete [] pszString; + } + buf.Clear(); +} + +void CSheet_PP_Mat::OpenFiledialog( bool bSave ) +{ + if ( m_hMaterialBrowser.Get() ) + m_hMaterialBrowser.Get()->MarkForDeletion(); + + m_hMaterialBrowser = new FileOpenDialog( this, + bSave ? "Save material" : "Load material", + bSave ? FOD_SAVE : FOD_OPEN, + new KeyValues("FileOpenContext", "context", + bSave ? "savec" : "openc" ) + ); + + if ( m_hMaterialBrowser.Get() ) + { + m_hMaterialBrowser->SetStartDirectoryContext( GetFODPathContext( FODPC_VMT ), VarArgs( "%s/materials", GetGamePath() ) ); + m_hMaterialBrowser->AddFilter( "*.vmt", "Valve material file", true ); + m_hMaterialBrowser->DoModal( true ); + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_mat.h b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_mat.h new file mode 100644 index 00000000..5dcd7f38 --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_mat.h @@ -0,0 +1,54 @@ +#ifndef CSHEET_PP_MAT_H +#define CSHEET_PP_MAT_H + +#include "vSheets.h" + +#define DEFAULT_VMT_CONTENT "\"EDITOR_SHADER\"\n{\n\t\"$SHADERNAME\"\t\"\"\n}" + +class CSheet_PP_Mat : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_PP_Mat, CSheet_Base ); + + CSheet_PP_Mat(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_PP_Mat(); + + virtual const char *GetSheetTitle(){return"Material";}; + + virtual bool RequiresReset(){ return m_bPerformedInjection; }; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + MESSAGE_FUNC( OnRestoreNode, "RestoreNode" ); + + MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", pKV ); + MESSAGE_FUNC_PARAMS( CheckButtonChecked, "CheckButtonChecked", pKV ); + //MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + + MESSAGE_FUNC_PARAMS( OnCodeUpdate, "CodeUpdate", pKV ); +protected: + + virtual void OnCommand( const char *cmd ); + +private: + + void WriteDataToKV( KeyValues *pKV ); + bool m_bPerformedInjection; + + char m_szMatPath[MAX_PATH*4]; + KeyValues *m_pVMTBuffer; + + DHANDLE< FileOpenDialog > m_hMaterialBrowser; + void OpenFiledialog( bool bSave ); + void DoSave(); + void DoLoad(); + + CheckButton *m_pCheck_Inline; + + Button *m_pLoadMaterial; + Button *m_pSaveMaterial; + Label *m_pLabel_MatPath; + +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_operations.cpp b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_operations.cpp new file mode 100644 index 00000000..6887f95d --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_operations.cpp @@ -0,0 +1,36 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CSheet_PP_ClearBuff::CSheet_PP_ClearBuff(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCheck_ClearColor = new CheckButton( this, "check_do_col", "Clear color" ); + m_pCheck_ClearDepth = new CheckButton( this, "check_do_depth", "Clear depth" ); + m_pText_Values = new TextEntry(this, "constantvalues"); + + LoadControlSettings( "shadereditorui/vgui/sheet_pp_clear_buffers.res" ); +} + +CSheet_PP_ClearBuff::~CSheet_PP_ClearBuff() +{ +} + +void CSheet_PP_ClearBuff::OnResetData() +{ + m_pText_Values->SetText( pData->GetString( "szConstantString" ) ); + m_pCheck_ClearColor->SetSelected( !!pData->GetInt( "iClear_Color" ) ); + m_pCheck_ClearDepth->SetSelected( !!pData->GetInt( "iClear_Depth" ) ); +} + +void CSheet_PP_ClearBuff::OnApplyChanges() +{ + char values_raw[MAX_PATH]; + m_pText_Values->GetText( values_raw, MAX_PATH ); + pData->SetString( "szConstantString", values_raw ); + + pData->SetInt( "iClear_Color", m_pCheck_ClearColor->IsSelected() ? 1 : 0 ); + pData->SetInt( "iClear_Depth", m_pCheck_ClearDepth->IsSelected() ? 1 : 0 ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_operations.h b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_operations.h new file mode 100644 index 00000000..817bf6d7 --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_operations.h @@ -0,0 +1,29 @@ +#ifndef CSHEET_PP_OPERATIONS_H +#define CSHEET_PP_OPERATIONS_H + +#include "vSheets.h" + +class CSheet_PP_ClearBuff : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_PP_ClearBuff, CSheet_Base ); + + CSheet_PP_ClearBuff(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_PP_ClearBuff(); + + virtual const char *GetSheetTitle(){return"Clear buffers";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +protected: + +private: + + CheckButton *m_pCheck_ClearColor; + CheckButton *m_pCheck_ClearDepth; + + TextEntry *m_pText_Values; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_renderview.cpp b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_renderview.cpp new file mode 100644 index 00000000..f48dad3f --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_renderview.cpp @@ -0,0 +1,179 @@ + +#include "cbase.h" +#include "vSheets.h" + +CSheet_PP_RenderView::CSheet_PP_RenderView(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pOptionsList = new PanelListPanel( this, "list_options" ); + m_pCBox_VrNames = new ComboBox( this, "cbox_vrnames", 20, false ); + m_pCheck_Scene = new CheckButton( this, "check_scenedraw", "Render during main scene" ); + + for ( int i = 0; i < GetPPCache()->GetNumVrCallbacks(); i++ ) + m_pCBox_VrNames->AddItem( GetPPCache()->GetVrCallback(i)->GetName(), NULL ); + + LoadControlSettings( "shadereditorui/vgui/sheet_pp_viewrender.res" ); + + m_pOptionsList->SetNumColumns( 1 ); + m_pOptionsList->SetVerticalBufferPixels( 0 ); +} + +CSheet_PP_RenderView::~CSheet_PP_RenderView() +{ +} + +void CSheet_PP_RenderView::OnResetData() +{ + const char *pszName = pData->GetString( "szVRCName" ); + + bool bReset = true; + for ( int i = 0; i < GetPPCache()->GetNumVrCallbacks(); i++ ) + { + if ( !Q_stricmp( GetPPCache()->GetVrCallback(i)->GetName(), pszName ) ) + { + m_pCBox_VrNames->SetText( GetPPCache()->GetVrCallback(i)->GetName() ); + FillOptions(); + bReset = false; + break; + } + } + + if ( bReset ) + m_pCBox_VrNames->ActivateItem( 0 ); + else + { + for ( int i = 0; i < hOptions_Bool.Count(); i++ ) + hOptions_Bool[i]->SetSelected( !!pData->GetInt( VarArgs( "options_bool_%i", i ) ) ); + + for ( int i = 0; i < hOptions_Int.Count(); i++ ) + hOptions_Int[i]->SetText( VarArgs( "%i", pData->GetInt( VarArgs( "options_int_%i", i ) ) ) ); + + for ( int i = 0; i < hOptions_Float.Count(); i++ ) + hOptions_Float[i]->SetText( VarArgs( "%f", pData->GetFloat( VarArgs( "options_float_%i", i ) ) ) ); + + for ( int i = 0; i < hOptions_String.Count(); i++ ) + hOptions_String[i]->SetText( VarArgs( "%s", pData->GetString( VarArgs( "options_string_%i", i ) ) ) ); + } + + m_pCheck_Scene->SetSelected( !!pData->GetInt( "iSceneDraw" ) ); +} + +void CSheet_PP_RenderView::OnApplyChanges() +{ + char tmp[MAX_PATH*4]; + m_pCBox_VrNames->GetText( tmp, sizeof(tmp) ); + pData->SetString( "szVRCName", tmp ); + + pData->SetInt( "options_bool_amt", hOptions_Bool.Count() ); + for ( int i = 0; i < hOptions_Bool.Count(); i++ ) + pData->SetInt( VarArgs( "options_bool_%i", i ), hOptions_Bool[i]->IsSelected() ? 1 : 0 ); + + pData->SetInt( "options_int_amt", hOptions_Int.Count() ); + for ( int i = 0; i < hOptions_Int.Count(); i++ ) + { + hOptions_Int[i]->GetText( tmp, sizeof( tmp ) ); + pData->SetInt( VarArgs( "options_int_%i", i ), atoi( tmp ) ); + } + + pData->SetInt( "options_float_amt", hOptions_Float.Count() ); + for ( int i = 0; i < hOptions_Float.Count(); i++ ) + { + hOptions_Float[i]->GetText( tmp, sizeof( tmp ) ); + pData->SetFloat( VarArgs( "options_float_%i", i ), atof( tmp ) ); + } + + pData->SetInt( "options_string_amt", hOptions_String.Count() ); + for ( int i = 0; i < hOptions_String.Count(); i++ ) + { + hOptions_String[i]->GetText( tmp, sizeof( tmp ) ); + pData->SetString( VarArgs( "options_string_%i", i ), tmp ); + } + + pData->SetInt( "iSceneDraw", m_pCheck_Scene->IsSelected() ? 1 : 0 ); +} + +void CSheet_PP_RenderView::OnTextChanged( KeyValues *pKV ) +{ + Panel *p = (Panel*)pKV->GetPtr("panel"); + + if ( p == m_pCBox_VrNames ) + FillOptions(); +} + +void CSheet_PP_RenderView::FillOptions() +{ + m_pOptionsList->DeleteAllItems(); + + hOptions_Bool.Purge(); + hOptions_Int.Purge(); + hOptions_Float.Purge(); + hOptions_String.Purge(); + + char tmp[MAX_PATH*4]; + m_pCBox_VrNames->GetText( tmp, sizeof(tmp) ); + int vrcIndex = GetPPCache()->FindVrCallback( tmp ); + + if ( vrcIndex < 0 ) + return; + + EditorRenderViewCommand_Definition *pVrC = GetPPCache()->GetVrCallback( vrcIndex ); + + for ( int i = 0; i < pVrC->GetNumVars( EditorRenderViewCommand_Definition::VAR_BOOL ); i++ ) + { + Label *pLName = new Label( m_pOptionsList, "", pVrC->GetVarName( EditorRenderViewCommand_Definition::VAR_BOOL, i ) ); + CheckButton *pCheck = new CheckButton( m_pOptionsList, "", "" ); + m_pOptionsList->AddItem( pLName, pCheck ); + hOptions_Bool.AddToTail( pCheck ); + + if ( pVrC->defaults.GetNumBool() > 0 ) + pCheck->SetSelected( pVrC->defaults.GetBoolVal( i ) ); + } + + for ( int i = 0; i < pVrC->GetNumVars( EditorRenderViewCommand_Definition::VAR_INT ); i++ ) + { + Label *pLName = new Label( m_pOptionsList, "", pVrC->GetVarName( EditorRenderViewCommand_Definition::VAR_INT, i ) ); + TextEntry *pText = new TextEntry( m_pOptionsList, "" ); + pText->SetText( "0" ); + m_pOptionsList->AddItem( pLName, pText ); + hOptions_Int.AddToTail( pText ); + + if ( pVrC->defaults.GetNumInt() > 0 ) + pText->SetText( VarArgs( "%i", pVrC->defaults.GetIntVal( i ) ) ); + } + + for ( int i = 0; i < pVrC->GetNumVars( EditorRenderViewCommand_Definition::VAR_FLOAT ); i++ ) + { + Label *pLName = new Label( m_pOptionsList, "", pVrC->GetVarName( EditorRenderViewCommand_Definition::VAR_FLOAT, i ) ); + TextEntry *pText = new TextEntry( m_pOptionsList, "" ); + pText->SetText( "0" ); + m_pOptionsList->AddItem( pLName, pText ); + hOptions_Float.AddToTail( pText ); + + if ( pVrC->defaults.GetNumFloat() > 0 ) + pText->SetText( VarArgs( "%f", pVrC->defaults.GetFloatVal( i ) ) ); + } + + for ( int i = 0; i < pVrC->GetNumVars( EditorRenderViewCommand_Definition::VAR_STRING ); i++ ) + { + Label *pLName = new Label( m_pOptionsList, "", pVrC->GetVarName( EditorRenderViewCommand_Definition::VAR_STRING, i ) ); + TextEntry *pText = new TextEntry( m_pOptionsList, "" ); + pText->SetText( "" ); + m_pOptionsList->AddItem( pLName, pText ); + hOptions_String.AddToTail( pText ); + + if ( pVrC->defaults.GetNumString() > 0 ) + pText->SetText( VarArgs( "%s", pVrC->defaults.GetStringVal( i ) ) ); + } +} + +void CSheet_PP_RenderView::PerformLayout() +{ + BaseClass::PerformLayout(); + + int sx,sy; + m_pOptionsList->GetSize( sx, sy ); + + m_pOptionsList->SetFirstColumnWidth( sx / 2 ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_renderview.h b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_renderview.h new file mode 100644 index 00000000..22fe9018 --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_renderview.h @@ -0,0 +1,39 @@ +#ifndef CSHEET_PP_RENDERVIEW_H +#define CSHEET_PP_RENDERVIEW_H + +#include "vSheets.h" + +class CSheet_PP_RenderView : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_PP_RenderView, CSheet_Base ); + + CSheet_PP_RenderView(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_PP_RenderView(); + + virtual const char *GetSheetTitle(){return"Render view";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + +protected: + + //virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void PerformLayout(); + +private: + + void FillOptions(); + CUtlVector< CheckButton* > hOptions_Bool; + CUtlVector< TextEntry* > hOptions_Int; + CUtlVector< TextEntry* > hOptions_Float; + CUtlVector< TextEntry* > hOptions_String; + + ComboBox *m_pCBox_VrNames; + PanelListPanel *m_pOptionsList; + CheckButton *m_pCheck_Scene; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_rt.cpp b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_rt.cpp new file mode 100644 index 00000000..d67d64ca --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_rt.cpp @@ -0,0 +1,114 @@ + +#include "cbase.h" +#include "vSheets.h" + +static const char *pszRTNames[] = { + "_rt_FullFrameFB", + "_rt_PowerOfTwoFB", + "_rt_SmallHDR0", + "_rt_SmallHDR1", + "_rt_SmallFB0", + "_rt_SmallFB1", + "_rt_WaterReflection", + "_rt_WaterRefraction", +}; +static const int iNumRTNames = ARRAYSIZE( pszRTNames ); + +CSheet_PP_RT::CSheet_PP_RT(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + //m_pText_RTName = new TextEntry( this, "textentry_rtname" ); + m_pCBox_RTName = new ComboBox( this, "textentry_rtname", 20, true ); + + for ( int i = 0; i < iNumRTNames; i++ ) + { + ITexture *pTex = materials->FindTexture( pszRTNames[i], TEXTURE_GROUP_OTHER, false ); + if ( IsErrorTexture( pTex ) ) + continue; + + m_pCBox_RTName->AddItem( pszRTNames[i], NULL ); + } + + for ( int i = 0; i < GetRTManager()->GetNumRTs(); i++ ) + m_pCBox_RTName->AddItem( GetRTManager()->GetRT(i)->GetName(), NULL ); + + m_pImgRef = new Panel( this, "img_ref" ); + m_pImgRef->SetPaintBackgroundEnabled( false ); + + LoadControlSettings( "shadereditorui/vgui/sheet_pp_rt.res" ); + + SetupVguiTex( m_iVguiPaint_Texture, "shadereditor/vguiTexSample" ); +} + +CSheet_PP_RT::~CSheet_PP_RT() +{ +} + +void CSheet_PP_RT::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + m_pImgRef->SetBorder(pScheme->GetBorder("DepressedButtonBorder")); +} + +void CSheet_PP_RT::OnResetData() +{ + m_pCBox_RTName->SetText( pData->GetString( "szRTName" ) ); +} + +void CSheet_PP_RT::OnApplyChanges() +{ + char tmp[MAX_PATH*4]; + m_pCBox_RTName->GetText( tmp, sizeof(tmp) ); + + pData->SetString( "szRTName", tmp ); +} + +void CSheet_PP_RT::OnTextChanged( KeyValues *pKV ) +{ + Panel *p = (Panel*)pKV->GetPtr("panel"); + + if ( !p ) + return; + + if ( p == m_pCBox_RTName ) + { + char tmp[MAX_PATH*4]; + m_pCBox_RTName->GetText( tmp, sizeof(tmp) ); + + IMaterial *pMat = materials->FindMaterial( "shadereditor/vguiTexSample", TEXTURE_GROUP_OTHER ); + if ( !pMat ) + return; + + bool bFound = false; + IMaterialVar *pBaseTex = pMat->FindVar( "$basetexture", &bFound ); + if ( !bFound ) + return; + + ITexture *tex = materials->FindTexture( tmp, TEXTURE_GROUP_OTHER, false ); + if ( IsErrorTexture(tex) ) + return; + + pBaseTex->SetTextureValue( tex ); +#ifdef SHADER_EDITOR_DLL_2006 + pMat->Refresh(); +#else + pMat->RefreshPreservingMaterialVars(); +#endif + pMat->RecomputeStateSnapshots(); + } +} + +void CSheet_PP_RT::Paint() +{ + BaseClass::Paint(); + + int x,y,sx,sy; + m_pImgRef->GetBounds( x,y,sx,sy); + + surface()->DrawSetColor( Color( 255,255,255,255) ); + surface()->DrawSetTexture( m_iVguiPaint_Texture ); + surface()->DrawTexturedRect( x,y,x+sx,y+sy); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/postprocessing/vsheet_pp_rt.h b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_rt.h new file mode 100644 index 00000000..e9ca2bf8 --- /dev/null +++ b/sp/src/shadereditor/properties/postprocessing/vsheet_pp_rt.h @@ -0,0 +1,36 @@ +#ifndef CSHEET_PP_RT_H +#define CSHEET_PP_RT_H + +#include "vSheets.h" + +class CSheet_PP_RT : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_PP_RT, CSheet_Base ); + + CSheet_PP_RT(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_PP_RT(); + + virtual const char *GetSheetTitle(){return"Rendertarget";}; + + void Paint(); + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + +protected: + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + +private: + + int m_iVguiPaint_Texture; + Panel *m_pImgRef; + + //TextEntry *m_pText_RTName; + ComboBox *m_pCBox_RTName; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmartautocomplete.cpp b/sp/src/shadereditor/properties/smarttext/vsmartautocomplete.cpp new file mode 100644 index 00000000..25bd467e --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmartautocomplete.cpp @@ -0,0 +1,525 @@ + +#include "cbase.h" + +#include "vSmartObject.h" +#include "vSmartObjectList.h" +#include "vSmartAutocomplete.h" +#include "vSmartTooltip.h" +#include "cRegex.h" + +#include "vgui/iinput.h" +#include + + +CSmartAutocomplete::CSmartAutocomplete( Panel *parent, const char *pElementname ) : BaseClass( parent, pElementname ) +{ + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( false ); + + SetVisible(true); + MakePopup(false); + + m_pMatchStr = NULL; + m_pInfoLabel = NULL; + + //SetSize( GetACSizeX(), GetACSizeY() ); + //SetMinimumSize( GetACSizeX(), GetACSizeY() ); + + m_pList = NULL; + + SetupVguiTex( m_iImg_Var, "shadereditor/ac_var" ); + SetupVguiTex( m_iImg_Func, "shadereditor/ac_func" ); + SetupVguiTex( m_iImg_Struct, "shadereditor/ac_struct" ); + SetupVguiTex( m_iImg_Def, "shadereditor/ac_def" ); +} + +CSmartAutocomplete::~CSmartAutocomplete() +{ + if ( m_pInfoLabel ) + m_pInfoLabel->MarkForDeletion(); + + delete m_pList; + delete [] m_pMatchStr; +} + +bool CSmartAutocomplete::InitList( CSmartObjectList *list, + int textPos, int iScopeDepth, int iScopeNum, + const char *pSourceFile, const char *pszVarName, bool bSort ) +{ + if ( pszVarName && Q_strlen( pszVarName ) ) + { + if ( !list || + !pszVarName || + !Q_strlen(pszVarName) ) + return false; + + CSmartObject *pVar = list->GetEntryByIdent( pszVarName ); + + if ( !pVar || pVar->m_iType != ACOMP_VAR || !pVar->m_pszDatatype ) + return false; + + char *pszDatatype = pVar->m_pszDatatype; + bool bSuccess = true; + bool bSort = true; + + CSmartObjectList *pNewList = new CSmartObjectList(); + + if ( CRegex::MatchSyntax_Datatypes( pszDatatype ) != __REGEX_INVALID ) + { + const char *pszMatch = "(:?double|float|half|HALF|int|uint|bool)(?:[1-4]|[1-4]x[1-4])"; + bSuccess = CRegex::RegexMatch( pszDatatype, pszMatch ); + + if ( bSuccess ) + { + int iC = Q_strlen( pszDatatype ) - 1; + + bool bMatrix = pszDatatype[iC-1] == 'x' && + pszDatatype[iC] >= '1' && pszDatatype[iC] <= '4' && + pszDatatype[iC-2] >= '1' && pszDatatype[iC-2] <= '4'; + + if ( bMatrix ) + { + char matType[12]; + Q_snprintf( matType, sizeof(matType), "_m[%c][%c]", pszDatatype[iC-2], pszDatatype[iC] ); + pNewList->AddUnit( new CSmartObject( ACOMP_VAR, "", matType, pszDatatype ) ); + } + else + { + int num = pszDatatype[iC] - '0'; + Assert( num >= 1 && num <= 4 ); + + bSort = false; + + const char *lookUpIdents[] = + { + "r", "g", "b", "a", "x", "y", "z", "w", + }; + + for ( int i = 0; i < num; i++ ) + pNewList->AddUnit( new CSmartObject( ACOMP_VAR, "", lookUpIdents[i], pszDatatype ) ); + for ( int i = 0; i < num; i++ ) + pNewList->AddUnit( new CSmartObject( ACOMP_VAR, "", lookUpIdents[i+4], pszDatatype ) ); + } + } + } + else + { + CSmartObject *pStruct = list->GetEntryByIdent( pszDatatype ); + + if ( !pStruct || !pStruct->IsObjectVisible( textPos, iScopeDepth, iScopeNum, pSourceFile ) || !pStruct->m_hChildren.Count() ) + bSuccess = false; + else + { + for ( int i = 0; i < pStruct->m_hChildren.Count(); i++ ) + pNewList->AddUnit( new CSmartObject( *pStruct->m_hChildren[i] ) ); + } + } + + if ( bSuccess ) + { + bSuccess = InitList( pNewList, 0, 0, 0, NULL, NULL, bSort ); + } + + delete pNewList; + + return bSuccess; + } + + + + + delete m_pList; + m_pList = new CSmartObjectList( *list ); + + if ( bSort ) + m_pList->DoSort(); + + bool bValid = false; + //for ( int i = 0; i < 30; i++ ) + // m_pACMenu->AddMenuItem( VarArgs( "empty item %02i ................", i ), this ); + + int numEntries = m_pList->GetNumEntries(); + + KeyValues *pItemData = new KeyValues( "data" ); + + for ( int i = 0; i < numEntries; i++ ) + { + CSmartObject *pO = m_pList->GetEntry( i ); + + if ( pO->m_bIntrinsic ) + continue; + + const char *pszIdent = pO->m_pszIdentifier; + + if ( !pszIdent ) + continue; + + if ( !pO->IsObjectVisible( textPos, iScopeDepth, iScopeNum, pSourceFile ) ) + continue; + + //if ( pszVarName && Q_strlen( pszVarName ) ) + //{ + //} + + bValid = true; + + pItemData->SetInt( "database_index", i ); + MenuItem *pItem = GetMenuItem( AddMenuItem( pszIdent, this, pItemData ) ); + + + Assert( pItem ); + + if ( !pItem ) + continue; + + pItem->SetIgnoreFirstClick( true ); + + int iImg = -1; + + switch ( pO->m_iType ) + { + case ACOMP_DEFINE: + iImg = m_iImg_Def; + break; + case ACOMP_FUNC: + iImg = m_iImg_Func; + break; + case ACOMP_STRUCT_DEF: + iImg = m_iImg_Struct; + break; + case ACOMP_VAR: + iImg = m_iImg_Var; + break; + } + + if ( iImg < 0 ) + continue; + + pItem->SetImage( iImg ); + } + + pItemData->deleteThis(); + + //ActivateItem( 0 ); + + SelectItem( 0 ); + + AddActionSignalTarget( this ); + + return bValid; +} + + +void CSmartAutocomplete::MatchInput( const char *str ) +{ + const bool bShowAll = str == NULL; + bool bMatchSuccessful = false; + + int iFirst = MatchSetVisible( bShowAll, str ); + + if ( iFirst < 0 ) + { + char *pTest = m_pMatchStr; + + if ( str && *str && !(IS_CHAR(*str)||IS_NUMERICAL(*str)) ) + pTest = NULL; + + iFirst = MatchSetVisible( bShowAll, pTest ); + + Assert( iFirst >= 0 ); + } + else + bMatchSuccessful = true; + + if ( bShowAll || bMatchSuccessful ) + { + Assert( bMatchSuccessful && str && *str || bShowAll ); + + delete [] m_pMatchStr; + m_pMatchStr = NULL; + + if ( str && *str ) + AutoCopyStringPtr( str, &m_pMatchStr ); + } + + InvalidateLayout( true ); + + SelectItem( iFirst ); +} +void CSmartAutocomplete::MatchInput( const wchar_t *str ) +{ + char *cStr = NULL; + + if ( str ) + { + int size = Q_wcslen( str ) + 1; + cStr = new char[size]; + Q_UnicodeToUTF8( str, cStr, size ); + } + + MatchInput( cStr ); + delete [] cStr; +} + +int CSmartAutocomplete::IsExactMatch( const char *str, bool bPartial ) +{ + if ( !str || !*str ) + return -1; + + char tmp[MAX_PATH]; + + CUtlVector hSuccess; + + for ( int i = 0; i < GetItemCount(); i++ ) + { + int mID = GetMenuID(i); + MenuItem *pItem = GetMenuItem(mID); + Assert( pItem ); + + if ( !pItem->IsVisible() ) + continue; + + pItem->GetText( tmp, sizeof(tmp) ); + + if ( !Q_strlen( tmp ) ) + continue; + + if ( Q_stricmp( tmp, str ) ) + { + if ( !bPartial || Q_stristr( tmp, str ) != tmp ) + { + hSuccess.Purge(); + return -1; + } + } + else + hSuccess.AddToTail( mID ); + } + + int result = hSuccess.Count() ? hSuccess[0] : -1; + + if ( hSuccess.Count() > 1 ) + { + for ( int i = 0; i < hSuccess.Count(); i++ ) + { + MenuItem *pItem = GetMenuItem(hSuccess[i]); + Assert( pItem ); + + if ( !pItem->IsVisible() ) + continue; + + pItem->GetText( tmp, sizeof(tmp) ); + + if ( !Q_strcmp( tmp, str ) ) + result = hSuccess[i]; + } + } + + hSuccess.Purge(); + return result; +} + +int CSmartAutocomplete::IsExactMatch( const wchar_t *str, bool bPartial ) +{ + char *cStr = NULL; + + if ( str && *str ) + { + int size = Q_wcslen( str ) + 1; + cStr = new char[size]; + Q_UnicodeToUTF8( str, cStr, size ); + } + + int bResult = IsExactMatch( cStr, bPartial ); + delete [] cStr; + + return bResult; +} + +int CSmartAutocomplete::MatchSetVisible( bool bAll, const char *str ) +{ + if ( !str || !*str ) + bAll = true; + + char buf[MAX_PATH]; + char exp[MAX_PATH+2]; + + int iFirstVisible = -1; + + for ( int i = 0; i < GetItemCount(); i++ ) + { + MenuItem *pItem = GetMenuItem(GetMenuID(i)); + Assert( pItem ); + + bool bShow = bAll; + + if ( !bAll ) + { + pItem->GetText( buf, sizeof( buf ) ); + Q_strlower( buf ); + + char *pSafe = CRegex::AllocSafeString( (char*)str ); + Q_snprintf( exp, sizeof(exp), "%s.*", pSafe ); + delete [] pSafe; + Q_strlower( exp ); + + bShow = CRegex::RegexMatch( buf, exp ); + } + + pItem->SetVisible( bShow ); + + if ( bShow && iFirstVisible < 0 ) + iFirstVisible = i; + } + + //if ( iFirstVisible < 0 ) + // iFirstVisible = 0; + + return iFirstVisible; +} +void CSmartAutocomplete::SelectItem( int i ) +{ + int last = GetCurrentlyHighlightedItem(); + + if ( i == last ) + return; + + ActivateItem( i ); + SetCurrentlyHighlightedItem( i ); +} + +char *CSmartAutocomplete::AllocHighlightItemName() +{ + char buf[MAX_PATH]; + GetItemText( GetCurrentlyHighlightedItem(), buf, sizeof(buf) ); + + if ( !*buf || Q_strlen(buf) < 1 ) + return NULL; + + char *pOut = new char[ Q_strlen(buf) + 1 ]; + Q_strcpy( pOut, buf ); + + return pOut; +} + +int CSmartAutocomplete::FindEntry( const char *pWord ) +{ + char buf[MAX_PATH]; + + for ( int i = 0; i < GetItemCount(); i++ ) + { + int iMID = GetMenuID(i); + Assert( GetMenuItem(iMID) ); + GetMenuItem(iMID)->GetText( buf, sizeof(buf) ); + + if ( Q_stricmp( buf, pWord ) ) + continue; + + KeyValues *pKV = GetItemUserData( iMID ); + if ( !pKV ) + { + Assert( 0 ); + break; + } + + return pKV->GetInt( "database_index", -1 ); + } + return 0; +} +void CSmartAutocomplete::ActivateEntry( int index ) +{ + if ( !m_pList ) + return; + + Assert( index >= 0 && index < m_pList->GetNumEntries() ); + + for ( int i = 0; i < GetItemCount(); i++ ) + { + int iMID = GetMenuID(i); + Assert( GetMenuItem(iMID) ); + KeyValues *pKV = GetItemUserData( iMID ); + if ( !pKV ) + continue; + + if ( pKV->GetInt( "database_index", -1 ) != index ) + continue; + + ActivateItem( iMID ); + break; + } +} + +void CSmartAutocomplete::PerformLayout() +{ + BaseClass::PerformLayout(); +} + +void CSmartAutocomplete::OnKillFocus() +{ + BaseClass::OnKillFocus(); + + //if (!input()->GetFocus() || !ipanel()->HasParent(input()->GetFocus(), GetVPanel())) + //{ + //} +} + +void CSmartAutocomplete::InternalMousePressed(int code) +{ +} + +void CSmartAutocomplete::MenuItemHighlight( int itemID ) +{ + UpdateTooltip(); +} + +void CSmartAutocomplete::UpdateTooltip() +{ + if ( m_pInfoLabel ) + m_pInfoLabel->MarkForDeletion(); + m_pInfoLabel = NULL; + + int item = GetCurrentlyHighlightedItem(); + + if ( item < 0 || item >= GetItemCount() ) + return; + + //int posy = GetVisibleItemIndex( item ); + + int px, py, sx, sy; + GetBounds( px, py, sx, sy ); + + MenuItem *pItem = GetMenuItem( item ); + + if ( !pItem ) + return; + + int ipx, ipy; + pItem->GetPos( ipx, ipy ); + + px += sx + 5; + py += ipy; + + m_pInfoLabel = new CSmartTooltip( this, "ACtooltip" ); + + Assert( pItem->GetUserData() ); + + int iObj = pItem->GetUserData()->GetInt( "database_index" ); + + Assert( m_pList ); + + if ( !m_pInfoLabel->Init( m_pList->GetEntry( iObj ) ) ) + { + m_pInfoLabel->MarkForDeletion(); + m_pInfoLabel = NULL; + } + else + { + int screenx, screeny; + surface()->GetScreenSize( screenx, screeny ); + m_pInfoLabel->GetSize( sx, sy ); + + if ( py + sy > screeny ) + py -= ( py + sy ) - screeny; + m_pInfoLabel->SetPos( px, py ); + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmartautocomplete.h b/sp/src/shadereditor/properties/smarttext/vsmartautocomplete.h new file mode 100644 index 00000000..2789e0b3 --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmartautocomplete.h @@ -0,0 +1,70 @@ +#ifndef V_SMART_AUTO_COMPLETE_H +#define V_SMART_AUTO_COMPLETE_H + +#include "cbase.h" +#include "vgui_controls/controls.h" +#include "vgui_controls/panel.h" +#include "vgui_controls/menu.h" + +using namespace vgui; + +class CSmartObjectList; +class CSmartTooltip; + +class CSmartAutocomplete : public Menu +{ + DECLARE_CLASS_SIMPLE( CSmartAutocomplete, Menu ); + +public: + CSmartAutocomplete( Panel *parent, const char *pElementname ); + ~CSmartAutocomplete(); + + // global identifier + // if pszVarName != NULL then find as var, generate sub list with children + bool InitList( CSmartObjectList *list, int textPos, int iScopeDepth, int iScopeNum, + const char *pSourceFile, const char *pszVarName, bool bSort = true ); + + // using database indices + int FindEntry( const char *pWord ); + void ActivateEntry( int index ); + + void PerformLayout(); + void OnKillFocus(); + + void OnCursorEnteredMenuItem( int i ){}; + void OnCursorExitedMenuItem( int i ){}; + void OnMousePressed( MouseCode c ){}; + //static const int GetACSizeX(){ return 160; }; + //static const int GetACSizeY(){ return 80; }; + + MESSAGE_FUNC_INT( InternalMousePressed, "MousePressed", code ); + MESSAGE_FUNC_INT( MenuItemHighlight, "MenuItemHighlight", itemID ); + + void MatchInput( const char *str ); + void MatchInput( const wchar_t *str ); + int IsExactMatch( const char *str, bool bPartial ); + int IsExactMatch( const wchar_t *str, bool bPartial ); + + char *AllocHighlightItemName(); + + void SelectItem( int i ); + +private: + + void UpdateTooltip(); + + int MatchSetVisible( bool bAll, const char *str ); + + CSmartObjectList *m_pList; + CSmartTooltip *m_pInfoLabel; + + int m_iImg_Var; + int m_iImg_Func; + int m_iImg_Struct; + int m_iImg_Def; + + char *m_pMatchStr; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmartobject.cpp b/sp/src/shadereditor/properties/smarttext/vsmartobject.cpp new file mode 100644 index 00000000..96a01636 --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmartobject.cpp @@ -0,0 +1,137 @@ + +#include "cbase.h" +#include "editorcommon.h" +#include "vSmartObject.h" + + +CSmartObject::CSmartObject( int type, const char *pszDef, const char *pszIdent, const char *pszDatatype ) +{ + m_iType = type; //ACOMP_INVALID; + + AutoCopyStringPtr( pszDef, &m_pszDefinition ); + AutoCopyStringPtr( pszIdent, &m_pszIdentifier ); + AutoCopyStringPtr( pszDatatype, &m_pszDatatype ); + m_pszHelptext = NULL; + m_pszSourceFile = NULL; + + m_iTextOffset = -1; + m_bHelpLocked = false; + m_bIntrinsic = false; + m_iScopeDepth = 0; + m_iScopeNum = 0; +} +CSmartObject::~CSmartObject() +{ + m_hChildren.PurgeAndDeleteElements(); + + delete [] m_pszDefinition; + delete [] m_pszIdentifier; + delete [] m_pszDatatype; + delete [] m_pszHelptext; + delete [] m_pszSourceFile; +} +CSmartObject::CSmartObject( const CSmartObject &o ) +{ + m_iType = o.m_iType; + m_iTextOffset = o.m_iTextOffset; + m_iScopeDepth = o.m_iScopeDepth; + m_iScopeNum = o.m_iScopeNum; + m_bHelpLocked = o.m_bHelpLocked; + m_bIntrinsic = o.m_bIntrinsic; + + m_pszDefinition = NULL; + m_pszIdentifier = NULL; + m_pszDatatype = NULL; + m_pszHelptext = NULL; + m_pszSourceFile = NULL; + + if ( o.m_pszDefinition ) + AutoCopyStringPtr( o.m_pszDefinition, &m_pszDefinition ); + if ( o.m_pszIdentifier ) + AutoCopyStringPtr( o.m_pszIdentifier, &m_pszIdentifier ); + if ( o.m_pszDatatype ) + AutoCopyStringPtr( o.m_pszDatatype, &m_pszDatatype ); + if ( o.m_pszHelptext ) + AutoCopyStringPtr( o.m_pszHelptext, &m_pszHelptext ); + if ( o.m_pszSourceFile ) + AutoCopyStringPtr( o.m_pszSourceFile, &m_pszSourceFile ); + + for ( int i = 0; i < o.m_hChildren.Count(); i++ ) + m_hChildren.AddToTail( new CSmartObject( *o.m_hChildren[i] ) ); + + Assert( m_hChildren.Count() == o.m_hChildren.Count() ); +} + +void CSmartObject::DebugPrint( int stage ) +{ + Assert( stage <= 15 ); + + if ( stage > 15 ) + return; + + const char *pTypeNames[] = + { + "invalid", + "def", + "var", + "func", + "struct", + }; + + Assert( ARRAYSIZE( pTypeNames ) == ACOMP_ + 1 ); + + Msg( "Autocompunit:: type: %s\n", pTypeNames[ m_iType + 1 ] ); + if ( m_pszHelptext ) + Warning( "Help:\n%s", m_pszHelptext ); + if ( m_pszDefinition ) + Msg( " definition: %s\n", m_pszDefinition ); + if ( m_pszIdentifier ) + Msg( " identifier: %s\n", m_pszIdentifier ); + if ( m_pszDatatype ) + Msg( " datatype: %s\n", m_pszDatatype ); + if ( m_hChildren.Count() ) + { + Msg( "CHILDREN START >> now at level %02i\n", stage ); + + stage++; + for ( int i = 0; i < m_hChildren.Count(); i++ ) + { + m_hChildren[ i ]->DebugPrint( stage ); + } + Msg( "CHILDREN END <<\n" ); + } + Msg( "\n" ); +} + +bool CSmartObject::IsObjectVisible( int textPos, int iScopeDepth, int iScopeNum, + const char *pSourceFile ) +{ + bool bDifferentFile = true; + + const char *pszObjectSrc = m_pszSourceFile; + if ( pszObjectSrc && pSourceFile && m_iTextOffset >= 0 ) + { + if ( !Q_stricmp( pszObjectSrc, pSourceFile ) ) + { + if ( textPos < m_iTextOffset ) + return false; + bDifferentFile = false; + } + } + + if ( bDifferentFile ) + { + if ( m_iScopeDepth > 0 ) + return false; + } + else if ( m_iScopeDepth > iScopeDepth || + m_iScopeDepth == iScopeDepth && m_iScopeNum != iScopeNum ) + return false; + + return true; +} + +bool CSmartObject::IsObjectVisible( CSmartObject *pViewer ) +{ + return IsObjectVisible( m_iTextOffset, m_iScopeDepth, m_iScopeNum, m_pszSourceFile ); +} diff --git a/sp/src/shadereditor/properties/smarttext/vsmartobject.h b/sp/src/shadereditor/properties/smarttext/vsmartobject.h new file mode 100644 index 00000000..a31117ff --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmartobject.h @@ -0,0 +1,87 @@ +#ifndef SMART_OBJECT_H +#define SMART_OBJECT_H + +#include "cbase.h" + +// #define A 1 + +// [const] [static] [datatype] blah [register]; + +// [datatype] func ([params]) + +// struct blah { [datatype] [varname]; }; + +enum +{ + ACOMP_INVALID = -1, + ACOMP_DEFINE = 0, + ACOMP_VAR, + ACOMP_FUNC, + ACOMP_STRUCT_DEF, + ACOMP_, +}; + +class CSmartObject +{ +public: + + CSmartObject( int type, const char *pszDef, const char *pszIdent = NULL, const char *pszDatatype = NULL ); + ~CSmartObject(); + CSmartObject( const CSmartObject &o ); + + inline bool operator == ( const CSmartObject &o ); + inline bool operator != ( const CSmartObject &o ); + + void DebugPrint( int stage = 0 ); + + int m_iType; + + char *m_pszDefinition; + char *m_pszIdentifier; + char *m_pszDatatype; + char *m_pszHelptext; + bool m_bHelpLocked; + + int m_iTextOffset; + int m_iScopeDepth; + int m_iScopeNum; + + char *m_pszSourceFile; + + CUtlVector< CSmartObject* >m_hChildren; + + bool IsObjectVisible( int textPos, int iScopeDepth, int iScopeNum, + const char *pSourceFile ); + bool IsObjectVisible( CSmartObject *pViewer ); + + bool m_bIntrinsic; +}; + + +bool CSmartObject::operator == ( const CSmartObject &o ) +{ + if ( !m_pszIdentifier || !o.m_pszIdentifier ) + { + Assert( 0 ); + return false; + } + if ( !m_pszDatatype || !o.m_pszDatatype ) + { + Assert( 0 ); + return false; + } + + bool bSameName = !Q_stricmp(m_pszIdentifier,o.m_pszIdentifier); + bool bSameDatatype = !Q_stricmp(m_pszDatatype,o.m_pszDatatype); + + if ( bSameName && bSameDatatype ) + return true; + + return false; +} +bool CSmartObject::operator != ( const CSmartObject &o ) +{ + return !( *this == o ); +} + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmartobjectlist.cpp b/sp/src/shadereditor/properties/smarttext/vsmartobjectlist.cpp new file mode 100644 index 00000000..886c8aaa --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmartobjectlist.cpp @@ -0,0 +1,1695 @@ + +#include "cbase.h" +#include "cRegex.h" +#include "vSmartObject.h" +#include "vSmartObjectList.h" + +#include "editorCommon.h" + +#define __DBG_PARSE DEBUG + +#if __DBG_PARSE +void ParseDbg( const char *msg, ... ) +{ + va_list argptr; + char str[512]; + Q_memset( str, 0, sizeof( str ) ); + + va_start( argptr, msg ); + Q_vsnprintf( str, sizeof( str ), msg, argptr ); + va_end( argptr ); + + Msg( "parser: %s\n", str ); +} +#else +#define ParseDbg( ... ) ((void)NULL) +#endif + +int NextNull( char **p ) +{ + int count = 0; + + while ( p && *p && **p ) + { + (*p)++; + count++; + } + + return count; +} +int NextLine( char **p ) +{ + int count = 0; + + while ( p && *p && **p ) + { + bool bLF = **p == '\n'; + + (*p)++; + count++; + + if ( bLF ) + break; + } + + return count; +} +void PreviousLine( char **p, int &size ) +{ + bool bGotStartThisLine = false; + while ( size > 0 ) + { + bool bLineStart = **p == '\n'; + + if ( bLineStart ) + { + if ( bGotStartThisLine ) + { + (*p)++; + size++; + break; + } + else + bGotStartThisLine = true; + } + + (*p)--; + size--; + } +} +int NextCharacter( char **p ) +{ + int count = 0; + + while ( p && *p && **p ) + { + if ( !IS_SPACE( **p ) ) + break; + + (*p)++; + count++; + } + + return count; +} +int NextSpace( char **p ) +{ + int count = 0; + + while ( p && *p && **p ) + { + if ( IS_SPACE( **p ) ) + break; + + (*p)++; + count++; + } + + return count; +} +// WORD +// | +char *MoveToWordLeft( char *pStrStart, char *pWord ) +{ + Assert( pStrStart && pWord && pWord >= pStrStart ); + + while ( pWord >= pStrStart && + ( IS_CHAR( *pWord ) || IS_NUMERICAL( *pWord ) ) && !IS_SPACE( *pWord ) ) + { + pWord--; + } + + pWord++; + + return pWord; +} +// WORD +// | +char *MoveToWordRight( char *pWord ) +{ + Assert( *pWord ); + + while ( *pWord && + ( IS_CHAR( *pWord ) || IS_NUMERICAL( *pWord ) ) && !IS_SPACE( *pWord ) ) + { + pWord++; + } + + //pWord--; + + return pWord; +} +char *CopyWord( char *pStrStart, int wordPos = 0 ) +{ + char *pWord = pStrStart; + + while ( pWord && *pWord && wordPos > 0 ) + { + pWord++; + wordPos--; + } + + Assert( pWord && *pWord && !IS_SPACE(*pWord) ); + + if ( !*pWord ) + return NULL; + + if ( IS_SPACE( *pWord ) ) + return NULL; + + char *pWordStart = MoveToWordLeft( pStrStart, pWord ); + char *pWordEnd = MoveToWordRight( pWord ); + + int wSize = pWordEnd - pWordStart; + + if ( wSize < 1 ) + return NULL; + + char *pOut = new char[ wSize + 1 ]; + Q_memcpy( pOut, pWordStart, wSize ); + pOut[ wSize ] = '\0'; + + return pOut; +} +char *CopyToDelimiter( char *pStart, const char delim = '\n', bool bInclusive = false ) +{ + char *pOut = NULL; + char *pDelimitedStart = pStart; + char *pDelimitedEnd = pDelimitedStart; + + while ( *pDelimitedEnd && *pDelimitedEnd != delim ) + pDelimitedEnd++; + + if ( *pDelimitedEnd == delim && bInclusive ) + pDelimitedEnd++; + + int delimSize = pDelimitedEnd - pDelimitedStart; + if ( delimSize > 0 ) + { + pOut = new char[ delimSize + 1 ]; + Q_memcpy( pOut, pDelimitedStart, delimSize ); + pOut[ delimSize ] = '\0'; + } + + return pOut; +} +void ConvertCharacter( char *pStr, char from, char to ) +{ + while ( pStr && *pStr ) + { + if ( *pStr == from ) + *pStr = to; + pStr++; + } +} +void CleanSpaces( char *pStr ) +{ + bool bHadSpace = false; + char *pSearch = pStr; + int len = Q_strlen( pStr ); + + while ( pSearch && *pSearch ) + { + if ( IS_SPACE( *pSearch ) ) + { + if ( *pSearch == '\t' || *pSearch == '\r' ) + { + *pSearch = ' '; + } + + if ( bHadSpace || pSearch == pStr ) + { + *pSearch = '\0'; + + char *pRest = pSearch + 1; + + if ( *pRest ) + { + Assert( Q_strlen( pStr ) < len ); + Q_strcat( pStr, pRest, len ); + continue; + } + } + + bHadSpace = true; + } + else + bHadSpace = false; + + pSearch++; + } +} + +CSmartObjectList::CSmartObjectList() +{ + m_pCurSourceFile = NULL; + m_pCopyTarget = NULL; +} +CSmartObjectList::~CSmartObjectList() +{ + hAutoCompUnits.PurgeAndDeleteElements(); +} +CSmartObjectList::CSmartObjectList( const CSmartObjectList &o ) +{ + m_pCurSourceFile = NULL; + m_pCopyTarget = NULL; + + for ( int i = 0; i < o.hAutoCompUnits.Count(); i++ ) + hAutoCompUnits.AddToTail( new CSmartObject( *o.hAutoCompUnits[i] ) ); + + Assert( hAutoCompUnits.Count() == o.hAutoCompUnits.Count() ); +} + +int ACompSort( CSmartObject * const *p1, CSmartObject * const *p2 ) +{ + if ( !(*p1)->m_pszIdentifier || !(*p2)->m_pszIdentifier ) + return 0; + + return Q_stricmp( (*p1)->m_pszIdentifier, (*p2)->m_pszIdentifier ); +} +void CSmartObjectList::DoSort() +{ + hAutoCompUnits.Sort( ACompSort ); +} + +int CSmartObjectList::GetNumEntries() +{ + return hAutoCompUnits.Count(); +} +CSmartObject *CSmartObjectList::GetEntry( int i ) +{ + Assert( i >= 0 && i < GetNumEntries() ); + + return hAutoCompUnits[ i ]; +} +CSmartObject *CSmartObjectList::GetEntryByIdent( const char *pIdent ) +{ + for ( int i = 0; i < GetNumEntries(); i++ ) + if ( GetEntry(i)->m_pszIdentifier && !Q_strcmp( GetEntry(i)->m_pszIdentifier, pIdent ) ) + return GetEntry(i); + return NULL; +} +CSmartObject *CSmartObjectList::GetEntryByIdent( const wchar_t *pIdent ) +{ + if ( !pIdent || !Q_wcslen( pIdent ) ) + return NULL; + + int len = Q_wcslen( pIdent ) + 1; + char *pCStr = new char[ len ]; + Q_UnicodeToUTF8( pIdent, pCStr, len ); + + CSmartObject *pOut = GetEntryByIdent( pCStr ); + + delete [] pCStr; + return pOut; +} + +bool CSmartObjectList::DatatypeMatch( const char *pWord ) +{ + if ( CRegex::MatchSyntax_Datatypes( pWord ) != __REGEX_INVALID ) + return true; + + for ( int s = 0; s < hAutoCompUnits.Count(); s++ ) + if ( hAutoCompUnits[s]->m_iType == ACOMP_STRUCT_DEF && + hAutoCompUnits[s]->m_pszIdentifier != NULL && + !Q_stricmp( pWord, hAutoCompUnits[s]->m_pszIdentifier ) ) + return true; + + return false; +} + +void CSmartObjectList::AddUnit( CSmartObject *pUnit ) +{ + //delete pUnit; + + bool bDoAdd = true; + + if ( pUnit->m_pszIdentifier && pUnit->m_iType != ACOMP_INVALID ) + { + for ( int i = 0; i < hAutoCompUnits.Count(); i++ ) + { + CSmartObject *p = hAutoCompUnits[i]; + + // no name, ignore + if ( !p->m_pszIdentifier ) + continue; + + // different name, ignore + if ( Q_stricmp( p->m_pszIdentifier, pUnit->m_pszIdentifier ) ) + continue; + + if ( p->IsObjectVisible( pUnit ) ) + continue; + + if ( p->m_iScopeDepth != pUnit->m_iScopeDepth || + p->m_iScopeNum != pUnit->m_iScopeNum ) + continue; + + // same name + different type -> delete + if ( p->m_iType != pUnit->m_iType ) + bDoAdd = false; + + //overloads for functions + if ( pUnit->m_iType == ACOMP_FUNC ) + { + // same amount of children, test them; different amount == valid overload + if ( pUnit->m_hChildren.Count() == p->m_hChildren.Count() ) + { + bool bDifferentChild = false; + for ( int c = 0; c < pUnit->m_hChildren.Count(); c++ ) + { + CSmartObject *c0 = pUnit->m_hChildren[ c ]; + CSmartObject *c1 = p->m_hChildren[ c ]; + + if ( *c0 != *c1 ) + bDifferentChild = true; + } + if ( !bDifferentChild ) + bDoAdd = false; + } + } + else + bDoAdd = false; + } + } + else + bDoAdd = false; + + //Assert( bDoAdd ); + + if ( bDoAdd ) + { + if ( m_pCurSourceFile != NULL && *m_pCurSourceFile && pUnit->m_pszSourceFile == NULL ) + AutoCopyStringPtr( m_pCurSourceFile, &pUnit->m_pszSourceFile ); + + hAutoCompUnits.AddToTail( pUnit ); + + if ( m_pCopyTarget ) + m_pCopyTarget->hAutoCompUnits.AddToTail( new CSmartObject( *pUnit ) ); + //pUnit->DebugPrint(); + } + else + delete pUnit; +} + +void CSmartObjectList::SetDatabaseCopy( CSmartObjectList *pCopyTarget ) +{ + m_pCopyTarget = pCopyTarget; +} + +void CSmartObjectList::MergeWithEntries( CSmartObjectList *pOther ) +{ + CUtlVector< char* >hSources; + + for ( int i = 0; i < pOther->GetNumEntries(); i++ ) + { + CSmartObject *pO = pOther->GetEntry( i ); + + if ( !pO->m_pszSourceFile ) + continue; + + bool bFound = false; + + for ( int c = 0; c < hSources.Count(); c++ ) + { + if ( !Q_stricmp( hSources[c], pO->m_pszSourceFile ) ) + bFound = true; + } + + if ( !bFound ) + hSources.AddToTail( pO->m_pszSourceFile ); + } + + for ( int c = 0; c < hSources.Count(); c++ ) + PurgeUnitsOfSameSource( hSources[c] ); + + hSources.Purge(); + + for ( int i = 0; i < pOther->GetNumEntries(); i++ ) + AddUnit( new CSmartObject( *pOther->GetEntry( i ) ) ); +} + +void CSmartObjectList::ParseCode( const char *pszFilename, bool bRecursive, CUtlVector< char* > *hIncludes ) +{ + if ( hIncludes != NULL ) + { + for ( int i = 0; i < hIncludes->Count(); i++ ) + if ( !Q_stricmp( hIncludes->Element( i ), pszFilename ) ) + return; + } + + char cFile[MAXTARGC]; + Q_snprintf( cFile, sizeof( cFile ), "%s\\%s", GetShaderSourceDirectory(), pszFilename ); + + bool bExists = g_pFullFileSystem->FileExists( cFile ); + //Assert( bExists ); + + //for ( int i = 0; i < 2000; i++ ) + // bExists = g_pFullFileSystem->FileExists( cFile ); + + if ( !bExists ) + return; + + int iFSize = g_pFullFileSystem->Size( cFile ); + Assert( iFSize > 0 ); + iFSize++; + + if ( iFSize <= 0 ) + return; + +#if __DBG_PARSE + Warning( "trying to alloc %i bytes... (step 1)\n", iFSize ); +#endif + + char *pBuff = new char[ iFSize ]; + Assert( pBuff != NULL ); + + if ( pBuff == NULL ) + return; + + Q_memset( pBuff, 0, iFSize ); + + + + char *pCopyBuff = new char[ iFSize ]; + +#if __DBG_PARSE + Warning( "trying to alloc %i bytes... (step 2)\n", iFSize ); +#endif + + CUtlBuffer buf( pBuff, iFSize ); + if ( pCopyBuff && g_pFullFileSystem->ReadFile( cFile, NULL, buf ) ) + { + char *pTextClearCR = pBuff; + int iSize = buf.Size(); + + while ( iSize > 0 ) + { + if ( *pTextClearCR == '\r' ) + *pTextClearCR = ' '; + + pTextClearCR++; + iSize--; + } + + Q_memcpy( pCopyBuff, pBuff, iFSize ); + + CUtlVector< CSmartObject* >hOldUnits; + hOldUnits.AddVectorToTail( hAutoCompUnits ); + hAutoCompUnits.Purge(); + + ParseCode_Stream( buf, bRecursive, hIncludes, pszFilename ); + + BuildHelpTexts( pCopyBuff, buf.Size() ); + + CUtlVector< CSmartObject* >hNewUnits; + hNewUnits.AddVectorToTail( hAutoCompUnits ); + hAutoCompUnits.Purge(); + + hAutoCompUnits.AddVectorToTail( hOldUnits ); + for ( int i = 0; i < hNewUnits.Count(); i++ ) + AddUnit( hNewUnits[ i ] ); + + hOldUnits.Purge(); + hNewUnits.Purge(); + } + + buf.Purge(); + delete [] pBuff; + delete [] pCopyBuff; +} + +void CSmartObjectList::BuildHelpTexts( char *pStreamCopy, int iSize ) +{ + pStreamCopy[ iSize - 1 ] = '\0'; + + for ( int i = 0; i < hAutoCompUnits.Count(); i++ ) + { + CSmartObject *p = hAutoCompUnits[i]; + + if ( p->m_bHelpLocked ) + continue; + + p->m_bHelpLocked = true; + + int offset = p->m_iTextOffset; + + if ( offset < 0 ) + continue; + + Assert( offset >= 0 && offset < iSize ); + + bool bLookRight = p->m_iType == ACOMP_DEFINE || p->m_iType == ACOMP_VAR; + char *pLineStart = pStreamCopy + offset; + + char *pSearchCommentStart = pLineStart; + int searchSizeStart = offset; + + CUtlVector< char* >hHelpLines; + + if ( bLookRight ) + { + while ( searchSizeStart < iSize - 2 && *pSearchCommentStart != '\n' ) + { + if ( *pSearchCommentStart == '/' && *(pSearchCommentStart+1) == '/' ) + { + hHelpLines.AddToTail( pSearchCommentStart ); + break; + } + + pSearchCommentStart++; + searchSizeStart++; + } + } + + if ( !hHelpLines.Count() ) + { + pSearchCommentStart = pLineStart - 1; + searchSizeStart = offset; + + while ( searchSizeStart >= 0 && ( IS_SPACE( *pSearchCommentStart ) || *pSearchCommentStart == '\n' ) ) + { + pSearchCommentStart--; + searchSizeStart--; + } + + // multiline comment, need to search from the very beginning + if ( searchSizeStart > 1 && *pSearchCommentStart == '/' && *(pSearchCommentStart-1) == '*' ) + { + bool bInComment = false; + char *pSearchMCStart = pStreamCopy; + char *pLastMCStart = NULL; + char *pLastMCEnd = NULL; + + while ( pSearchMCStart <= pSearchCommentStart ) + { + if ( *pSearchMCStart == '/' && *(pSearchMCStart+1) == '/' ) + { + NextLine( &pSearchMCStart ); + continue; + } + else if ( !bInComment && *pSearchMCStart == '/' && *(pSearchMCStart+1) == '*' ) + { + pLastMCStart = pSearchMCStart; + bInComment = true; + } + else if ( bInComment && *(pSearchMCStart-1) == '*' && *(pSearchMCStart) == '/' ) + { + pLastMCEnd = pSearchMCStart; + bInComment = false; + } + + pSearchMCStart++; + } + + if ( !bInComment && pLastMCEnd == pSearchCommentStart ) + { + char *pListCmtLines = pLastMCStart; + while ( pListCmtLines < pLastMCEnd ) + { + hHelpLines.AddToTail( pListCmtLines ); + NextLine( &pListCmtLines ); + } + } + } + // check for single line comment and extent upwards for as many lines as possible + else + { + pSearchCommentStart = pLineStart; + searchSizeStart = offset; + + for (;;) + { + PreviousLine( &pSearchCommentStart, searchSizeStart ); + + if ( *pSearchCommentStart == '/' && *(pSearchCommentStart+1) == '/' ) + hHelpLines.AddToHead( pSearchCommentStart ); + else break; + + if ( searchSizeStart <= 0 ) + break; + } + } + } + + if ( hHelpLines.Count() ) + { + CUtlVector< char* >hCleanLines; + + for ( int i = 0; i < hHelpLines.Count(); i++ ) + { + bool bAddLinebreak = i < hHelpLines.Count() - 1; + hCleanLines.AddToTail(CopyToDelimiter( hHelpLines[i], '\n', bAddLinebreak )); + } + + int completeLength = 1; + for ( int i = 0; i < hCleanLines.Count(); i++ ) + { + if ( hCleanLines[ i ] == NULL ) + { + hCleanLines.Remove( i ); + i--; + } + + completeLength += Q_strlen( hCleanLines[ i ] ); + } + + char *pCombined = new char[ completeLength ]; + pCombined[ 0 ] = '\0'; + + for ( int i = 0; i < hCleanLines.Count(); i++ ) + { + Q_strcat( pCombined, hCleanLines[ i ], completeLength ); + delete [] hCleanLines[ i ]; + } + + hCleanLines.Purge(); + + p->m_pszHelptext = pCombined; + } + + hHelpLines.Purge(); + } + + //for ( int i = 0; i < hAutoCompUnits.Count(); i++ ) + // hAutoCompUnits[ i ]->DebugPrint(); +} + + +void CSmartObjectList::Parse_Include( char *pRead, CUtlVector< char* > *hIncludes ) +{ + Assert( hIncludes != NULL ); + + char *pBracketStart = pRead; + char *pBracketEnd = NULL; + + while ( pBracketStart && *pBracketStart ) + { + if ( *pBracketStart == '\"' || *pBracketStart == '<' ) + { + pBracketEnd = pBracketStart + 1; + while ( *pBracketEnd ) + { + if ( *pBracketEnd == *pBracketStart ) + break; + pBracketEnd++; + } + break; + } + pBracketStart++; + } + + if ( pBracketEnd && *pBracketEnd ) + { + pBracketStart++; + *pBracketEnd = '\0'; + ParseDbg( "valid include: %s -> %s", pRead, pBracketStart ); + + ParseCode( pBracketStart, true, hIncludes ); + } + else + { + ParseDbg( "invalid include: %s", pRead ); + } + + return; +} + +void CSmartObjectList::Parse_Define( char *pRead, const int iOffset ) +{ + const char *pszDef = "define"; + char *pSearch_Def = Q_stristr( pRead, pszDef ); + if ( !pRead ) + return; + + char *pExpStart_0 = pSearch_Def + Q_strlen( pszDef ) + 1; + + NextCharacter( &pExpStart_0 ); + + if ( !*pExpStart_0 ) + return; + + char *pExpEnd = pExpStart_0; + if ( !NextSpace( &pExpEnd ) || !IS_SPACE( *pExpEnd ) ) + return; + + //*pExpEnd = '\0'; + + char *pExpStart_1 = pExpEnd; + if ( !NextCharacter( &pExpStart_1 ) ) + return; + + if ( !*pExpStart_1 ) + return; + + int len = Q_strlen( pRead ); + char *pDef = new char[ len + 1 ]; + Q_memcpy( pDef, pRead, len ); + pDef[len] = '\0'; + char *pIdent = CopyWord( pExpStart_0 ); + CleanSpaces( pDef ); + + if ( !DatatypeMatch( pIdent ) ) + { + CSmartObject *p = new CSmartObject( ACOMP_DEFINE, pDef, pIdent ); + p->m_iTextOffset = iOffset; + AddUnit( p ); + } + + delete [] pDef; + delete [] pIdent; +} + +void CSmartObjectList::Parse_Variable( char *pRead, const int iOffset, const int iScopeDepth, const int iScopeNum ) +{ + int iSteps = 0; + char *pDataType = NULL; + char *pIdent = NULL; + char *pVar_Search = pRead; + + for(;iSteps < 32;) + { + iSteps++; + + NextCharacter( &pVar_Search ); + + char *pWord = CopyWord( pVar_Search ); + + if ( !pWord ) + { + Assert( 0 ); + break; + } + + bool bSuccess = DatatypeMatch( pWord ) || pDataType != NULL; + delete [] pWord; + + if ( bSuccess ) + { + if ( pDataType != NULL ) + { + pIdent = pVar_Search; + break; + } + else + pDataType = pVar_Search; + } + + NextSpace( &pVar_Search ); + } + + Assert( iSteps < 31 && pDataType && pIdent ); + + if ( !pDataType || !pIdent ) + return; + + pIdent = CopyWord( pIdent ); + pDataType = CopyWord( pDataType ); + CleanSpaces( pRead ); + + if ( !DatatypeMatch( pIdent ) ) + { + CSmartObject *p = new CSmartObject( ACOMP_VAR, pRead, pIdent, pDataType ); + p->m_iTextOffset = iOffset; + p->m_iScopeDepth = iScopeDepth; + p->m_iScopeNum = iScopeNum; + AddUnit( p ); + } + + delete [] pIdent; + delete [] pDataType; +} + +void CSmartObjectList::Parse_Function( char *pRead, const int iOffset, const int iScopeDepth, const int iScopeNum, + const int iInlineScopeDepth, const int iInlineScopeNum ) +{ + int iSteps = 0; + char *pDataType = NULL; + char *pIdent = NULL; + char *pVar_Search = pRead; + + char *pParamEnd = NULL; + + CUtlVector< CSmartObject* >hChildren; + + for(;iSteps < 32;) + { + iSteps++; + + NextCharacter( &pVar_Search ); + + char *pWord = CopyWord( pVar_Search ); + + if ( !pWord ) + { + Assert( 0 ); + break; + } + + bool bSuccess = DatatypeMatch( pWord ) || pDataType != NULL; + delete [] pWord; + + if ( bSuccess ) + { + if ( pDataType != NULL ) + pIdent = pVar_Search; + else + pDataType = pVar_Search; + } + + if ( pIdent == NULL ) + NextSpace( &pVar_Search ); + else + { + char *pParamStart = pVar_Search; + while ( *pParamStart && *pParamStart != '(' ) + pParamStart++; + + if ( !*pParamStart || !*(pParamStart+1) ) + return; + pParamStart++; + + int bracketCount = 0; + pParamEnd = pParamStart; + // blah ( omg() ) + // | | + // + // adfsda () + // | + while ( *pParamEnd && ( *pParamEnd != ')' || bracketCount != 0 ) ) + { + if ( *pParamEnd == '(' ) + bracketCount++; + else if ( *pParamEnd == ')' ) + bracketCount--; + pParamEnd++; + } + + if ( pParamEnd <= pParamStart ) + break; + + char *pSearchVarStuff = pParamStart; + char *pVar_Datatype = NULL; + char *pVar_Name = NULL; + const char *pParam_Start = NULL; + + while ( pSearchVarStuff < pParamEnd ) + { + NextCharacter( &pSearchVarStuff ); + + if ( !*pSearchVarStuff || pSearchVarStuff == pParamEnd ) + break; + + if ( !pParam_Start ) + pParam_Start = pSearchVarStuff; + + char *pWord = CopyWord( pSearchVarStuff ); + + if ( !pWord ) + break; + + if ( pVar_Datatype != NULL ) + { + pVar_Name = pWord; + pWord = NULL; + } + else if ( DatatypeMatch( pWord ) ) + { + pVar_Datatype = pWord; + pWord = NULL; + } + + if ( pVar_Name && pVar_Datatype ) + { + char *pDef = NULL; + if ( pParam_Start ) + { + const char *pParam_End = pParam_Start; + while ( *pParam_End && *pParam_End != ',' && *pParam_End != ')' ) + pParam_End++; + + while ( pParam_End > pParam_Start && IS_SPACE( *(pParam_End-1) ) ) + pParam_End--; + + int len = pParam_End - pParam_Start + 1; + pDef = new char[ len ]; + Q_memcpy( pDef, pParam_Start, len - 1 ); + pDef[len-1] = '\0'; + + pParam_Start = NULL; + } + CSmartObject *pC = new CSmartObject( ACOMP_VAR, pDef, pVar_Name, pVar_Datatype ); + delete [] pDef; + delete [] pVar_Name; + delete [] pVar_Datatype; + pVar_Datatype = NULL; + pVar_Name = NULL; + + hChildren.AddToTail( pC ); + + while ( *pSearchVarStuff && *pSearchVarStuff != ',' ) + pSearchVarStuff++; + + if ( *pSearchVarStuff ) + pSearchVarStuff++; + } + else + NextSpace( &pSearchVarStuff ); + + delete [] pWord; + } + + delete [] pVar_Datatype; + delete [] pVar_Name; + + break; + } + } + + Assert( iSteps < 31 && pDataType && pIdent && pParamEnd ); + + if ( !pDataType || !pIdent || !pParamEnd ) + { + hChildren.PurgeAndDeleteElements(); + return; + } + + int defSize = pParamEnd - pRead + 1; + char *pDef = new char[ defSize + 1 ]; + Q_memcpy( pDef, pRead, defSize ); + pDef[ defSize ] = '\0'; + CleanSpaces( pDef ); + + pIdent = CopyWord( pIdent ); + pDataType = CopyWord( pDataType ); + + if ( !DatatypeMatch( pIdent ) ) + { + CSmartObject *p = new CSmartObject( ACOMP_FUNC, pDef, pIdent, pDataType ); + p->m_iTextOffset = iOffset; + p->m_iScopeDepth = iScopeDepth; + p->m_iScopeNum = iScopeNum; + p->m_hChildren.AddVectorToTail( hChildren ); + AddUnit( p ); + + for ( int i = 0; i < hChildren.Count(); i++ ) + { + CSmartObject *p = new CSmartObject( *hChildren[i] ); + p->m_iTextOffset = iOffset; + p->m_iScopeDepth = iInlineScopeDepth; + p->m_iScopeNum = iInlineScopeNum; + AddUnit( p ); + } + + hChildren.Purge(); + } + else + hChildren.PurgeAndDeleteElements(); + + delete [] pIdent; + delete [] pDataType; + delete [] pDef; +} +void CSmartObjectList::Parse_Struct( char *pRead, const int iOffset, const int iScopeDepth, const int iScopeNum ) +{ + char *pDefStart = Q_stristr( pRead, "struct" ); + char *pStructStart = pDefStart; + char *pIdent = NULL; + + if ( !pStructStart ) + return; + + NextSpace( &pStructStart ); + NextCharacter( &pStructStart ); + + pIdent = pStructStart; + + char *pSearch_Children = pStructStart; + while ( *pSearch_Children && *pSearch_Children != '{' ) + pSearch_Children++; + + if ( !*pSearch_Children ) + return; + + pSearch_Children++; + NextCharacter( &pSearch_Children ); + + char *pStructEnd = pSearch_Children; + + while ( *pStructEnd && *pStructEnd != '}' ) + pStructEnd++; + + if ( !*pStructEnd ) + return; + + CUtlVector< CSmartObject* >hChildren; + + //int iSteps = 0; + + { + int structlen = pStructEnd - pSearch_Children + 1; + char *localStruct = new char[ structlen + 1 ]; + Q_memcpy( localStruct, pSearch_Children, structlen ); + localStruct[ structlen ] = '\0'; + ConvertCharacter( localStruct, '\n', ' ' ); + pSearch_Children = localStruct; + char *pStructEnd_Local = pSearch_Children + structlen - 1; + + char *pVar_Datatype = NULL; + char *pVar_Name = NULL; + char *pVar_Search = pSearch_Children; + + + while ( pVar_Search < pStructEnd_Local ) + { + NextCharacter( &pVar_Search ); + + if ( !*pVar_Search || pVar_Search == pStructEnd_Local ) + break; + + char *pWord = CopyWord( pVar_Search ); + + if ( !pWord ) + break; + + if ( pVar_Datatype != NULL ) + { + pVar_Name = pWord; + pWord = NULL; + } + else if ( DatatypeMatch( pWord ) ) + { + pVar_Datatype = pWord; + pWord = NULL; + } + + if ( pVar_Name && pVar_Datatype ) + { + CSmartObject *pC = new CSmartObject( ACOMP_VAR, NULL, pVar_Name, pVar_Datatype ); + delete [] pVar_Name; + delete [] pVar_Datatype; + pVar_Datatype = NULL; + pVar_Name = NULL; + + hChildren.AddToTail( pC ); + + while ( *pVar_Search && *pVar_Search != ';' ) + pVar_Search++; + + if ( *pVar_Search ) + pVar_Search++; + } + else + NextSpace( &pVar_Search ); + + delete [] pWord; + } + + delete [] pVar_Datatype; + delete [] pVar_Name; + delete [] localStruct; + } + + Assert( /*iSteps < 31 &&*/ pIdent && pStructEnd ); + + + if ( !pIdent || !pStructEnd ) + { + hChildren.PurgeAndDeleteElements(); + return; + } + + int defSize = pStructEnd - pDefStart + 1; + char *pDef = new char[ defSize + 1 ]; + Q_memcpy( pDef, pDefStart, defSize ); + pDef[ defSize ] = '\0'; + CleanSpaces( pDef ); + + pIdent = CopyWord( pIdent ); + + CSmartObject *p = new CSmartObject( ACOMP_STRUCT_DEF, pDef, pIdent ); + p->m_iTextOffset = iOffset; + p->m_iScopeDepth = iScopeDepth; + p->m_iScopeNum = iScopeNum; + p->m_hChildren.AddVectorToTail( hChildren ); + AddUnit( p ); + + hChildren.Purge(); + delete [] pIdent; + delete [] pDef; +} + +void CSmartObjectList::ParseCode_Stream( CUtlBuffer &hStream, bool bRecursive, CUtlVector< char* > *hIncludes, const char *sourceFile, int scopeOffset ) +{ + bool bOwnsIncludeVec = false; + + if ( bRecursive ) + { + if ( !hIncludes ) + { + bOwnsIncludeVec = true; + hIncludes = new CUtlVector< char* >(); + } + + Assert( hIncludes ); + + char *pSelf = NULL; + AutoCopyStringPtr( sourceFile, &pSelf ); + + hIncludes->AddToTail( pSelf ); + } + + const char *pszOldSrcFile = m_pCurSourceFile; + m_pCurSourceFile = sourceFile; + + if ( m_pCurSourceFile != NULL && *m_pCurSourceFile ) + PurgeUnitsOfSameSource( m_pCurSourceFile ); + + ParseCode_RemoveComments( hStream ); + + char *pText = (char*)hStream.Base(); + char *pRead_LineStart = pText; + + // list lines + CUtlVector< char* >hLines; + const int Size = hStream.Size(); + int iSizeItr = Size; + + while ( pRead_LineStart && *pRead_LineStart && iSizeItr > 0 ) + { + bool bHasChars = false; + + while ( *pRead_LineStart && iSizeItr > 0 ) + { + if ( *pRead_LineStart == '\n' ) + break; + + else if ( !IS_SPACE( *pRead_LineStart ) ) + { + bHasChars = true; + break; + } + pRead_LineStart++; + iSizeItr--; + } + + if ( bHasChars ) + hLines.AddToTail( pRead_LineStart ); + + int moved = NextLine( &pRead_LineStart ); + iSizeItr -= moved; + } + + // per physical line + ParseCode_PreProc( hLines, bRecursive, hIncludes, pText ); + + // kill preprocessor code + ParseCode_KillPreProc( hLines ); + + // list expressions + CUtlVector< char* >hExpressions; + char *pReadExpression = pText; + iSizeItr = Size; + + while ( pReadExpression && *pReadExpression && iSizeItr > 0 ) + { + // first nonwhite space char + while ( *pReadExpression && iSizeItr > 0 && IS_SPACE( *pReadExpression ) || *pReadExpression == '\n' ) + { + pReadExpression++; + iSizeItr--; + } + + hExpressions.AddToTail( pReadExpression ); + + // end of current expression + while ( *pReadExpression && iSizeItr > 0 && *pReadExpression != ';' ) + { + pReadExpression++; + iSizeItr--; + } + + if ( *pReadExpression == ';' && iSizeItr > 0 ) + { + pReadExpression++; + iSizeItr--; + } + } + + // code per expression + //ParseCode_RemoveInvisibleExpressions( hExpressions, scopeOffset, pText, Size ); + ParseCode_Expressions( hExpressions, pText ); + + hExpressions.Purge(); + hLines.Purge(); + + m_pCurSourceFile = pszOldSrcFile; + + if ( bOwnsIncludeVec ) + { + for ( int i = 0; i < hIncludes->Count(); i++ ) + delete [] hIncludes->Element( i ); + + hIncludes->Purge(); + delete hIncludes; + } +} +void CSmartObjectList::PurgeUnitsOfSameSource( const char *pszSrc ) +{ + for ( int i = 0; i < hAutoCompUnits.Count(); i++ ) + { + if ( !hAutoCompUnits[i]->m_pszSourceFile || !*hAutoCompUnits[i]->m_pszSourceFile ) + continue; + + if ( Q_stricmp( pszSrc, hAutoCompUnits[i]->m_pszSourceFile ) ) + continue; + + delete hAutoCompUnits[i]; + hAutoCompUnits.Remove(i); + i--; + } +} +void CSmartObjectList::ParseCode_PreProc( CUtlVector< char* > &hLines, bool bRecursive, CUtlVector< char* > *hIncludes, const char *pTextStart ) +{ + char *pLine = NULL; + for ( int i = 0; i < hLines.Count(); i++ ) + { + delete [] pLine; + pLine = CopyToDelimiter( hLines[ i ] ); + + if ( !pLine || !*pLine || *pLine != '#' ) + continue; + + int iOffset = hLines[ i ] - pTextStart; + + //Msg( "%s\n", pLine ); + if ( bRecursive && CRegex::MatchSyntax_Preproc( pLine ) == __REGEX__PREPROC_INC ) + { + Parse_Include( pLine, hIncludes ); + continue; + } + + // handle #define + if ( CRegex::MatchSyntax_Preproc( pLine ) == __REGEX__PREPROC_DEFINE ) + { + Parse_Define( pLine, iOffset ); + continue; + } + } + + delete [] pLine; +} + +//void CSmartObjectList::ParseCode_RemoveInvisibleExpressions( CUtlVector< char* > &hExpressions, int scopeOffset, const char *pTextStart, const int iSize ) +//{ +// if ( !hExpressions.Count() ) +// return; +// +// Assert( hExpressions.Count() && pTextStart <= hExpressions[0] ); +// Assert( scopeOffset <= iSize ); +// +// if ( scopeOffset < 0 ) +// return; +//} + +/* +deklarationen nach dem öffnen eines scopes werden ignoriert +deklarationen in impliziten scopes auch (egal?) +expressions werden zB in for(;;) gesplittet (egal?) +*/ + +void CSmartObjectList::ParseCode_Expressions( CUtlVector< char* > &hExpressions, const char *pTextStart ) +{ + char accessModRegexTmp[2048]; + char regexTmp_Var[ sizeof(accessModRegexTmp) ]; + char regexTmp_Func[ sizeof(accessModRegexTmp) ]; + char regexTmp_Struct[ sizeof(accessModRegexTmp) ]; + bool bRegexTmpNeedsRebuild = true; + + + int iScopeLevel = 0; + char *pExp = NULL; + + CUtlVector< int >hScopeCounter; + hScopeCounter.AddToTail(0); + + + for ( int i = 0; i < hExpressions.Count(); i++ ) + { + delete [] pExp; + pExp = CopyToDelimiter( hExpressions[ i ], ';' ); + ConvertCharacter( pExp, '\n', ' ' ); + + if ( !pExp ) + continue; + + //Warning( "EXP: %s\n", pExp ); + bool bEvaluatedExpression = false; + char *pScopeReader = pExp; + + while ( pScopeReader && *pScopeReader ) + { + if ( *pScopeReader == '{' ) + { + iScopeLevel++; + bEvaluatedExpression = false; + + if ( iScopeLevel >= hScopeCounter.Count() ) + { + hScopeCounter.AddToTail( -1 ); + } + + Assert( iScopeLevel < hScopeCounter.Count() ); + hScopeCounter[ iScopeLevel ]++; + } + else if ( *pScopeReader == '}' ) + { + iScopeLevel--; + bEvaluatedExpression = false; + } + else if ( !IS_SPACE( *pScopeReader ) ) + { + //if ( iScopeLevel != 0 ) + // bEvaluatedExpression = false; + //else if ( bEvaluatedExpression == false ) + if ( !IS_BRACKET( *pScopeReader ) && !IS_SPACE( *pScopeReader ) && !bEvaluatedExpression ) + { + bEvaluatedExpression = true; +#if __DBG_PARSE + Warning( "%c ", *pScopeReader ); +#endif + //Msg( "%s\n", pScopeReader ); + + if ( bRegexTmpNeedsRebuild ) + { + CUtlVector< CSmartObject* >hStructs; + + for ( int s = 0; s < hAutoCompUnits.Count(); s++ ) + if ( hAutoCompUnits[s]->m_iType == ACOMP_STRUCT_DEF && hAutoCompUnits[s]->m_pszIdentifier != NULL ) + hStructs.AddToTail( hAutoCompUnits[s] ); + + Q_snprintf( accessModRegexTmp, sizeof( accessModRegexTmp ), "(?:" ); + for ( int iKeyword = 0; iKeyword <= __REGEX_KEYWORDS_LASTACCESS_MOD; iKeyword++ ) + { + Q_strcat( accessModRegexTmp, CRegex::GetSyntaxList_KeyWords()[iKeyword], sizeof( accessModRegexTmp ) ); + + if ( iKeyword < __REGEX_KEYWORDS_LASTACCESS_MOD ) + Q_strcat( accessModRegexTmp, "|", sizeof( accessModRegexTmp ) ); + else + Q_strcat( accessModRegexTmp, "| |\\t)*", sizeof( accessModRegexTmp ) ); + } + + int structNum = 0; + const int iDefDType = CRegex::GetSyntaxNum_Datatypes_Regex(); + const int iDType = iDefDType + hStructs.Count(); + + Q_strcat( accessModRegexTmp, "(?:", sizeof( accessModRegexTmp ) ); + for ( int iDatatype = 0; iDatatype < iDType; iDatatype++ ) + { + if ( iDatatype < iDefDType ) + Q_strcat( accessModRegexTmp, CRegex::GetSyntaxList_Datatypes_Regex()[iDatatype], sizeof( accessModRegexTmp ) ); + else + { + char *pszSafe = CRegex::AllocSafeString( hStructs[structNum]->m_pszIdentifier ); + if ( pszSafe ) + Q_strcat( accessModRegexTmp, pszSafe, sizeof( accessModRegexTmp ) ); + delete [] pszSafe; + structNum++; + } + + if ( iDatatype < iDType - 1 ) + Q_strcat( accessModRegexTmp, "|", sizeof( accessModRegexTmp ) ); + else + Q_strcat( accessModRegexTmp, ")", sizeof( accessModRegexTmp ) ); + } + + //Q_snprintf( regexTmp_Var, sizeof( regexTmp_Var ), "%s[ \\t]+[\\w\\d]+(?:[ \\t]*[^\\( \\t].*)?", accessModRegexTmp ); + Q_snprintf( regexTmp_Var, sizeof( regexTmp_Var ), "%s[ \\t]+[\\w\\d]+.*?", accessModRegexTmp ); + Q_snprintf( regexTmp_Func, sizeof( regexTmp_Func ), "%s[ \\t]+[\\w\\d]+[ \\t]*\\((?:[[:print:]\\t]+)?\\)[[:print:]\\t]*", accessModRegexTmp ); + Q_snprintf( regexTmp_Struct, sizeof( regexTmp_Struct ), "struct[ \\t]+[\\w\\d]+[ \\t]+\\{.*" ); + + bRegexTmpNeedsRebuild = false; + hStructs.Purge(); + } + + // const bool g_bHighQualityShadows : register( b0 ) + // (const|static| |\\t){0,}double([1-4]??|[1-4]x[1-4]) [ \\t]{1,}[a-zA-Z0-9_]{1,}[ \\t]{0,}[\\=\\:]?\0 + + Assert( !iScopeLevel || iScopeLevel < hScopeCounter.Count() ); + + const int iOffset = hExpressions[ i ] - pTextStart + pScopeReader - pExp; + const int iScopeDepth = iScopeLevel; + const int iScopeNum = iScopeLevel ? hScopeCounter[ iScopeLevel ] : 0; + + if ( CRegex::RegexMatch( pScopeReader, regexTmp_Struct ) ) + { + ParseDbg( "got STRUCT: %s", pScopeReader ); + Parse_Struct( hExpressions[ i ] + ( pScopeReader - pExp ), iOffset, iScopeDepth, iScopeNum ); + bRegexTmpNeedsRebuild = true; + } + else if ( CRegex::RegexMatch( pScopeReader, regexTmp_Func ) ) + { + ParseDbg( "got FUNC: %s", pScopeReader ); + const int inlineLevel = iScopeDepth + 1; + if ( inlineLevel >= hScopeCounter.Count() ) + hScopeCounter.AddToTail( -1 ); + Assert( inlineLevel < hScopeCounter.Count() ); + int inlineNum = hScopeCounter[ inlineLevel ] + 1; + + Parse_Function( pScopeReader, iOffset, iScopeDepth, iScopeNum, inlineLevel, inlineNum ); + } + else if ( CRegex::RegexMatch( pScopeReader, regexTmp_Var ) ) + { + ParseDbg( "got VAR: %s", pScopeReader ); + Parse_Variable( pScopeReader, iOffset, iScopeDepth, iScopeNum ); + } + else + { + ParseDbg( "UNHANDLED: %s", pScopeReader ); + } + + //pScopeReader = NULL; + //break; + } + } + + pScopeReader++; + } + } + + hScopeCounter.Purge(); + delete [] pExp; +} + +void CSmartObjectList::ParseCode_KillPreProc( CUtlVector< char* > &hLines ) +{ + for ( int i = 0; i < hLines.Count(); i++ ) + { + char *pReadLine = hLines[i]; + + while ( *pReadLine && IS_SPACE(*pReadLine) ) + pReadLine++; + + if ( *pReadLine == '\n' ) + { + // these should have been removed already + Assert( 0 ); + continue; + } + + if ( *pReadLine == '#' ) + { + // assume preproc statement, kill it + while ( *pReadLine && *pReadLine != '\n' ) + { + // expression iterator will jump over LF and may hit this stuff again + *pReadLine = ' '; + pReadLine++; + } + + hLines.Remove( i ); + i--; + continue; + } + } +} + +void CSmartObjectList::ParseCode_RemoveComments( CUtlBuffer &hStream ) +{ + char *pText = (char*)hStream.Base(); + char *pRead_ClearCR = pText; + + const int Size = hStream.Size(); + int iSizeItr = Size; + + bool bInSingleLineCmt = false; + bool bInMultiLineCmt = false; + + while ( pRead_ClearCR && *pRead_ClearCR && iSizeItr > 0 ) + { + //if ( *pRead_ClearCR == '\r' ) + // *pRead_ClearCR = ' '; + + if ( bInSingleLineCmt ) + { + if ( *pRead_ClearCR == '\n' ) + bInSingleLineCmt = false; + else + *pRead_ClearCR = ' '; + } + else if ( bInMultiLineCmt ) + { + if ( iSizeItr > 1 ) + { + if ( *(pRead_ClearCR) == '*' && *(pRead_ClearCR+1) == '/' ) + { + *(pRead_ClearCR+1) = ' '; + bInMultiLineCmt = false; + } + + *pRead_ClearCR = ' '; + } + } + else if ( iSizeItr > 1 ) + { + if ( *pRead_ClearCR == '/' && *(pRead_ClearCR+1) == '/' ) + { + bInSingleLineCmt = true; + *pRead_ClearCR = ' '; + } + else if ( *pRead_ClearCR == '/' && *(pRead_ClearCR+1) == '*' ) + { + bInMultiLineCmt = true; + *pRead_ClearCR = ' '; + *(pRead_ClearCR+1) = ' '; + } + } + + pRead_ClearCR++; + iSizeItr--; + } +} + +static const char *pszDatatypes[] = { + "double", + "float", + "half", + "HALF", + "int", + "uint", + "bool", + + "sampler", + "Buffer", + "matrix", + "vector", +}; +static const int iDatatypesSize = ARRAYSIZE( pszDatatypes ); + +static const char *vecLookUpIdents[] = +{ + "x", "y", "z", "w", +}; + +CSmartObject *AllocIntrinsicChild( int datatype, int index ) +{ + Assert( datatype >= 0 && datatype < iDatatypesSize ); + Assert( index >= 0 && index < 4 ); + + char tmp[MAX_PATH]; + Q_snprintf( tmp, sizeof(tmp), "%s %s", pszDatatypes[datatype], vecLookUpIdents[index] ); + CSmartObject *pO = new CSmartObject( ACOMP_VAR, tmp, vecLookUpIdents[index], pszDatatypes[datatype] ); + pO->m_bIntrinsic = true; + return pO; +} + + +void CSmartObjectList::BuildIntrinsicDatatypes() +{ + const int iFirstLocked = 7; + + char tmp[MAX_PATH]; + char tmp_dtype[MAX_PATH]; + char tmp_child[MAX_PATH]; + + for ( int i = 0; i < iDatatypesSize; i++ ) + { + if ( i < iFirstLocked ) + { + Q_snprintf( tmp, sizeof(tmp), "%s( %s x )", pszDatatypes[i], pszDatatypes[i] ); + + CSmartObject *pO = new CSmartObject( ACOMP_FUNC, tmp, pszDatatypes[i], pszDatatypes[i] ); + pO->m_bIntrinsic = true; + pO->m_hChildren.AddToTail( AllocIntrinsicChild( i, 0 ) ); + AddUnit( pO ); + + for ( int d1 = 1; d1 <= 4; d1++ ) + { + Q_snprintf( tmp, sizeof(tmp), "%s%d(", pszDatatypes[i], d1 ); + + for ( int child = 0; child < d1; child++ ) + { + Q_snprintf( tmp_child, sizeof(tmp_child), " %s %s", pszDatatypes[i], vecLookUpIdents[child] ); + Q_strcat( tmp, tmp_child, sizeof(tmp) ); + Q_strcat( tmp, (childm_bIntrinsic = true; + for ( int child = 0; child < d1; child++ ) + pO->m_hChildren.AddToTail( AllocIntrinsicChild( i, child ) ); + AddUnit( pO ); + } + } + else + { + CSmartObject *pO = new CSmartObject( ACOMP_VAR, pszDatatypes[i], pszDatatypes[i] ); + pO->m_bIntrinsic = true; + AddUnit( pO ); + } + } +} + +#ifndef SHADER_EDITOR_DLL_2006 +CON_COMMAND( test_parse, "" ) +{ + CSmartObjectList l; + + int idx = ( args.ArgC() > 1 ) ? atoi( args[ 1 ] ) : 0; + + CUtlVector< char* > hIncludes; + + const char *pfile = "common_ps_fxc.h"; + switch ( idx ) + { + case 1: + pfile = "common_vertexlitgeneric_dx9.h"; + break; + case 2: + pfile = "common_lightmappedgeneric_fxc.h"; + break; + case 3: + pfile = "common_flashlight_fxc.h"; + break; + case 4: + pfile = "common_parallax.h"; + break; + case 5: + pfile = "common_vs_fxc.h"; + break; + case 6: + pfile = ".h"; + break; + } + l.ParseCode( pfile, true, &hIncludes ); + + for ( int i = 0; i < hIncludes.Count(); i++ ) + delete [] hIncludes[ i ]; + + hIncludes.Purge(); +} +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmartobjectlist.h b/sp/src/shadereditor/properties/smarttext/vsmartobjectlist.h new file mode 100644 index 00000000..b69f633f --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmartobjectlist.h @@ -0,0 +1,66 @@ +#ifndef SMART_OBJECT_LIST_H +#define SMART_OBJECT_LIST_H + +#include "cbase.h" + +#define IDENT_LIVE_CODE "__EDITORCODE" +#define IDENT_STATIC_LIVE_CODE "__EDITORCODE_AUTO" + +class CSmartObject; + +class CSmartObjectList +{ +public: + + CSmartObjectList(); + ~CSmartObjectList(); + CSmartObjectList( const CSmartObjectList &o ); + + int GetNumEntries(); + CSmartObject *GetEntry( int i ); + CSmartObject *GetEntryByIdent( const char *pIdent ); + CSmartObject *GetEntryByIdent( const wchar_t *pIdent ); + + void ParseCode( const char *pszFilename, bool bRecursive = false, CUtlVector< char* > *hIncludes = NULL ); + void ParseCode_Stream( CUtlBuffer &hStream, bool bRecursive = false, CUtlVector< char* > *hIncludes = NULL, const char *sourceFile = NULL, int scopeOffset = -1 ); + + void DoSort(); + + void MergeWithEntries( CSmartObjectList *pOther ); + void PurgeUnitsOfSameSource( const char *pszSrc ); + + void AddUnit( CSmartObject *pUnit ); + + void SetDatabaseCopy( CSmartObjectList *pCopyTarget ); + + void BuildIntrinsicDatatypes(); + +private: + + void BuildHelpTexts( char *pStreamCopy, int iSize ); + + void ParseCode_PreProc( CUtlVector< char* > &hLines, bool bRecursive, CUtlVector< char* > *hIncludes, const char *pTextStart ); + void ParseCode_KillPreProc( CUtlVector< char* > &hLines ); + void ParseCode_RemoveComments( CUtlBuffer &hStream ); + //void ParseCode_RemoveInvisibleExpressions( CUtlVector< char* > &hExpressions, int scopeOffset, const char *pTextStart, const int iSize ); + void ParseCode_Expressions( CUtlVector< char* > &hExpressions, const char *pTextStart ); + + void Parse_Include( char *pRead, CUtlVector< char* > *hIncludes ); + void Parse_Define( char *pRead, const int iOffset ); + void Parse_Variable( char *pRead, const int iOffset, const int iScopeDepth, const int iScopeNum ); + void Parse_Function( char *pRead, const int iOffset, const int iScopeDepth, const int iScopeNum, + const int iInlineScopeDepth, const int iInlineScopeNum ); + void Parse_Struct( char *pRead, const int iOffset, const int iScopeDepth, const int iScopeNum ); + + + bool DatatypeMatch( const char *pWord ); + + CUtlVector< CSmartObject* >hAutoCompUnits; + + const char *m_pCurSourceFile; + CSmartObjectList *m_pCopyTarget; +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmartrow.cpp b/sp/src/shadereditor/properties/smarttext/vsmartrow.cpp new file mode 100644 index 00000000..3163b43c --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmartrow.cpp @@ -0,0 +1,1296 @@ + +#include "cbase.h" +#include "vSmartRow.h" +#include "cRegex.h" + + +#define __ROWCALC_INTRO( x ) int iLastsplit = 0;\ + int cur_x = 0;\ + int cWidth = 0;\ + for ( int i = 0; i < x; i++ )\ + {\ + wchar_t &ch = hText[ i ] + +#define __ROWCALC_SPLIT_INTRO() if ( ShouldSplit( cur_x, iLastsplit, i ) )\ + {\ + iLastsplit = i;\ + cur_x = GetAutoCRWidth() + +#define __ROWCALC_SPLIT_OUTRO() }\ + cWidth = GetCharWidth( ch, cur_x ) + +#define __ROWCALC_OUTRO() cur_x += cWidth;\ + } + + +_inlineFormat::_inlineFormat() +{ + start = 0; + end = 1; + + bOverride_fg = false; + bOverride_bg = false; + + bCRBlock = false; +} + +bool _inlineFormat::ShouldOverride( int pos ) +{ + return pos >= start && ( end == -1 || pos < end ); +} + +_cmtCtrl::_cmtCtrl() +{ + _cmtCtrl( 0, 0, 0 ); +} +_cmtCtrl::_cmtCtrl( int row, int x0, int x1 ) +{ + _y = row; + _x0 = x0; + _x1 = x1; +} + +bool _cmtCtrl::IsCommented( int x, int y ) +{ + return _y == y && + x >= _x0 && + ( _x1 == -1 || x <= _x1 ); +} + +_smartRow::_smartRow( HFont font, const int &w, const int &inset ) +{ + m_pszHighlightRef = NULL; + + _font = font; + m_iInteriorWidth = w; + m_iInsetWidth = inset; + m_bDirty = false; + SetLocked( false ); + SetDeletable( true ); + m_bDirty_HighlightRef = false; + m_bDynamicSpacing_Enabled = false; + + m_iCached_Charwidth = 0; + m_iCached_Renderlen = 0; + MakeLayoutDirty(); + + SetupVguiTex( m_iTex_Arrow, "shadereditor/char_arrow" ); + SetupVguiTex( m_iTex_CR, "shadereditor/char_cr" ); + +#if DEFAULT_ROW_CAPACITY > 0 + hText.EnsureCapacity( DEFAULT_ROW_CAPACITY ); +#endif +#if DEFAULT_ROW_GROWSIZE > 0 + hText.SetGrowSize( DEFAULT_ROW_GROWSIZE ); +#endif +} + +_smartRow::~_smartRow() +{ + hText.Purge(); + hSyntaxFormat.PurgeAndDeleteElements(); + ClearHighlightFormats(); + ClearTopFormats(); +} + +_smartRow::_smartRow( const _smartRow &o ) +{ + m_bDirty_HighlightRef = false; + m_bDynamicSpacing_Enabled = o.m_bDynamicSpacing_Enabled; + m_pszHighlightRef = NULL; + + _font = o._font; + m_iInteriorWidth = o.m_iInteriorWidth; + m_iInsetWidth = o.m_iInsetWidth; + + hText.AddVectorToTail( o.hText ); + + for ( int i = 0; i < o.hSyntaxFormat.Count(); i++ ) + hSyntaxFormat.AddToTail( new _inlineFormat( *o.hSyntaxFormat[i] ) ); + for ( int i = 0; i < o.hUserHighlight.Count(); i++ ) + hUserHighlight.AddToTail( new _inlineFormat( *o.hUserHighlight[i] ) ); + for ( int i = 0; i < o.hTopHighlight.Count(); i++ ) + hTopHighlight.AddToTail( new _inlineFormat( *o.hTopHighlight[i] ) ); + + m_iTex_Arrow = o.m_iTex_Arrow; + m_iTex_CR = o.m_iTex_CR; + + m_iCached_Charwidth = o.m_iCached_Charwidth; + m_iCached_Renderlen = o.m_iCached_Renderlen; + m_bDirty = o.m_bDirty; + m_bDirty_CharWidth = o.m_bDirty_CharWidth; + m_bDirty_Renderlen = o.m_bDirty_Renderlen; + + m_bLocked = o.m_bLocked; + m_bDeletable = o.m_bDeletable; +} + + +void _smartRow::SetLocked( bool bLocked ) +{ + m_bLocked = bLocked; +} +bool _smartRow::IsLocked() +{ + return m_bLocked; +} +void _smartRow::SetDeletable( bool bDeletable ) +{ + m_bDeletable = bDeletable; +} +bool _smartRow::IsDeletable() +{ + if ( IsLocked() ) + return false; + + return m_bDeletable; +} + + +void _smartRow::DoSyntaxHighlighting( const bool bStringLiterals, const bool bBrackets, const bool bHLSL ) +{ + hSyntaxFormat.PurgeAndDeleteElements(); + + //int LFs = 0; + KillLineBreaks(); + + for ( int x0 = 0; x0 < hText.Count(); x0++ ) + { + //if ( !hText[ x0 ] ) + //{ + // LFs++; + // continue; + //} + + if ( IS_SPACE( hText[ x0 ] ) ) + continue; + + int x1 = GetWordRight( x0, true, true ); + + if ( x1 == x0 ) + continue; + + wchar_t *word = ReadInterval( x0, x1 - 1, false ); + + if ( word == NULL ) + continue; + + const Color *pCol = CRegex::GetColorForWordBySyntax( word, bStringLiterals, + bBrackets, bHLSL ); + + if ( pCol != NULL ) + { + _inlineFormat *f = new _inlineFormat(); + f->bOverride_fg = true; + f->col_fg = *pCol; + f->start = x0; // - LFs; + f->end = x1; // - LFs; + + hSyntaxFormat.AddToTail( f ); + } + + delete [] word; + + x0 = x1 - 1; + } + + UpdateLinebreaks(); +} + +void _smartRow::SetFont( HFont f ) +{ + _font = f; + + MakeLayoutDirty(); +} + +void _smartRow::SetInteriorWidth( const int &w, const int &inset ) +{ + m_iInteriorWidth = w; + m_iInsetWidth = inset; + + OnTextChanged( true ); +} + +int _smartRow::GetInteriorWidth() +{ + return m_iInteriorWidth; +} + +void _smartRow::KillLineBreaks() +{ + for ( int i = 0; i < hText.Count(); i++ ) + { + if ( !hText[i] ) + { + hText.Remove( i ); + i--; + } + } +} +void _smartRow::UpdateLinebreaks() +{ +#if DEBUG + for ( int i = 0; i < hText.Count(); i++ ) + if ( !hText[i] ) + Assert( 0 ); +#endif + + __ROWCALC_INTRO( hText.Count() ); + __ROWCALC_SPLIT_INTRO(); + hText.InsertBefore( i, L'\0' ); + __ROWCALC_SPLIT_OUTRO(); + __ROWCALC_OUTRO(); +} + +void _smartRow::SetHighlightRef( wchar_t *pszRef ) +{ + m_pszHighlightRef = pszRef; + + if ( pszRef ) + MakeHighlightRefDirty(); +} + +void _smartRow::ClearHighlightFormats() +{ + m_pszHighlightRef = NULL; + + hUserHighlight.PurgeAndDeleteElements(); +} + +void _smartRow::AddHighlightFormat( _inlineFormat *format ) +{ + hUserHighlight.AddToTail( format ); +} + +void _smartRow::ClearTopFormats() +{ + hTopHighlight.PurgeAndDeleteElements(); +} + +void _smartRow::AddTopFormat( _inlineFormat *format ) +{ + hTopHighlight.AddToTail( format ); +} + +bool _smartRow::IsDynamicSpacingEnabled() +{ + return m_bDynamicSpacing_Enabled; +} + +void _smartRow::SetDynamicSpacingEnabled( bool bEnabled ) +{ + m_bDynamicSpacing_Enabled = bEnabled; +} + +void _smartRow::DrawRow( const int &x, int &y, + const Color &col_fg ) +{ + if ( IsHighlightRefDirty() ) + MakeHighlightRefClean(); + + int c_t = surface()->GetFontTall( _font ); + int RealPos = 0; + + CUtlVector< _inlineFormat* > hFormatStack; + + __ROWCALC_INTRO( hText.Count() ); + __ROWCALC_SPLIT_INTRO(); + y += c_t; + + int ico_tall = c_t / 2; + surface()->DrawSetTexture( m_iTex_CR ); + surface()->DrawSetColor( ST_COL_SPACING ); + surface()->DrawTexturedRect( x + ico_tall, y + ico_tall / 2, + x + ico_tall * 3, y + ico_tall / 2 + ico_tall ); + + __ROWCALC_SPLIT_OUTRO(); + + surface()->DrawSetTextColor( col_fg ); + + for ( int f = 0; f < hFormatStack.Count(); f++ ) + if ( !hFormatStack[ f ]->ShouldOverride( RealPos ) ) + { + hFormatStack.Remove( f ); + f--; + } + + for ( int f = 0; f < hSyntaxFormat.Count(); f++ ) + if ( hSyntaxFormat[ f ]->ShouldOverride( RealPos ) && !hFormatStack.HasElement( hSyntaxFormat[ f ] ) ) + hFormatStack.AddToHead( hSyntaxFormat[ f ] ); + + for ( int f = 0; f < hUserHighlight.Count(); f++ ) + if ( ( hUserHighlight[ f ]->ShouldOverride( RealPos ) ) && !hFormatStack.HasElement( hUserHighlight[ f ] ) ) + hFormatStack.AddToTail( hUserHighlight[ f ] ); + + for ( int f = 0; f < hTopHighlight.Count(); f++ ) + if ( ( hTopHighlight[ f ]->ShouldOverride( RealPos ) ) && !hFormatStack.HasElement( hTopHighlight[ f ] ) ) + hFormatStack.AddToTail( hTopHighlight[ f ] ); + + for ( int f = 0; f < hFormatStack.Count(); f++ ) + { + _inlineFormat *format = hFormatStack[ f ]; + + if ( format->bOverride_fg ) + surface()->DrawSetTextColor( format->col_fg ); + if ( format->bOverride_bg ) + { + int rect_w = cWidth; + if ( rect_w == 0 ) + rect_w = GetCharWidth( L' ' ) / 2; + + surface()->DrawSetColor( format->col_bg ); + surface()->DrawFilledRect( cur_x + x, y, cur_x + x + rect_w, y + c_t ); + } + } + + if ( ch ) + RealPos++; + + surface()->DrawSetTextPos( cur_x + x, y ); + + if ( !IsDynamicSpacingEnabled() ) + { + if ( ch == ' ' ) + { + surface()->DrawSetTextColor( ST_COL_SPACING ); + surface()->DrawUnicodeChar( L'\x00B7' ); + } + else if ( ch == 9 ) + { + int ico_tall = (int)(c_t*0.42f); // 42! + int ico_spacing = ( c_t - ico_tall ) / 2; + surface()->DrawSetTexture( m_iTex_Arrow ); + surface()->DrawSetColor( ST_COL_SPACING ); + surface()->DrawTexturedRect( cur_x + x, y + ico_spacing, cur_x + x + ico_tall * 2, y + ico_spacing + ico_tall ); + } + else if ( ch != 0 ) + { + surface()->DrawUnicodeChar( ch ); + } + } + + __ROWCALC_OUTRO(); + + for ( int f = 0; f < hUserHighlight.Count(); f++ ) + { + _inlineFormat *format = hUserHighlight[ f ]; + + if ( !format->bCRBlock ) + continue; + + if ( format->bOverride_fg ) + surface()->DrawSetTextColor( format->col_fg ); + if ( format->bOverride_bg ) + { + int rect_w = GetCharWidth( L' ' ) / 2; + + surface()->DrawSetColor( format->col_bg ); + surface()->DrawFilledRect( cur_x + x, y, cur_x + x + rect_w, y + c_t ); + } + } + + y += c_t; + hFormatStack.Purge(); +} + +int _smartRow::GetRenderNumRows_Internal( int cursor_x, bool bPartial ) +{ + int heightOut = 1; + cursor_x = min( cursor_x, hText.Count() ); + + __ROWCALC_INTRO( cursor_x ); + if ( !ch && bPartial ) + { + cursor_x = min( cursor_x + 1, hText.Count() ); + } + __ROWCALC_SPLIT_INTRO(); + heightOut++; + __ROWCALC_SPLIT_OUTRO(); + __ROWCALC_OUTRO(); + + return heightOut; +} + + +int _smartRow::GetRenderNumRows( int cursor_x ) +{ + int result = 0; + const bool bLimited = cursor_x >= 0; + + if ( bLimited || IsLayoutDirty_Renderlen() ) + { + if ( !bLimited ) + cursor_x = hText.Count(); + + result = GetRenderNumRows_Internal( cursor_x, bLimited ); + + if ( !bLimited ) + { + m_iCached_Renderlen = result; + MakeLayoutClean_Renderlen(); + } + } + else + result = m_iCached_Renderlen; + + return result; +} +int _smartRow::GetRenderHeight() +{ + return GetRenderNumRows() * surface()->GetFontTall( _font ); +} +void _smartRow::RelativeRowCursorToPanel( const int &cursor_x, int &movex, int &movey ) +{ + movey = 0; + int c_t = surface()->GetFontTall( _font ); + + __ROWCALC_INTRO( min( hText.Count(), cursor_x ) ); + __ROWCALC_SPLIT_INTRO(); + movey += c_t; + __ROWCALC_SPLIT_OUTRO(); + __ROWCALC_OUTRO(); + + movex = cur_x; + movex += m_iInsetWidth; +} + +int _smartRow::PanelToCursorCalcX( int virtualRow, int pixelx ) +{ + pixelx -= m_iInsetWidth; + + if ( hText.Count() < 1 ) + return 0; + + int best_pos = 0; + int best_dist = 99999; + bool bGotHit = false; + + __ROWCALC_INTRO( hText.Count() ); + if ( virtualRow == 0 ) + { + int cur_dist = abs( cur_x - pixelx ); + + if ( cur_dist <= best_dist ) + { + best_dist = cur_dist; + best_pos = i; + + bGotHit = true; + } + else if ( bGotHit ) + return best_pos; + } + __ROWCALC_SPLIT_INTRO(); + virtualRow--; + if ( virtualRow < 0 ) + return i; + __ROWCALC_SPLIT_OUTRO(); + __ROWCALC_OUTRO(); + + if ( abs( cur_x - pixelx ) < best_dist ) + best_pos++; + + return best_pos; +} + +bool _smartRow::ShouldSplit( int curpixelpos, int localRowStart, int localRowCur ) +{ + Assert( localRowStart < hText.Count() && localRowCur < hText.Count() ); + + wchar_t &ch = hText[ localRowCur ]; + if ( !ch ) + return true; + + //int cwidth = ( ch == L'\t' ) ? GetCharWidth( L' ' ) : GetCharWidth( ch ); + int cwidth = GetCharWidth( ch, curpixelpos ); + + if ( curpixelpos + cwidth > m_iInteriorWidth ) + return true; + + // is there a space to the left? + //for ( int i = localRowStart; i < localRowCur; i++ ) + // if ( IS_SPACE( hText[ i ] ) ) + if ( localRowCur > 0 && IS_SPACE( hText[ localRowCur - 1 ] ) ) + { + int tmpPixelPos = curpixelpos; + // any more spaces to the right? + for ( int c = localRowCur; c < hText.Count(); c++ ) + { + wchar_t &curWord = hText[ c ]; + if ( IS_SPACE( curWord ) ) + return false; + tmpPixelPos += GetCharWidth( curWord, tmpPixelPos ); + if ( tmpPixelPos > m_iInteriorWidth ) + break; + } + + tmpPixelPos = curpixelpos; + // does this 'word' cross the border? + for ( int c = localRowCur; c < hText.Count(); c++ ) + { + wchar_t &curWord = hText[ c ]; + tmpPixelPos += GetCharWidth( curWord, tmpPixelPos ); + if ( tmpPixelPos > m_iInteriorWidth ) + return true; + } + //break; + } + + return false; +} + +int _smartRow::GetWordLeft( int pos ) +{ + Assert( pos >= 0 && pos <= hText.Count() ); + + if ( pos == hText.Count() ) + pos--; + + while ( pos >= 0 && hText[ pos ] == 0 ) + pos--; + + if ( pos < 0 ) + return 0; + + const wchar_t ref = hText[ pos ]; + wchar_t lastCh = ref; + + //bool bHitMinus = false; + //bool bHitChar = false; + + pos--; + + for (;;) + { + if ( pos < 0 ) + return 0; + + const wchar_t cur = hText[ pos ]; + + if ( !IsWordConcat( ref, cur, false, false ) ) + { + bool bCur_Period = cur == L'.'; + bool bRef_Period = ref == L'.'; + + if ( ( bRef_Period || bCur_Period ) ) + { + int nextStart = pos + ( bCur_Period ? -1 : 0 ); + + if ( nextStart >= 0 ) + { + const wchar_t &ch = hText[ nextStart ]; + + if ( IS_SPACE( ch ) ) + nextStart++; + else + nextStart = GetWordLeft( nextStart ); + } + + if ( nextStart >= 0 ) + { + const wchar_t &ch = hText[ nextStart ]; + + if ( IS_NUMERICAL( ch ) ) + { + pos = nextStart - 1; + } + } + } + + return max( 0, pos + 1 ); + } + + lastCh = cur; + + //bool bMinus = cur == L'-'; + //if ( IS_CHAR( cur ) ) + // bHitChar = true; + + //if ( ( !bMinus || bHitMinus ) && + // !IsWordConcat( ref, cur, false, !bHitChar ) ) + // return max( 0, min( pos + 1, maxchar ) ); + + //if ( bMinus ) + // bHitMinus = true; + + pos--; + } + + return 0; +} + +int _smartRow::GetWordRight( int pos, bool bPreprocTest, bool bStringTest ) +{ + Assert( pos >= 0 && pos <= hText.Count() ); + + if ( pos == hText.Count() ) + pos--; + + int maxLen = hText.Count(); + int read0 = max( 0, pos ); + const wchar_t ref = hText[ read0 ]; + + if ( bPreprocTest && ref == L'#' ) + { + int end = -1; + + for ( int i = pos + 1; i < hText.Count() && end == -1; i++ ) + { + if ( !hText[i] || !IS_SPACE( hText[i] ) ) + end = i; + } + + if ( end >= 0 ) + { + end = GetWordRight( end ); + + wchar_t *strStart = ReadInterval( pos, end - 1 ); //hText.Base() + pos; + + if ( CRegex::MatchSyntax_Preproc( strStart ) ) + { + for ( int x = pos+1; x < hText.Count(); x++ ) + { + if ( hText[ x ] && !IS_SPACE( hText[ x ] ) ) + return GetWordRight( x ); + } + } + + delete [] strStart; + } + } + else if ( bStringTest && + ( ref == L'\"' || ref == L'\'' ) ) + { + for ( int i = read0 + 1; i < hText.Count(); i++ ) + { + if ( hText[ i ] == '\\' ) + { + i++; + continue; + } + + if ( hText[ i ] == ref ) + return i+1; + } + + return maxLen; + } + + pos++; + + for (;;) + { + if ( pos >= maxLen ) + return maxLen; + + const wchar_t cur = hText[ pos ]; + + if ( !IsWordConcat( ref, cur, true, true ) ) + return pos; + + pos++; + } + + return maxLen - 1; +} + +bool _smartRow::IsWordConcat( const wchar_t ref, const wchar_t test, bool bLoose, bool bIsValue ) +{ + if ( IS_SPACE( ref ) && IS_SPACE( test ) ) + return true; + + bool bLoose_ref = bLoose && ( ref == L'-' || ref == L'.' ); + //bool bLoose_test = bLoose && ( test == L'-' || test == L'.' ); + bool bLoose_test = bLoose && ( test == L'.' ); + //bool bLoose_ref = ref == L'-' || bLoose && ref == L'.'; + //bool bLoose_test = test == L'-' || bLoose && test == L'.'; + + //if ( bIsValue && + // ( ref == L'.' || IS_NUMERICAL( ref ) || bLoose_ref ) ) + //{ + // if ( IS_NUMERICAL( test ) || test == L'.' || bLoose_test ) + // return true; + + // if ( !bLoose && IS_CHAR( test ) ) + // return true; + //} + + if ( ref == L'.' || + ref == L';' || + ref == L':' || + ref == L'\'' || + ref == L'\"' ) + return false; + + if ( ( IS_NUMERICAL( ref ) || bLoose_ref ) && + ( IS_NUMERICAL( test ) || bLoose_test ) ) + return true; + + if ( ( IS_CHAR( ref ) || IS_NUMERICAL( ref ) ) && + ( IS_CHAR( test ) || IS_NUMERICAL( test ) ) ) + return true; + + if ( ref == test ) + { + if ( ref == L'&' || + ref == L'|' || + ref == L'=' || + ref == L'+' || + ref == L'-' ) //&& abs(ref-test) <= 1 ) + return true; + } + + return false; +} + +int _smartRow::GetTextLen( bool bIgnoreLineBreaks ) +{ + if ( !bIgnoreLineBreaks ) + return hText.Count(); + else + { + int c = 0; + for ( int i = 0; i < hText.Count(); i++ ) + if ( hText[i] ) + c++; + return c; + } +} + +void _smartRow::ToRealCursor( text_cursor &c ) +{ + int cPos = ( c.x < hText.Count() && hText[ c.x ] != 0 ) ? c.x + 1 : c.x; + for ( int i = 0; i < min( cPos, hText.Count() ); i++ ) + { + if ( !hText[i] ) + c.x--; + } +} + +void _smartRow::ToVirtualCursor( text_cursor &c ) +{ + for ( int i = 0; i < min( c.x, hText.Count() ); i++ ) + { + if ( !hText[i] ) + c.x++; + } +} + +bool _smartRow::HasLinebreakAtCursor( const text_cursor &c ) +{ + return hText.Count() > c.x && hText[ c.x ] == 0; +} + +int _smartRow::GetCharWidth( wchar_t c, int rowPos ) +{ + if ( !c ) + return 0; + + Assert( rowPos >= 0 ); + + if ( IsLayoutDirty_CharWidth() ) + { + m_iCached_Charwidth = surface()->GetCharacterWidth( _font, ' ' ); + MakeLayoutClean_CharWidth(); + } + + if ( c == L'\t' ) + { + int pixelRight = m_iInteriorWidth - rowPos; + pixelRight = clamp( pixelRight / m_iCached_Charwidth, 1, 4 ); + int dynSize = ( 4 - ( (rowPos/m_iCached_Charwidth) % 4 ) ); + + if ( pixelRight < 4 ) + return m_iCached_Charwidth * min( pixelRight, dynSize ); + else + return m_iCached_Charwidth * dynSize; + } + + return m_iCached_Charwidth; +} + +const int _smartRow::GetAutoCRWidth() +{ + return GetCharWidth( L' ' ) * 2; +} + +int _smartRow::InsertChar( const wchar_t c, int pos, bool bFast, bool bSmartTabs ) +{ + if ( IsLocked() ) + return 0; + + Assert( c != L'\r' && c != L'\n' ); + + if ( pos < hText.Count() ) + hText.InsertBefore( pos, c ); + else + hText.AddToTail( c ); + + int curMoved = 0; + + if ( bSmartTabs && c == 9 ) + { + //KillLineBreaks(); + int parserPos = clamp( pos - 1, 0, hText.Count() - 1 ); + + while ( parserPos >= 0 && + ( IS_SPACE( hText[ parserPos ] ) || !hText[ parserPos ] ) ) + { + parserPos--; + } + + parserPos++; + ConvertSpaceToTab( parserPos ); + + /* + int numSpaces = 0; + int parserPos = clamp( pos - 1, 0, hText.Count() - 1 ); + + while ( parserPos >= 0 && + ( IS_SPACE( hText[ parserPos ] ) || !hText[ parserPos ] ) ) + { + if ( hText[ parserPos ] == ' ' ) + { + hText.Remove( parserPos ); + numSpaces++; + curMoved--; + } + + if ( numSpaces >= 4 ) + { + numSpaces = 0; + hText.InsertBefore( parserPos, L'\t' ); + curMoved++; + } + + parserPos--; + } + */ + } + + if ( !bFast ) + OnTextChanged(); + + return curMoved; +} +void _smartRow::InsertString( const wchar_t *sz, int pos, int iLength, bool bFast ) +{ + if ( IsLocked() ) + return; + + Assert( sz != NULL ); + +#if DEBUG + for ( int i = 0; ( (iLength >= 0) ? (sz && i < iLength) : (sz && sz[i]) ); i++ ) + Assert( sz[i] != L'\n' && sz[i] != L'\r' ); +#endif + + if ( pos < 0 ) + pos = hText.Count(); + + if ( iLength >= 0 ) + { + if ( pos < hText.Count() ) + hText.InsertMultipleBefore( pos, iLength, sz ); + else + hText.AddMultipleToTail( iLength, sz ); + + if ( !bFast ) + OnTextChanged(); + + return; + } + +#if DEBUG + for ( unsigned int i = 0; i < wcslen( sz ); i++ ) + Assert( sz[i] != L'\n' ); +#endif + + for ( unsigned int i = 0; i < wcslen( sz ); i++ ) + { + InsertChar( sz[i], pos, true ); + pos++; // = hText.Count(); + } + + if ( !bFast ) + OnTextChanged(); +} +void _smartRow::InsertString( const char *sz, int pos, int iLength, bool bFast ) +{ + int len = Q_strlen( sz ) + 1; + wchar_t *pWStr = new wchar_t[ len ]; + Q_UTF8ToUnicode( sz, pWStr, len * sizeof(wchar_t) ); + InsertString( pWStr, pos, iLength, bFast ); + delete [] pWStr; +} + +void _smartRow::PerformShiftTab( bool bIndent ) +{ + if ( IsLocked() ) + return; + + ConvertSpaceToTab(); + + if ( bIndent ) + InsertChar( L'\t', 0 ); + else if ( hText.Count() && hText[ 0 ] == L'\t' ) + { + hText.Remove( 0 ); + OnTextChanged(); + } +} + +void _smartRow::ConvertSpaceToTab( int start ) +{ + bool bEarlyOut = true; + int SingleCWidth = GetCharWidth( L' ' ); + //int end = start; + + // ( 4 - ( (rowPos/m_iCached_Charwidth) % 4 ) ) + + for ( int i = start; i < hText.Count(); i++ ) + { + if ( !hText[ i ] ) + continue; + + if ( hText[ i ] == L' ' ) + bEarlyOut = false; + else if ( !IS_SPACE( hText[ i ] ) ) + break; + } + + __ROWCALC_INTRO( hText.Count() ); + //if ( hText[i] && !IS_SPACE( hText[i] ) ) + // break; + //else if ( hText[i] == L' ' ) + // bEarlyOut = false; + __ROWCALC_SPLIT_INTRO(); + __ROWCALC_SPLIT_OUTRO(); + if ( i >= start ) + break; + __ROWCALC_OUTRO(); + + if ( bEarlyOut ) + return; + + int startDist = cur_x; + + for ( int i = start; i < hText.Count(); i++ ) + { + if ( !hText[i] ) + continue; + + if ( !IS_SPACE( hText[i] ) ) + break; + + int cur_width = SingleCWidth; + + if ( hText[i] == '\t' ) + cur_width *= ( 4 - ( (cur_x/cur_width) % 4 ) ); + + cur_x += cur_width; + } + + cur_x -= startDist; + int slotsOccupied = cur_x / SingleCWidth; + + for ( int i = start; i < hText.Count(); i++ ) + { + if ( !hText[ i ] || IS_SPACE( hText[ i ] ) ) + { + hText.Remove( i ); + i--; + } + else + break; + } + + int tgTabs = slotsOccupied / 4 + ( (slotsOccupied % 4 != 0) ? 1 : 0 ); + + for ( int i = 0; i < tgTabs; i++ ) + InsertChar( L'\t', start ); +} +void _smartRow::RemoveLeadingSpaces() +{ + ConvertSpaceToTab(); + + while ( hText.Count() ) + { + if ( hText[0] == L'\t' ) + hText.Remove( 0 ); + else + break; + } +} +wchar_t *_smartRow::CopyLeadingSpaces() +{ + int x1 = -1; + + for ( int i = 0; i < hText.Count(); i++ ) + { + if ( !hText[ i ] ) + continue; + + if ( !IS_SPACE( hText[ i ] ) ) + break; + + x1++; + } + + if ( x1 < 0 ) + return NULL; + + return ReadInterval( 0, x1, false, true ); +} + +wchar_t *_smartRow::ReadInterval( int start, int end, bool bAllowLF, bool bIgnoreLF ) +{ + if ( hText.Count() < 1 ) + { + wchar_t *ret = NULL; + if ( bAllowLF ) + { + ret = new wchar_t[ 2 ]; + ret[0] = L'\n'; + ret[1] = L'\0'; + } + return ret; + } + + if ( start < 0 ) + start = 0; + if ( end < 0 ) + end = hText.Count(); + + //bool bEndLF = bAllowCR; + + //if ( bEndLF && + // ( ( start != 0 || end != hText.Count() ) ) + // ) + // bEndLF = false; + + if ( bIgnoreLF ) + { + for ( int i = 0; i < hText.Count() && i < start; i++ ) + { + if ( !hText[i] ) + { + start++; + end++; + } + } + } + + //Assert( start <= end ); + + CUtlVector< wchar_t >internalText; + + for ( int i = start; i <= end; i++ ) + { + if ( i >= hText.Count() ) + { + if ( bAllowLF ) + { + internalText.AddToTail( L'\n' ); + break; + } + } + else if ( !hText[i] ) + { + if ( bIgnoreLF ) + end++; + } + else // if ( hText[i] ) + //else + internalText.AddToTail( hText[i] ); + } + + //Assert( end <= hText.Count() ); + + //if ( bEndLF ) + // internalText.AddToTail( L'\n' ); + + internalText.AddToTail( L'\0' ); + + Assert( internalText.Count() ); + + wchar_t *out = new wchar_t[ internalText.Count() ]; + Q_memset( out, 0, sizeof( wchar_t ) / sizeof( char ) * internalText.Count() ); + + for ( int i = 0; i < internalText.Count(); i++ ) + { + out[ i ] = internalText[ i ]; + } + + internalText.Purge(); + + return out; +} +void _smartRow::DeleteInterval( int start, int end, bool bFast ) +{ + if ( IsLocked() ) + return; + + if ( end < 0 ) + end = hText.Count() - 1; + + while( start < hText.Count() && start <= end ) + { + hText.Remove( start ); + end--; + } + + if ( !bFast ) + OnTextChanged(); +} +void _smartRow::DeleteChar( int x, bool bAfter, bool bFast ) +{ + if ( IsLocked() ) + return; + + if ( hText.Count() < 1 ) + return; + + x = clamp( x, bAfter ? 0 : 1, hText.Count() - ( bAfter ? 1 : 0 ) ); + + if ( !bAfter ) + x--; + + Assert( x >= 0 && x < hText.Count() ); + + hText.Remove( x ); + + if ( !bFast ) + OnTextChanged(); +} +_smartRow *_smartRow::Split( int pos ) +{ + if ( IsLocked() ) + return NULL; + + _smartRow *row = new _smartRow( _font, m_iInteriorWidth, m_iInsetWidth ); + + if ( pos < hText.Count() ) + { + wchar_t *text = ReadInterval( pos, -1 ); + row->InsertString( text ); + delete [] text; + + + DeleteInterval( pos, -1 ); + } + + return row; +} + +void _smartRow::OnTextChanged( bool bOnlyLayout ) +{ + KillLineBreaks(); + + UpdateLinebreaks(); + + MakeLayoutDirty(); + + if ( !bOnlyLayout ) + MakeTextDirty(); +} + +bool _smartRow::IsTextDirty() +{ + return m_bDirty; +} +void _smartRow::MakeTextDirty() +{ + m_bDirty = true; +} +void _smartRow::MakeTextClean( const bool bStringLiterals, const bool bBrackets, const bool bHLSL ) +{ + if ( !m_bDirty ) + return; + + DoSyntaxHighlighting(bStringLiterals, bBrackets, bHLSL); + + m_bDirty = false; +} + +bool _smartRow::IsLayoutDirty_CharWidth() +{ + return m_bDirty_CharWidth; +} +bool _smartRow::IsLayoutDirty_Renderlen() +{ + return m_bDirty_Renderlen; +} +void _smartRow::MakeLayoutDirty() +{ + m_bDirty_CharWidth = true; + m_bDirty_Renderlen = true; +} +void _smartRow::MakeLayoutClean_CharWidth() +{ + m_bDirty_CharWidth = false; +} +void _smartRow::MakeLayoutClean_Renderlen() +{ + m_bDirty_Renderlen = false; +} + +bool _smartRow::IsHighlightRefDirty() +{ + return m_bDirty_HighlightRef; +} +void _smartRow::MakeHighlightRefDirty() +{ + m_bDirty_HighlightRef = true; +} +void _smartRow::MakeHighlightRefClean() +{ + m_bDirty_HighlightRef = false; + + if ( m_pszHighlightRef ) + { + for (int i = 0; i < hText.Count(); i++) + { + const wchar_t *pBase = hText.Base() + i; + const wchar_t *pRead = m_pszHighlightRef; + int steps = 0; + + while ( *pRead && *pBase ) + { + if ( *pRead != *pBase ) + { + pRead = NULL; + break; + } + + pRead++; + pBase++; + steps++; + } + + int maxStep = i + steps; + + if ( pRead != NULL && steps > 0 && + ( i == 0 || !IS_CHAR(hText[i-1])&&!IS_NUMERICAL(hText[i-1])) && + (maxStep >= hText.Count() || !IS_CHAR(hText[maxStep])&&!IS_NUMERICAL(hText[maxStep]) ) + ) + { + text_cursor cmin( i, 0 ); + text_cursor cmax( i + steps, 0 ); + + ToRealCursor( cmin ); + ToRealCursor( cmax ); + + _inlineFormat *pFormat = new _inlineFormat(); + pFormat->start = cmin.x; + pFormat->end = cmax.x; + pFormat->bOverride_bg = true; + pFormat->col_bg.SetColor( 80, 65, 40, 255 ); + hUserHighlight.AddToHead( pFormat ); + + i += steps - 1; + } + } + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmartrow.h b/sp/src/shadereditor/properties/smarttext/vsmartrow.h new file mode 100644 index 00000000..bca5ef0e --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmartrow.h @@ -0,0 +1,199 @@ +#ifndef C_SMART_ROW_H +#define C_SMART_ROW_H + +#include "vSheets.h" +#include + +//#define ST_TEXT_INSET 48 + +#define DEFAULT_ROW_CAPACITY 0 +#define DEFAULT_ROW_GROWSIZE 64 + +#define ST_COL_SPACING Color( 32, 128, 196, 255 ) +#define ST_COL_SELECTION_BG Color( 255, 128, 40, 255 ) +#define ST_COL_SELECTION_FG Color( 16, 16, 16, 255 ) +#define ST_COL_CMT_FG Color( 64, 64, 64, 255 ) +#define ST_COL_HIGHLIGHT_BRACKET Color( 164, 32, 8, 255 ) + +#define CR_HACK_CHAR 1 // '\r' + +struct text_cursor +{ +public: + text_cursor() + { + }; + + text_cursor( int x0, int y0 ) + { + x = x0; + y = y0; + }; + + int x; + int y; + + inline bool operator> ( const text_cursor &o ) const + { return (*this).y > o.y || (*this).y == o.y && (*this).x > o.x; }; + inline bool operator>= ( const text_cursor &o ) const + { return *this > o || *this == o; }; + inline bool operator< ( const text_cursor &o ) const + { return (*this).y < o.y || (*this).y == o.y && (*this).x < o.x; }; + inline bool operator<= ( const text_cursor &o ) const + { return *this < o || *this == o; } + inline bool operator== ( const text_cursor &o ) const + { return (*this).x == o.x && (*this).y == o.y; }; + inline bool operator!= ( const text_cursor &o ) const + { return !( (*this) == o ); }; +}; + + +struct _inlineFormat +{ +public: + _inlineFormat(); + + bool ShouldOverride( int pos ); + + // NOT inclusive + int start; + int end; + + bool bOverride_fg; + bool bOverride_bg; + Color col_fg; + Color col_bg; + + bool bCRBlock; +}; + +struct _cmtCtrl +{ +public: + _cmtCtrl(); + _cmtCtrl( int row, int x0, int x1 ); + bool IsCommented( int x, int y ); + + int _y; + // inclusive + int _x0, _x1; +}; + + +struct _smartRow +{ +public: + _smartRow( HFont font, const int &w, const int &inset ); + ~_smartRow(); + _smartRow( const _smartRow &o ); + + void SetFont( HFont f ); + int InsertChar( const wchar_t c, int pos, bool bFast = false, bool bSmartTabs = false ); + void InsertString( const wchar_t *sz, int pos = -1, int iLength = -1, bool bFast = false ); + void InsertString( const char *sz, int pos = -1, int iLength = -1, bool bFast = false ); + + void PerformShiftTab( bool bIndent = true ); + void ConvertSpaceToTab( int start = 0 ); + void RemoveLeadingSpaces(); + wchar_t *CopyLeadingSpaces(); + + void SetInteriorWidth( const int &w, const int &inset ); + int GetInteriorWidth(); + void DrawRow( const int &x, int &y, + const Color &col_fg ); + + bool IsDynamicSpacingEnabled(); + void SetDynamicSpacingEnabled( bool bEnabled ); + +private: + int GetRenderNumRows_Internal( int cursor_x, bool bPartial ); + + bool m_bDynamicSpacing_Enabled; + +public: + int GetRenderNumRows( int cursor_x = -1 ); + int GetRenderHeight(); + int GetCharWidth( wchar_t c, int rowPos = 0 ); + const int GetAutoCRWidth(); + void RelativeRowCursorToPanel( const int &cursor_x, int &movex, int &movey ); + + int GetWordLeft( int pos ); + int GetWordRight( int pos, bool bPreprocTest = false, bool bStringTest = false ); + int GetTextLen( bool bIgnoreLineBreaks = false ); + void ToRealCursor( text_cursor &c ); + void ToVirtualCursor( text_cursor &c ); + bool HasLinebreakAtCursor( const text_cursor &c ); + + int PanelToCursorCalcX( int virtualRow, int pixelx ); + + void OnTextChanged( bool bOnlyLayout = false ); + void KillLineBreaks(); + void UpdateLinebreaks(); + + // inclusive + wchar_t *ReadInterval( int start = -1, int end = -1, bool bAllowLF = false, bool bIgnoreLF = false ); + void DeleteInterval( int start = 0, int end = -1, bool bFast = false ); + void DeleteChar( int x, bool bAfter = false, bool bFast = false ); + _smartRow *Split( int pos ); + CUtlVector< wchar_t > &Read(){ return hText; }; + + void ClearHighlightFormats(); + void AddHighlightFormat( _inlineFormat *format ); + void ClearTopFormats(); + void AddTopFormat( _inlineFormat *format ); + + void DoSyntaxHighlighting( const bool bStringLiterals, const bool bBrackets, const bool bHLSL ); + + bool IsTextDirty(); + void MakeTextDirty(); + void MakeTextClean( const bool bStringLiterals, const bool bBrackets, const bool bHLSL ); + + bool IsLayoutDirty_CharWidth(); + bool IsLayoutDirty_Renderlen(); + void MakeLayoutDirty(); + void MakeLayoutClean_CharWidth(); + void MakeLayoutClean_Renderlen(); + + bool IsHighlightRefDirty(); + void MakeHighlightRefDirty(); + void MakeHighlightRefClean(); + void SetHighlightRef( wchar_t *pszRef ); + + void SetLocked( bool bLocked ); + bool IsLocked(); + void SetDeletable( bool bDeletable ); + bool IsDeletable(); + +private: + + bool ShouldSplit( int curpixelpos, int localRowStart, int localRowCur ); + bool IsWordConcat( const wchar_t ref, const wchar_t test, bool bLoose, bool bIsValue ); + + HFont _font; + int m_iInteriorWidth; + int m_iInsetWidth; + + CUtlVector< wchar_t > hText; + + CUtlVector< _inlineFormat* > hSyntaxFormat; + CUtlVector< _inlineFormat* > hUserHighlight; + CUtlVector< _inlineFormat* > hTopHighlight; + + + int m_iTex_Arrow; + int m_iTex_CR; + + wchar_t *m_pszHighlightRef; + + int m_iCached_Charwidth; + int m_iCached_Renderlen; + bool m_bDirty; + bool m_bDirty_CharWidth; + bool m_bDirty_Renderlen; + bool m_bDirty_HighlightRef; + + bool m_bLocked; + bool m_bDeletable; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmarttext.cpp b/sp/src/shadereditor/properties/smarttext/vsmarttext.cpp new file mode 100644 index 00000000..3b1809ac --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmarttext.cpp @@ -0,0 +1,3686 @@ + +#include "cbase.h" +#include "vSmartText.h" +#include "vSmartObject.h" +#include "vSmartObjectList.h" +#include "vSmartAutocomplete.h" +#include "vSmartTooltip.h" +#include "vgui_controls/menuitem.h" +#include "cRegex.h" +#include + +//#define UCHAR_MDOT L'\x00B7' +//#define UCHAR_ARROW_R L'\x2192' +//#define UCHAR_AUTO_CR L'\x2514' + +HFont *CSmartText::m_pFontRef = NULL; + +enum +{ + PARSERREQUEST_INVALID = 0, + + PARSERREQUEST_PS = ( 1 << 0 ), + PARSERREQUEST_VS = ( 1 << 1 ), + PARSERREQUEST_USER = ( 1 << 2 ), + + PARSERREQUEST_STOPTHREAD = ( 1 << 31 ), + PARSERREQUEST_, +}; + +struct ParserThreadCmd_Request +{ + ParserThreadCmd_Request(){ + pszMem = NULL; + pParentDatabase = NULL; + }; + + //CSmartText *pTarget; + int flags; + wchar_t *pszMem; + CSmartObjectList *pParentDatabase; +}; +struct ParserThreadCmd_Response +{ + ParserThreadCmd_Response(){}; + //CSmartText *pTarget; + CSmartObjectList *pList; + int flags; +}; + +class CParserThread : public CThread +{ +public: + int Run(); + + CMessageQueue< ParserThreadCmd_Request* > m_QueueParse; + + // take ownership of mem + static void RequestUpdate( /*CSmartText *target,*/ int flags = PARSERREQUEST_PS | PARSERREQUEST_VS, wchar_t *pszStream = NULL, CSmartObjectList *pParentDB = NULL ); +}; + +class CParserHelper : public CAutoGameSystemPerFrame +{ +public: + CParserHelper(); + ~CParserHelper(){ + delete pLastList; + delete pLiveList; + }; + + CMessageQueue< ParserThreadCmd_Response* > m_QueueResponse; + + void Update( float frametime ); + void Shutdown(); + + bool HasDatabaseWaiting(){ return pLastList != NULL; }; + bool HasLiveDatabaseWaiting(){ return pLiveList != NULL; }; + CSmartObjectList *ObtainDatabase(){ + Assert( pLastList != NULL ); + CSmartObjectList *tmp = pLastList; + pLastList = NULL; + return tmp; + }; + CSmartObjectList *ObtainLiveDatabase(){ + Assert( pLiveList != NULL ); + CSmartObjectList *tmp = pLiveList; + pLiveList = NULL; + return tmp; + }; + +private: + CSmartObjectList *pLastList; + CSmartObjectList *pLiveList; +}; + +static CParserThread ParserThread; +static CParserHelper ParserHelper; + +int CParserThread::Run() +{ + for ( bool bFinished = false; !bFinished ;) + { + while ( m_QueueParse.MessageWaiting() ) + { + ParserThreadCmd_Request *pMsg; + m_QueueParse.WaitMessage( &pMsg ); + + bool bExit = pMsg->flags == PARSERREQUEST_STOPTHREAD; + + if ( bExit ) + { + bFinished = true; + + Assert( !pMsg->pszMem ); + Assert( !pMsg->pParentDatabase ); + + delete pMsg; + break; + } +#if ENABLE_AUTOCOMP_PARSER + else + { + //while (true) + //{ + char *pStream = NULL; + int len = 0; + + if ( pMsg->pszMem ) + { + len = Q_wcslen( pMsg->pszMem ) + 1; + if ( len > 1 ) + pStream = new char[ len ]; + } + + CSmartObjectList *l = new CSmartObjectList(); + + CUtlVector< char* > hIncludes; + + if ( pStream != NULL ) + { + CUtlBuffer buf( pStream, len ); + Q_UnicodeToUTF8( pMsg->pszMem, pStream, len ); + + CSmartObjectList *pRef = pMsg->pParentDatabase ? pMsg->pParentDatabase : l; + + if ( pRef != l ) + pRef->SetDatabaseCopy( l ); + + pRef->ParseCode_Stream( buf, true, NULL, IDENT_LIVE_CODE, Q_strlen(pStream) - 1 ); + + buf.Clear(); + delete [] pStream; + } + else if ( pMsg->flags & PARSERREQUEST_PS || pMsg->flags & PARSERREQUEST_VS ) + { + l->ParseCode( "intrinsic.h", true, &hIncludes ); + l->BuildIntrinsicDatatypes(); + + if ( pMsg->flags & PARSERREQUEST_VS ) + { + l->ParseCode( "common_vs_fxc.h", true, &hIncludes ); + } + if ( pMsg->flags & PARSERREQUEST_PS ) + { + l->ParseCode( "common_ps_fxc.h", true, &hIncludes ); + l->ParseCode( "common_vertexlitgeneric_dx9.h", true, &hIncludes ); + l->ParseCode( "common_lightmappedgeneric_fxc.h", true, &hIncludes ); + l->ParseCode( "common_flashlight_fxc.h", true, &hIncludes ); + l->ParseCode( "common_parallax.h", true, &hIncludes ); + } + } + else + Assert( 0 ); + + for ( int i = 0; i < hIncludes.Count(); i++ ) + delete [] hIncludes[ i ]; + + delete [] pMsg->pszMem; + delete pMsg->pParentDatabase; + + hIncludes.Purge(); + //} + + ParserThreadCmd_Response *pResponse = new ParserThreadCmd_Response(); + //pResponse->pTarget = pMsg->pTarget; + pResponse->pList = l; + pResponse->flags = pMsg->flags; + //pResponse->pList = NULL; + ParserHelper.m_QueueResponse.QueueMessage( pResponse ); + //} + } +#endif + + delete pMsg; + } + + //Yield(); + Sleep( 1 ); + } + + return 0; +} + +void CParserThread::RequestUpdate( /*CSmartText *target,*/ int flags, wchar_t *pszStream, CSmartObjectList *pParentDB ) +{ + ParserThreadCmd_Request *pR = new ParserThreadCmd_Request(); + pR->flags = flags; + pR->pszMem = pszStream; + pR->pParentDatabase = pParentDB; + //pR->pTarget = target; + + ParserThread.m_QueueParse.QueueMessage( pR ); + + if ( !ParserThread.IsAlive() ) + ParserThread.Start(); + + // +} + + +CParserHelper::CParserHelper() : CAutoGameSystemPerFrame( "auto_parser_helper" ) +{ + pLastList = NULL; + pLiveList = NULL; +} + +void CParserHelper::Update( float frametime ) +{ + while ( m_QueueResponse.MessageWaiting() ) + { + ParserThreadCmd_Response *pMsg; + m_QueueResponse.WaitMessage( &pMsg ); + + if ( pMsg->flags & PARSERREQUEST_USER ) + { + delete pLiveList; + pLiveList = pMsg->pList; + } + else + { + delete pLastList; + pLastList = pMsg->pList; + } + + delete pMsg; + } +} + +void CParserHelper::Shutdown() +{ + if ( ParserThread.IsAlive() ) + { + ParserThreadCmd_Request *pR = new ParserThreadCmd_Request(); + pR->flags = PARSERREQUEST_STOPTHREAD; + ParserThread.m_QueueParse.QueueMessage( pR ); + + VCRHook_WaitForSingleObject( ParserThread.GetThreadHandle(), TT_INFINITE ); + } +} + +static __handleFontCache __hfcInstance; +__handleFontCache *GetFontCacheHandle() +{ + return &__hfcInstance; +} + +__handleFontCache::__handleFontCache() +{ + CSmartText::m_pFontRef = NULL; + m_iTooltipFont = 0; + m_bFontsReady = false; +} +__handleFontCache::~__handleFontCache() +{ + delete [] CSmartText::m_pFontRef; +} +void __handleFontCache::AllocFonts() +{ + if ( CSmartText::m_pFontRef != NULL && m_bFontsReady ) + return; + + numFonts = ( fSizeMax() - fSizeMin() ) / fStepSize() + 1; + + if ( CSmartText::m_pFontRef == NULL ) + { + CSmartText::m_pFontRef = new HFont[ numFonts ]; + Q_memset( CSmartText::m_pFontRef, 0, sizeof( unsigned long ) * numFonts ); + } + + int iError = 0; + + for ( int i = 0; i < numFonts; i++ ) + iError = max( iError, CreateMonospaced( CSmartText::m_pFontRef[ i ], fSizeMin() + fStepSize() * i ) ); + + iError = max( iError, CreateMonospaced( m_iTooltipFont, 14 ) ); + + if ( iError == 2 ) + Warning( "Unable to locate fonts: 'Consolas' (not shipped), 'monofur' (shipped)!\nFont rendering will be compromised.\n" ); + else if ( iError ) + Warning( "Unable to locate font: 'Consolas' (not shipped)!\nFalling back to 'monofur'.\n" ); + + m_bFontsReady = true; +} +void __handleFontCache::InvalidateFonts() +{ + m_bFontsReady = false; +} +int __handleFontCache::CreateMonospaced( HFont &font, const int size ) +{ + if ( font == 0 ) + font = surface()->CreateFont(); + + int flags = +#ifndef SHADER_EDITOR_DLL_SWARM + ISurface::FONTFLAG_CUSTOM | ISurface::FONTFLAG_ANTIALIAS +#else + FONTFLAG_CUSTOM | FONTFLAG_ANTIALIAS +#endif + ; + + if ( !surface()->SetFontGlyphSet( font, "Consolas", size, 0, 0, 0, flags ) ) + { + if ( !surface()->SetFontGlyphSet( font, "monofur", size, 0, 0, 0, flags ) ) + return 2; + else return 1; + } + return 0; +} +HFont __handleFontCache::GetFont( int realSize ) +{ + AllocFonts(); + + Assert( realSize >= fSizeMin() && realSize <= fSizeMax() ); + + realSize -= fSizeMin(); + realSize /= fStepSize(); + + Assert( realSize >= 0 && realSize < numFonts ); + + return CSmartText::m_pFontRef[ realSize ]; +} +HFont __handleFontCache::GetTooltipFont() +{ + AllocFonts(); + + return m_iTooltipFont; +} + +HHISTORYIDX CSmartText::sm_iHistoryIndex = 0; + +CSmartText::CSmartText( Panel *parent, const char *name, CodeEditMode_t mode ) : BaseClass( parent, name ) +{ + this->mode = mode; + + InitColors(); + __hfcInstance.AllocFonts(); + + //if ( m_pFontRef == NULL ) + // m_pFontRef = new HFont( surface()->CreateFont() ); + m_bEnableLiveParse = true; + m_bEnableAC = true; + m_bEnableSyntaxHighlight = true; + + //m_Font = *m_pFontRef; + hRows.SetGrowSize( 64 ); + + m_iFontSize = ::__hfcInstance.fSizeDefault(); + m_iTextInset = 0; + m_iEnvInfo = 0; + m_iActiveHistoryIndex = 0; + m_bTopHighlightLock = false; + m_bTopHighlightOnTyped = false; + m_bTopFormatsDirty = false; + + m_pGlobalDatabase = NULL; + m_pACMenu = NULL; + m_pFuncTooltip = NULL; + m_pHoverTooltip = NULL; + m_bAllowHoverTooltip = false; + + m_pszLastSelectedWord = NULL; + + m_lLastCursorMoved = 0.0; + + m_bCodeDirty = false; + m_bHistoryDirty = false; + m_flLastCodeParse = 0; + + UpdateFont(); + + cur.x = cur.y = 0; + + m_iXCursorHistory = 0; + scrollDelay = 0; + m_bIsSelecting = false; + m_bIsRowSelecting = false; + m_iBlinkTime = 0; + + //input()->OnChangeIMEByHandle( input()->GetEnglishIMEHandle() ); + SetupVguiTex( m_iTex_Lock, "shadereditor/lock" ); + + m_pScrollBar_V = new ScrollBar( this, "", true ); + m_pScrollBar_V->AddActionSignalTarget( this ); + m_pScrollBar_V->SetValue(0); + + InsertRow(); + + OnLayoutUpdated(); + Selection_Reset(); + + SetDropEnabled( true ); + + //ParserThread.RequestUpdate(); + + MakeHistoryDirty(); +} + +CSmartText::~CSmartText() +{ + FlushHistory(); + delete m_pGlobalDatabase; + KillCmtList(); + hRows.PurgeAndDeleteElements(); + DestroyACMenu(); + delete [] m_pszLastSelectedWord; +} + +void CSmartText::SetLiveParseEnabled( bool bEnabled ) +{ + m_bEnableLiveParse = bEnabled; +} +void CSmartText::SetACEnabled( bool bEnabled ) +{ + m_bEnableAC = bEnabled; +} +void CSmartText::SetSyntaxHighlightEnabled( bool bEnabled ) +{ + m_bEnableSyntaxHighlight = bEnabled; +} + +bool CSmartText::IsLiveParseEnabled() +{ + return m_bEnableLiveParse; +} +bool CSmartText::IsACEnabled() +{ + return m_bEnableAC; +} +bool CSmartText::IsSyntaxHighlightEnabled() +{ + return m_bEnableSyntaxHighlight; +} + +const bool CSmartText::IsHLSL() +{ + return mode == CODEEDITMODE_HLSL; +} +const bool CSmartText::IsVMT() +{ + return mode == CODEEDITMODE_VMT; +} + +void CSmartText::DoFullParserUpdate( int hlslhierachy_flags ) +{ + int flags = 0; + + if ( hlslhierachy_flags & HLSLHIERACHY_PS ) + flags |= PARSERREQUEST_PS; + + if ( hlslhierachy_flags & HLSLHIERACHY_VS ) + flags |= PARSERREQUEST_VS; + + if ( !flags ) + flags |= PARSERREQUEST_PS | PARSERREQUEST_VS; + + ParserThread.RequestUpdate( flags ); +} + +void CSmartText::SetEnvInfo( int flags ) +{ + m_iEnvInfo = flags; +} + +void CSmartText::UpdateFont() +{ + //m_Font = surface()->CreateFont(); + m_Font = __hfcInstance.GetFont( m_iFontSize ); +} + +void CSmartText::ChangeFontSize( int delta ) +{ + m_iFontSize = clamp( m_iFontSize + delta * __hfcInstance.fStepSize(), + __hfcInstance.fSizeMin(), + __hfcInstance.fSizeMax() ); + UpdateFont(); + OnLayoutUpdated(); +} +void CSmartText::ApplySchemeSettings( IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + SetPaintBackgroundEnabled( true ); + SetKeyBoardInputEnabled( true ); + SetMouseInputEnabled( true ); + + InitColors(); + _col_SelectionBG = pScheme->GetColor( "SmartText.SelectionBG", _col_SelectionBG ); + _col_SelectionFG = pScheme->GetColor( "SmartText.SelectionFG", _col_SelectionFG ); + + SetBorder( pScheme->GetBorder("ButtonDepressedBorder") ); + + UpdateScrollbar(); +} + +void CSmartText::InitColors() +{ + _col_SelectionBG = ST_COL_SELECTION_BG; + _col_SelectionFG = ST_COL_SELECTION_FG; +} + +void CSmartText::OnSizeChanged( int wide, int tall ) +{ + DestroyACMenu(); + + //BaseClass::OnSizeChanged( wide, tall ); + InvalidateLayout(true); + + OnLayoutUpdated(); +} +void CSmartText::OnMoved() +{ + DestroyACMenu(); +} +void CSmartText::OnLayoutUpdated() +{ + int lastRealRow, lastVRow; + CalcCurrentRenderRow( lastRealRow, lastVRow ); + + m_iTextInset = surface()->GetCharacterWidth( m_Font, ' ' ) * 6; + + int rowwide = CalcInteriorWidth(); + int iOffset = ( hRows.Count() && hRows[ 0 ]->GetInteriorWidth() > rowwide ) ? 0 : 1; + + int oldVRow = hRows[ cur.y ]->GetRenderNumRows( cur.x - iOffset ); + for ( int i = 0; i < hRows.Count(); i++ ) + { + hRows[ i ]->SetFont( m_Font ); + hRows[i]->SetInteriorWidth( rowwide, m_iTextInset ); + } + int newVRow = hRows[ cur.y ]->GetRenderNumRows( cur.x - iOffset ); + + cur.x += newVRow - oldVRow; + + OnTextChanged( lastRealRow ); +} + +int CSmartText::CalcInteriorWidth() +{ + int sx,sy,scrollbar_sx,scrollbar_sy; + GetSize( sx, sy ); + m_pScrollBar_V->GetSize( scrollbar_sx, scrollbar_sy ); + return sx - scrollbar_sx - m_iTextInset; +} + +void CSmartText::UpdateScrollbar( int lastRealRow ) +{ + int sx, sy; + GetSize( sx, sy ); + + m_pScrollBar_V->SetSize( 20, sy ); + m_pScrollBar_V->SetPos( sx - 20, 0 ); + + //int iLastValue = m_pScrollBar_V->GetValue(); + int iNewValue = m_pScrollBar_V->GetValue(); + const bool bPerformLayoutTest = lastRealRow >= 0; + + int rows = 0; + for ( int i = 0; i < hRows.Count(); i++ ) + { + if ( bPerformLayoutTest && lastRealRow == i ) + iNewValue = rows; + + rows += hRows[i]->GetRenderNumRows(); + } + + //if ( m_pScrollBar_V->GetValue() > rows ) + // m_pScrollBar_V->SetValue( rows ); + + int iBloat = max( 6, (int)( rows * 0.1f ) ); + m_pScrollBar_V->SetRange( 0, rows + iBloat ); + m_pScrollBar_V->SetRangeWindow( 1 + iBloat ); + m_pScrollBar_V->InvalidateLayout(true); + + if ( bPerformLayoutTest ) + m_pScrollBar_V->SetValue( iNewValue ); +} + +void CSmartText::Paint() +{ + BaseClass::Paint(); + + int scrollbar_sx, scrollbar_sy; + m_pScrollBar_V->GetSize( scrollbar_sx, scrollbar_sy ); + + int sx, sy; + GetSize( sx, sy ); + + int virtualRow, realRow; + CalcCurrentRenderRow( realRow, virtualRow ); + + const int ifonttall = FontTall(); + int xpos = m_iTextInset; //sx - scrollbar_sx - rowwide; + int ypos = virtualRow * -ifonttall; + int cWidth = surface()->GetCharacterWidth( m_Font, ' ' ); + const int iLockInset = cWidth * 0.5f; + + Color col_fg( 230, 230, 232, 255 ); + + int linex = xpos - (int)( m_iTextInset * 0.05f ); + + surface()->DrawSetColor( Color( 24, 24, 24, 255 ) ); + surface()->DrawFilledRect( 0, 0, linex, sy ); + + surface()->DrawSetColor( col_fg ); + surface()->DrawFilledRect( linex, 0, linex + 1, sy ); + + surface()->DrawSetTextFont( m_Font ); + + for ( int i = realRow; i < hRows.Count(); i++ ) + { + int rowNum = i + 1; + int numPos = 1 + cWidth * 5; + + /* + for ( int insCalc = 1000; insCalc > 0; insCalc /= 10 ) + if ( rowNum / insCalc > 0 ) + break; + else + numPos += cWidth; + */ + for ( int insCalc = 1; ( rowNum / insCalc ) > 0; insCalc *= 10 ) + numPos -= cWidth; + + if ( i <= 99999 ) + { + char numStrC[6]; + wchar_t numStrLC[6]; + Q_snprintf( numStrC, sizeof( numStrC ), "%i", rowNum ); + Q_UTF8ToUnicode( numStrC, numStrLC, sizeof( numStrLC ) ); + + surface()->DrawSetTextPos( numPos, ypos ); + surface()->DrawSetTextColor( ST_COL_SPACING ); + surface()->DrawPrintText( numStrLC, Q_strlen( numStrC ) ); + } + + if ( hRows[ i ]->IsTextDirty() ) //&& IsSyntaxHighlightEnabled() ) + hRows[ i ]->MakeTextClean( true, true, IsSyntaxHighlightEnabled() ); + + + if ( hRows[ i ]->IsLocked() ) + { + surface()->DrawSetColor( Color( 60, 65, 68, 255 ) ); + surface()->DrawFilledRect( xpos, ypos, sx - scrollbar_sx, + ypos + hRows[ i ]->GetRenderHeight() ); + + surface()->DrawSetTexture( m_iTex_Lock ); + surface()->DrawSetColor( Color( 220, 200, 10, 255 ) ); + + surface()->DrawTexturedRect( 0, ypos + iLockInset, + ifonttall - iLockInset * 2, ypos + ifonttall - iLockInset ); + } + + hRows[ i ]->DrawRow( xpos, ypos, col_fg ); + + if ( ypos > sy ) + break; + } + + long blinkDelta = system()->GetTimeMillis() - m_iBlinkTime; + + if ( (blinkDelta / 300) % 2 == 0 ) + { + surface()->DrawSetColor( col_fg ); + + int cx, cy; + CursorToPanel( cur, cx, cy ); + int fontHeight = FontTall(); + + surface()->DrawFilledRect( cx, cy, cx + 1, cy + fontHeight ); + } + + /*int mx, my; + input()->GetCursorPosition( mx, my ); + ScreenToLocal( mx, my ); + text_cursor cc; + PanelToCursor( mx, my, cc ); + int cx, cy; + CursorToPanel( cc, cx, cy ); + + surface()->DrawSetColor( Color( 255, 0, 0, 255 ) ); + int fontHeight = FontTall(); + surface()->DrawFilledRect( cx, cy, cx + 1, cy + fontHeight );*/ +} + +void CSmartText::CalcCurrentRenderRow( int &realRow, int &virtualRow ) +{ + virtualRow = m_pScrollBar_V->GetValue(); + int tmpVRow = virtualRow; + realRow = 0; + + for (;;) + { + Assert( realRow >= 0 && realRow < hRows.Count() ); + if ( realRow >= hRows.Count() ) + break; + + tmpVRow -= hRows[ realRow ]->GetRenderNumRows(); + + if ( tmpVRow < 0 ) + break; + + virtualRow = abs( tmpVRow ); + realRow++; + } +} + +void CSmartText::ResetBlinkTime() +{ + m_iBlinkTime = system()->GetTimeMillis(); +} + +void CSmartText::OnKeyCodeTyped( KeyCode code ) +{ + ResetBlinkTime(); + + DestroyHoverTooltip(); + + if ( OnACCatchKeyCode( code ) ) + return; + + const bool shift = ( input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ) ); + const bool ctrl = ( input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ) ); + + bool bMoving = false; + bool bCtn_Shift = code == KEY_LSHIFT || code == KEY_RSHIFT; + bool bCtn_Ctrl = code == KEY_LCONTROL || code == KEY_RCONTROL; + + switch ( code ) + { + case KEY_ENTER: + { + bool bSomethingChanged = Selection_Active() && select[0] != select[1]; + + Selection_Delete(); + + if ( SplitRow( cur ) ) + { + cur.x = 0; + cur.y++; + ValidateCursor(); + + if ( !hRows[cur.y]->GetTextLen() ) + hRows[cur.y]->SetDynamicSpacingEnabled( true ); + + CalcSmartTabs( cur.y ); + AdvanceScrollbarOnDemand(); + + MakeTopFormatsDirty(); + ReleaseTooltipOnDemand(); + + bSomethingChanged = true; + } + + if ( bSomethingChanged ) + MakeHistoryDirty(); + } + break; + case KEY_LEFT: + { + int lastRow = cur.y; + MoveCursor( -1, 0, ctrl, shift ); + AdvanceScrollbarOnDemand(); + bMoving = true; + ReleaseTooltipOnDemand(); + + if ( lastRow != cur.y ) + OnRowEnter(-1,true); + } + break; + case KEY_RIGHT: + { + int lastRow = cur.y; + MoveCursor( 1, 0, ctrl, shift ); + AdvanceScrollbarOnDemand(); + bMoving = true; + ReleaseTooltipOnDemand(); + + if ( lastRow != cur.y ) + OnRowEnter(-1,true); + } + break; + case KEY_UP: + MoveCursor( 0, -1, ctrl, shift ); + AdvanceScrollbarOnDemand(); + bMoving = true; + ReleaseTooltipOnDemand(); + OnRowEnter(); + break; + case KEY_DOWN: + MoveCursor( 0, 1, ctrl, shift ); + AdvanceScrollbarOnDemand(); + bMoving = true; + ReleaseTooltipOnDemand(); + OnRowEnter(); + break; + case KEY_HOME: + { + if ( ctrl ) + { + cur.y = 0; + cur.x = 0; + } + else + { + text_cursor firstChar( 0, cur.y ); + while ( CanRead(&firstChar) && IS_SPACE( Read(&firstChar) ) ) + MoveCursor( 1, 0, false, false, &firstChar ); + + if ( (cur.x == 0 || firstChar.x < cur.x) && + firstChar.x != 0 && + firstChar.x != hRows[firstChar.y]->GetTextLen() - 1 ) + cur.x = firstChar.x; + else + cur.x = 0; + } + + ValidateCursor(); + bMoving = true; + } + break; + case KEY_END: + if ( ctrl ) + cur.y = hRows.Count() - 1; + + MoveCursorToEndOfRow(); + ValidateCursor(); + bMoving = true; + break; + case KEY_LSHIFT: + case KEY_RSHIFT: + bMoving = true; + break; + case KEY_LCONTROL: + case KEY_RCONTROL: + bMoving = true; + break; + case KEY_DELETE: + case KEY_BACKSPACE: + ProcessDelete( code == KEY_DELETE ); + OnACKeyTyped( 0 ); + break; + case KEY_X: + if ( ctrl ) + ProcessCut(); + break; + case KEY_C: + if ( ctrl ) + ProcessCopy(); + break; + case KEY_V: + if ( ctrl ) + ProcessPaste(); + break; + case KEY_Z: + if ( ctrl ) + PopHistory( shift ? -1 : 1 ); + break; + case KEY_Y: + if ( ctrl ) + PopHistory(-1); + break; + case KEY_A: + if ( ctrl ) + { + MoveCursorToEndOfRow( hRows.Count() - 1 ); + Selection_Reset(); + Selection_Select( text_cursor( 0, 0 ) ); + Selection_Select( cur ); + } + break; + case KEY_0: + case KEY_PAD_0: + if ( ctrl ) + { + m_iFontSize = ::__hfcInstance.fSizeDefault(); + ChangeFontSize( 0 ); + } + break; + case KEY_PAD_PLUS: + if ( ctrl ) + ChangeFontSize( 1 ); + break; + case KEY_MINUS: + case KEY_PAD_MINUS: + if ( ctrl ) + ChangeFontSize( -1 ); + break; + } + + if ( bMoving ) + MakeTopFormatsDirty(); + + if ( bMoving && ( !bCtn_Shift || !Selection_Active() ) ) + { + if ( shift ) + Selection_Select( cur ); + else if ( !bCtn_Ctrl ) + Selection_Reset(); + } + + //BaseClass::OnKeyCodeTyped( code ); +} +void CSmartText::OnKeyTyped( wchar_t c ) +{ + const bool bTab = c == 9; + const bool shift = ( input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ) ); + const bool ctrl = ( input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ) ); + + if ( iswcntrl( c ) && !bTab || + c == 0 ) + { + if ( !shift && !ctrl ) + Selection_Reset(); + return; + } + + //if ( OnACKeyTyped( c ) ) + // return; + + if ( ctrl && c == L' ' ) + { + CreateACMenu(); + return; + } + + text_cursor sr[2]; + Selection_GetSorted( sr ); + + OnRowEdit(); + + if ( bTab && Selection_Valid() && + ( sr[0].y != sr[1].y || + sr[0].x == 0 && sr[1].x == hRows[sr[1].y ]->GetTextLen( true ) ) ) + { + text_cursor rCur = cur; + hRows[rCur.y]->ToRealCursor( rCur ); + + bool cursorAtEnd = rCur == sr[1]; + + if ( sr[1].y > 0 && sr[1].x == 0 ) + { + sr[1].y--; + sr[1].x = hRows[ sr[1].y ]->GetTextLen( true ); + } + + for ( int i = sr[0].y; i <= sr[1].y; i++ ) + { + hRows[ i ]->PerformShiftTab( !shift ); + MakeHistoryDirty(); + } + + Selection_Reset(); + + for ( int i = sr[0].y; i <= sr[1].y; i++ ) + Selection_AddRow( i ); + + Selection_GetSorted( select ); + + if ( cursorAtEnd ) + MoveCursorToEndOfRow( sr[1].y ); + else + swap( select[0], select[1] ); + } + else + { + ValidateCursor(); + + if ( Selection_Valid() ) + { + cur = sr[0]; + hRows[cur.y]->ToVirtualCursor( cur ); + } + + Selection_Delete(); + + text_cursor pos = cur; + pos.y = clamp( pos.y, 0, hRows.Count() - 1 ); + + Assert( pos.y >= 0 && pos.y < hRows.Count() ); + + hRows[pos.y]->ToRealCursor( cur ); + hRows[pos.y]->KillLineBreaks(); + + int oldLen = hRows[pos.y]->GetTextLen( true ); + hRows[pos.y]->InsertChar( c, cur.x, false, true ); + int newLen = hRows[pos.y]->GetTextLen( true ); + + cur.x += newLen - oldLen; + + //hRows[pos.y]->UpdateLinebreaks(); + hRows[pos.y]->ToVirtualCursor( cur ); + + ValidateCursor(); + + MakeHistoryDirty(); + } + + if ( c == L'#' && cur.x > 1 ) + { + int iPosFirst = 0; + for ( ; iPosFirst < hRows[ cur.y ]->Read().Count(); iPosFirst++ ) + { + if ( !IS_SPACE( hRows[ cur.y ]->Read()[iPosFirst] ) ) + break; + } + + if ( iPosFirst == cur.x - 1 ) + { + hRows[ cur.y ]->DeleteInterval( 0, cur.x - 2 ); + cur.x = 1; + + ValidateCursor(); + } + } + + if ( c == L'{' || c == L'}' ) + CalcSmartTabs( cur.y, true ); + else + OnTextChanged(); + + m_bTopHighlightOnTyped = true; + + MakeTopFormatsDirty(); + + AdvanceScrollbarOnDemand(); + + OnACKeyTyped( c ); +} + +void CSmartText::OnMousePressed( MouseCode code ) +{ + ResetBlinkTime(); + + DestroyHoverTooltip(); + + if ( m_pACMenu ) + DestroyACMenu(); + + int x, y; + input()->GetCursorPosition( x, y ); + ScreenToLocal( x, y ); + + m_bIsRowSelecting = x < m_iTextInset; + + if ( code == MOUSE_LEFT ) + Selection_Reset(); + else + m_bIsRowSelecting = false; + + if ( code == MOUSE_LEFT || + code == MOUSE_RIGHT && !Selection_Valid() ) + { + PanelToCursor( x, y, cur ); + ValidateCursor(); + + input()->SetMouseCapture( GetVPanel() ); + m_bIsSelecting = true; + + if ( m_bIsRowSelecting ) + { + Selection_AddRow( cur.y ); + + x = 0; + y += FontTall(); + PanelToCursor( x, y, cur ); + ValidateCursor(); + } + + OnRowEnter( cur.y, m_bIsRowSelecting ); + } + + MakeTopFormatsDirty(); + + ReleaseTooltipOnDemand(); +} +void CSmartText::OnMouseDoublePressed( MouseCode code ) +{ + if ( code != MOUSE_LEFT ) + return; + + int x, y; + input()->GetCursorPosition( x, y ); + ScreenToLocal( x, y ); + + Selection_Reset(); + PanelToCursor( x, y, cur ); + ValidateCursor(); + + int x0 = hRows[cur.y]->GetWordLeft( cur.x ); + int x1 = hRows[cur.y]->GetWordRight( x0 ); + + //int x1 = hRows[cur.y]->GetWordRight( cur.x ); + //int x0 = hRows[cur.y]->GetWordLeft( x1 ); + + text_cursor sr; + sr.y = cur.y; + sr.x = x0; + Selection_Select( sr ); + sr.x = x1; + Selection_Select( sr ); + + MoveCursorTo( sr ); + + MakeTopFormatsDirty(); +} +void CSmartText::OnMouseReleased( MouseCode code ) +{ + input()->SetMouseCapture( NULL ); +} +void CSmartText::OnMouseWheeled( int d ) +{ + const bool ctrl = ( input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ) ); + + if ( ctrl ) + ChangeFontSize( d ); + else + m_pScrollBar_V->SetValue( m_pScrollBar_V->GetValue() + d * -10 ); +} +void CSmartText::OnCursorMoved( int x, int y ) +{ + m_lLastCursorMoved = system()->GetTimeMillis(); + + BaseClass::OnCursorMoved( x, y ); +} +void CSmartText::OnMouseFocusTicked() +{ + int x, y; + input()->GetCursorPosition( x, y ); + ScreenToLocal( x, y ); + SetCursor( ( x < m_iTextInset ) ? dc_up : dc_ibeam ); + + //SetDragEnabled( x >= m_iTextInset && Selection_Valid() ); + + BaseClass::OnMouseFocusTicked(); +} +void CSmartText::OnCursorEntered() +{ + m_bAllowHoverTooltip = true; + BaseClass::OnCursorEntered(); +} +void CSmartText::OnCursorExited() +{ + m_bAllowHoverTooltip = false; + BaseClass::OnCursorExited(); +} +void CSmartText::OnMouseCaptureLost() +{ + BaseClass::OnMouseCaptureLost(); + + m_bIsSelecting = false; +} +void CSmartText::OnThink() +{ + BaseClass::OnThink(); + + if ( IsHistoryDirty() ) + OnHistoryDirty(); + else + { + if ( hHistory_Old.Count() ) + hHistory_Old[0]->cursor = cur; + } + + if ( ParserHelper.HasDatabaseWaiting() ) + { + delete m_pGlobalDatabase; + m_pGlobalDatabase = ParserHelper.ObtainDatabase(); + + AddEnvInfoToDB(); + } + + if ( ParserHelper.HasLiveDatabaseWaiting() && m_pGlobalDatabase ) + { + CSmartObjectList *pLiveList = ParserHelper.ObtainLiveDatabase(); + m_pGlobalDatabase->MergeWithEntries( pLiveList ); + delete pLiveList; + } + + if ( IsTopFormatsDirty() ) + UpdateTopFormats(); + + UpdateParseCode(); + + if ( m_bIsSelecting && input()->IsMouseDown( MOUSE_LEFT ) ) + { + ResetBlinkTime(); + + int sx, sy; + GetSize( sx, sy ); + + int x, y; + input()->GetCursorPosition( x, y ); + ScreenToLocal( x, y ); + + if ( m_bIsRowSelecting ) + { + x = 0; + text_cursor test; + PanelToCursor( x, y, test ); + + int numVRows = hRows[ test.y ]->GetRenderNumRows(); + + if ( test.y == hRows.Count() - 1 ) + x = sx; + + if ( test.y >= select[0].y ) + y += FontTall() * numVRows; + + PanelToCursor( x, y, test ); + } + + PanelToCursor( x, y, cur ); + Selection_Select( cur ); + + if ( Selection_Valid() ) + OnRowEnter(-1, true); + + int offsetDir = ( y > sy ) ? 1 : ( y < 0 ) ? -1 : 0; + if ( y > sy ) + y -= sy; + y = abs( y ); + + int speed = max( 1, 60 - y ) * 8; + + if ( system()->GetTimeMillis() - scrollDelay > speed ) + { + scrollDelay = system()->GetTimeMillis(); + m_pScrollBar_V->SetValue( m_pScrollBar_V->GetValue() + offsetDir ); + } + + if ( Selection_Valid() ) + MakeTopFormatsDirty(); + } + + CreateHoverTooltipThink(); + + UpdateTooltipPositions(); +} + +void CSmartText::AddEnvInfoToDB() +{ + if ( !m_pGlobalDatabase ) + return; + + CSmartObject *pO = NULL; + char tmp[MAX_PATH]; + int len = 0; + + if ( m_iEnvInfo & NODECUSTOM_ADDENV_LIGHTING_PS ) + { + Q_snprintf( tmp, sizeof( tmp ), "#define %s", GetComboNameByID( HLSLCOMBO_NUM_LIGHTS ) ); + pO = new CSmartObject( ACOMP_DEFINE, tmp, GetComboNameByID( HLSLCOMBO_NUM_LIGHTS ) ); + Q_snprintf( tmp, sizeof( tmp ), "// Dynamic combo\n// Range: 0 - 4" ); + len = Q_strlen( tmp ) + 1; + pO->m_pszHelptext = new char[len]; + Q_strcpy( pO->m_pszHelptext, tmp ); + AutoCopyStringPtr( IDENT_STATIC_LIVE_CODE, &pO->m_pszSourceFile ); + m_pGlobalDatabase->AddUnit( pO ); + + pO = new CSmartObject( ACOMP_VAR, "const float3 g_cAmbientCube[6]", "g_cAmbientCube", "float3" ); + AutoCopyStringPtr( IDENT_STATIC_LIVE_CODE, &pO->m_pszSourceFile ); + m_pGlobalDatabase->AddUnit( pO ); + + pO = new CSmartObject( ACOMP_VAR, "PixelShaderLightInfo g_cLightInfo[3]", "g_cLightInfo", "PixelShaderLightInfo" ); + AutoCopyStringPtr( IDENT_STATIC_LIVE_CODE, &pO->m_pszSourceFile ); + m_pGlobalDatabase->AddUnit( pO ); + } + else if ( m_iEnvInfo & NODECUSTOM_ADDENV_LIGHTING_VS ) + { + Q_snprintf( tmp, sizeof( tmp ), "#define %s", GetComboNameByID( HLSLCOMBO_LIGHT_STATIC ) ); + pO = new CSmartObject( ACOMP_DEFINE, tmp, GetComboNameByID( HLSLCOMBO_LIGHT_STATIC ) ); + Q_snprintf( tmp, sizeof( tmp ), "// Dynamic combo\n// Range: 0 - 1" ); + len = Q_strlen( tmp ) + 1; + pO->m_pszHelptext = new char[len]; + Q_strcpy( pO->m_pszHelptext, tmp ); + AutoCopyStringPtr( IDENT_STATIC_LIVE_CODE, &pO->m_pszSourceFile ); + m_pGlobalDatabase->AddUnit( pO ); + + Q_snprintf( tmp, sizeof( tmp ), "#define %s", GetComboNameByID( HLSLCOMBO_LIGHT_DYNAMIC ) ); + pO = new CSmartObject( ACOMP_DEFINE, tmp, GetComboNameByID( HLSLCOMBO_LIGHT_DYNAMIC ) ); + Q_snprintf( tmp, sizeof( tmp ), "// Dynamic combo\n// Range: 0 - 1" ); + len = Q_strlen( tmp ) + 1; + pO->m_pszHelptext = new char[len]; + Q_strcpy( pO->m_pszHelptext, tmp ); + AutoCopyStringPtr( IDENT_STATIC_LIVE_CODE, &pO->m_pszSourceFile ); + m_pGlobalDatabase->AddUnit( pO ); + } +} + +_smartRow *CSmartText::InsertRow( const wchar_t *text, int y ) +{ + _smartRow *pRow = new _smartRow( m_Font, CalcInteriorWidth(), m_iTextInset ); + if ( text != NULL ) + pRow->InsertString( text, 0 ); + + if ( y < 0 ) + hRows.AddToTail( pRow ); + else + hRows.InsertBefore( y, pRow ); + + OnTextChanged(); + return pRow; +} + +_smartRow *CSmartText::InsertRow( const char *text, int y ) +{ + wchar_t *pWStr = NULL; + + if ( text != NULL && *text ) + { + int len = Q_strlen( text ) + 1; + pWStr = new wchar_t[ len ]; + Q_UTF8ToUnicode( text, pWStr, len * sizeof(wchar_t) ); + } + + _smartRow *p = InsertRow( pWStr, y ); + + delete [] pWStr; + return p; +} +void CSmartText::ClearDynamicSpacing() +{ + for ( int i = 0; i < hRows.Count(); i++ ) + { + if ( hRows[i]->IsDynamicSpacingEnabled() ) + hRows[i]->RemoveLeadingSpaces(); + } + ValidateCursor(); +} +int CSmartText::FindRow( _smartRow *p ) +{ + if ( !p ) + return -1; + + int index = hRows.Find( p ); + if ( hRows.IsValidIndex( index ) ) + return index; + + return -1; +} +int CSmartText::GetLockedRow( int iNumLocked ) +{ + int curLocked = 0; + for ( int i = 0; i < hRows.Count(); i++ ) + { + if ( hRows[i]->IsLocked() ) + curLocked++; + if ( curLocked == iNumLocked ) + return i; + } + + return -1; +} +void CSmartText::DeleteRow( int y ) +{ + if ( y < 0 ) + y = hRows.Count() - 1; + + if ( y >= hRows.Count() ) + return; + + if ( !hRows[ y ]->IsDeletable() ) + return; + + delete hRows[ y ]; + hRows.Remove( y ); + + MakeHistoryDirty(); +} +void CSmartText::SetRowLocked( bool bLocked, int y ) +{ + if ( y == -1 ) + y = hRows.Count() - 1; + if ( y >= hRows.Count() ){ Assert(0); return; } + hRows[y]->SetLocked( bLocked ); +} +void CSmartText::SetRowDeletable( bool bDeletable, int y ) +{ + if ( y == -1 ) + y = hRows.Count() - 1; + if ( y >= hRows.Count() ){ Assert(0); return; } + hRows[y]->SetDeletable( bDeletable ); +} +bool CSmartText::IsRowLocked( int y ) +{ + if ( y == -1 ) + y = hRows.Count() - 1; + if ( y >= hRows.Count() ){ Assert(0); return false; } + return hRows[y]->IsLocked(); +} +bool CSmartText::IsRowDeletable( int y ) +{ + if ( y == -1 ) + y = hRows.Count() - 1; + if ( y >= hRows.Count() ){ Assert(0); return false; } + return hRows[y]->IsDeletable(); +} +bool CSmartText::SplitRow( text_cursor pos ) +{ + pos.y = clamp( pos.y, 0, hRows.Count() - 1 ); + + _smartRow *pNewRow = hRows[pos.y]->Split( pos.x ); + + if ( !pNewRow ) + return false; + + hRows.InsertAfter(pos.y, pNewRow); + + OnTextChanged(); + return true; +} +void CSmartText::CalcSmartTabs( int y, bool bOnTyping ) +{ + if ( y < 1 ) + { + if ( bOnTyping ) + OnTextChanged(); + return; + } + + int iIndent = 0; + //int lastRow = min( bOnTyping ? y : ( y - 1 ), hRows.Count() - 1 ); + + //bool bInComment = false; + + wchar_t *pszLastIndent = NULL; //hRows[y - 1]->CopyLeadingSpaces(); + + text_cursor cw( bOnTyping ? cur.x : 0, y ); + + GenerateCmtList(); + + for (;;) + { + MoveCursor( -1, 0, false, false, &cw ); + + bool bSkipLine = IsCommented( cw.x, cw.y ); + if ( !bSkipLine ) + { + for ( int i = 0; i < hRows[cw.y]->Read().Count(); i++ ) + { + const wchar_t &c = hRows[cw.y]->Read()[ i ]; + if ( c && !IS_SPACE( c ) ) + { + if ( c == L'#' ) + bSkipLine = true; + break; + } + } + } + + if ( cw.x < hRows[cw.y]->Read().Count() && + !bSkipLine ) + { + const wchar_t &c = Read(&cw); //hRows[cw.y]->Read()[cw.x]; + bool bEndParse = false; + //bool bSearchScopeLine = false; + + text_cursor cw_orig( -1, -1 ); + + if ( !c || IS_SPACE( c ) ) + { + } + else if ( ( c == L'{' && !bOnTyping ) ) + { + iIndent++; + bEndParse = true; + } + else + { + if ( c != L';' && c != L'{' && c != L'}' && IsHLSL() ) + { + bool bArrayDef = false; + int iscopecheck_intern = 0; + if ( c == L',' ) + { + text_cursor checkArray = cw; + while ( MoveCursor( -1, 0, false, false, &checkArray ) ) + { + if ( !CanRead( &checkArray ) ) + continue; + if ( IsCommented( checkArray.x, checkArray.y ) ) + continue; + + const wchar_t &c_intern = Read(&checkArray); + + if ( c_intern == '(' ) + { + iscopecheck_intern++; + } + else if ( c_intern == ')' ) + { + iscopecheck_intern--; + } + else if ( c_intern == '{' ) + { + if ( iscopecheck_intern == 0 ) + bArrayDef = true; + break; + } + else if ( c_intern == ';' ) + break; + } + } + + if ( !bArrayDef ) + { + iIndent++; + cw_orig = cw; + } + } + + bEndParse = true; + //bSearchScopeLine = true; + + if ( !bOnTyping || cw.x >= 1 && IS_SPACE( hRows[cw.y]->Read()[cw.x - 1] ) ) + { + text_cursor bracketClose( cw ); + text_cursor bracketCurScope( -1, -1 ); + + const bool bOnScopeClose = c == L'}'; + int iBracketCounter = ( bOnScopeClose ) ? -1 : 0; + bool bScopeTestDirty = iBracketCounter != 0; + + for (;;) + { + MoveCursor( -1, 0, false, false, &bracketClose ); + + bool bSkipLine = IsCommented( bracketClose.x, bracketClose.y ); + if ( !bSkipLine ) + { + for ( int i = 0; i < hRows[bracketClose.y]->Read().Count(); i++ ) + { + const wchar_t &c2 = hRows[bracketClose.y]->Read()[ i ]; + if ( c2 && !IS_SPACE( c2 ) ) + { + if ( c2 == L'#' ) + bSkipLine = true; + break; + } + } + } + + if ( !bSkipLine && bracketClose.x < hRows[bracketClose.y]->Read().Count() ) + { + const wchar_t &cB = Read(&bracketClose); //hRows[ bracketClose.y ]->Read()[ bracketClose.x ]; + + if ( cB == L'{' ) + { + iBracketCounter++; + bScopeTestDirty = true; + + if ( bracketCurScope.x < 0 && bracketClose.y + 1 < hRows.Count() ) + { + bracketCurScope = bracketClose; + + if ( c != L'}' ) + iIndent++; + } + } + else if ( cB == L'}' ) + { + iBracketCounter--; + bScopeTestDirty = true; + } + + if ( bScopeTestDirty && ( iBracketCounter >= 0 || iBracketCounter < 0 && !bOnScopeClose ) ) + break; + } + + if ( bracketClose.x <= 0 && bracketClose.y <= 0 ) + break; + } + + //if ( iBracketCounter >= 0 ) + { + if ( bScopeTestDirty && iBracketCounter > 0 && bracketCurScope.y >= 0 ) + cw = bracketCurScope; + else + cw = bracketClose; + } + } + } + + if ( bEndParse ) + { + if ( cw_orig == cw ) + cw.x = cw.y = 0; + + pszLastIndent = hRows[cw.y]->CopyLeadingSpaces(); + break; + } + } + + if ( cw.x <= 0 && cw.y <= 0 ) + break; + } + + KillCmtList(); + + int oldLen = hRows[ y ]->GetTextLen(); + + if ( bOnTyping ) + hRows[ y ]->RemoveLeadingSpaces(); + + if ( pszLastIndent ) + { + hRows[ y ]->InsertString( pszLastIndent, 0 ); + delete [] pszLastIndent; + } + + for ( int i = 0; i < iIndent; i++ ) + { + hRows[ y ]->PerformShiftTab(); + } + + int newLen = hRows[ y ]->GetTextLen(); + + cur.x += newLen - oldLen; + + ValidateCursor(); + + OnTextChanged(); +} + +void CSmartText::CursorToPanel( const text_cursor &c, int &x, int &y ) +{ + x = 0; + + int rowStart = m_pScrollBar_V->GetValue(); + +#if DEBUG + int numRowsAll = 0; + for ( int i = 0; i < hRows.Count(); i++ ) + numRowsAll += hRows[ i ]->GetRenderNumRows(); + Assert( rowStart >= 0 && rowStart < numRowsAll ); +#endif + Assert( c.y >= 0 && c.y < hRows.Count() ); + + int fontHeight = FontTall(); + + y = fontHeight * -rowStart; + + for ( int i = 0; i < c.y; i++ ) + y += hRows[ i ]->GetRenderHeight(); + + int rowmove_x, rowmove_y; + hRows[ c.y ]->RelativeRowCursorToPanel( c.x, rowmove_x, rowmove_y ); + + x += rowmove_x; + y += rowmove_y; +} + +void CSmartText::PanelToCursor( const int &x, const int &y, text_cursor &c ) +{ + int fontHeight = FontTall(); + int virtualRow, realRow; + CalcCurrentRenderRow( realRow, virtualRow ); + if ( realRow > 0 ) + virtualRow += hRows[realRow-1]->GetRenderNumRows(); + + int curTestPos = fontHeight / 2 - ( virtualRow ) * fontHeight; + int best_row_real = realRow; + int best_row_virtual = virtualRow; + int best_dist = 99999; + + bool bHitLastTime = false; + + for ( int i = max( 0, realRow - 1 ); i < hRows.Count(); i++ ) + { + int curVirtualRows = hRows[i]->GetRenderNumRows(); + for ( int j = 0; j < curVirtualRows; j++ ) + { + int cur_dist = abs( curTestPos - y ); + + if ( cur_dist < best_dist ) + { + best_dist = cur_dist; + best_row_real = i; + best_row_virtual = j; + + bHitLastTime = true; + } + else if ( bHitLastTime ) + i = hRows.Count(); + + curTestPos += fontHeight; + } + } + + c.y = best_row_real; + c.x = hRows[ c.y ]->PanelToCursorCalcX( best_row_virtual, x ); +} +void CSmartText::MoveCursorTo( int x, int y ) +{ + cur.y = clamp( y, 0, hRows.Count() - 1 ); + cur.x = clamp( x, 0, hRows[ y ]->GetTextLen() ); +} +void CSmartText::MoveCursorTo( text_cursor c ) +{ + MoveCursorTo( c.x, c.y ); +} +bool CSmartText::MoveCursor( int leftright, int updown, + bool bWordJump, bool bSelectRange, text_cursor *c ) +{ + text_cursor &cw = c ? *c : cur; + + text_cursor startpos = cw; + //int startposx = cw.x; + + if ( leftright != 0 ) + { + Assert( cw.y >= 0 && cw.y < hRows.Count() ); + + while ( leftright < 0 ) + { + if ( cw.y == 0 && cw.x == 0 ) + break; + + cw.x--; + + if ( bWordJump && cw.x >= 0 ) + { + if ( !CanRead( &cw ) || Read( &cw ) ) + cw.x = hRows[ cw.y ]->GetWordLeft( cw.x ); + } + + if ( cw.y > 0 && ( cw.x < 0 || + startpos.x == 0 && startpos.x == cw.x && bWordJump ) ) + { + cw.y = cw.y - 1; + cw.x = hRows[ cw.y ]->GetTextLen(); + } + leftright++; + } + while ( leftright > 0 ) + { + if ( cw.y == hRows.Count() - 1 && cw.x == hRows[ cw.y ]->GetTextLen() ) + break; + + if ( bWordJump ) + cw.x = hRows[ cw.y ]->GetWordRight( cw.x ); + else + cw.x++; + + if ( cw.x > hRows[ cw.y ]->GetTextLen() || + startpos.x == cw.x && bWordJump ) + { + cw.y = min( hRows.Count() - 1, cw.y + 1 ); + cw.x = 0; + } + leftright--; + } + + if ( c == NULL ) + StompCursorHistory(); + } + + //while ( updown != 0 ) + if ( updown != 0 ) + { + //if ( hRows[ cur.y ]->GetRenderNumRows() == 1 ) + // cur.y + + int x, y; + CursorToPanel( cw, x, y ); + y += FontTall() / 2 + FontTall() * updown; + + Assert( !c || c != &cur ); + + x = c ? x : max( m_iXCursorHistory, x ); + if ( !c ) + m_iXCursorHistory = max( m_iXCursorHistory, x ); + + PanelToCursor( x, y, cw ); + } + + if ( !bWordJump && bSelectRange && hRows[ cw.y ]->HasLinebreakAtCursor( cw ) ) + cw.x += ( startpos.x > cw.x ) ? -1 : 1; + + ValidateCursor( &startpos ); + +#if DEBUG + text_cursor _check = startpos; + ValidateCursor( &_check ); + Assert( _check == startpos ); +#endif + + return startpos != cw; +} +void CSmartText::MoveCursorToEndOfRow( int y, text_cursor *c ) +{ + if ( !c ) + c = &cur; + + if ( y < 0 ) + y = c->y; + + if ( y < 0 || y >= hRows.Count() ) + return; + + c->y = y; + c->x = hRows[ c->y ]->GetTextLen(); +} + +void CSmartText::MoveCursorToEndOfText( text_cursor *c ) +{ + if ( !c ) + c = &cur; + + c->y = hRows.Count() - 1; + MoveCursorToEndOfRow( -1, c ); +} + +void CSmartText::OnTextChanged( int lastRealRow ) +{ + StompCursorHistory(); + ValidateCursor(); + + UpdateScrollbar( lastRealRow ); + OnSelectionChanged(); + + //UpdateTopFormats(); + MakeCodeDirty(); +} + +void CSmartText::ValidateCursor( text_cursor *c ) +{ + Assert( hRows.Count() > 0 ); + + text_cursor &cw = ( c != NULL ) ? *c : cur; + + cw.y = clamp( cw.y, 0, hRows.Count() - 1 ); + cw.x = clamp( cw.x, 0, hRows[ cw.y ]->GetTextLen() ); +} + +int CSmartText::FontTall() +{ + return surface()->GetFontTall( m_Font ); +} + +void CSmartText::StompCursorHistory() +{ + m_iXCursorHistory = 0; +} + +void CSmartText::AdvanceScrollbarOnDemand() +{ + int x,y; + CursorToPanel( cur, x, y ); + int sx, sy; + GetSize( sx, sy ); + + int fontTall = FontTall(); + + int ydelta = 0; + if ( y < 0 ) + ydelta = abs( y ) / fontTall * -1; + else if ( y + fontTall >= sy ) + ydelta = ( y - sy + fontTall ) / fontTall + 1; + + if ( ydelta == 0 ) + return; + + m_pScrollBar_V->SetValue( m_pScrollBar_V->GetValue() + ydelta ); +} + +void CSmartText::UpdateSelectionFormat() +{ + delete [] m_pszLastSelectedWord; + m_pszLastSelectedWord = NULL; + + if ( Selection_Active() && select[0] != select[1] ) + { + int x0, x1; + text_cursor sr[2]; + Selection_GetSorted( sr ); + + if ( sr[0].y == sr[1].y && sr[0] < sr[1] ) + { + text_cursor href_min = sr[0]; + text_cursor href_max = sr[1]; + href_max.x -= 1; + + text_cursor href_bounds_0 = href_min; + text_cursor href_bounds_1 = href_max; + href_bounds_0.x--; + href_bounds_1.x++; + + hRows[href_bounds_0.y]->ToVirtualCursor(href_bounds_0); + hRows[href_bounds_1.y]->ToVirtualCursor(href_bounds_1); + + if ( (!CanRead(&href_bounds_0) || !IS_CHAR(Read(&href_bounds_0)) && !IS_NUMERICAL(Read(&href_bounds_0)) ) && + (!CanRead(&href_bounds_1) || !IS_CHAR(Read(&href_bounds_1)) && !IS_NUMERICAL(Read(&href_bounds_1)) ) ) + { + m_pszLastSelectedWord = hRows[href_min.y]->ReadInterval( href_min.x, href_max.x, false, true ); + wchar_t *pwalkref = m_pszLastSelectedWord; + while ( *pwalkref ) + { + if ( !IS_CHAR(*pwalkref) && + !IS_NUMERICAL(*pwalkref) ) + { + pwalkref = NULL; + break; + } + pwalkref++; + } + + if ( pwalkref != NULL ) + for ( int i = 0; i < hRows.Count(); i++ ) + hRows[i]->SetHighlightRef(m_pszLastSelectedWord); + } + } + + for ( int i = sr[0].y; i <= min( sr[1].y, hRows.Count() - 1 ); i++ ) + { + if ( !Selection_GetRowRange( i, x0, x1 ) ) + continue; + + _inlineFormat *f = new _inlineFormat(); + f->bOverride_fg = true; + f->bOverride_bg = true; + f->col_fg = _col_SelectionFG; + f->col_bg = _col_SelectionBG; + f->start = x0; + f->end = x1; + + if ( sr[1].y > i ) + f->bCRBlock = true; + + hRows[i]->AddHighlightFormat( f ); + } + } +} + +void CSmartText::UpdateHighlightFormats() +{ + for ( int i = 0; i < hRows.Count(); i++ ) + { + hRows[ i ]->ClearHighlightFormats(); + } + + UpdateCmtFormat(); + UpdateSelectionFormat(); +} + +void CSmartText::MakeTopFormatsDirty() +{ + m_bTopFormatsDirty = true;; +} +bool CSmartText::IsTopFormatsDirty() +{ + return m_bTopFormatsDirty; +} +void CSmartText::UpdateTopFormats( bool bDoHighlights ) +{ + m_bTopFormatsDirty = false; + + if ( m_bTopHighlightLock ) + return; + + for ( int i = 0; i < hRows.Count(); i++ ) + hRows[ i ]->ClearTopFormats(); + + if ( !bDoHighlights || Selection_Valid() ) + return; + + text_cursor bracketHighlight = cur; + + if ( m_bTopHighlightOnTyped ) + { + m_bTopHighlightOnTyped = false; + MoveCursor( -1, 0, false, false, &bracketHighlight ); + } + + if ( !hRows[ bracketHighlight.y ]->Read().Count() || + bracketHighlight.x >= hRows[ bracketHighlight.y ]->Read().Count() ) + return; + + const wchar_t &ref = Read(&bracketHighlight); //hRows[ bracketHighlight.y ]->Read()[ bracketHighlight.x ]; + const int iDir = IS_BRACKET_OPENING( ref ) ? 1 : IS_BRACKET_CLOSING( ref ) ? -1 : 0; + + if ( !iDir ) + return; + + int iBracketCounter = iDir; + + text_cursor bracketHighlight_0 = bracketHighlight; + + m_bTopHighlightLock = true; + + for (;;) + { + MoveCursor( iDir, 0, false, false, &bracketHighlight ); + + bool bValid = true; + + if ( bracketHighlight.x < 0 && bracketHighlight.y < 0 ) + bValid = false; + + if ( bracketHighlight.x >= hRows[ bracketHighlight.y ]->GetTextLen() && bracketHighlight.y >= hRows.Count() - 1 ) + bValid = false; + + if ( bValid && CanRead( &bracketHighlight ) ) + { + const wchar_t &cur = Read(&bracketHighlight); //hRows[ bracketHighlight.y ]->Read()[ bracketHighlight.x ]; + + if ( IS_BRACKET_SAME_TYPE( ref, cur ) ) + { + iBracketCounter += IS_BRACKET_OPENING( cur ) ? 1 : -1; + } + } + + if ( !iBracketCounter ) + break; + + if ( !bValid || bracketHighlight.x <= 0 && bracketHighlight.y <= 0 ) + { + iBracketCounter = -1; + break; + } + } + + m_bTopHighlightLock = false; + + if ( iBracketCounter == 0 ) + { + hRows[bracketHighlight_0.y]->ToRealCursor( bracketHighlight_0 ); + hRows[bracketHighlight.y]->ToRealCursor( bracketHighlight ); + + _inlineFormat *f = new _inlineFormat(); + f->bOverride_bg = true; + f->col_bg = ST_COL_HIGHLIGHT_BRACKET; + f->start = bracketHighlight_0.x; + f->end = bracketHighlight_0.x + 1; + hRows[ bracketHighlight_0.y ]->AddTopFormat( f ); + + f = new _inlineFormat( *f ); + f->start = bracketHighlight.x; + f->end = bracketHighlight.x + 1; + hRows[ bracketHighlight.y ]->AddTopFormat( f ); + } +} + +void CSmartText::ProcessDelete( bool bAfter ) +{ + if ( Selection_Valid() ) + { + text_cursor rg[2]; + Selection_GetSorted( rg ); + + hRows[ rg[0].y ]->ToVirtualCursor( rg[0] ); + MoveCursorTo( rg[0] ); + Selection_Delete(); + } + else + { + //text_cursor orig = cur; + + hRows[ cur.y ]->ToRealCursor( cur ); + hRows[ cur.y ]->KillLineBreaks(); + + int currowLen = hRows[ cur.y ]->GetTextLen(); + + if ( bAfter && cur.x < currowLen || + !bAfter && cur.x > 0 ) + { + if ( !hRows[ cur.y ]->IsLocked() ) + { + MakeHistoryDirty(); + hRows[ cur.y ]->DeleteChar( cur.x, bAfter ); + } + } + + wchar_t *append = NULL; + + if ( !bAfter && cur.x == 0 && cur.y > 0 ) + { + if ( hRows[ cur.y ]->IsDeletable() ) + { + if ( !hRows[ cur.y ]->IsDynamicSpacingEnabled() ) + append = hRows[ cur.y ]->ReadInterval(); + + DeleteRow( cur.y ); + + MoveCursorToEndOfRow( cur.y - 1 ); + } + } + else if ( bAfter && cur.x == currowLen && cur.y < hRows.Count() - 1 ) + { + if ( hRows[ cur.y + 1 ]->IsDeletable() ) + { + if ( !hRows[ cur.y + 1 ]->IsDynamicSpacingEnabled() ) + append = hRows[ cur.y + 1 ]->ReadInterval(); + + DeleteRow( cur.y + 1 ); + + hRows[ cur.y ]->UpdateLinebreaks(); + MoveCursorToEndOfRow(); + } + } + else + { + if ( !bAfter && cur.x > 0 ) + MoveCursor( -1 ); + + hRows[ cur.y ]->ToVirtualCursor( cur ); + } + + if ( append != NULL ) + { + int oldVRows = hRows[ cur.y ]->GetRenderNumRows( cur.x ); + hRows[ cur.y ]->InsertString( append ); + int newVRows = hRows[ cur.y ]->GetRenderNumRows( cur.x ); + MoveCursor( newVRows - oldVRows ); + + delete [] append; + } + } + + OnTextChanged(); + + MakeTopFormatsDirty(); +} +void CSmartText::ProcessCut() +{ + ValidateCursor(); + + ProcessCopy(); + + if ( Selection_Valid() ) + { + text_cursor rg[2]; + Selection_GetSorted( rg ); + + hRows[ rg[0].y ]->ToVirtualCursor( rg[0] ); + MoveCursorTo( rg[0] ); + Selection_Delete(); + } + else if ( hRows.Count() > 1 ) + { + if ( hRows[ cur.y ]->IsDeletable() ) + { + DeleteRow( cur.y ); + ValidateCursor(); + } + } + + OnTextChanged(); + + MakeTopFormatsDirty(); +} +void CSmartText::ProcessCopy() +{ + ValidateCursor(); + + if ( Selection_Valid() ) + Selection_Copy(); + else + { + wchar_t *pRow = hRows[ cur.y ]->ReadInterval( -1, -1, true, true ); + int wStrLen = Q_wcslen( pRow ) + 2; + wchar_t *CRRow = new wchar_t[ wStrLen ]; + + // wasted 4 hours tracking down this crash. comment for memorial! + Q_memset( CRRow, 0, wStrLen * sizeof(wchar_t) ); // takes bytes, not array length, BRO + + CRRow[ 0 ] = CR_HACK_CHAR; + CRRow++; + Q_wcsncpy( CRRow, pRow, (wStrLen-1) * sizeof( wchar_t ) ); // Uhhhhhhhh + CRRow--; + + delete [] pRow; + system()->SetClipboardText( CRRow, Q_wcslen( CRRow ) ); + delete [] CRRow; + } + + OnTextChanged(); +} +void CSmartText::ProcessPaste() +{ + Selection_Delete(); + + int strLen = system()->GetClipboardTextCount(); + wchar_t *buf = new wchar_t[ strLen + 1 ]; + Q_memset( buf, 0, sizeof( wchar_t ) * strLen ); + system()->GetClipboardText( 0, buf, sizeof( wchar_t ) * strLen ); + + if ( buf && Q_wcslen(buf) ) + MakeHistoryDirty(); + + ParseInsertText( buf ); + delete [] buf; + + OnTextChanged(); + AdvanceScrollbarOnDemand(); +} + +void CSmartText::OnRowEdit( int y ) +{ + if ( y < 0 ) + y = cur.y; + + if ( hRows.IsValidIndex( y ) && hRows[y]->IsDynamicSpacingEnabled() ) + { + hRows[y]->SetDynamicSpacingEnabled( false ); + + if ( cur.x < hRows[y]->GetTextLen() ) + hRows[y]->RemoveLeadingSpaces(); + } +} + +void CSmartText::OnRowEnter( int y, bool bNoTabs ) +{ + if ( y < 0 ) + y = cur.y; + + const bool bEmpty = !hRows[y]->GetTextLen(); + const bool bIsDynamic = hRows[y]->IsDynamicSpacingEnabled(); + + if ( !hRows.IsValidIndex( y ) || ( !bIsDynamic && !bEmpty ) ) + return; + + if ( bEmpty ) + hRows[y]->SetDynamicSpacingEnabled( true ); + + int oldCursorX = m_iXCursorHistory; + + hRows[y]->RemoveLeadingSpaces(); + + if ( !bNoTabs ) + CalcSmartTabs(y); + + m_iXCursorHistory = oldCursorX; + ValidateCursor(); +} + +void CSmartText::ParseInsertText( const wchar_t *str ) +{ + OnRowEdit(); + + ValidateCursor(); + + const wchar_t *walk = str; + + while ( walk && *walk ) + { + //bool bAdvance_x = true; + + if ( *walk == L'\r' ) + { + } + else if ( *walk == CR_HACK_CHAR ) + { + cur.x = 0; + //bAdvance_x = false; + } + else if ( *walk == L'\n' ) + { + if ( SplitRow( cur ) ) + { + hRows[ cur.y ]->OnTextChanged(); + + //hRows[ cur.y ]->OnTextChanged(); + //MoveCursorToEndOfRow(); + + //MoveCursor( 1 ); + //bAdvance_x = false; + cur.x = 0; + cur.y++; + ValidateCursor(); + } + } + else + { + const wchar_t *findEndRow = walk; + + while ( findEndRow && *findEndRow && + *findEndRow != CR_HACK_CHAR && + *findEndRow != L'\n' && + *findEndRow != L'\r' ) + findEndRow++; + + bool bHaltOnWcntrl = findEndRow && *findEndRow; + + int numMoved_Str = findEndRow - walk; // - ( *findEndRow ? 1 : 0 ); + int numMoved_Row = bHaltOnWcntrl ? numMoved_Str : hRows[ cur.y ]->GetTextLen(); + + //hRows[ cur.y ]->InsertString( walk, cur.x, numMoved_Str - (bHaltOnWcntrl?1:0), true ); + hRows[ cur.y ]->InsertString( walk, cur.x, numMoved_Str, true ); + + //hRows[ cur.y ]->KillLineBreaks(); + //hRows[ cur.y ]->UpdateLinebreaks(); + hRows[ cur.y ]->ToRealCursor( cur ); + + if ( !bHaltOnWcntrl ) + { + numMoved_Row = hRows[ cur.y ]->GetTextLen() - numMoved_Row; + } + + hRows[ cur.y ]->OnTextChanged(); + + //else + // cur.x = hRows[ cur.y ]->GetTextLen(); + + cur.x += numMoved_Row; + hRows[ cur.y ]->ToVirtualCursor( cur ); + + walk = findEndRow - 1; + + //hRows[ cur.y ]->InsertChar( *walk, cur.x, true ); + } + + //if ( bAdvance_x ) + // cur.x++; + walk++; + } + + hRows[ cur.y ]->OnTextChanged(); +} + +void CSmartText::ParseInsertText( const char *str ) +{ + if ( !str || !*str ) + return; + + int len = Q_strlen( str ) + 1; + wchar_t *pW = new wchar_t[len]; + Q_UTF8ToUnicode( str, pW, sizeof(wchar_t) * len ); + + ParseInsertText(pW); + + delete [] pW; +} + +bool CSmartText::Selection_GetRowRange( const int &row, int &x_min, int &x_max, + text_cursor *cMin, text_cursor *cMax ) +{ + Assert( row >= 0 && row < hRows.Count() ); + text_cursor sr[2]; + + if ( !cMin || !cMax ) + Selection_GetSorted( sr ); + else + { + Assert( (*cMin) <= (*cMax) ); + + sr[0] = *cMin; + sr[1] = *cMax; + } + + if ( sr[0].y > row || sr[1].y < row ) + return false; + + if ( sr[0].y == row ) + { + x_min = sr[0].x; + if ( sr[1].y == row ) + x_max = sr[1].x; + else + x_max = hRows[ row ]->GetTextLen( true ); + } + else if ( sr[1].y == row ) + { + x_min = 0; + x_max = sr[1].x; + } + else + { + x_min = 0; + x_max = hRows[ row ]->GetTextLen( true ); + } + + return true; +} +void CSmartText::OnSelectionChanged() +{ + for ( int i = 0; i < 2; i++ ) + { + select[i].y = clamp( select[i].y, 0, hRows.Count() - 1 ); + select[i].x = clamp( select[i].x, 0, hRows[ select[i].y ]->GetTextLen() ); + } + + UpdateHighlightFormats(); +} +void CSmartText::Selection_Reset() +{ + bool bWasValid = m_bSelectionValid; + m_bSelectionValid = false; + + for ( int i = 0; i < 2; i++ ) + select[i].x = select[i].y = 0; + + if ( bWasValid ) + OnSelectionChanged(); +} +void CSmartText::Selection_Select( text_cursor pos ) +{ + Assert( pos.y >= 0 && pos.y < hRows.Count() ); + + hRows[ pos.y ]->ToRealCursor( pos ); + + if ( !Selection_Active() ) + select[0] = select[1] = pos; + else + select[1] = pos; + + m_bSelectionValid = true; + + OnSelectionChanged(); +} +void CSmartText::Selection_AddRow( int y ) +{ + Assert( y >= 0 && y < hRows.Count() ); + + text_cursor tmp; + tmp.y = y; + tmp.x = 0; + + Selection_Select( tmp ); + tmp.x = hRows[y]->GetTextLen(); + Selection_Select( tmp ); +} +void CSmartText::Selection_Delete() +{ + if ( Selection_Active() && select[0] != select[1] ) + { + int x0, x1; + text_cursor sr[2]; + Selection_GetSorted( sr ); + + MoveCursorTo( sr[0] ); + + wchar_t *append = NULL; + + for ( int i = hRows.Count() - 1; i >= 0; i-- ) + { + if ( !Selection_GetRowRange( i, x0, x1 ) ) + continue; + + hRows[ i ]->KillLineBreaks(); + + if ( !append && + x0 == 0 && + x1 < hRows[ i ]->GetTextLen( true ) && + sr[0].y < i ) + { + append = hRows[ i ]->ReadInterval( x1 ); + } + + if ( sr[ 0 ].y < i ) + { + if ( hRows[ i ]->IsDeletable() ) + { + DeleteRow( i ); + } + else if ( !hRows[ i ]->IsLocked() ) + hRows[ i ]->DeleteInterval(); + else + hRows[ i ]->UpdateLinebreaks(); + } + else + { + hRows[ i ]->DeleteInterval( x0, x1 - 1 ); + } + } + + if ( append ) + { + hRows[ sr[0].y ]->InsertString( append ); + + delete [] append; + } + + ValidateCursor(); + + MakeHistoryDirty(); + } + + Selection_Reset(); +} +void CSmartText::Selection_Copy( text_cursor *cMin, text_cursor *cMax, wchar_t **pBuffOut, bool bAddCR ) +{ +#if DEBUG + if ( cMin == NULL && cMax == NULL ) + Assert( Selection_Valid() ); +#endif + + int x0, x1; + CUtlVector< wchar_t* >hRowStream; + + text_cursor sr[2]; + + if ( !cMin || !cMax ) + Selection_GetSorted( sr ); + else + { + if ( cMax->y < 0 ) + cMax->y = hRows.Count() - 1; + if ( cMax->x < 0 ) + MoveCursorToEndOfRow( -1, cMax ); + + Assert( (*cMin) <= (*cMax) ); + + sr[0] = *cMin; + sr[1] = *cMax; + } + + if ( sr[0] >= sr[1] ) + { + if ( pBuffOut ) + *pBuffOut = NULL; + return; + } + + for ( int i = 0; i < hRows.Count(); i++ ) + { + if ( !Selection_GetRowRange( i, x0, x1, &sr[0], &sr[1] ) ) + continue; + + wchar_t *rowStr = NULL; + + bool bAllowLF = i < sr[1].y; + + if ( sr[0].y == sr[1].y && i == sr[0].y ) + x1 -= 1; + + if ( sr[1].y == i && sr[1].x == 0 ) + { + if ( bAllowLF ) + { + rowStr = new wchar_t[2]; + rowStr[0] = L'\n'; + rowStr[1] = L'\0'; + } + } + else + rowStr = hRows[i]->ReadInterval( x0, x1, bAllowLF, true ); + + if ( rowStr ) + hRowStream.AddToTail( rowStr ); + } + + int wholeBuffLen = 1; + for ( int i = 0; i < hRowStream.Count(); i++ ) + wholeBuffLen += Q_wcslen( hRowStream[ i ] ); + + if ( bAddCR ) + wholeBuffLen += hRowStream.Count() - 1; + + wchar_t *pszBuff = new wchar_t[ wholeBuffLen ]; + wchar_t *pWriter = pszBuff; + Q_memset( pszBuff, 0, sizeof( wchar_t ) * wholeBuffLen ); + + for ( int i = 0; i < hRowStream.Count(); i++ ) + { + int rowLen = Q_wcslen( hRowStream[ i ] ); + Q_memcpy( pWriter, hRowStream[ i ], sizeof( wchar_t ) * rowLen ); + pWriter += rowLen; + + if ( bAddCR && i < hRowStream.Count() - 1 ) + { + pWriter--; + *pWriter = '\r'; + pWriter++; + *pWriter = '\n'; + pWriter++; + } + } + + for ( int i = 0; i < hRowStream.Count(); i++ ) + delete [] hRowStream[ i ]; + hRowStream.Purge(); + + //pWriter--; + *pWriter = L'\0'; + + if ( pBuffOut != NULL ) + *pBuffOut = pszBuff; + else + { + system()->SetClipboardText( pszBuff, wholeBuffLen - 1 ); //Q_wcslen( pszBuff ) ); + delete [] pszBuff; + } +} +void CSmartText::Selection_GetSorted( text_cursor *v ) +{ + text_cursor &a = v[0]; + text_cursor &b = v[1]; + + a = select[0]; + b = select[1]; + + if ( select[0] > select[1] ) + swap( a, b ); +} + +void CSmartText::KillCmtList() +{ + m_hCmtList.Purge(); +} + +void CSmartText::GenerateCmtList() +{ + KillCmtList(); + + CUtlVector< wchar_t >*phReader; + + _cmtCtrl MultilineCmt; + bool bInMultilineCmt = false; + + for ( int y = 0; y < hRows.Count(); y++ ) + { + phReader = &hRows[ y ]->Read(); + + if ( bInMultilineCmt ) + { + MultilineCmt = _cmtCtrl( y, 0, -1 ); + } + + int readerPos = 0; + + for ( int x = 0; x < phReader->Count() - 1; x++ ) + { + const wchar_t &c = phReader->Element( x ); + + if ( !c ) + continue; + + if ( bInMultilineCmt ) + { + if ( c == L'*' && phReader->Element( x + 1 ) == L'/' ) + { + MultilineCmt._x1 = readerPos + 1; + m_hCmtList.AddToTail( MultilineCmt ); + + bInMultilineCmt = false; + } + } + else if ( c == L'/' && phReader->Element( x + 1 ) == L'/' ) + { + m_hCmtList.AddToTail( _cmtCtrl( y, readerPos, -1 ) ); + + //y++; + break; + } + else if ( c == L'/' && phReader->Element( x + 1 ) == L'*' ) + { + MultilineCmt = _cmtCtrl( y, readerPos, -1 ); + bInMultilineCmt = true; + } + + readerPos++; + } + + if ( bInMultilineCmt ) + { + m_hCmtList.AddToTail( MultilineCmt ); + + //bInMultilineCmt = false; + } + } +} + +bool CSmartText::IsCommented( int x, int y ) +{ + for ( int i = 0; i < m_hCmtList.Count(); i++ ) + if ( m_hCmtList[i].IsCommented( x, y ) ) + return true; + + return false; +} + +void CSmartText::UpdateCmtFormat() +{ + GenerateCmtList(); + + for ( int i = 0; i < m_hCmtList.Count(); i++) + { + _inlineFormat *f = new _inlineFormat(); + f->bOverride_fg = true; + f->col_fg = ST_COL_CMT_FG; + f->start = m_hCmtList[i]._x0; + f->end = m_hCmtList[i]._x1; + + if ( m_hCmtList[i]._x1 >= 0 ) + f->end++; + + hRows[ m_hCmtList[i]._y ]->AddHighlightFormat( f ); + } + + KillCmtList(); +} + + +void CSmartText::CreateACMenu( int iTooltipMode ) +{ + if ( !IsACEnabled() ) + return; + + const bool bFunctionTooltip = iTooltipMode == ACTOOLTIP_FUNC; + const bool bObjectTooltip = iTooltipMode == ACTOOLTIP_OBJECT; + const bool bManualMode = !bFunctionTooltip && !bObjectTooltip; + + DestroyACMenu(true, !bObjectTooltip); + + if ( !m_pGlobalDatabase || m_pGlobalDatabase->GetNumEntries() < 1 ) + { + OnACMenuCreationFailed(); + return; + } + + text_cursor action_start = cur; + + //if ( !CanRead( &action_start ) && action_start.x > 0 ) + if ( action_start.x > 0 ) + action_start.x--; + + GetWordLeft( action_start ); + + // blah. + // blah( + // blah ( + // blah ( dagfdag, agdag, + // datatype blah ( sgsgj // NOT + // sdghg; sdgsdgh + + // only go left? + + + bool bObjectAccess = false; + bool bFunctionParams = false; + bool bExpressionStart = false; + + int moves = 0; + int bracketScope = 0; + + do + { + if ( !CanRead( &action_start ) ) + continue; + + const wchar_t &c = Read( &action_start ); + + if ( bFunctionTooltip ) + { + if ( c == L')' ) + bracketScope--; + else if ( c == L'(' ) + bracketScope++; + else if ( bFunctionTooltip && bracketScope > 0 && !IS_SPACE( c ) ) + bFunctionParams = true; + else if ( c == L';' ) + bExpressionStart = true; + } + else if ( bObjectTooltip ) + { + if ( !moves && c == L'.' ) + bObjectAccess = true; + //else if ( bObjectAccess && !IS_CHAR( c ) && !IS_NUMERICAL( c ) ) + // break; + else if ( c == L';' ) + bExpressionStart = true; + } + else + { + bExpressionStart = true; + } + + moves++; + + } while ( !bObjectAccess && !bFunctionParams && !bExpressionStart && + MoveCursor( -1, 0, false, false, &action_start ) ); + + //const bool bOriginSameRow = action_start.y == cur.y; + char *pMasterVar = NULL; + + //bFunctionParams = bFunctionParams && bOriginSameRow; + + if ( bFunctionParams ) + { + GetWordLeft( action_start ); + } + + text_cursor menuPosRef = ( bFunctionParams || bObjectAccess ) ? action_start : cur; + + + if ( bFunctionTooltip ) + { + m_curACStart = menuPosRef; + + if ( !bFunctionParams || !CanRead( &m_curACStart ) || !m_pGlobalDatabase ) + return; + + if ( !IS_CHAR( Read( &m_curACStart ) ) ) + return; + + Assert( !m_pFuncTooltip ); + + int x0 = m_curACStart.x; + int x1 = hRows[m_curACStart.y]->GetWordRight( x0 ) - 1; + + if ( x1 < x0 ) + return; + + wchar_t *snippet = hRows[m_curACStart.y]->ReadInterval( x0, x1, false, true ); + char cSnippet[MAX_PATH]; + + if ( !snippet ) + return; + + Q_UnicodeToUTF8( snippet, cSnippet, sizeof(cSnippet) ); + + int iscopedepth, iscopenum, textPos; + GetScopeData( m_curACStart, iscopedepth, iscopenum, textPos ); + + CSmartObject *pOFunc = NULL; + for ( int i = 0; i < m_pGlobalDatabase->GetNumEntries(); i++ ) + { + CSmartObject *pO = m_pGlobalDatabase->GetEntry(i); + + if ( pO->m_iType != ACOMP_FUNC ) + continue; + if ( !pO->m_pszIdentifier ) + continue; + if ( !pO->IsObjectVisible( textPos, iscopedepth, iscopenum, IDENT_LIVE_CODE ) ) + continue; + + if ( Q_strcmp( pO->m_pszIdentifier, cSnippet ) ) + continue; + + pOFunc = pO; + } + + if ( pOFunc != NULL ) + { + m_pFuncTooltip = new CSmartTooltip( this, "functooltip" ); + m_pFuncTooltip->Init( pOFunc, CSmartTooltip::STTIPMODE_FUNCTIONPARAMS ); + + UpdateTooltipPositions(); + } + + delete [] snippet; + + return; + } + else if ( bManualMode ) + { + text_cursor test = menuPosRef; + test.x--; + + if ( GetWordLeft( test ) ) + menuPosRef = test; + } + else if ( bObjectTooltip ) + { + if ( !bObjectAccess ) + return; + + menuPosRef.x++; + text_cursor wordStart = action_start; + wordStart.x--; + + text_cursor checkArray( wordStart ); + do + { + if ( !CanRead( &checkArray ) ) + continue; + const wchar_t &c = Read( &checkArray ); + + if ( c == '[' ) + { + checkArray.x--; + if ( CanRead( &checkArray ) ) + { + wordStart = checkArray; + action_start = wordStart; + action_start.x++; + } + } + else if ( IS_SPACE(c) || c == '.' ) + break; + + } while( MoveCursor( -1, 0, false, false, &checkArray ) ); + + if ( !GetWordLeft( wordStart ) ) + return; + + if ( !CanRead( &wordStart ) ) + return; + + wchar_t *pWMasterVar = hRows[wordStart.y]->ReadInterval( wordStart.x, action_start.x - 1, false, true ); + if ( pWMasterVar && *pWMasterVar ) + { + int len = Q_wcslen( pWMasterVar ) + 1; + pMasterVar = new char[ len ]; + Q_UnicodeToUTF8( pWMasterVar, pMasterVar, len ); + } + delete [] pWMasterVar; + } + + + text_cursor save_ac_start = m_curACStart; + m_curACStart = menuPosRef; + + int iscopedepth, iscopenum, textPos; + GetScopeData( m_curACStart, iscopedepth, iscopenum, textPos ); + + + m_pACMenu = new CSmartAutocomplete( this, "acmenu" ); + m_pACMenu->SetFont( __hfcInstance.GetFont( __hfcInstance.fSizeMin() + __hfcInstance.fStepSize() * 2 ) ); + m_pACMenu->SetMenuItemHeight( m_pACMenu->GetMenuItemHeight() - 2 ); + m_pACMenu->SetNumberOfVisibleItems( 10 ); + + bool bTryObject = bObjectTooltip && bObjectAccess; + + bool bSuccess = m_pACMenu->InitList( m_pGlobalDatabase, textPos, iscopedepth, iscopenum, + IDENT_LIVE_CODE, bTryObject ? pMasterVar : NULL ); + + if ( bManualMode && CanRead( &menuPosRef ) ) + { + int x0 = menuPosRef.x; + int x1 = hRows[menuPosRef.y]->GetWordRight( x0 ); + + bool bRead = x1 >= x0; + + wchar_t *snippet = bRead ? hRows[menuPosRef.y]->ReadInterval( x0, x1 - 1 ) : NULL; + m_pACMenu->MatchInput( snippet ); + delete [] snippet; + } + + delete [] pMasterVar; + + + if ( !bSuccess ) + { + m_curACStart = save_ac_start; + DestroyACMenu( true, !bObjectTooltip ); + return; + } + + int pX, pY, mX, mY; + m_pACMenu->InvalidateLayout( true ); + m_pACMenu->GetSize( mX, mY ); + + CalcACPos( menuPosRef, pX, pY, mX, mY ); + m_pACMenu->SetPos( pX, pY ); + m_pACMenu->SetKeyBoardInputEnabled( false ); + + m_pACMenu->RequestFocus(); +} +void CSmartText::CreateHoverTooltipThink() +{ + if ( !IsACEnabled() ) + return; + + if ( m_lLastCursorMoved <= 0.0l || + !m_bAllowHoverTooltip ) + { + DestroyHoverTooltip(); + return; + } + + if ( m_pHoverTooltip != NULL && m_pHoverTooltip->IsVisible() ) + return; + + long delta = system()->GetTimeMillis() - m_lLastCursorMoved; + if ( delta <= 600 ) + return; + + DestroyHoverTooltip(); + + int mx, my; + text_cursor curHover; + input()->GetCursorPosition( mx, my ); + ScreenToLocal( mx, my ); + PanelToCursor( mx, my, curHover ); + + if ( !CanRead(&curHover) || !m_pGlobalDatabase ) + return; + + if ( !IS_CHAR(Read(&curHover)) && !IS_NUMERICAL(Read(&curHover)) ) + return; + + m_curHoverMin = curHover; + GetWordLeft( m_curHoverMin ); + ValidateCursor( &m_curHoverMin ); + + int x0 = m_curHoverMin.x; + int x1 = hRows[m_curHoverMin.y]->GetWordRight( x0 ) - 1; + + if ( x1 < x0 ) + return; + + wchar_t *snippet = hRows[m_curHoverMin.y]->ReadInterval( x0, x1, false, true ); + + m_curHoverMax = text_cursor( x1 + 1, m_curHoverMin.y ); + + if ( !snippet ) + return; + + int len = Q_wcslen( snippet ) + 1; + char *pCStr = new char[ len ]; + Assert( pCStr ); + Q_UnicodeToUTF8( snippet, pCStr, len ); + + int iscopedepth, iscopenum, textPos; + GetScopeData( curHover, iscopedepth, iscopenum, textPos ); + + CSmartObject *pO = NULL; + for ( int i = 0; i < m_pGlobalDatabase->GetNumEntries() /*&& !pO*/; i++ ) + { + CSmartObject *pCur = m_pGlobalDatabase->GetEntry(i); + + if ( !pCur->m_pszIdentifier || Q_strcmp( pCur->m_pszIdentifier, pCStr ) ) + continue; + + if ( !pCur->IsObjectVisible( textPos, iscopedepth, iscopenum, IDENT_LIVE_CODE ) ) + continue; + + if ( pO && pO->m_iScopeDepth >= pCur->m_iScopeDepth ) + continue; + + if ( pO && pO->m_iScopeNum > pCur->m_iScopeNum ) + continue; + + pO = pCur; + } + + delete [] snippet; + delete [] pCStr; + + if ( !pO ) + return; + + m_pHoverTooltip = new CSmartTooltip( this, "hovertooltip" ); + m_pHoverTooltip->Init( pO ); + + UpdateTooltipPositions(); +} +void CSmartText::DestroyACMenu( bool bMenu, bool bTooltip ) +{ + if ( bMenu ) + { + if ( m_pACMenu ) + m_pACMenu->MarkForDeletion(); + m_pACMenu = NULL; + } + + if ( bTooltip ) + { + if ( m_pFuncTooltip ) + m_pFuncTooltip->MarkForDeletion(); + m_pFuncTooltip = NULL; + } +} +void CSmartText::DestroyHoverTooltip() +{ + if ( m_pHoverTooltip ) + { + m_pHoverTooltip->MarkForDeletion(); + m_lLastCursorMoved = 0.0l; + m_pHoverTooltip = NULL; + } +} +void CSmartText::CalcACPos( const text_cursor &c, int &x, int &y, int menuSizeX, int menuSizeY ) +{ + int sX, sY; + CursorToPanel( c, x, y ); + LocalToScreen( x, y ); + surface()->GetScreenSize( sX, sY ); + + if ( y + FontTall() + menuSizeY <= sY ) + y += FontTall(); + else + y -= menuSizeY; + + if ( x + menuSizeX > sX ) + x -= x + menuSizeX - sX; + else + x += 2; +} +void CSmartText::OnACMenuCreationFailed() +{ +} +bool CSmartText::OnACCatchKeyCode( KeyCode code ) +{ + if ( !m_pACMenu || !m_pACMenu->IsVisible() ) + { + ReleaseTooltipOnDemand(); + return false; + } + + if ( code == KEY_UP || code == KEY_DOWN ) + { + m_pACMenu->MoveAlongMenuItemList( (code == KEY_UP) ? Menu::MENU_UP : Menu::MENU_DOWN, 0, true ); + return true; + } + else if ( code == KEY_ENTER ) + { + InsertFromAC(); + return true; + } + else if ( code == KEY_SPACE || code == KEY_PERIOD ) + { + text_cursor findWord = cur; + findWord.x--; + + wchar_t *snippet = NULL; + + if ( CanRead( &findWord ) && IS_CHAR( Read( &findWord ) ) ) + if ( GetWordLeft( findWord ) && CanRead( &findWord ) ) + snippet = hRows[ findWord.y ]->ReadInterval( findWord.x, cur.x - 1, false, true ); + + if ( snippet && m_pACMenu->IsExactMatch( snippet, true ) >= 0 ) + InsertFromAC(); + else + DestroyACMenu(); + + delete [] snippet; + } + else if ( code == KEY_LEFT || code == KEY_RIGHT || + code == KEY_SPACE || code == KEY_ESCAPE ) + { + DestroyACMenu(); + } + else if ( code == KEY_BACKSPACE ) + { + if ( cur <= m_curACStart ) + DestroyACMenu(); + } + + return false; +} +void CSmartText::InsertFromAC( const char *pIdent ) +{ + bool bOwnsMemory = pIdent == NULL; + + if ( !pIdent ) + pIdent = m_pACMenu->AllocHighlightItemName(); + + if ( pIdent ) + { + if ( CanRead(&m_curACStart) && + ( IS_CHAR(Read(&m_curACStart)) || IS_NUMERICAL(Read(&m_curACStart)) ) + ) + { + text_cursor cRight = m_curACStart; + cRight.x = hRows[cRight.y]->GetWordRight( cRight.x ) - 1; + + if ( cRight.x >= m_curACStart.x ) + hRows[m_curACStart.y]->DeleteInterval( m_curACStart.x, cRight.x ); + } + + text_cursor rep = m_curACStart; + //text_cursor repPre = rep; + //repPre.x--; + + //if ( !CanRead( &rep ) && CanRead( &repPre ) ) + //{ + // wchar_t chPre = Read( &repPre ); + + // if ( IS_NUMERICAL(chPre) || IS_CHAR(chPre) ) + // rep = repPre; + //} + + //if ( CanRead(&rep) //&& + // //( IS_CHAR( Read(&rep) ) || IS_NUMERICAL( Read(&rep) ) ) + // ) + //{ + // GetWordLeft( rep ); + + // if ( CanRead(&rep) && !IS_SPACE( Read(&rep) ) //&& + // //( IS_CHAR( Read(&rep) ) || IS_NUMERICAL( Read(&rep) ) ) + // ) + // { + // int iRight = hRows[rep.y]->GetWordRight( rep.x ) - 1; + // if ( iRight >= rep.x ) + // hRows[rep.y]->DeleteInterval( rep.x, iRight ); + // } + //} + + //int lenOld = hRows[rep.y]->GetTextLen(); + + cur = rep; + hRows[rep.y]->ToRealCursor( cur ); + hRows[rep.y]->InsertString( pIdent, rep.x ); + cur.x += Q_strlen( pIdent ); + hRows[rep.y]->ToVirtualCursor( cur ); + + ValidateCursor(); + + if ( bOwnsMemory ) + delete [] pIdent; + + OnRowEdit( cur.y ); + MakeHistoryDirty(); + } + DestroyACMenu(); + +} +bool CSmartText::OnACKeyTyped( wchar_t c ) +{ + if ( c == '.' ) + { + CreateACMenu( ACTOOLTIP_OBJECT ); + return false; + } + else if ( c == '(' || c == ',' || c == ')' ) + { + CreateACMenu( ACTOOLTIP_FUNC ); + ReleaseTooltipOnDemand(); + return false; + } + + if ( !m_pACMenu || !m_pACMenu->IsVisible() ) + { + ReleaseTooltipOnDemand(); + return false; + } + + if ( c && !IS_CHAR( c ) && !IS_NUMERICAL( c ) ) + { + DestroyACMenu(); + return false; + } + + text_cursor wleft = cur; + wleft.x--; + GetWordLeft( wleft ); + ValidateCursor( &wleft ); + + int x0 = wleft.x; + int x1 = hRows[wleft.y]->GetWordRight( x0 ); + + bool bRead = x1 >= x0; + + wchar_t *snippet = bRead ? hRows[wleft.y]->ReadInterval( x0, x1 - 1 ) : NULL; + + m_pACMenu->MatchInput( snippet ); + + int ACResult = m_pACMenu->IsExactMatch( snippet, false ); + if ( ACResult >= 0 ) + { + char tmp[MAX_PATH]; + m_pACMenu->GetItemText( ACResult, tmp, sizeof( tmp ) ); + InsertFromAC( tmp ); + } + + delete [] snippet; + + return false; +} + +void CSmartText::ReleaseTooltipOnDemand() +{ + if ( ShouldReleaseTooltip() ) + DestroyACMenu(); +} + +bool CSmartText::ShouldReleaseTooltip() +{ + if ( !m_pFuncTooltip || !m_pFuncTooltip->IsVisible() ) + return false; + + if ( cur <= m_curACStart ) + return true; + + bool bExpressionChange = false; + + GenerateCmtList(); + + text_cursor scopeTest = cur; + int iScope = 0; + bool bHitBracket = false; + int iCountCommas = 0; + + while ( MoveCursor( -1, 0, false, false, &scopeTest ) && m_curACStart < scopeTest ) + { + if ( IsCommented( scopeTest.x, scopeTest.y ) ) + continue; + + if ( !CanRead(&scopeTest) ) + continue; + + const wchar_t &ch = Read( &scopeTest ); + + switch ( ch ) + { + case L'(': + iScope++; + bHitBracket = true; + break; + case L')': + iScope--; + bHitBracket = true; + break; + case L';': + bExpressionChange = true; + break; + case L',': + if ( iScope > 0 ) + { + iScope = 0; + iCountCommas = 0; + } + if ( iScope == 0 ) + iCountCommas++; + break; + } + } + + KillCmtList(); + + if ( bExpressionChange || + iScope == 0 && bHitBracket ) + return true; + + m_pFuncTooltip->MoveToFront(); + m_pFuncTooltip->SetActiveParam( bHitBracket ? iCountCommas + 1 : 0 ); + return false; +} + +void CSmartText::UpdateTooltipPositions() +{ + if ( m_pFuncTooltip && m_pFuncTooltip->IsVisible() ) + { + int pX, pY, mX, mY; + + CursorToPanel( cur, pX, pY ); + CursorToPanel( m_curACStart, mX, mY ); + int yDelta = pY - mY; + + if ( m_pFuncTooltip->IsLayoutInvalid() ) + m_pFuncTooltip->InvalidateLayout( true ); + + m_pFuncTooltip->GetSize( mX, mY ); + CalcACPos( m_curACStart, pX, pY, mX, mY ); + m_pFuncTooltip->SetPos( max( 0, pX ), pY + yDelta ); + } + + if ( m_pHoverTooltip && m_pHoverTooltip->IsVisible() ) + { + int mx, my; + text_cursor curHover; + input()->GetCursorPosition( mx, my ); + ScreenToLocal( mx, my ); + PanelToCursor( mx, my, curHover ); + + if ( curHover < m_curHoverMin || curHover > m_curHoverMax ) + DestroyHoverTooltip(); + else + { + int pX, pY, mX, mY; + CursorToPanel( m_curHoverMin, pX, pY ); + + if ( m_pHoverTooltip->IsLayoutInvalid() ) + m_pHoverTooltip->InvalidateLayout( true ); + + m_pHoverTooltip->GetSize( mX, mY ); + CalcACPos( m_curHoverMin, pX, pY, mX, mY ); + m_pHoverTooltip->SetPos( max(0, pX), pY ); + } + } +} +bool CSmartText::GetWordLeft( text_cursor &c ) +{ + //text_cursor wordStart = action_start; + + bool bMoved = false; + + while ( CanRead( &c ) ) + { + const wchar_t &ch = Read( &c ); + + if ( !( IS_CHAR( ch ) || IS_NUMERICAL( ch ) ) ) + break; + + c.x--; + bMoved = true; + } + + if ( bMoved ) + c.x++; + + return bMoved; + //action_start = wordStart; +} + +void CSmartText::OnMenuItemSelected( Panel *panel ) +{ + MenuItem *pItem = assert_cast< MenuItem* >( panel ); + Assert( pItem ); + + if ( !pItem ) + return; + + if ( m_pACMenu && ipanel()->HasParent( pItem->GetVPanel(), m_pACMenu->GetVPanel() ) ) + { + char buf[MAX_PATH]; + pItem->GetText( buf, sizeof(buf) ); + InsertFromAC(buf); + } +} + +void CSmartText::MakeCodeDirty() +{ + m_bCodeDirty = true; +} +bool CSmartText::IsCodeDirty() +{ + return m_bCodeDirty; +} +void CSmartText::UpdateParseCode() +{ + if ( !IsLiveParseEnabled() ) + return; + + if ( !IsCodeDirty() ) + return; + + if ( gpGlobals->curtime - m_flLastCodeParse < 1.0f ) + return; + + m_flLastCodeParse = gpGlobals->curtime; + + if ( !m_pGlobalDatabase ) + return; + + if ( !hRows.Count() ) + return; + + text_cursor cu_0( 0, 0 ); + text_cursor cu_1( hRows[hRows.Count()-1]->GetTextLen(true), hRows.Count() - 1 ); + + if ( cu_1 <= cu_0 ) + { + m_pGlobalDatabase->PurgeUnitsOfSameSource( IDENT_LIVE_CODE ); + return; + } + + m_bCodeDirty = false; + + wchar_t *pBuff = NULL; + + Selection_Copy( &cu_0, &cu_1, &pBuff ); + + if ( pBuff == NULL ) + return; + + ParserThread.RequestUpdate( PARSERREQUEST_USER, pBuff, new CSmartObjectList( *m_pGlobalDatabase ) ); + + //int len = Q_wcslen( pBuff ) + 1; + + //if ( len > 1 ) + //{ + // char *pCStrBuff = new char[ len ]; + + // if ( pCStrBuff != NULL ) + // { + // CUtlBuffer buf( pCStrBuff, len ); + // Q_UnicodeToUTF8( pBuff, pCStrBuff, len ); + + // m_pGlobalDatabase->ParseCode_Stream( buf, false, NULL, IDENT_LIVE_CODE, Q_strlen(pCStrBuff) - 1 ); + // buf.Clear(); + + // delete [] pCStrBuff; + // } + //} + + //delete [] pBuff; +} + +bool CSmartText::CanRead( text_cursor *c ) +{ + text_cursor &cw = ( c != NULL ) ? *c : cur; + return cw.y >= 0 && cw.y < hRows.Count() && cw.x >= 0 && cw.x < hRows[cw.y]->Read().Count(); +} + +const wchar_t &CSmartText::Read( text_cursor *c ) +{ + text_cursor &cw = ( c != NULL ) ? *c : cur; + Assert( CanRead( &cw ) ); + + return hRows[cw.y]->Read()[cw.x]; +} + +void CSmartText::GetScopeData( text_cursor c, int &iScopeDepth, int &iScopeNum, int &iTextPos ) +{ + iScopeDepth = iScopeNum = iTextPos = 0; + text_cursor cread(0,0); + + if ( c <= cread ) + return; + + for ( int i = 0; i < c.y; i++ ) + iTextPos += hRows[i]->GetTextLen( true ) + 1; + iTextPos += c.x; + + GenerateCmtList(); + + CUtlVector< int >hScopeCounter; + hScopeCounter.AddToTail(0); + + while ( cread < c ) + { + if ( !IsCommented( cread.x, cread.y ) && CanRead( &cread ) ) + { + const wchar_t &ch = Read( &cread ); + + if ( ch == L'{' ) + { + iScopeDepth++; + + if ( iScopeDepth >= hScopeCounter.Count() ) + hScopeCounter.AddToTail( -1 ); + + Assert( iScopeDepth < hScopeCounter.Count() ); + hScopeCounter[ iScopeDepth ]++; + } + else if ( ch == L'}' ) + { + iScopeDepth--; + } + } + + MoveCursor( 1, 0, false, false, &cread ); + } + + Assert( iScopeDepth < hScopeCounter.Count() ); + iScopeNum = hScopeCounter[ iScopeDepth ]; + + hScopeCounter.Purge(); + + KillCmtList(); + + //wchar_t *pBuff = NULL; + //Selection_Copy( &cmin, &c, &pBuff ); + + //if ( !pBuff ) + // return; + + + //delete [] pBuff; +} + +bool CSmartText::IsHistoryDirty() +{ + return m_bHistoryDirty; +} + +void CSmartText::MakeHistoryDirty() +{ + m_bHistoryDirty = true; +} + +void CSmartText::OnHistoryDirty() +{ + m_bHistoryDirty = false; + PushHistory(); + + m_iActiveHistoryIndex = sm_iHistoryIndex; + sm_iHistoryIndex++; + + PostActionSignal( new KeyValues( "CodeChanged" ) ); +} + +HHISTORYIDX CSmartText::GetCurrentHistoryIndex() +{ + return m_iActiveHistoryIndex; +} + +void CSmartText::FlushHistory( bool bOld /*= true*/, bool bNew /*= true*/ ) +{ + if ( bOld ) + hHistory_Old.PurgeAndDeleteElements(); + if ( bNew ) + hHistory_New.PurgeAndDeleteElements(); +} + +void CSmartText::PushHistory( int dir /*= 1*/ ) +{ + Assert( dir != 0 ); + + if ( dir > 0 ) + { + if ( dir < 2 ) + FlushHistory(false); + + __sTextHistory *pEntry = CreateHistoryEntry(); + hHistory_Old.AddToHead( pEntry ); + + while ( hHistory_Old.Count() > MAX_SMARTEDIT_HISTORY ) + { + delete hHistory_Old[ MAX_SMARTEDIT_HISTORY ]; + hHistory_Old.Remove( MAX_SMARTEDIT_HISTORY ); + } + } + else + { + if ( !hHistory_Old.Count() ) + return; + + hHistory_New.AddToHead( hHistory_Old[0] ); + hHistory_Old.Remove( 0 ); + } +} + +void CSmartText::PopHistory( int dir /*= 1*/ ) +{ + Assert( dir != 0 ); + + if ( dir > 0 ) + { + if ( hHistory_Old.Count() < 2 ) + return; + + ApplyHistoryEntry( hHistory_Old[1] ); + PushHistory(-1); + } + else + { + if ( hHistory_New.Count() < 1 ) + return; + + ApplyHistoryEntry( hHistory_New[0] ); + PushHistory(2); + + delete hHistory_New[0]; + hHistory_New.Remove(0); + } +} + +__sTextHistory *CSmartText::CreateHistoryEntry() +{ + Assert( hRows.Count() ); + __sTextHistory *out = new __sTextHistory( sm_iHistoryIndex ); + + ValidateCursor(); + + for ( int i = 0; i < hRows.Count(); i++ ) + out->rows.AddToTail( new _smartRow( *hRows[i] ) ); + out->cursor = cur; + + return out; +} + +void CSmartText::ApplyHistoryEntry(__sTextHistory *history ) +{ + if ( history->rows.Count() ) + { + hRows.PurgeAndDeleteElements(); + + for ( int i = 0; i < history->rows.Count(); i++ ) + hRows.AddToTail( new _smartRow( *history->rows[i] ) ); + } + + cur = history->cursor; + m_iActiveHistoryIndex = history->iIndex; + ValidateCursor(); + + OnTextChanged(); + OnLayoutUpdated(); + + AdvanceScrollbarOnDemand(); + + PostActionSignal( new KeyValues( "CodeChanged" ) ); +} diff --git a/sp/src/shadereditor/properties/smarttext/vsmarttext.h b/sp/src/shadereditor/properties/smarttext/vsmarttext.h new file mode 100644 index 00000000..9f9283a9 --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmarttext.h @@ -0,0 +1,320 @@ +#ifndef C_SMART_TEXT_H +#define C_SMART_TEXT_H + +#include "vSheets.h" +#include +#include +#include "vSmartRow.h" +#include "vSmartObjectList.h" + +#define MAX_SMARTEDIT_HISTORY 100 + +typedef unsigned int HHISTORYIDX; + +class __handleFontCache +{ +public: + __handleFontCache(); + ~__handleFontCache(); + + void AllocFonts(); + HFont GetFont( int realSize ); + HFont GetTooltipFont(); + + const int fSizeDefault() const { return 17; }; + const int fSizeMin() const { return 7; }; + const int fSizeMax() const { return 67; }; + const int fStepSize() const { return 5; }; + + int numFonts; + void InvalidateFonts(); + +private: + int CreateMonospaced( HFont &font, const int size ); + + HFont m_iTooltipFont; + bool m_bFontsReady; +}; + +__handleFontCache *GetFontCacheHandle(); + +class CSmartAutocomplete; +class CSmartTooltip; + +struct __sTextHistory +{ +public: + __sTextHistory( HHISTORYIDX index ) + { + iIndex = index; + cursor = text_cursor( 0, 0 ); + }; + ~__sTextHistory() + { + rows.PurgeAndDeleteElements(); + }; + __sTextHistory( const __sTextHistory &o ) + { + cursor = o.cursor; + + for ( int i = 0; i < o.rows.Count(); i++ ) + rows.AddToTail( new _smartRow( *o.rows[i] ) ); + }; + + CUtlVector< _smartRow* > rows; + text_cursor cursor; + + HHISTORYIDX iIndex; +}; + +class CSmartText : public Panel +{ + DECLARE_CLASS_SIMPLE( CSmartText, Panel ); + + static HHISTORYIDX sm_iHistoryIndex; + HHISTORYIDX m_iActiveHistoryIndex; + +public: + enum CodeEditMode_t + { + CODEEDITMODE_HLSL = 0, + CODEEDITMODE_VMT, + }; + + CSmartText( Panel *parent, const char *name, CodeEditMode_t mode ); + ~CSmartText(); + + void DoFullParserUpdate( int hlslhierachy_flags ); + void SetEnvInfo( int flags ); + + void ApplySchemeSettings( IScheme *pScheme ); + void OnSizeChanged( int wide, int tall ); + void OnMoved(); + void OnLayoutUpdated(); + + void Paint(); + void OnThink(); + + void OnKeyCodeTyped( KeyCode code ); + void OnKeyTyped( wchar_t c ); + + void OnMousePressed( MouseCode code ); + void OnMouseDoublePressed( MouseCode code ); + void OnMouseReleased( MouseCode code ); + void OnCursorMoved( int x, int y ); + void OnCursorEntered(); + void OnCursorExited(); + void OnMouseCaptureLost(); + void OnMouseWheeled( int d ); + + MESSAGE_FUNC( OnMouseFocusTicked, "OnMouseFocusTicked" ); + MESSAGE_FUNC_PTR( OnMenuItemSelected, "MenuItemSelected", panel ); + + _smartRow *InsertRow( const wchar_t *text = NULL, int y = -1 ); + _smartRow *InsertRow( const char *text, int y = -1 ); + void DeleteRow( int y = -1 ); + bool SplitRow( text_cursor pos ); + void CalcSmartTabs( int y, bool bOnTyping = false ); + void SetRowLocked( bool bLocked, int y = -1 ); + void SetRowDeletable( bool bDeletable, int y = -1 ); + bool IsRowLocked( int y = -1 ); + bool IsRowDeletable( int y = -1 ); + int FindRow( _smartRow *p ); + int GetLockedRow( int iNumLocked ); + void ClearDynamicSpacing(); + + bool MoveCursor( int leftright, int updown = 0, + bool bWordJump = false, bool bSelectRange = false, text_cursor *c = NULL ); + void MoveCursorTo( int x, int y ); + void MoveCursorTo( text_cursor c ); + void MoveCursorToEndOfRow( int y = -1, text_cursor *c = NULL ); + void MoveCursorToEndOfText( text_cursor *c = NULL ); + + static HFont *m_pFontRef; + + //MESSAGE_FUNC( OnKillFocus, "KillFocus" ); + + void SetLiveParseEnabled( bool bEnabled ); + void SetACEnabled( bool bEnabled ); + void SetSyntaxHighlightEnabled( bool bEnabled ); + + bool IsLiveParseEnabled(); + bool IsACEnabled(); + bool IsSyntaxHighlightEnabled(); + + const bool IsHLSL(); + const bool IsVMT(); + +private: + + void InitColors(); + Color _col_SelectionFG; + Color _col_SelectionBG; + + bool m_bEnableLiveParse; + bool m_bEnableAC; + bool m_bEnableSyntaxHighlight; + + CodeEditMode_t mode; + + void OnRowEdit( int y = -1 ); + void OnRowEnter( int y = -1, bool bNoTabs = false ); + + void UpdateScrollbar( int lastRealRow = -1 ); + void OnTextChanged( int lastRealRow = -1 ); + void ValidateCursor( text_cursor *c = NULL ); + + int CalcInteriorWidth(); + void CalcCurrentRenderRow( int &realRow, int &virtualRow ); + + int FontTall(); + + long m_iBlinkTime; + void ResetBlinkTime(); + + void UpdateFont(); + HFont m_Font; + int m_iFontSize; + int m_iTextInset; + int m_iEnvInfo; + void ChangeFontSize( int delta ); + + text_cursor cur; + text_cursor select[2]; + bool m_bSelectionValid; + + void ProcessDelete( bool bAfter = false ); + void ProcessCut(); + void ProcessCopy(); + void ProcessPaste(); + + + void UpdateHighlightFormats(); + void UpdateSelectionFormat(); + void OnSelectionChanged(); + + void Selection_Reset(); + void Selection_Select( text_cursor pos ); + void Selection_AddRow( int y ); + void Selection_Delete(); +public: + void ParseInsertText( const wchar_t *str ); + void ParseInsertText( const char *str ); + void Selection_Copy( text_cursor *cMin = NULL, text_cursor *cMax = NULL, wchar_t **pBuffOut = NULL, bool bAddCR = false ); // pBuffOut takes ownership +private: + void Selection_GetSorted( text_cursor *v ); + bool Selection_Active(){ return m_bSelectionValid; }; + bool Selection_Valid(){ return Selection_Active() && select[0] != select[1]; }; + bool Selection_GetRowRange( const int &row, int &x_min, int &x_max, + text_cursor *cMin = NULL, text_cursor *cMax = NULL ); + wchar_t *m_pszLastSelectedWord; + + int m_iXCursorHistory; + void StompCursorHistory(); + + bool m_bIsSelecting; + bool m_bIsRowSelecting; + long scrollDelay; + ScrollBar *m_pScrollBar_V; + CUtlVector< _smartRow* > hRows; + + void CursorToPanel( const text_cursor &c, int &x, int &y ); + void PanelToCursor( const int &x, const int &y, text_cursor &c ); + + void AdvanceScrollbarOnDemand(); + + void KillCmtList(); + void GenerateCmtList(); + void UpdateCmtFormat(); + bool IsCommented( int x, int y ); + CUtlVector< _cmtCtrl > m_hCmtList; + + bool m_bTopFormatsDirty; + bool m_bTopHighlightLock; + bool m_bTopHighlightOnTyped; + + void UpdateTopFormats( bool bDoHighlights = true ); + void MakeTopFormatsDirty(); + bool IsTopFormatsDirty(); + + + + // ac control + enum + { + ACTOOLTIP_NONE = 0, + ACTOOLTIP_FUNC, + ACTOOLTIP_OBJECT, + }; + + CSmartObjectList *m_pGlobalDatabase; + + void CreateACMenu( int iTooltipMode = ACTOOLTIP_NONE ); + void DestroyACMenu( bool bMenu = true, bool bTooltip = true ); + void DestroyHoverTooltip(); + void CreateHoverTooltipThink(); + + void OnACMenuCreationFailed(); + bool OnACCatchKeyCode( KeyCode code ); + bool OnACKeyTyped( wchar_t c ); + + void AddEnvInfoToDB(); + + void InsertFromAC( const char *pIdent = NULL ); + void CalcACPos( const text_cursor &c, int &x, int &y, int menuSizeX, int menuSizeY ); + void ReleaseTooltipOnDemand(); + bool ShouldReleaseTooltip(); + bool GetWordLeft( text_cursor &c ); + + text_cursor m_curACStart; + text_cursor m_curHoverMin, m_curHoverMax; + CSmartAutocomplete *m_pACMenu; + CSmartTooltip *m_pFuncTooltip; + CSmartTooltip *m_pHoverTooltip; + bool m_bAllowHoverTooltip; + double m_lLastCursorMoved; + + void UpdateTooltipPositions(); + + // live ac + bool m_bCodeDirty; + float m_flLastCodeParse; + + void MakeCodeDirty(); + bool IsCodeDirty(); + void UpdateParseCode(); + + + + int m_iTex_Lock; + + // history + bool IsHistoryDirty(); + void MakeHistoryDirty(); + void OnHistoryDirty(); + + void FlushHistory( bool bOld = true, bool bNew = true ); + void PushHistory( int dir = 1 ); + void PopHistory( int dir = 1 ); + + __sTextHistory *CreateHistoryEntry(); + void ApplyHistoryEntry( __sTextHistory *history ); + + CUtlVector< __sTextHistory* >hHistory_Old; + CUtlVector< __sTextHistory* >hHistory_New; + bool m_bHistoryDirty; + +public: + HHISTORYIDX GetCurrentHistoryIndex(); + +private: + + + + bool CanRead( text_cursor *c = NULL ); + const wchar_t &Read( text_cursor *c = NULL ); + void GetScopeData( text_cursor c, int &iScopeDepth, int &iScopeNum, int &iTextPos ); +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmarttooltip.cpp b/sp/src/shadereditor/properties/smarttext/vsmarttooltip.cpp new file mode 100644 index 00000000..7dc9e737 --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmarttooltip.cpp @@ -0,0 +1,223 @@ + +#include "cbase.h" +#include "vSmartObject.h" +#include "vSmartTooltip.h" +#include "vSmartText.h" + + +CSmartTooltip::CSmartTooltip( Panel *parent, const char *pElementname ) : BaseClass( parent, pElementname ) +{ + m_iParamHighlight = 0; + m_iMode = STTIPMODE_NORMAL; + m_pCurObject = NULL; + m_iFont = GetFontCacheHandle()->GetTooltipFont(); //GetFont( GetFontCacheHandle()->fSizeMin() + GetFontCacheHandle()->fStepSize() * 2 ); + + SetVisible( true ); + MakePopup( false ); + + SetMouseInputEnabled( false ); + SetKeyBoardInputEnabled( false ); +} + +CSmartTooltip::~CSmartTooltip() +{ + delete m_pCurObject; +} + +bool CSmartTooltip::IsFunctionParams() +{ + return m_iMode == STTIPMODE_FUNCTIONPARAMS; +} + +void CSmartTooltip::SetActiveParam( int iP ) +{ + m_iParamHighlight = iP; +} + +bool CSmartTooltip::Init( CSmartObject *pO, int iMode ) +{ + Assert( pO != NULL ); + m_iMode = iMode; + + delete m_pCurObject; + m_pCurObject = new CSmartObject( *pO ); + + int width = 0; + int rows = 0; + + if ( m_iMode == STTIPMODE_FUNCTIONPARAMS ) + { + width = surface()->GetCharacterWidth( m_iFont, ' ' ) * ( Q_strlen( pO->m_pszDefinition ) + 1 ); + + int screenx, screeny; + surface()->GetScreenSize( screenx, screeny ); + + rows = 1; + rows += width / screenx; + + width = min( screenx, width ); + } + else + { + rows += GetNumRowsForString( pO->m_pszDefinition, &width ); + int crows = GetNumRowsForString( pO->m_pszHelptext, &width ); + if ( crows ) crows++; + rows += crows; + crows = GetNumRowsForString( pO->m_pszSourceFile, &width ); + if ( crows ) crows++; + rows += crows; + } + + + if ( !rows || !width ) + return false; + + SetSize( width, rows * surface()->GetFontTall( m_iFont ) ); + + return true; +} + +void CSmartTooltip::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + SetBorder( pScheme->GetBorder("ButtonBorder") ); + + SetBgColor( Color( 150, 170, 220, 160 ) ); +} + +void CSmartTooltip::Paint() +{ + BaseClass::Paint(); + + if ( !m_pCurObject ) + return; + + const char *pStr[] = { + m_pCurObject->m_pszDefinition, + m_pCurObject->m_pszHelptext, + m_pCurObject->m_pszSourceFile, + }; + + int iFontTall = surface()->GetFontTall( m_iFont ); + int iCWidth = surface()->GetCharacterWidth( m_iFont, ' ' ); + int screenx, screeny; + surface()->GetScreenSize( screenx, screeny ); + + int cX, cY; + int sX, sY; + GetSize( sX, sY ); + sX -= iCWidth; + + const bool bFuncDraw = m_iMode == STTIPMODE_FUNCTIONPARAMS; + + Color colDef( 10, 10, 11, 255 ); + Color colHighlight( 0, 0, 0, 255 ); + + if ( bFuncDraw ) + colDef = Color( 70, 70, 70, 255 ); + + surface()->DrawSetTextFont( m_iFont ); + surface()->DrawSetTextColor( colDef ); + + cY = 0; + + int iCurParam = 1; + bool bHitBracket = false; + + for ( int i = 0; i < 3; i++ ) + { + if ( !pStr[i] || !*pStr[i] ) + continue; + + cX = 0; + + const char *pWalk = pStr[i]; + bool bLastLinebreak = false; + while ( *pWalk ) + { + const bool bLineBreak = *pWalk == '\n'; + const bool bTab = *pWalk == '\t'; + const bool bComma = *pWalk == ','; + const bool bBracket = *pWalk == '('; + + surface()->DrawSetTextPos( cX, cY ); + + if ( bFuncDraw && bHitBracket ) + surface()->DrawSetTextColor( (!bComma && iCurParam == m_iParamHighlight) ? colHighlight : colDef ); + + if ( !bLineBreak ) + surface()->DrawUnicodeChar( bTab ? L' ' : *pWalk ); + + if ( bFuncDraw ) + { + if ( bComma ) + iCurParam++; + if ( bBracket ) + bHitBracket = true; + } + + int curWidth = iCWidth; //surface()->GetCharacterWidth( m_iFont, *pWalk ); + + if ( cX + (curWidth) < sX && !bLineBreak ) + { + cX += curWidth; + bLastLinebreak = false; + } + else if ( *( pWalk + 1 ) || bLineBreak && !bLastLinebreak ) + { + cX = 0; + cY += iFontTall; + bLastLinebreak = bLineBreak; + } + + pWalk++; + } + + cY += iFontTall * 2; + } +} + +int CSmartTooltip::GetNumRowsForString( const char *pStr, int *max_x ) +{ + if ( !pStr || !*pStr ) + return 0; + + int numRows = 1; + + //int x,y; + //GetSize( x, y ); + const int x = 400; + + int curX = 0; + int curMax = 0; + + int iCWidth = surface()->GetCharacterWidth( m_iFont, ' ' ); + + const char *pWalk = pStr; + bool bLastLinebreak = false; + while ( pWalk && *pWalk ) + { + const int curSize = iCWidth; //surface()->GetCharacterWidth( m_iFont, *pWalk ); + const bool bLineBreak = *pWalk == '\n'; + if ( curX + (curSize) < x && !bLineBreak ) + { + curX += curSize; + bLastLinebreak = false; + } + else if ( *( pWalk + 1 ) || bLineBreak && !bLastLinebreak ) + { + curX = 0; + numRows++; + bLastLinebreak = bLineBreak; + } + + curMax = max( curMax, curX ); + pWalk++; + } + + if ( max_x != NULL ) + *max_x = max( *max_x, curMax + iCWidth * 2 ); + + return numRows; +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/smarttext/vsmarttooltip.h b/sp/src/shadereditor/properties/smarttext/vsmarttooltip.h new file mode 100644 index 00000000..d039a7ac --- /dev/null +++ b/sp/src/shadereditor/properties/smarttext/vsmarttooltip.h @@ -0,0 +1,46 @@ +#ifndef SMART_TOOLTIP_H +#define SMART_TOOLTIP_H + +#include "cbase.h" +#include "vgui_controls/controls.h" +#include + +using namespace vgui; + +class CSmartObject; + +class CSmartTooltip : public Panel +{ + DECLARE_CLASS_SIMPLE( CSmartTooltip, Panel ); +public: + + enum + { + STTIPMODE_NORMAL = 0, + STTIPMODE_FUNCTIONPARAMS + }; + + CSmartTooltip( Panel *parent, const char *pElementname ); + ~CSmartTooltip(); + + bool Init( CSmartObject *pO, int iMode = STTIPMODE_NORMAL ); + + void SetActiveParam( int iP ); + + void Paint(); + void ApplySchemeSettings(IScheme *pScheme); + + bool IsFunctionParams(); + +private: + int GetNumRowsForString( const char *pStr, int *max_x = NULL ); + + CSmartObject *m_pCurObject; + + int m_iFont; + + int m_iMode; + int m_iParamHighlight; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vcodeeditor.cpp b/sp/src/shadereditor/properties/vcodeeditor.cpp new file mode 100644 index 00000000..6228518d --- /dev/null +++ b/sp/src/shadereditor/properties/vcodeeditor.cpp @@ -0,0 +1,308 @@ + +#include "cbase.h" +#include "vSheets.h" +#include "vSmartText.h" +#include "vSmartRow.h" +#include "editorcommon.h" + +CCode_Editor::CCode_Editor( CSheet_Base *parent, const char *pName, CSmartText::CodeEditMode_t mode ) : BaseClass( parent, pName ) +{ + m_iMode = mode; + + Activate(); + SetVisible( true ); + + SetPaintBackgroundEnabled(true); + SetPaintEnabled(true); + + SetSizeable(true); + SetMoveable(true); + SetMinimumSize( 500, 400 ); + + SetDeleteSelfOnClose( true ); + + m_iLastAppliedCodeIndex = 0; + + m_pCodeWindow = new CSmartText( this, "codewindow", mode ); + m_pCodeWindow->AddActionSignalTarget( this ); + + /* + TextEntry *pT = new TextEntry( this, "codewindow" ); + pT->SetMultiline( true ); + pT->SetEditable( true ); + pT->SetCatchEnterKey( true ); + pT->SetVerticalScrollbar( true ); + */ + + LoadControlSettings( "shadereditorui/vgui/code_editor_Window.res" ); + + UpdateButtonEnabled( true, true ); + SetCloseButtonVisible(false); + + int w,t; + surface()->GetScreenSize( w, t ); + w *= 0.75f; + t *= 0.75f; + SetSize( max( w, 500 ), max( t, 400 ) ); + + //SetKeyBoardInputEnabled( false ); + //SetMouseInputEnabled( true ); + + //SetTitle( "Editor", true ); + SetTitle( "", false ); + + Panel *pButton = FindChildByName( "button_save" ); + if ( pButton ) + pButton->SetKeyBoardInputEnabled( false ); + + pButton = FindChildByName( "button_apply" ); + if ( pButton ) + pButton->SetKeyBoardInputEnabled( false ); + pButton = FindChildByName( "button_cancel" ); + if ( pButton ) + pButton->SetKeyBoardInputEnabled( false ); + + DoModal(); + + int rx, ry, rsx, rsy; + if ( pEditorRoot->GetCodeEditorBounds( rx, ry, rsx, rsy ) ) + SetBounds( rx, ry, rsx, rsy ); + else + MoveToCenterOfScreen(); +} + +CCode_Editor::~CCode_Editor() +{ + int rx, ry, rsx, rsy; + GetBounds( rx, ry, rsx, rsy ); + pEditorRoot->SetCodeEditorBounds( rx, ry, rsx, rsy ); +} + +void CCode_Editor::OnKeyCodeTyped( KeyCode code ) +{ + if ( code == KEY_B && + input()->IsKeyDown( KEY_LSHIFT ) && + input()->IsKeyDown( KEY_LCONTROL ) && + input()->IsKeyDown( KEY_LALT ) ) + { + BaseClass::OnKeyCodeTyped( code ); + return; + } + + if ( IsBuildModeActive() ) + BaseClass::OnKeyCodeTyped( code ); + else + m_pCodeWindow->OnKeyCodeTyped( code ); +} + +void CCode_Editor::OnKeyTyped( wchar_t c ) +{ + if ( IsBuildModeActive() ) + BaseClass::OnKeyTyped( c ); + else + m_pCodeWindow->OnKeyTyped( c ); +} + +void CCode_Editor::InitHlsl( const char *pszFunctionName, CUtlVector< __funcParamSetup* > *input, CUtlVector< __funcParamSetup* > *output, + const char *pszCodeGlobal, const char *pszCodeBody, + const int iHlslHierachy, const int iEnvData ) +{ + Assert( pszFunctionName && input && output ); + + m_pCodeWindow->SetEnvInfo( iEnvData ); + m_pCodeWindow->DoFullParserUpdate( iHlslHierachy ); + + char szFunc[MAX_PATH*4]; + BuildUserFunctionName( pszFunctionName, *input, *output, szFunc, sizeof(szFunc) ); + m_pCodeWindow->SetRowDeletable(false); + + const bool bGlobalValid = pszCodeGlobal && Q_strlen(pszCodeGlobal) >= 1; + if ( bGlobalValid ) + { + m_pCodeWindow->MoveCursorTo( 0, 0 ); + m_pCodeWindow->ParseInsertText( pszCodeGlobal ); + } + + m_pCodeWindow->InsertRow( szFunc ); + m_pCodeWindow->SetRowLocked(true); + + m_pCodeWindow->InsertRow( "{" ); + m_pCodeWindow->SetRowLocked(true); + + const bool bBodyValid = pszCodeBody && Q_strlen(pszCodeBody) >= 1; + _smartRow *pBodyFirstLine = m_pCodeWindow->InsertRow( bBodyValid ? NULL : "\t" ); + m_pCodeWindow->SetRowDeletable( false ); + + if ( bBodyValid ) + { + m_pCodeWindow->MoveCursorTo( 0, m_pCodeWindow->FindRow( pBodyFirstLine ) ); + m_pCodeWindow->ParseInsertText( pszCodeBody ); + } + + m_pCodeWindow->InsertRow( "}" ); + m_pCodeWindow->SetRowLocked(true); + + m_pCodeWindow->MoveCursorTo( 1, m_pCodeWindow->FindRow( pBodyFirstLine ) ); +} + +void CCode_Editor::InitVMT( const char *pszVmt ) +{ + Assert( pszVmt && *pszVmt ); + + m_pCodeWindow->MoveCursorTo( 0, 0 ); + m_pCodeWindow->ParseInsertText( pszVmt ); + + m_pCodeWindow->SetACEnabled( false ); + m_pCodeWindow->SetLiveParseEnabled( false ); + m_pCodeWindow->SetSyntaxHighlightEnabled( false ); +} + +void CCode_Editor::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( cmd, "save_code" ) ) + { + ApplyCode( false ); + + Close(); + } + else if ( !Q_stricmp( cmd, "apply_code" ) ) + { + ApplyCode( true ); + } + else + BaseClass::OnCommand( cmd ); +} + +void CCode_Editor::ApplyCode( bool bDoInject ) +{ + if ( m_iMode == CSmartText::CODEEDITMODE_HLSL ) + { + text_cursor start( 0, 0 ); + text_cursor end( 0, m_pCodeWindow->GetLockedRow( 1 ) - 1 ); + m_pCodeWindow->MoveCursorToEndOfRow( -1, &end ); + + text_cursor start_body( 0, m_pCodeWindow->GetLockedRow( 2 ) + 1 ); + text_cursor end_body( 0, m_pCodeWindow->GetLockedRow( 3 ) - 1 ); + m_pCodeWindow->MoveCursorToEndOfRow( -1, &end_body ); + + m_pCodeWindow->ClearDynamicSpacing(); + + char *pGlobal = ReadSnippet( start, end ); + char *pBody = ReadSnippet( start_body, end_body ); + + KeyValues *pCodeMsg = new KeyValues("CodeUpdate"); + if ( pGlobal && Q_strlen( pGlobal ) ) + CKVPacker::KVPack( pGlobal, "szcode_global", pCodeMsg ); + //pCodeMsg->SetString( "szcode_global", pGlobal ); + if ( pBody && Q_strlen( pBody ) ) + CKVPacker::KVPack( pBody, "szcode_body", pCodeMsg ); + //pCodeMsg->SetString( "szcode_body", pBody ); + pCodeMsg->SetInt( "doinject", bDoInject ? 1 : 0 ); + PostActionSignal( pCodeMsg ); + + delete [] pGlobal; + delete [] pBody; + } + else if ( m_iMode == CSmartText::CODEEDITMODE_VMT ) + { + text_cursor start( 0, 0 ); + text_cursor end( -1, -1 ); + m_pCodeWindow->MoveCursorToEndOfText( &end ); + + m_pCodeWindow->ClearDynamicSpacing(); + + char *pVMT = ReadSnippet( start, end ); + + KeyValues *pVMTMsg = new KeyValues("CodeUpdate"); + if ( pVMT ) + CKVPacker::KVPack( pVMT, "szVMTString", pVMTMsg ); + //pVMTMsg->SetString( "szVMTString", pVMT ); + pVMTMsg->SetInt( "doinject", bDoInject ? 1 : 0 ); + PostActionSignal( pVMTMsg ); + + delete [] pVMT; + } + else + Assert(0); + + m_iLastAppliedCodeIndex = m_pCodeWindow->GetCurrentHistoryIndex(); + UpdateButtonEnabled( true, false ); +} + +void CCode_Editor::OnCodeChanged() +{ + HHISTORYIDX curIdx = m_pCodeWindow->GetCurrentHistoryIndex(); + + UpdateButtonEnabled( true, curIdx != m_iLastAppliedCodeIndex ); +} + +void CCode_Editor::UpdateButtonEnabled( bool bShowSave, bool bShowApply ) +{ + Panel *pButton = FindChildByName( "button_save" ); + if ( pButton ) + pButton->SetEnabled( bShowSave ); + + pButton = FindChildByName( "button_apply" ); + if ( pButton ) + pButton->SetEnabled( bShowApply ); +} + +char *CCode_Editor::ReadSnippet( text_cursor c0, text_cursor c1, bool bAddCR ) +{ + if ( c1 < c0 ) + return NULL; + + wchar_t *pW; + m_pCodeWindow->Selection_Copy( &c0, &c1, &pW, bAddCR ); + + if ( !pW ) + return NULL; + + bool bValid = false; + wchar_t *pFindChar = pW; + + while ( *pFindChar && !bValid ) + { + if ( *pFindChar != L' ' && + *pFindChar != L'\t' && + *pFindChar != L'\r' && + *pFindChar != L'\n' ) + bValid = true; + pFindChar++; + } + + char *pC = NULL; + + if ( bValid ) + { + int len = Q_wcslen( pW ) + 1; + pC = new char[ len ]; + Q_UnicodeToUTF8( pW, pC, len ); + } + + delete [] pW; + return pC; +} + +#if DEBUG +CON_COMMAND( memTest, "" ) +{ + CUtlVector< unsigned char* >hMem; + for ( int i = 0; i < 9999999; i++ ) + { + //int len = 1; //RandomInt( 0, 2 ) ? RandomInt( 1, 5 ) : RandomInt( 1, 99 ); + + unsigned char *_array = new unsigned char; + + //for ( int a = 0; a < len; a++ ) + *_array = 255; //RandomInt( 0, 255 ); + + hMem.AddToTail( _array ); + } + + for ( int i = 0; i < hMem.Count(); i++ ) + delete hMem[i]; + + hMem.Purge(); +} +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vcodeeditor.h b/sp/src/shadereditor/properties/vcodeeditor.h new file mode 100644 index 00000000..8b938b5e --- /dev/null +++ b/sp/src/shadereditor/properties/vcodeeditor.h @@ -0,0 +1,51 @@ +#ifndef CCODE_EDITOR_H +#define CCODE_EDITOR_H + +#include "vSheets.h" + +#include +#include "vSmartText.h" + +//class CSmartText; +class CSheet_Base; +struct _smartRow; +struct text_cursor; + +class CCode_Editor : public Frame +{ +public: + DECLARE_CLASS_SIMPLE( CCode_Editor, Frame ); + + CCode_Editor( CSheet_Base *parent, const char *pName, CSmartText::CodeEditMode_t mode = CSmartText::CODEEDITMODE_HLSL ); + ~CCode_Editor(); + + void InitHlsl( const char *pszFunctionName = NULL, CUtlVector< __funcParamSetup* > *input = NULL, CUtlVector< __funcParamSetup* > *output = NULL, + const char *pszCodeGlobal = NULL, const char *pszCodeBody = NULL, + const int iHlslHierachy = HLSLHIERACHY_PS | HLSLHIERACHY_VS, const int iEnvData = 0 ); + void InitVMT( const char *pszVmt ); + + void OnKeyCodeTyped( KeyCode code ); + void OnKeyTyped( wchar_t c ); + + void OnCommand( const char *cmd ); + + MESSAGE_FUNC( OnCodeChanged, "CodeChanged" ); + +private: + + CSmartText::CodeEditMode_t m_iMode; + + void ApplyCode( bool bDoInject ); + + HHISTORYIDX m_iLastAppliedCodeIndex; + + void UpdateButtonEnabled( bool bShowSave, bool bShowApply ); + + CSmartText *m_pCodeWindow; + + char *ReadSnippet( text_cursor c0, text_cursor c1, bool bAddCR = true ); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vnodeproperties.cpp b/sp/src/shadereditor/properties/vnodeproperties.cpp new file mode 100644 index 00000000..52ed491f --- /dev/null +++ b/sp/src/shadereditor/properties/vnodeproperties.cpp @@ -0,0 +1,85 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CNodePropertySheet::CNodePropertySheet( CBaseNode *pNode, CNodeView *parent, const char *panelName ) + : BaseClass( parent, panelName ) +{ + n = pNode; + pNodeView = parent; + + SetSize( 480, 400 ); + MoveToCenterOfScreen(); + + SetApplyButtonVisible( false ); + //DoModal(); + + SetTitle( "Properties", false ); + + pKV_NodeSettings = GetNode()->AllocateKeyValues(0); + pKV_NodeSettings_Original = pKV_NodeSettings->MakeCopy(); +} + +CNodePropertySheet::~CNodePropertySheet() +{ + if ( pKV_NodeSettings ) + pKV_NodeSettings->deleteThis(); + + if ( pKV_NodeSettings_Original ) + pKV_NodeSettings_Original->deleteThis(); +} + +CBaseNode *CNodePropertySheet::GetNode() +{ + return n; +} + +KeyValues *CNodePropertySheet::GetPropertyContainer() +{ + return pKV_NodeSettings; +} + +void CNodePropertySheet::ResetAllData() +{ + BaseClass::ResetAllData(); +} + +bool CNodePropertySheet::OnOK(bool applyOnly) +{ + bool b = BaseClass::OnOK(applyOnly); + + if ( GetPropertySheet() ) + { + for ( int i = 0; i < GetPropertySheet()->GetNumPages(); i++ ) + PostMessage( GetPropertySheet()->GetPage(i), new KeyValues( "RestoreNode" ) ); + } + + GetNode()->RestoreFromKeyValues( pKV_NodeSettings ); + //GetNode()->RestoreFromKeyValues_CreateBridges( pKV_NodeSettings ); + + pNodeView->MakeSolversDirty(); + + return b; +} + +void CNodePropertySheet::OnCancel() +{ + bool bDoReset = false; + for ( int i = 0; i < GetPropertySheet()->GetNumPages(); i++ ) + { + CSheet_Base *pSheet = assert_cast< CSheet_Base* >( GetPropertySheet()->GetPage( i ) ); + + if ( pSheet->RequiresReset() ) + bDoReset = true; + } + + if ( bDoReset ) + { + GetNode()->RestoreFromKeyValues( pKV_NodeSettings_Original ); + + pNodeView->MakeSolversDirty(); + } + + BaseClass::OnCancel(); +} diff --git a/sp/src/shadereditor/properties/vnodeproperties.h b/sp/src/shadereditor/properties/vnodeproperties.h new file mode 100644 index 00000000..cb7f18fe --- /dev/null +++ b/sp/src/shadereditor/properties/vnodeproperties.h @@ -0,0 +1,45 @@ +#ifndef CNODEPROPERTIES_H +#define CNODEPROPERTIES_H + +#include "vSheets.h" + +#include "vgui_controls/Controls.h" +#include +#include +#include +#include +#include +#include +#include +#include + +class CNodePropertySheet : public PropertyDialog +{ +public: + DECLARE_CLASS_SIMPLE( CNodePropertySheet, PropertyDialog ); + + CNodePropertySheet(CBaseNode *pNode, CNodeView *parent, const char *panelName); + ~CNodePropertySheet(); + + CBaseNode *GetNode(); + + virtual void ResetAllData(); + + KeyValues *GetPropertyContainer(); + +protected: + virtual bool OnOK(bool applyOnly); + virtual void OnCancel(); + + CBaseNode *n; + KeyValues *pKV_NodeSettings; + KeyValues *pKV_NodeSettings_Original; + + CNodeView *pNodeView; + +private: + CNodePropertySheet( const CNodePropertySheet &other ); +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_array.cpp b/sp/src/shadereditor/properties/vsheet_array.cpp new file mode 100644 index 00000000..26c3f3ab --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_array.cpp @@ -0,0 +1,288 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Array::CSheet_Array(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pTEntry_Size_X = new TextEntry( this, "asize_x" ); + m_pTEntry_Size_Y = new TextEntry( this, "asize_y" ); + m_pTEntry_Gauss_Bias = new TextEntry( this, "gauss_bias" ); + m_pTEntry_Random_Min = new TextEntry( this, "ran_min" ); + m_pTEntry_Random_Max = new TextEntry( this, "ran_max" ); + m_pCBox_Datatype = new ComboBox( this, "cbox_datatype", 10, false ); + for ( int i = 0; i < 4; i++ ) + m_pCBox_Datatype->AddItem( ::GetVarTypeName( i ), NULL ); + + m_pArrayPanel = new PanelListPanel( this, "array_panel" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_array.res" ); + + m_pTEntry_Random_Min->SetText( "0" ); + m_pTEntry_Random_Max->SetText( "1" ); +} +CSheet_Array::~CSheet_Array() +{ + for ( int i = 0; i < m_hArray_Y_Major.Count(); i++ ) + { + m_hArray_Y_Major[i]->Purge(); + delete m_hArray_Y_Major[i]; + } + m_hArray_Y_Major.Purge(); +} + +void CSheet_Array::OnResetData() +{ + int num_x = pData->GetInt( "i_array_size_x", 1 ); + int num_y = pData->GetInt( "i_array_size_y", 1 ); + m_pTEntry_Size_X->SetText( VarArgs( "%i", num_x ) ); + m_pTEntry_Size_Y->SetText( VarArgs( "%i", num_y ) ); + m_pTEntry_Gauss_Bias->SetText( "0.0" ); + int iEnum = ::GetVarFlagsVarValue( pData->GetInt( "i_array_datatype" ) ); + m_pCBox_Datatype->ActivateItem( iEnum ); + + UpdateArrayBlocks( num_x, num_y ); + + ::TokenChannels_t tokens; + for ( int x = 0; x < num_x; x++ ) + { + for ( int y = 0; y < num_y; y++ ) + { + int element = num_y * x + y; + + char tmp[MAX_PATH]; + Q_snprintf( tmp, sizeof( tmp ), "%s", pData->GetString( VarArgs( "pfl_arraydata_%03i", element ) ) ); + + tokens.bAllowChars = false; + tokens.SetDefaultChannels(); + tokens.Tokenize( tmp ); + tokens.iActiveChannels = iEnum + 1; + tokens.PrintTargetString( tmp, sizeof( tmp ) ); + + m_hArray_Y_Major[ y ]->Element( x )->SetText( tmp ); + } + } +} +void CSheet_Array::OnApplyChanges() +{ + int cur_x, cur_y; + char ***entries = BuildStringSheet( cur_x, cur_y ); + int iEnum = clamp( m_pCBox_Datatype->GetActiveItem(), 0, 3 ); + + pData->SetInt( "i_array_datatype", ::GetVarTypeFlag( iEnum ) ); + pData->SetInt( "i_array_size_x", cur_x ); + pData->SetInt( "i_array_size_y", cur_y ); + + ::TokenChannels_t tokens; + + for ( int x = 0; x < cur_x; x++ ) + { + for ( int y = 0; y < cur_y; y++ ) + { + int element = cur_y * x + y; + //m_hArray_X_Major[ x ]->Element( y )->GetText( tmp, sizeof( tmp ) ); + char *str = entries[x][y]; + char tmp[MAX_PATH]; + + tokens.bAllowChars = false; + tokens.Tokenize( str ); + tokens.PrintTargetString( tmp, sizeof( tmp ) ); + pData->SetString( VarArgs( "pfl_arraydata_%03i", element ), tmp ); + } + } + + DestroyStringSheet( entries, cur_x, cur_y ); +} + +void CSheet_Array::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( cmd, "update_array" ) ) + { + int new_x = 1; + int new_y = 1; + + char tmp[MAX_PATH]; + m_pTEntry_Size_X->GetText( tmp, sizeof( tmp ) ); + new_x = max( new_x, atoi( tmp ) ); + m_pTEntry_Size_Y->GetText( tmp, sizeof( tmp ) ); + new_y = max( new_y, atoi( tmp ) ); + + UpdateArrayBlocks( new_x, new_y ); + } + else if ( !Q_stricmp( cmd, "fill_gauss" ) ) + { + m_pCBox_Datatype->ActivateItem( 0 ); + + char tmp[MAX_PATH]; + m_pTEntry_Gauss_Bias->GetText( tmp, sizeof( tmp ) ); + + float gauss_bias = atof( tmp ); + int asize_y = m_hArray_Y_Major.Count(); + int asize_x = ( asize_y > 0 ) ? m_hArray_Y_Major[0]->Count() : 0; + bool bIs2D = asize_y > 1; + for ( int x = 0; x < asize_x; x++ ) + { + for ( int y = 0; y < asize_y; y++ ) + { + float flWeight = 0; + if ( bIs2D ) + flWeight = ::GaussianWeight_2D( x, y, asize_x, asize_y, gauss_bias ); + else + flWeight = ::GaussianWeight_1D( x, asize_x, gauss_bias ); + m_hArray_Y_Major[y]->Element(x)->SetText( VarArgs( "%f", flWeight ) ); + } + } + } + else if ( !Q_stricmp( cmd, "fill_random" ) ) + { + int numComps = m_pCBox_Datatype->GetActiveItem(); + float ran_min, ran_max; + char tmp[MAX_PATH]; + + m_pTEntry_Random_Min->GetText( tmp, sizeof( tmp ) ); + ran_min = atof( tmp ); + m_pTEntry_Random_Max->GetText( tmp, sizeof( tmp ) ); + ran_max = atof( tmp ); + + int asize_y = m_hArray_Y_Major.Count(); + int asize_x = ( asize_y > 0 ) ? m_hArray_Y_Major[0]->Count() : 0; + + for ( int x = 0; x < asize_x; x++ ) + { + for ( int y = 0; y < asize_y; y++ ) + { + tmp[0] = '\0'; + + char szComp[32]; + for ( int c = 0; c <= numComps; c++ ) + { + Q_snprintf( szComp, sizeof( szComp ), "%f", RandomFloat( ran_min, ran_max ) ); + Q_strcat( tmp, szComp, sizeof( tmp ) ); + if ( c < numComps ) + Q_strcat( tmp, " ", sizeof( tmp ) ); + } + + m_hArray_Y_Major[y]->Element(x)->SetText( tmp ); + } + } + } + else + BaseClass::OnCommand( cmd ); +} +void CSheet_Array::OnTextFocusLost( KeyValues *pKV ) +{ + Panel *pCaller = (Panel*)pKV->GetPtr("panel"); + if ( pCaller == m_pTEntry_Size_X || pCaller == m_pTEntry_Size_Y ) + { + } +} +void CSheet_Array::OnTextChanged( KeyValues *pKV ) +{ + //Panel *pCaller = (Panel*)pKV->GetPtr("panel"); +} + +char ***CSheet_Array::BuildStringSheet( int &sizex, int &sizey ) +{ + sizey = m_hArray_Y_Major.Count(); + sizex = ( sizey > 0 ) ? m_hArray_Y_Major[0]->Count() : 0; + + if ( sizex <= 0 || sizey <= 0 ) + return NULL; + + char ***strings = new char**[sizex]; + for ( int x = 0; x < sizex; x++ ) + { + strings[ x ] = new char*[sizey]; + for ( int y = 0; y < sizey; y++ ) + { + char szOld[MAX_PATH]; + m_hArray_Y_Major[y]->Element( x )->GetText( szOld, sizeof( szOld ) ); + int textlen = Q_strlen( szOld ) + 1; + strings[x][y] = new char[ textlen ]; + Q_strcpy( strings[x][y], szOld ); + } + } + + return strings; +} +void CSheet_Array::DestroyStringSheet( char ***strings, const int &sizex, const int &sizey ) +{ + for ( int x = 0; x < sizex; x++ ) + { + for ( int y = 0; y < sizey; y++ ) + delete [] strings[x][y]; + delete [] strings[x]; + } + delete[] strings; +} +void CSheet_Array::UpdateArrayBlocks( const int &dest_x, const int &dest_y ) +{ + int old_x, old_y; + old_x = old_y = 0; + char ***oldEntires = BuildStringSheet( old_x, old_y ); + + for ( int y = 0; y < old_y; y++ ) + { + //for ( int x = 0; x < old_x; x++ ) + m_hArray_Y_Major[y]->Purge(); + delete m_hArray_Y_Major[y]; + } + m_hArray_Y_Major.Purge(); + + int iCurItem = m_pArrayPanel->FirstItem(); + while ( iCurItem != m_pArrayPanel->InvalidItemID() ) + { + Panel *pA = m_pArrayPanel->GetItemLabel( iCurItem ); + Panel *pB = m_pArrayPanel->GetItemPanel( iCurItem ); + if ( pA != NULL ) + pA->MarkForDeletion(); + if ( pB != NULL ) + pB->MarkForDeletion(); + iCurItem = m_pArrayPanel->NextItem( iCurItem ); + } + m_pArrayPanel->DeleteAllItems(); + m_pArrayPanel->RemoveAll(); + + for ( int y = 0; y < dest_y; y++ ) + { + CUtlVector< TextEntry* > *cur = new CUtlVector< TextEntry* >; + m_hArray_Y_Major.AddToTail( cur ); + } + + m_pArrayPanel->SetNumColumns( dest_y ); + for ( int x = 0; x < dest_x; x++ ) + { + for ( int y = 0; y < dest_y; y++ ) + { + CUtlVector< TextEntry* > *cur = m_hArray_Y_Major[y]; + + TextEntry *pEntry = new TextEntry( m_pArrayPanel, "arrayslot" ); + pEntry->AddActionSignalTarget( this ); + cur->AddToTail( pEntry ); + + if ( x < old_x && + y < old_y && oldEntires != NULL ) + { + pEntry->SetText( oldEntires[x][y] ); + } + else + pEntry->SetText( "0" ); + + Label *pHeader = NULL; + if ( y == 0 ) + pHeader = new Label( m_pArrayPanel, "", VarArgs( "%i:", x ) ); + + m_pArrayPanel->AddItem( pHeader, pEntry ); + pEntry->MakeReadyForUse(); + pEntry->InvalidateLayout( true, true ); + pEntry->SetBgColor( TOKENCHANNELS_SUPPORTED_COLOR ); + } + } + m_pArrayPanel->SetFirstColumnWidth( 20 ); + + if ( oldEntires != NULL ) + DestroyStringSheet( oldEntires, old_x, old_y ); +} diff --git a/sp/src/shadereditor/properties/vsheet_array.h b/sp/src/shadereditor/properties/vsheet_array.h new file mode 100644 index 00000000..13e651a1 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_array.h @@ -0,0 +1,46 @@ +#ifndef CSHEET_ARRAY_H +#define CSHEET_ARRAY_H + +#include "vSheets.h" + + +class CSheet_Array : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Array, CSheet_Base ); + + CSheet_Array(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Array(); + + virtual const char *GetSheetTitle(){return"Array";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_PARAMS( OnTextFocusLost, "TextKillFocus", pKV ); + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + + void OnCommand( const char *cmd ); + +private: + + char ***BuildStringSheet( int &sizex, int &sizey ); + void DestroyStringSheet( char ***strings, const int &sizex, const int &sizey ); + + void UpdateArrayBlocks( const int &dest_x, const int &dest_y ); + + TextEntry *m_pTEntry_Size_X; + TextEntry *m_pTEntry_Size_Y; + + TextEntry *m_pTEntry_Random_Min; + TextEntry *m_pTEntry_Random_Max; + TextEntry *m_pTEntry_Gauss_Bias; + + ComboBox *m_pCBox_Datatype; + + PanelListPanel *m_pArrayPanel; + CUtlVector< CUtlVector< TextEntry* >* >m_hArray_Y_Major; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_base.cpp b/sp/src/shadereditor/properties/vsheet_base.cpp new file mode 100644 index 00000000..9e12eada --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_base.cpp @@ -0,0 +1,32 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Base::CSheet_Base(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) : PropertyPage( parent, "" ) +{ + n = pNode; + pData = data; + pView = view; + szDynamicTitle = NULL; +} +CSheet_Base::~CSheet_Base() +{ + delete [] szDynamicTitle; +} + +CBaseNode *CSheet_Base::GetNode() +{ + return n; +} +KeyValues *CSheet_Base::GetData() +{ + return pData; +} + +void CSheet_Base::SetDynamicTitle( const char *name ) +{ + delete [] szDynamicTitle; + szDynamicTitle = new char[Q_strlen(name)+1]; + Q_strcpy( szDynamicTitle, name ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_base.h b/sp/src/shadereditor/properties/vsheet_base.h new file mode 100644 index 00000000..220f0f6b --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_base.h @@ -0,0 +1,37 @@ +#ifndef CSHEET_BASE_H +#define CSHEET_BASE_H + +#include "vSheets.h" + + +class CSheet_Base : public PropertyPage +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Base, PropertyPage ); + + CSheet_Base(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + virtual ~CSheet_Base(); + + CBaseNode *GetNode(); + KeyValues *GetData(); + + //virtual const char *GetSheetTitle(){return"base";}; + virtual const char *GetSheetTitle(){Assert(szDynamicTitle); return szDynamicTitle;}; + void SetDynamicTitle( const char *name ); + + virtual bool RequiresReset(){ return false; }; + +protected: + CNodeView *pView; + + CBaseNode *n; + KeyValues *pData; + + char *szDynamicTitle; + +private: + CSheet_Base( const CSheet_Base &other ); +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_callback.cpp b/sp/src/shadereditor/properties/vsheet_callback.cpp new file mode 100644 index 00000000..105fec16 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_callback.cpp @@ -0,0 +1,55 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Callback::CSheet_Callback(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_Callbacks = new ComboBox( this, "cbox_callbacks", 10, false ); + + for ( int i = 0; i < shaderEdit->GetNumCallbacks(); i++ ) + { + _clCallback *c = shaderEdit->GetCallback( i ); + m_pCBox_Callbacks->AddItem( c->name, NULL ); + } + + LoadControlSettings( "shadereditorui/vgui/sheet_callback.res" ); +} +CSheet_Callback::~CSheet_Callback() +{ +} + +void CSheet_Callback::OnResetData() +{ + const char *callbackname = pData->GetString( "sz_callbackname" ); + int target = -1; + for ( int i = 0; i < m_pCBox_Callbacks->GetItemCount(); i++ ) + { + char tmp[ MAX_PATH ]; + m_pCBox_Callbacks->GetItemText( i, tmp, MAX_PATH ); + if ( !Q_stricmp( tmp, callbackname ) ) + target = i; + } + + if ( target >= 0 ) + m_pCBox_Callbacks->ActivateItem( target ); +} +void CSheet_Callback::OnApplyChanges() +{ + if ( !m_pCBox_Callbacks->GetItemCount() ) + return; + + int ID = m_pCBox_Callbacks->GetActiveItem(); + if ( ID < 0 || ID >= shaderEdit->GetNumCallbacks() ) + return; + + char tmp[ MAX_PATH ]; + m_pCBox_Callbacks->GetItemText( ID, tmp, MAX_PATH ); + pData->SetString( "sz_callbackname", tmp ); + + _clCallback *c = shaderEdit->GetCallback( ID ); + pData->SetInt( "i_numc", c->numComps ); +} diff --git a/sp/src/shadereditor/properties/vsheet_callback.h b/sp/src/shadereditor/properties/vsheet_callback.h new file mode 100644 index 00000000..ad1fc184 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_callback.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_CALLBACK_H +#define CSHEET_CALLBACK_H + +#include "vSheets.h" + + +class CSheet_Callback : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Callback, CSheet_Base ); + + CSheet_Callback(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Callback(); + + virtual const char *GetSheetTitle(){return"Callback";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_Callbacks; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_cmatrix.cpp b/sp/src/shadereditor/properties/vsheet_cmatrix.cpp new file mode 100644 index 00000000..ec1f0e5d --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_cmatrix.cpp @@ -0,0 +1,28 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_CMatrix::CSheet_CMatrix(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_MType = new ComboBox( this, "cbox_mtype", 10, false ); + for ( int i = 0; i < CMATRIX_LAST; i++ ) + m_pCBox_MType->AddItem( GetCMatrixInfo( i )->szCanvasName, NULL ); + + LoadControlSettings( "shadereditorui/vgui/sheet_cmatrix.res" ); +} +CSheet_CMatrix::~CSheet_CMatrix() +{ +} + +void CSheet_CMatrix::OnResetData() +{ + m_pCBox_MType->ActivateItem( pData->GetInt( "i_c_matrix" ) ); +} +void CSheet_CMatrix::OnApplyChanges() +{ + pData->SetInt( "i_c_matrix", m_pCBox_MType->GetActiveItem() ); +} diff --git a/sp/src/shadereditor/properties/vsheet_cmatrix.h b/sp/src/shadereditor/properties/vsheet_cmatrix.h new file mode 100644 index 00000000..1ed598cf --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_cmatrix.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_CMATRIX_H +#define CSHEET_CMATRIX_H + +#include "vSheets.h" + + +class CSheet_CMatrix : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_CMatrix, CSheet_Base ); + + CSheet_CMatrix(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_CMatrix(); + + virtual const char *GetSheetTitle(){return"Custom matrix";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_MType; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_combo.cpp b/sp/src/shadereditor/properties/vsheet_combo.cpp new file mode 100644 index 00000000..c48c7af1 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_combo.cpp @@ -0,0 +1,45 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Combo::CSheet_Combo(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_Condition = new ComboBox( this, "cbox_condition", 6, false ); + for ( int i = 0; i < 5; i++ ) + m_pCBox_Condition->AddItem( GetConditionCodeString( i ), NULL ); + + m_pText_ComboName = new TextEntry( this, "text_cname" ); + m_pText_ComboVar = new TextEntry( this, "text_cvar" ); + m_pCheck_Static = new CheckButton( this, "check_static", "" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_combo.res" ); +} +CSheet_Combo::~CSheet_Combo() +{ +} + +void CSheet_Combo::OnResetData() +{ + m_pCBox_Condition->ActivateItem( clamp( pData->GetInt( "i_combo_condition" ), 0, 4 ) ); + m_pText_ComboVar->SetText( VarArgs( "%i", pData->GetInt( "i_combo_value" ) ) ); + m_pText_ComboName->SetText( pData->GetString( "sz_cname" ) ); + m_pCheck_Static->SetSelected( !!pData->GetInt( "i_combo_static" ) ); +} +void CSheet_Combo::OnApplyChanges() +{ + char tmp[MAX_PATH]; + char tmp2[MAX_PATH]; + m_pText_ComboName->GetText( tmp, MAX_PATH ); + ::CleanupString( tmp, tmp2, MAX_PATH ); + pData->SetString( "sz_cname", tmp2 ); + + m_pText_ComboVar->GetText( tmp, MAX_PATH ); + pData->SetInt( "i_combo_value", atoi( tmp ) ); + + pData->SetInt( "i_combo_condition", m_pCBox_Condition->GetActiveItem() ); + pData->SetInt( "i_combo_static", m_pCheck_Static->IsSelected() ? 1 : 0 ); +} diff --git a/sp/src/shadereditor/properties/vsheet_combo.h b/sp/src/shadereditor/properties/vsheet_combo.h new file mode 100644 index 00000000..751ef7ca --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_combo.h @@ -0,0 +1,29 @@ +#ifndef CSHEET_COMBO_H +#define CSHEET_COMBO_H + +#include "vSheets.h" + + +class CSheet_Combo : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Combo, CSheet_Base ); + + CSheet_Combo(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Combo(); + + virtual const char *GetSheetTitle(){return"Combo";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_Condition; + TextEntry *m_pText_ComboName; + TextEntry *m_pText_ComboVar; + CheckButton *m_pCheck_Static; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_comment.cpp b/sp/src/shadereditor/properties/vsheet_comment.cpp new file mode 100644 index 00000000..f83d14e5 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_comment.cpp @@ -0,0 +1,34 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Comment::CSheet_Comment(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pText_Values = new TextEntry(this, "constantvalues"); + + LoadControlSettings( "shadereditorui/vgui/sheet_comment.res" ); +} +CSheet_Comment::~CSheet_Comment() +{ +} + +void CSheet_Comment::OnCommand( const char *cmd ) +{ + BaseClass::OnCommand( cmd ); +} + +void CSheet_Comment::OnResetData() +{ + m_pText_Values->SetText( pData->GetString( "szConstantString" ) ); +} +void CSheet_Comment::OnApplyChanges() +{ + char values_raw[MAX_PATH]; + m_pText_Values->GetText( values_raw, MAX_PATH ); + + pData->SetString( "szConstantString", values_raw ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_comment.h b/sp/src/shadereditor/properties/vsheet_comment.h new file mode 100644 index 00000000..a050abaa --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_comment.h @@ -0,0 +1,28 @@ +#ifndef CSHEET_COMMENT_H +#define CSHEET_COMMENT_H + +#include "vSheets.h" + + +class CSheet_Comment : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Comment, CSheet_Base ); + + CSheet_Comment(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Comment(); + + virtual const char *GetSheetTitle(){return"Group";}; + + void OnCommand( const char *cmd ); + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + TextEntry *m_pText_Values; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_condition.cpp b/sp/src/shadereditor/properties/vsheet_condition.cpp new file mode 100644 index 00000000..1e22f2eb --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_condition.cpp @@ -0,0 +1,28 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Condition::CSheet_Condition(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_Condition = new ComboBox( this, "cbox_condition", 6, false ); + for ( int i = 0; i < 5; i++ ) + m_pCBox_Condition->AddItem( GetConditionCodeString( i ), NULL ); + + LoadControlSettings( "shadereditorui/vgui/sheet_condition.res" ); +} +CSheet_Condition::~CSheet_Condition() +{ +} + +void CSheet_Condition::OnResetData() +{ + m_pCBox_Condition->ActivateItem( clamp( pData->GetInt( "i_combo_condition" ), 0, 4 ) ); +} +void CSheet_Condition::OnApplyChanges() +{ + pData->SetInt( "i_combo_condition", m_pCBox_Condition->GetActiveItem() ); +} diff --git a/sp/src/shadereditor/properties/vsheet_condition.h b/sp/src/shadereditor/properties/vsheet_condition.h new file mode 100644 index 00000000..79e9af03 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_condition.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_CONDITION_H +#define CSHEET_CONDITION_H + +#include "vSheets.h" + + +class CSheet_Condition : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Condition, CSheet_Base ); + + CSheet_Condition(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Condition(); + + virtual const char *GetSheetTitle(){return"Condition";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_Condition; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_constant.cpp b/sp/src/shadereditor/properties/vsheet_constant.cpp new file mode 100644 index 00000000..abe0367b --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_constant.cpp @@ -0,0 +1,102 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Constant::CSheet_Constant(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pText_Values = new TextEntry(this, "constantvalues"); + + LoadControlSettings( "shadereditorui/vgui/sheet_constant.res" ); +} +CSheet_Constant::~CSheet_Constant() +{ +} + +void CSheet_Constant::OnCommand( const char *cmd ) +{ + BaseClass::OnCommand( cmd ); +} + +void CSheet_Constant::OnResetData() +{ + m_pText_Values->SetText( pData->GetString( "szConstantString" ) ); +} +void CSheet_Constant::OnApplyChanges() +{ + char values_raw[MAX_PATH]; + m_pText_Values->GetText( values_raw, MAX_PATH ); + + pData->SetString( "szConstantString", values_raw ); +} + + + +CSheet_Random::CSheet_Random(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_NumComp = new ComboBox(this, "vartype", 6, false); + for (int i = 0; i < 4; i++ ) + m_pCBox_NumComp->AddItem( ::GetVarTypeName( i ), NULL ); + + m_pTEntry_ValueMin = new TextEntry( this, "value_min" ); + m_pTEntry_ValueMax = new TextEntry( this, "value_max" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_random.res" ); +} +CSheet_Random::~CSheet_Random() +{ +} +void CSheet_Random::OnResetData() +{ + m_pCBox_NumComp->ActivateItem( pData->GetInt( "i_num_comps" ) ); + m_pTEntry_ValueMin->SetText( VarArgs( "%f", pData->GetFloat( "fl_value_min" ) ) ); + m_pTEntry_ValueMax->SetText( VarArgs( "%f", pData->GetFloat( "fl_value_max" ) ) ); +} +void CSheet_Random::OnApplyChanges() +{ + pData->SetInt( "i_num_comps", m_pCBox_NumComp->GetActiveItem() ); + + char tmp[MAX_PATH]; + m_pTEntry_ValueMin->GetText( tmp, MAX_PATH ); + float valtmp = atof( tmp ); + pData->SetFloat( "fl_value_min", valtmp ); + + m_pTEntry_ValueMax->GetText( tmp, MAX_PATH ); + valtmp = atof( tmp ); + pData->SetFloat( "fl_value_max", valtmp ); +} + + + +CSheet_EnvCTexelsize::CSheet_EnvCTexelsize(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_FBScaling = new ComboBox(this, "fbscaling", 6, false); + m_pCBox_FBScaling->AddItem( "Full", NULL ); + m_pCBox_FBScaling->AddItem( "Half", NULL ); + m_pCBox_FBScaling->AddItem( "Quarter", NULL ); + + LoadControlSettings( "shadereditorui/vgui/sheet_fbtexelsize.res" ); +} +CSheet_EnvCTexelsize::~CSheet_EnvCTexelsize() +{ +} +void CSheet_EnvCTexelsize::OnResetData() +{ + int index = (int)( pData->GetFloat( "flSmartVal0" ) / 2.0f ); + Assert( index >= 0 && index <= 2 ); + + m_pCBox_FBScaling->ActivateItem( index ); +} +void CSheet_EnvCTexelsize::OnApplyChanges() +{ + pData->SetFloat( "flSmartVal0", m_pCBox_FBScaling->GetActiveItem() * 2.0f ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_constant.h b/sp/src/shadereditor/properties/vsheet_constant.h new file mode 100644 index 00000000..c28547f1 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_constant.h @@ -0,0 +1,68 @@ +#ifndef CSHEET_CONSTANT_H +#define CSHEET_CONSTANT_H + +#include "vSheets.h" + + +class CSheet_Constant : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Constant, CSheet_Base ); + + CSheet_Constant(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Constant(); + + virtual const char *GetSheetTitle(){return"Constant";}; + + void OnCommand( const char *cmd ); + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + TextEntry *m_pText_Values; +}; + +class CSheet_Random : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Random, CSheet_Base ); + + CSheet_Random(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Random(); + + virtual const char *GetSheetTitle(){return"Random";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_NumComp; + TextEntry *m_pTEntry_ValueMin; + TextEntry *m_pTEntry_ValueMax; +}; + + + +class CSheet_EnvCTexelsize : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_EnvCTexelsize, CSheet_Base ); + + CSheet_EnvCTexelsize(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_EnvCTexelsize(); + + virtual const char *GetSheetTitle(){return"Framebuffer texelsize";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_FBScaling; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_custom.cpp b/sp/src/shadereditor/properties/vsheet_custom.cpp new file mode 100644 index 00000000..38411610 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_custom.cpp @@ -0,0 +1,646 @@ + +#include "cbase.h" +#include "vSheets.h" + +__customCtrlEntry::__customCtrlEntry() +{ + pName = NULL; + pType = NULL; + pDel = NULL; +} + +void __customCtrlEntry::Delete( bool killChildren ) +{ + if ( killChildren ) + { + if ( pName != NULL ) + { + pName->SetParent( (Panel*)NULL ); + pName->MarkForDeletion(); + } + if ( pType != NULL ) + { + pType->SetParent( (Panel*)NULL ); + pType->MarkForDeletion(); + } + if ( pDel != NULL ) + { + pDel->SetParent( (Panel*)NULL ); + pDel->MarkForDeletion(); + } + } + delete this; +} + +CSheet_Custom::CSheet_Custom(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + m_pIO_Page = NULL; + m_szFilePath[0] = '\0'; + m_bPerformedInjection = false; + m_pKVCodeCache = new KeyValues(""); + + m_pEntry_FuncName = new TextEntry( this, "function_name" ); + m_pLabel_Path = new Label( this, "file_path", "-" ); + + m_pCheck_Inline = new CheckButton( this, "check_inline", "Save in canvas" ); + m_pCheck_Lighting_PS = new CheckButton( this, "check_lighting_ps", "Add pixel shader lighting" ); + m_pCheck_Lighting_VS = new CheckButton( this, "check_lighting_vs", "Add vertex shader lighting" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_custom_code.res" ); + + int iType = n->GetHierachyTypeIterateFullyRecursive(); + bool bIsPS = ( iType & HLSLHIERACHY_PS ) != 0; + bool bIsVS = ( iType & HLSLHIERACHY_VS ) != 0; + + m_pCheck_Lighting_PS->SetEnabled( bIsPS || !bIsVS ); + m_pCheck_Lighting_VS->SetEnabled( bIsVS || !bIsPS ); + + m_pCheck_Inline->SetSelected( true ); +} + +CSheet_Custom::~CSheet_Custom() +{ + m_pKVCodeCache->deleteThis(); +} + +void CSheet_Custom::SetIOPage( CSheet_Custom_IO *p ) +{ + m_pIO_Page = p; +} + +bool CSheet_Custom::RequiresReset() +{ + return m_bPerformedInjection; +} + +void CSheet_Custom::OnCodeUpdate( KeyValues *pKV ) +{ + //const char *pCodeGlobal = pKV->GetString( "szcode_global" ); + //const char *pCodeBody = pKV->GetString( "szcode_body" ); + char *pCodeGlobal = CKVPacker::KVUnpack( pKV, "szcode_global" ); + char *pCodeBody = CKVPacker::KVUnpack( pKV, "szcode_body" ); + + const bool bDoInjection = pKV->GetInt( "doinject" ) != 0; + + m_bPerformedInjection = m_bPerformedInjection || bDoInjection; + + char *pszSafeG = CKVPacker::ConvertKVSafeString( pCodeGlobal, true ); + char *pszSafeB = CKVPacker::ConvertKVSafeString( pCodeBody, true ); + + //m_pKVCodeCache->SetString( "szcode_global", pszSafeG ); + //m_pKVCodeCache->SetString( "szcode_body", pszSafeB ); + CKVPacker::KVPack( pszSafeG, "szcode_global", m_pKVCodeCache ); + CKVPacker::KVPack( pszSafeB, "szcode_body", m_pKVCodeCache ); + + delete [] pCodeGlobal; + delete [] pCodeBody; + + delete [] pszSafeG; + delete [] pszSafeB; + + if ( bDoInjection ) + { + KeyValues *pKV_Injection = pData->MakeCopy(); + + WriteDataToKV( pKV_Injection, false ); + m_pIO_Page->WriteDataToKV( pKV_Injection ); + + n->RestoreFromKeyValues_Specific( pKV_Injection ); + pView->MakeSolversDirty(); + + pKV_Injection->deleteThis(); + } +} + +void CSheet_Custom::OnCommand( KeyValues *pKV ) +//void CSheet_Custom::OnCommand( const char *cmd ) +{ + const char *cmd = pKV->GetString( "command" ); + + if ( !Q_stricmp( cmd, "editcode" ) ) + { + Assert( m_pIO_Page ); + + int iType = n->GetHierachyTypeIterateFullyRecursive(); + + m_pIO_Page->AllocNodeData(); + + CCode_Editor *pCEdit = new CCode_Editor( this, "ceditinstance" ); + pCEdit->AddActionSignalTarget( this ); + pCEdit->MoveToFront(); + + char szFunc[MAX_PATH]; + szFunc[0] = 0; + m_pEntry_FuncName->GetText( szFunc, sizeof( szFunc ) ); + if ( !Q_strlen( szFunc ) ) + BuildDefaultFunctionName(szFunc, sizeof(szFunc), n ); + + char *pszUnpackedGlobal = CKVPacker::KVUnpack( m_pKVCodeCache, "szcode_global" ); + char *pszUnpackedBody = CKVPacker::KVUnpack( m_pKVCodeCache, "szcode_body" ); + + char *pUnSafeG = CKVPacker::ConvertKVSafeString( pszUnpackedGlobal, false ); + char *pUnSafeB = CKVPacker::ConvertKVSafeString( pszUnpackedBody, false ); + + pCEdit->InitHlsl( szFunc, &m_pIO_Page->m_hszVarNames_In, &m_pIO_Page->m_hszVarNames_Out, + pUnSafeG, pUnSafeB, iType, BuildEnvDataFlags() ); + + delete [] pszUnpackedGlobal; + delete [] pszUnpackedBody; + + delete [] pUnSafeG; + delete [] pUnSafeB; + } + else if ( !Q_stricmp( cmd, "save_code" ) ) + { + OpenFiledialog( true ); + } + else if ( !Q_stricmp( cmd, "load_code" ) ) + { + OpenFiledialog( false ); + } + else + BaseClass::OnCommand( cmd ); +} + +int CSheet_Custom::BuildEnvDataFlags() +{ + int i = 0; + if ( m_pCheck_Lighting_PS->IsSelected() ) //&& m_pCheck_Lighting_PS->IsEnabled() ) + i |= NODECUSTOM_ADDENV_LIGHTING_PS; + if ( m_pCheck_Lighting_VS->IsSelected() ) //&& m_pCheck_Lighting_VS->IsEnabled() ) + i |= NODECUSTOM_ADDENV_LIGHTING_VS; + return i; +} + +void CSheet_Custom::OnResetData() +{ + m_pEntry_FuncName->SetText(""); + + const char *pszFunc = pData->GetString( "szFunctionName" ); + const char *pWalk = pszFunc; + while ( pWalk && *pWalk ) + { + if ( *pWalk != ' ' ) + { + m_pEntry_FuncName->SetText( pszFunc ); + break; + } + + pWalk++; + } + const bool bInline = pData->GetInt( "iInline", 1 ) != 0; + m_pCheck_Inline->SetSelected( bInline ); + + const char *pszPath = pData->GetString( "szFilePath" ); + if ( !bInline ) + Q_snprintf( m_szFilePath, sizeof( m_szFilePath ), "%s", pszPath ); + + CKVPacker::KVCopyPacked( pData, m_pKVCodeCache, "szcode_global" ); + CKVPacker::KVCopyPacked( pData, m_pKVCodeCache, "szcode_body" ); + + //m_pKVCodeCache->SetString( "szcode_global", pData->GetString( "szcode_global" ) ); + //m_pKVCodeCache->SetString( "szcode_body", pData->GetString( "szcode_body" ) ); + + int iEnvFlags = pData->GetInt( "iEnvFlags" ); + + m_pCheck_Lighting_PS->SetSelected( ( iEnvFlags & NODECUSTOM_ADDENV_LIGHTING_PS ) != 0 ); + m_pCheck_Lighting_VS->SetSelected( ( iEnvFlags & NODECUSTOM_ADDENV_LIGHTING_VS ) != 0 ); +} + +void CSheet_Custom::OnApplyChanges() +{ + WriteDataToKV( pData ); +} + +void CSheet_Custom::WriteDataToKV( KeyValues *pKV, bool bCheckFilePath ) +{ + char szFunc[MAX_PATH]; + szFunc[0] = 0; + m_pEntry_FuncName->GetText( szFunc, sizeof( szFunc ) ); + + bool bFileValid = Q_strlen(m_szFilePath) && ( !bCheckFilePath || g_pFullFileSystem->FileExists( m_szFilePath ) ); + + if ( !bFileValid ) + m_szFilePath[0] = '\0'; + + pKV->SetString( "szFunctionName", szFunc ); + pKV->SetString( "szFilePath", m_szFilePath ); + pKV->SetInt( "iInline", ( m_pCheck_Inline->IsSelected() || !bFileValid ) ? 1 : 0 ); + + CKVPacker::KVCopyPacked( m_pKVCodeCache, pKV, "szcode_global" ); + CKVPacker::KVCopyPacked( m_pKVCodeCache, pKV, "szcode_body" ); + //pKV->SetString( "szcode_global", m_pKVCodeCache->GetString( "szcode_global" ) ); + //pKV->SetString( "szcode_body", m_pKVCodeCache->GetString( "szcode_body" ) ); + + int iEnvFlags = BuildEnvDataFlags(); + + pKV->SetInt( "iEnvFlags", iEnvFlags ); +} + +void CSheet_Custom::OnRestoreNode() +{ + if ( !m_pCheck_Inline->IsSelected() && Q_strlen( m_szFilePath ) ) + { + DoSave(); + + pEditorRoot->RefreshNodeInstances( HLSLNODE_UTILITY_CUSTOMCODE, new KeyValues( "info", "filepath", m_szFilePath ) ); + } +} + + +void CSheet_Custom::CheckButtonChecked( KeyValues *pKV ) +{ + bool bChecked = pKV->GetInt( "state" ) != 0; + Panel *p = (Panel*)pKV->GetPtr( "panel" ); + + Assert( p ); + + if ( p == m_pCheck_Inline ) + { + Panel *p = FindChildByName( "button_save" ); + if ( p ) + p->SetEnabled( !bChecked ); + p = FindChildByName( "button_load" ); + if ( p ) + p->SetEnabled( !bChecked ); + + m_pLabel_Path->SetText( bChecked ? "-" : m_szFilePath ); + } +} + +void CSheet_Custom::OnFileSelected( KeyValues *pKV ) +{ + KeyValues *pContext = pKV->FindKey( "FileOpenContext" ); + if ( !pContext ) + return; + + const char *__c = pContext->GetString( "context" ); + bool bSaving = true; + if ( !Q_stricmp( __c, "openc" ) ) + bSaving = false; + + const char *pathIn = pKV->GetString( "fullpath" ); + if ( Q_strlen( pathIn ) <= 1 ) + return; + + if ( !g_pFullFileSystem->FullPathToRelativePath( pathIn, m_szFilePath, sizeof(m_szFilePath) ) ) + { + Q_snprintf( m_szFilePath, sizeof(m_szFilePath), "%s", pathIn ); + + vgui::PromptSimple *prompt = new vgui::PromptSimple( this, "ERROR" ); + prompt->MoveToCenterOfScreen(); + prompt->SetText( "The selected file is not located in the game directory!" ); + prompt->AddButton( "Ok" ); + prompt->MakeReadyForUse(); + prompt->InvalidateLayout( true, true ); + } + + m_pLabel_Path->SetText( m_szFilePath ); + + if ( bSaving ) + { + DoSave(); + } + else + { + DoLoad(); + } +} + +void CSheet_Custom::DoSave() +{ + KeyValues *pCodeFile = new KeyValues("user_func"); + + WriteDataToKV( pCodeFile, false ); + m_pIO_Page->WriteDataToKV( pCodeFile ); + + pCodeFile->SaveToFile( g_pFullFileSystem, m_szFilePath, "MOD" ); + pCodeFile->deleteThis(); + + //m_bPerformedInjection = false; +} + +void CSheet_Custom::DoLoad() +{ + KeyValues *pCodeFile = new KeyValues(""); + + if ( pCodeFile->LoadFromFile( g_pFullFileSystem, m_szFilePath, "MOD" ) ) + { + m_pIO_Page->ClearIOs( pData ); + //pData->SetString( "szcode_global", "" ); + //pData->SetString( "szcode_body", "" ); + CKVPacker::KVClearPacked( "szcode_global", pData ); + CKVPacker::KVClearPacked( "szcode_body", pData ); + + for ( KeyValues *pKey = pCodeFile->GetFirstValue(); pKey; pKey = pKey->GetNextValue() ) + { + const char *pszName = pKey->GetName(); + switch ( pKey->GetDataType() ) + { + case KeyValues::TYPE_STRING: + pData->SetString( pszName, pKey->GetString() ); + break; + case KeyValues::TYPE_INT: + pData->SetInt( pszName, pKey->GetInt() ); + break; + } + } + } + + pCodeFile->deleteThis(); + + m_pIO_Page->PurgeNameVecs(); + + OnResetData(); + m_pIO_Page->OnResetData(); +} + +void CSheet_Custom::OpenFiledialog( bool bSave ) +{ + if ( m_hCodeBrowser.Get() ) + m_hCodeBrowser.Get()->MarkForDeletion(); + + m_hCodeBrowser = new FileOpenDialog( this, + bSave ? "Save code" : "Load code", + bSave ? FOD_SAVE : FOD_OPEN, + new KeyValues("FileOpenContext", "context", + bSave ? "savec" : "openc" ) + ); + + if ( m_hCodeBrowser.Get() ) + { + m_hCodeBrowser->SetStartDirectoryContext( GetFODPathContext( FODPC_USERFUNCTION ), GetUserFunctionDirectory() ); + m_hCodeBrowser->AddFilter( "*.ufunc", "User function", true ); + m_hCodeBrowser->DoModal( true ); + } +} + + + + + + +CSheet_Custom_IO::CSheet_Custom_IO(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + m_pList_Jacks = new PanelListPanel( this, "list_data_parent" ); + m_pList_Jacks->SetNumColumns( 1 ); + m_pList_Jacks->SetFirstColumnWidth( 0 ); + + AllocList(); + + LoadControlSettings( "shadereditorui/vgui/sheet_custom_code_io.res" ); +} +CSheet_Custom_IO::~CSheet_Custom_IO() +{ + m_hCtrl_In.PurgeAndDeleteElements(); + m_hCtrl_Out.PurgeAndDeleteElements(); + + PurgeNameVecs(); +} +void CSheet_Custom_IO::PurgeNameVecs() +{ + m_hszVarNames_In.PurgeAndDeleteElements(); + m_hszVarNames_Out.PurgeAndDeleteElements(); +} + +__customCtrlEntry *CSheet_Custom_IO::AllocEntry( int idx, bool bOutput, __funcParamSetup *data, Panel **p ) +{ + PanelListPanel *pRow = new PanelListPanel( NULL, "" ); + pRow->SetInnerPanel( true ); + pRow->SetNumColumns( 3 ); + pRow->SetFirstColumnWidth( 15 ); + pRow->SetVerticalBufferPixels( 0 ); + + Label *pName = new Label( pRow, "", VarArgs( "%i:", idx ) ); + + TextEntry *pIn = new TextEntry( pRow, "" ); + pIn->SetMaximumCharCount( 32 ); + pIn->SetText( data->pszName ); + + ComboBox *pCBoxType = new ComboBox( pRow, "", 10, false ); + FillComboBox( pCBoxType ); + pCBoxType->ActivateItem( GetVarFlagsVarValue( data->iFlag ) ); + + Button *pButRemove = new Button( pRow, "", "Delete" ); + KeyValues *pCmd = new KeyValues( "Command" ); + pCmd->SetString( "command", bOutput ? "removeoutput" : "removeinput" ); + pCmd->SetInt( "entryidx", idx ); + pButRemove->SetCommand( pCmd ); + pButRemove->AddActionSignalTarget( this ); + + pRow->AddItem( pName, pIn ); + pRow->AddItem( NULL, pCBoxType ); + pRow->AddItem( NULL, pButRemove ); + + pRow->SetPaintBackgroundEnabled( false ); + pRow->SetPaintBorderEnabled( false ); + int w, t; + pRow->GetSize( w, t ); + pRow->SetSize( w, 26 ); + Panel *pScrollBar = pRow->FindChildByName( "PanelListPanelVScroll" ); + Assert( pScrollBar != NULL ); + pScrollBar->SetSize( 0, 0 ); + + __customCtrlEntry *pEntry = new __customCtrlEntry(); + pEntry->pName = pIn; + pEntry->pDel = pButRemove; + pEntry->pType = pCBoxType; + + //pRow->InvalidateLayout(true,true); + //InvalidateLayout(); + + *p = pRow; + return pEntry; +} +void CSheet_Custom_IO::AllocList() +{ + Assert( m_pList_Jacks != NULL ); + + m_pList_Jacks->DeleteAllItems(); + m_hCtrl_In.PurgeAndDeleteElements(); + m_hCtrl_Out.PurgeAndDeleteElements(); + + InvalidateLayout( true, true ); + + m_pList_Jacks->AddItem( NULL, new Label( NULL, "", "Inputs" ) ); + + for ( int i = 0; i < m_hszVarNames_In.Count(); i++ ) + { + Panel *pRow = NULL; + m_hCtrl_In.AddToTail( AllocEntry( i, false, m_hszVarNames_In[ i ], &pRow ) ); + m_pList_Jacks->AddItem( NULL, pRow ); + pRow->InvalidateLayout( true, true ); + } + + m_pList_Jacks->AddItem( NULL, new Label( NULL, "", "Outputs" ) ); + + for ( int i = 0; i < m_hszVarNames_Out.Count(); i++ ) + { + Panel *pRow = NULL; + m_hCtrl_Out.AddToTail( AllocEntry( i, true, m_hszVarNames_Out[ i ], &pRow ) ); + m_pList_Jacks->AddItem( NULL, pRow ); + pRow->InvalidateLayout( true, true ); + } +} + +void CSheet_Custom_IO::AllocNodeData() +{ + PurgeNameVecs(); + + for ( int i = 0; i < m_hCtrl_In.Count(); i++ ) + { + __customCtrlEntry *ctrl = m_hCtrl_In[ i ]; + + Assert( ctrl->pName != NULL ); + + char tmp[33]; + ctrl->pName->GetText( tmp, 33 ); + + m_hszVarNames_In.AddToTail( + CNodeCustom::AllocOutputSetup( false, tmp, ctrl->pType ? GetVarTypeFlag( ctrl->pType->GetActiveItem() ) : HLSLVAR_FLOAT1 ) + ); + } + for ( int i = 0; i < m_hCtrl_Out.Count(); i++ ) + { + __customCtrlEntry *ctrl = m_hCtrl_Out[ i ]; + + Assert( ctrl->pName != NULL ); + + char tmp[33]; + ctrl->pName->GetText( tmp, 33 ); + + m_hszVarNames_Out.AddToTail( + CNodeCustom::AllocOutputSetup( true, tmp, ctrl->pType ? GetVarTypeFlag( ctrl->pType->GetActiveItem() ) : HLSLVAR_FLOAT1 ) + ); + } +} + +void CSheet_Custom_IO::FillComboBox( ComboBox *c ) +{ + for ( int i = 0; i < NUM_CBOX_VARTYPES_CFULL; i++ ) + { + KeyValues *data = new KeyValues( VarArgs( "vartype_%i", i ), "vartype", i ); + c->AddItem( GetVarTypeName( i ), data ); + data->deleteThis(); + } +} + +void CSheet_Custom_IO::OnCommand( KeyValues *pKV ) +//void CSheet_Custom::OnCommand( const char *cmd ) +{ + const char *cmd = pKV->GetString( "command" ); + + if ( !Q_stricmp( cmd, "addoutput" ) ) + { + AllocNodeData(); + m_hszVarNames_Out.AddToTail( CNodeCustom::AllocOutputSetup( true, "", HLSLVAR_FLOAT1 ) ); + AllocList(); + } + else if ( !Q_stricmp( cmd, "addinput" ) ) + { + AllocNodeData(); + m_hszVarNames_In.AddToTail( CNodeCustom::AllocOutputSetup( false, "", HLSLVAR_FLOAT1 ) ); + AllocList(); + } + else if ( !Q_stricmp( cmd, "removeinput" ) ) + { + AllocNodeData(); + int idx = pKV->GetInt( "entryidx", -1 ); + Assert( idx >= 0 && idx < m_hszVarNames_In.Count() ); + delete m_hszVarNames_In[ idx ]; + m_hszVarNames_In.Remove( idx ); + AllocList(); + } + else if ( !Q_stricmp( cmd, "removeoutput" ) ) + { + AllocNodeData(); + int idx = pKV->GetInt( "entryidx", -1 ); + Assert( idx >= 0 && idx < m_hszVarNames_Out.Count() ); + delete m_hszVarNames_Out[ idx ]; + m_hszVarNames_Out.Remove( idx ); + AllocList(); + } + else if ( !Q_stricmp( cmd, "resetio" ) ) + { + PurgeNameVecs(); + AllocList(); + } + else + BaseClass::OnCommand( cmd ); +} + +void CSheet_Custom_IO::OnResetData() +{ + CNodeCustom::FillJackDataFromKV( pData, m_hszVarNames_In, m_hszVarNames_Out ); + + AllocList(); +} + +void CSheet_Custom_IO::OnApplyChanges() +{ + WriteDataToKV( pData ); +} + +void CSheet_Custom_IO::WriteDataToKV( KeyValues *pKV ) +{ + AllocNodeData(); + + CNodeCustom::WriteJackDataFromKV( pKV, m_hszVarNames_In, m_hszVarNames_Out, + m_hszVarNames_In.Count(), m_hszVarNames_Out.Count() ); + + + ClearIOs( pKV, m_hszVarNames_In.Count(), m_hszVarNames_Out.Count() ); +} + +void CSheet_Custom_IO::ClearIOs( KeyValues *pKV, int firstIn, int firstOut ) +{ + KeyValues *pSub = NULL; + + int itr = firstIn; + for (;;) + { + pSub = pKV->FindKey( VarArgs( "varType_In_%i", itr ) ); + if ( pSub == NULL ) + break; + + pKV->RemoveSubKey( pSub ); + pSub->deleteThis(); + itr++; + } + itr = firstIn; + for (;;) + { + pSub = pKV->FindKey( VarArgs( "varName_In_%i", itr ) ); + if ( pSub == NULL ) + break; + + pKV->RemoveSubKey( pSub ); + pSub->deleteThis(); + itr++; + } + + itr = firstOut; + for (;;) + { + pSub = pKV->FindKey( VarArgs( "varType_Out_%i", itr ) ); + if ( pSub == NULL ) + break; + + pKV->RemoveSubKey( pSub ); + pSub->deleteThis(); + itr++; + } + itr = firstOut; + for (;;) + { + pSub = pKV->FindKey( VarArgs( "varName_Out_%i", itr ) ); + if ( pSub == NULL ) + break; + + pKV->RemoveSubKey( pSub ); + pSub->deleteThis(); + itr++; + } +} diff --git a/sp/src/shadereditor/properties/vsheet_custom.h b/sp/src/shadereditor/properties/vsheet_custom.h new file mode 100644 index 00000000..ffa13b54 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_custom.h @@ -0,0 +1,113 @@ +#ifndef CSHEET_CUSTOM_H +#define CSHEET_CUSTOM_H + +#include "vSheets.h" + +struct __customCtrlEntry +{ + __customCtrlEntry(); + void Delete( bool killChildren = false ); + + TextEntry *pName; + ComboBox *pType; + Button *pDel; +}; + +class CSheet_Custom_IO; + +class CSheet_Custom : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Custom, CSheet_Base ); + + CSheet_Custom(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Custom(); + + virtual const char *GetSheetTitle(){return"Custom code";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + MESSAGE_FUNC( OnRestoreNode, "RestoreNode" ); + + MESSAGE_FUNC_PARAMS( OnCommand, "Command", pKV ); + MESSAGE_FUNC_PARAMS( OnCodeUpdate, "CodeUpdate", pKV ); + //MESSAGE_FUNC_CHARPTR( OnCommand, "Command", command ); + + //MESSAGE_FUNC_CHARPTR( OnComboboxClose, "OnMenuClose", szName ); + //MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + + MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", pKV ); + MESSAGE_FUNC_PARAMS( CheckButtonChecked, "CheckButtonChecked", pKV ); + + void SetIOPage( CSheet_Custom_IO *p ); + + virtual bool RequiresReset(); + +private: + KeyValues *m_pKVCodeCache; + bool m_bPerformedInjection; + + void WriteDataToKV( KeyValues *pKV, bool bCheckFilePath = true ); + + DHANDLE< FileOpenDialog > m_hCodeBrowser; + void OpenFiledialog( bool bSave ); + void DoSave(); + void DoLoad(); + + char m_szFilePath[MAX_PATH*4]; + + Label *m_pLabel_Path; + TextEntry *m_pEntry_FuncName; + + vgui::CheckButton *m_pCheck_Inline; + vgui::CheckButton *m_pCheck_Lighting_PS; + vgui::CheckButton *m_pCheck_Lighting_VS; + + int BuildEnvDataFlags(); + + CSheet_Custom_IO *m_pIO_Page; +}; + + +class CSheet_Custom_IO : public CSheet_Base +{ +public: + friend class CSheet_Custom; + + DECLARE_CLASS_SIMPLE( CSheet_Custom_IO, CSheet_Base ); + + CSheet_Custom_IO(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Custom_IO(); + + virtual const char *GetSheetTitle(){return"Inputs/ Outputs";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_PARAMS( OnCommand, "Command", pKV ); + +private: + + void ClearIOs( KeyValues *pKV, int firstIn = 0, int firstOut = 0 ); + + void WriteDataToKV( KeyValues *pKV ); + + void PurgeNameVecs(); + + __customCtrlEntry *AllocEntry( int idx, bool bOutput, __funcParamSetup *data, Panel **p ); + void AllocList(); + void AllocNodeData(); + + PanelListPanel *m_pList_Jacks; + + void FillComboBox( ComboBox *c ); + + CUtlVector< __funcParamSetup* >m_hszVarNames_In; + CUtlVector< __funcParamSetup* >m_hszVarNames_Out; + + CUtlVector< __customCtrlEntry* >m_hCtrl_In; + CUtlVector< __customCtrlEntry* >m_hCtrl_Out; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_final.cpp b/sp/src/shadereditor/properties/vsheet_final.cpp new file mode 100644 index 00000000..15ef0584 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_final.cpp @@ -0,0 +1,32 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Final::CSheet_Final(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_Tonemap = new ComboBox( this, "cbox_tonemap", 4, false ); + m_pCBox_Tonemap->AddItem( "None", NULL ); + m_pCBox_Tonemap->AddItem( "Linear", NULL ); + m_pCBox_Tonemap->AddItem( "Gamma", NULL ); + m_pCheck_WriteDepth = new CheckButton(this, "slight",""); + + LoadControlSettings( "shadereditorui/vgui/sheet_final.res" ); +} +CSheet_Final::~CSheet_Final() +{ +} + +void CSheet_Final::OnResetData() +{ + m_pCBox_Tonemap->ActivateItem( pData->GetInt( "i_final_tonemap" ) ); + m_pCheck_WriteDepth->SetSelected( ( pData->GetInt( "i_final_wdepth" ) != 0 ) ); +} +void CSheet_Final::OnApplyChanges() +{ + pData->SetInt( "i_final_tonemap", m_pCBox_Tonemap->GetActiveItem() ); + pData->SetInt( "i_final_wdepth", m_pCheck_WriteDepth->IsSelected() ? 1 : 0 ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_final.h b/sp/src/shadereditor/properties/vsheet_final.h new file mode 100644 index 00000000..aea1c212 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_final.h @@ -0,0 +1,27 @@ +#ifndef CSHEET_FINAL_H +#define CSHEET_FINAL_H + +#include "vSheets.h" + + +class CSheet_Final : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Final, CSheet_Base ); + + CSheet_Final(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Final(); + + virtual const char *GetSheetTitle(){return"Final output";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_Tonemap; + CheckButton *m_pCheck_WriteDepth; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_flashlight.cpp b/sp/src/shadereditor/properties/vsheet_flashlight.cpp new file mode 100644 index 00000000..d62842dd --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_flashlight.cpp @@ -0,0 +1,26 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Flashlight::CSheet_Flashlight(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCheck_Specular = new CheckButton(this, "check_spec",""); + + LoadControlSettings( "shadereditorui/vgui/sheet_flashlight.res" ); +} +CSheet_Flashlight::~CSheet_Flashlight() +{ +} + +void CSheet_Flashlight::OnResetData() +{ + m_pCheck_Specular->SetSelected( ( pData->GetInt( "i_flashlight_Spec" ) != 0 ) ); +} +void CSheet_Flashlight::OnApplyChanges() +{ + pData->SetInt( "i_flashlight_Spec", m_pCheck_Specular->IsSelected() ? 1 : 0 ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_flashlight.h b/sp/src/shadereditor/properties/vsheet_flashlight.h new file mode 100644 index 00000000..45041ef1 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_flashlight.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_FLASHLIGHT_H +#define CSHEET_FLASHLIGHT_H + +#include "vSheets.h" + + +class CSheet_Flashlight : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Flashlight, CSheet_Base ); + + CSheet_Flashlight(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Flashlight(); + + virtual const char *GetSheetTitle(){return"Flashlight";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + CheckButton *m_pCheck_Specular; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_general.cpp b/sp/src/shadereditor/properties/vsheet_general.cpp new file mode 100644 index 00000000..394bf89e --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_general.cpp @@ -0,0 +1,93 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_General::CSheet_General(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + m_pCheck_Preview = NULL; + + m_pText_Name = new TextEntry(this, "name"); + if ( !pNode->IsNodeCrucial() ) + m_pCheck_Preview = new CheckButton(this, "preview",""); + + m_pLabel_Name = new Label( this, "label_name", "NAME" ); + m_pLabel_Info = new Label( this, "label_info", "INFO" ); + m_pLabel_Example = new Label( this, "label_example", "EXAMPLE" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_general.res" ); + + m_pLabel_Name->MoveToFront(); + m_pLabel_Info->MoveToFront(); + m_pLabel_Example->MoveToFront(); + + m_pLabel_Name->SetText( "" ); + m_pLabel_Info->SetText( "" ); + m_pLabel_Example->SetText( "" ); + + KeyValues *pNodeHelp = pEditorRoot->GetNodeHelpContainer(); + if ( pNodeHelp ) + { + KeyValues *pKV = pNodeHelp->FindKey( VarArgs( "%i", pNode->GetNodeType() ) ); + if ( pKV ) + { + char *pszName = CKVPacker::ConvertKVSafeString( pKV->GetString( "name" ), false ); + char *pszInfo = CKVPacker::ConvertKVSafeString( pKV->GetString( "info" ), false ); + char *pszCode = CKVPacker::ConvertKVSafeString( pKV->GetString( "code" ), false ); + + if ( pszName ) + m_pLabel_Name->SetText( pszName ); + if ( pszInfo ) + m_pLabel_Info->SetText( pszInfo ); + if ( pszCode ) + m_pLabel_Example->SetText( VarArgs( "Example: %s", pszCode ) ); + + delete [] pszName; + delete [] pszInfo; + delete [] pszCode; + } + } +} +CSheet_General::~CSheet_General() +{ +} + +void CSheet_General::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + Panel *p = FindChildByName( "info_bg" ); + if ( p ) + p->SetBorder( pScheme->GetBorder( "ButtonDepressedBorder" ) ); +} + +void CSheet_General::PerformLayout() +{ + BaseClass::PerformLayout(); + + m_pLabel_Name->SetFgColor( Color( 255, 255, 255, 255 ) ); + m_pLabel_Info->SetFgColor( Color( 210, 210, 210, 255 ) ); + m_pLabel_Example->SetFgColor( Color( 200, 210, 250, 255 ) ); +} + +void CSheet_General::OnResetData() +{ + m_pText_Name->SetText( pData->GetString( "szName" ) ); + if ( m_pCheck_Preview ) + m_pCheck_Preview->SetSelected( ( pData->GetInt( "iPreview" ) != 0 ) ); +} +void CSheet_General::OnApplyChanges() +{ + char name[MAX_PATH]; + char nameModified[MAX_PATH]; + m_pText_Name->GetText( name, MAX_PATH ); + //CleanupString( name, nameModified, MAX_PATH, true ); + Q_strcpy( nameModified, name ); + + pData->SetString( "szName", nameModified ); + + if ( m_pCheck_Preview ) + pData->SetInt( "iPreview", m_pCheck_Preview->IsSelected() ? 1 : 0 ); +} diff --git a/sp/src/shadereditor/properties/vsheet_general.h b/sp/src/shadereditor/properties/vsheet_general.h new file mode 100644 index 00000000..c1d3336d --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_general.h @@ -0,0 +1,39 @@ +#ifndef CSHEET_GENERAL_H +#define CSHEET_GENERAL_H + +#include "vSheets.h" + + +class CSheet_General : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_General, CSheet_Base ); + + CSheet_General(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_General(); + + virtual const char *GetSheetTitle(){return"General";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + //MESSAGE_FUNC( OnPageShow, "PageShow" ); + //MESSAGE_FUNC( OnPageHide, "PageHide" ); + +protected: + void PerformLayout(); + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + +private: + + TextEntry *m_pText_Name; + CheckButton *m_pCheck_Preview; + + Label *m_pLabel_Name; + Label *m_pLabel_Info; + Label *m_pLabel_Example; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_lightscale.cpp b/sp/src/shadereditor/properties/vsheet_lightscale.cpp new file mode 100644 index 00000000..c88c0b81 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_lightscale.cpp @@ -0,0 +1,28 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Lightscale::CSheet_Lightscale(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_Lightscale = new ComboBox( this, "cbox_lightscale", LSCALE_MAX, false ); + for ( int i = 0; i < LSCALE_MAX; i++ ) + m_pCBox_Lightscale->AddItem( GetLightscaleGameString(i), NULL ); + + LoadControlSettings( "shadereditorui/vgui/sheet_lightscale.res" ); +} +CSheet_Lightscale::~CSheet_Lightscale() +{ +} + +void CSheet_Lightscale::OnResetData() +{ + m_pCBox_Lightscale->ActivateItem( clamp( pData->GetInt( "i_lscale_type" ), 0, (LSCALE_MAX-1) ) ); +} +void CSheet_Lightscale::OnApplyChanges() +{ + pData->SetInt( "i_lscale_type", m_pCBox_Lightscale->GetActiveItem() ); +} diff --git a/sp/src/shadereditor/properties/vsheet_lightscale.h b/sp/src/shadereditor/properties/vsheet_lightscale.h new file mode 100644 index 00000000..1118e1ce --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_lightscale.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_LIGHTSCALE_H +#define CSHEET_LIGHTSCALE_H + +#include "vSheets.h" + + +class CSheet_Lightscale : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Lightscale, CSheet_Base ); + + CSheet_Lightscale(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Lightscale(); + + virtual const char *GetSheetTitle(){return"Lightscale";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_Lightscale; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_loop.cpp b/sp/src/shadereditor/properties/vsheet_loop.cpp new file mode 100644 index 00000000..f46d048d --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_loop.cpp @@ -0,0 +1,42 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Loop::CSheet_Loop(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_Condition = new ComboBox( this, "cbox_condition", 4, false ); + for ( int i = 0; i < 4; i++ ) + m_pCBox_Condition->AddItem( GetConditionCodeString( i ), NULL ); + + m_pText_Start = new TextEntry( this, "text_start" ); + m_pText_End = new TextEntry( this, "text_end" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_loop.res" ); +} +CSheet_Loop::~CSheet_Loop() +{ +} + +void CSheet_Loop::OnResetData() +{ + m_pCBox_Condition->ActivateItem( clamp( pData->GetInt( "loop_condition" ), 0, 3 ) ); + m_pText_Start->SetText( VarArgs( "%i", pData->GetInt( "loop_value_min" ) ) ); + m_pText_End->SetText( VarArgs( "%i", pData->GetInt( "loop_value_max" ) ) ); +} +void CSheet_Loop::OnApplyChanges() +{ + int _min, _max; + char tmp[MAX_PATH]; + m_pText_Start->GetText( tmp, MAX_PATH ); + _min = atoi( tmp ); + m_pText_End->GetText( tmp, MAX_PATH ); + _max = atoi( tmp ); + + pData->SetInt( "loop_condition", m_pCBox_Condition->GetActiveItem() ); + pData->SetInt( "loop_value_min", _min ); + pData->SetInt( "loop_value_max", _max ); +} diff --git a/sp/src/shadereditor/properties/vsheet_loop.h b/sp/src/shadereditor/properties/vsheet_loop.h new file mode 100644 index 00000000..7e9cc049 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_loop.h @@ -0,0 +1,28 @@ +#ifndef CSHEET_LOOP_H +#define CSHEET_LOOP_H + +#include "vSheets.h" + + +class CSheet_Loop : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Loop, CSheet_Base ); + + CSheet_Loop(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Loop(); + + virtual const char *GetSheetTitle(){return"Loop";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_Condition; + TextEntry *m_pText_Start; + TextEntry *m_pText_End; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_mcomp.cpp b/sp/src/shadereditor/properties/vsheet_mcomp.cpp new file mode 100644 index 00000000..d82dc658 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_mcomp.cpp @@ -0,0 +1,46 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_MComp::CSheet_MComp(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_MType = new ComboBox( this, "cbox_mtype", 4, false ); + m_pCBox_MType->AddItem( "Matrix 3x3", NULL ); + m_pCBox_MType->AddItem( "Matrix 4x3", NULL ); + m_pCBox_MType->AddItem( "Matrix 4x4", NULL ); + + m_pCheck_Columns = new CheckButton( this, "check_columns", "" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_mcompose.res" ); +} +CSheet_MComp::~CSheet_MComp() +{ +} + +void CSheet_MComp::OnResetData() +{ + int mflag = pData->GetInt( "i_mcomp_matrix" ); + int item = 0; + if ( mflag == HLSLVAR_MATRIX4X3 ) + item = 1; + else if ( mflag == HLSLVAR_MATRIX4X4 ) + item = 2; + m_pCBox_MType->ActivateItem( item ); + m_pCheck_Columns->SetSelected( !!pData->GetInt( "i_mcomp_c" ) ); +} +void CSheet_MComp::OnApplyChanges() +{ + int item = m_pCBox_MType->GetActiveItem(); + int mflag = HLSLVAR_MATRIX3X3; + if ( item == 1 ) + mflag = HLSLVAR_MATRIX4X3; + else if ( item == 2 ) + mflag = HLSLVAR_MATRIX4X4; + + pData->SetInt( "i_mcomp_matrix", mflag ); + pData->SetInt( "i_mcomp_c", m_pCheck_Columns->IsSelected() ? 1 : 0 ); +} diff --git a/sp/src/shadereditor/properties/vsheet_mcomp.h b/sp/src/shadereditor/properties/vsheet_mcomp.h new file mode 100644 index 00000000..7c444b14 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_mcomp.h @@ -0,0 +1,27 @@ +#ifndef CSHEET_MCOMP_H +#define CSHEET_MCOMP_H + +#include "vSheets.h" + + +class CSheet_MComp : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_MComp, CSheet_Base ); + + CSheet_MComp(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_MComp(); + + virtual const char *GetSheetTitle(){return"Matrix compose";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_MType; + CheckButton *m_pCheck_Columns; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_multiply.cpp b/sp/src/shadereditor/properties/vsheet_multiply.cpp new file mode 100644 index 00000000..2d59825a --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_multiply.cpp @@ -0,0 +1,26 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Multiply::CSheet_Multiply(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCheck_MatrixAsRotation = new CheckButton( this, "rotationmatrix", "Matrix rotation only" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_multiply.res" ); +} +CSheet_Multiply::~CSheet_Multiply() +{ +} + +void CSheet_Multiply::OnResetData() +{ + m_pCheck_MatrixAsRotation->SetSelected( pData->GetInt( "i_mat_rotation" ) != 0 ); +} +void CSheet_Multiply::OnApplyChanges() +{ + pData->SetInt( "i_mat_rotation", m_pCheck_MatrixAsRotation->IsSelected() ? 1 : 0 ); +} diff --git a/sp/src/shadereditor/properties/vsheet_multiply.h b/sp/src/shadereditor/properties/vsheet_multiply.h new file mode 100644 index 00000000..e712f90a --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_multiply.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_MULTIPLY_H +#define CSHEET_MULTIPLY_H + +#include "vSheets.h" + + +class CSheet_Multiply : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Multiply, CSheet_Base ); + + CSheet_Multiply(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Multiply(); + + virtual const char *GetSheetTitle(){return"Multiply";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + CheckButton *m_pCheck_MatrixAsRotation; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_parallax.cpp b/sp/src/shadereditor/properties/vsheet_parallax.cpp new file mode 100644 index 00000000..7a3a4da4 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_parallax.cpp @@ -0,0 +1,74 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Parallax::CSheet_Parallax(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + pTEntry_MinSamples = new TextEntry( this, "samp_min" ); + pTEntry_MaxSamples = new TextEntry( this, "samp_max" ); + pTEntry_BinarySamples = new TextEntry( this, "samp_binary" ); + + pCheck_DepthTest = new CheckButton( this, "check_deptht", "Calc Geometry offset" ); + pCheck_GradientRead = new CheckButton( this, "check_grad", "Use gradient lookup" ); + + pCBox_PrlxMode = new ComboBox( this, "cbox_mode", 6, false ); + pCBox_PrlxMode->AddItem( "Parallax occlusion mapping", NULL ); + pCBox_PrlxMode->AddItem( "Relief mapping", NULL ); + + LoadControlSettings( "shadereditorui/vgui/sheet_parallax.res" ); +} +CSheet_Parallax::~CSheet_Parallax() +{ +} + +void CSheet_Parallax::OnResetData() +{ + pTEntry_MinSamples->SetText( VarArgs( "%i", pData->GetInt( "i_samples_min" ) ) ); + pTEntry_MaxSamples->SetText( VarArgs( "%i", pData->GetInt( "i_samples_max" ) ) ); + pTEntry_BinarySamples->SetText( VarArgs( "%i", pData->GetInt( "i_samples_binary" ) ) ); + pCheck_DepthTest->SetSelected( !!pData->GetInt( "i_dtest" ) ); + pCheck_GradientRead->SetSelected( !!pData->GetInt( "i_gradient" ) ); + pCBox_PrlxMode->ActivateItem( pData->GetInt( "i_prlx_mode" ) ); +} +void CSheet_Parallax::OnApplyChanges() +{ + char tmp[MAX_PATH]; + pTEntry_MinSamples->GetText( tmp, sizeof( tmp ) ); + int samp_min = atoi( tmp ); + pTEntry_MaxSamples->GetText( tmp, sizeof( tmp ) ); + int samp_max = atoi( tmp ); + pTEntry_BinarySamples->GetText( tmp, sizeof( tmp ) ); + int samp_bin = atoi( tmp ); + + pData->SetInt( "i_samples_min", max( 1, samp_min ) ); + pData->SetInt( "i_samples_max", max( 1, samp_max ) ); + pData->SetInt( "i_samples_binary", max( 1, samp_bin ) ); + pData->SetInt( "i_dtest", pCheck_DepthTest->IsSelected() ? 1 : 0 ); + pData->SetInt( "i_gradient", pCheck_GradientRead->IsSelected() ? 1 : 0 ); + pData->SetInt( "i_prlx_mode", pCBox_PrlxMode->GetActiveItem() ); +} + +void CSheet_Parallax::OnTextChanged( KeyValues *pKV ) +{ + UpdateLayout( (Panel*)pKV->GetPtr( "panel" ) ); +} +void CSheet_Parallax::OnCheckButtonChecked( KeyValues *pKV ) +{ + UpdateLayout( (Panel*)pKV->GetPtr( "panel" ) ); +} +void CSheet_Parallax::UpdateLayout( Panel *pCaller ) +{ + const bool bDoRelief = pCBox_PrlxMode->GetActiveItem() == ParallaxConfig_t::PCFG_RELIEF; + + const bool bBinary = bDoRelief; + const bool bGradient = bDoRelief; + const bool bLinear_min = !bDoRelief || pCheck_GradientRead->IsSelected(); + + pTEntry_BinarySamples->SetEnabled( bBinary ); + pCheck_GradientRead->SetEnabled( bGradient ); + pTEntry_MinSamples->SetEnabled( bLinear_min ); +} diff --git a/sp/src/shadereditor/properties/vsheet_parallax.h b/sp/src/shadereditor/properties/vsheet_parallax.h new file mode 100644 index 00000000..bdac5d2f --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_parallax.h @@ -0,0 +1,39 @@ +#ifndef CSHEET_PARALLAX_H +#define CSHEET_PARALLAX_H + +#include "vSheets.h" +#include "editorcommon.h" + + +class CSheet_Parallax : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Parallax, CSheet_Base ); + + CSheet_Parallax(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Parallax(); + + virtual const char *GetSheetTitle(){return"Parallax UV";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + MESSAGE_FUNC_PARAMS( OnCheckButtonChecked, "CheckButtonChecked", pData ); + +private: + + void UpdateLayout( Panel *pCaller ); + + TextEntry *pTEntry_MinSamples; + TextEntry *pTEntry_MaxSamples; + TextEntry *pTEntry_BinarySamples; + + CheckButton *pCheck_DepthTest; + CheckButton *pCheck_GradientRead; + + ComboBox *pCBox_PrlxMode; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_psoutput.cpp b/sp/src/shadereditor/properties/vsheet_psoutput.cpp new file mode 100644 index 00000000..ba01eca7 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_psoutput.cpp @@ -0,0 +1,40 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_PSOutput::CSheet_PSOutput(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + m_pSlider_col = new Slider(this, "col" ); + m_pSlider_col->SetRange( 1, 4 ); + m_pSlider_col->SetNumTicks( 3 ); + m_pSlider_col->SetThumbWidth( SHEET_SLIDER_THUMB_SIZE ); + + m_pCheck_Depth = new CheckButton(this, "depth",""); + + m_pLabel_Info_Num_Colors = new Label( this, "info_col", "" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_psoutput.res" ); +} +CSheet_PSOutput::~CSheet_PSOutput() +{ +} + +void CSheet_PSOutput::OnResetData() +{ + m_pSlider_col->SetValue( pData->GetInt( "numColors" ) ); + m_pCheck_Depth->SetSelected( ( pData->GetInt( "enable_Depth" ) != 0 ) ); +} +void CSheet_PSOutput::OnApplyChanges() +{ + pData->SetInt( "numColors",m_pSlider_col->GetValue() ); + pData->SetInt( "enable_Depth", m_pCheck_Depth->IsSelected() ? 1 : 0 ); +} + + +void CSheet_PSOutput::OnSliderMoved( int position ) +{ + int numCol = m_pSlider_col->GetValue(); + m_pLabel_Info_Num_Colors->SetText( VarArgs( "%1i", numCol ) ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_psoutput.h b/sp/src/shadereditor/properties/vsheet_psoutput.h new file mode 100644 index 00000000..799746d7 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_psoutput.h @@ -0,0 +1,32 @@ +#ifndef CSHEET_PSOUTPUT_H +#define CSHEET_PSOUTPUT_H + +#include "vSheets.h" + +class CSheet_PSOutput : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_PSOutput, CSheet_Base ); + + CSheet_PSOutput(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_PSOutput(); + + virtual const char *GetSheetTitle(){return"PS Output";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_INT( OnSliderMoved, "SliderMoved", position ); + + //MESSAGE_FUNC_CHARPTR( OnComboboxClose, "OnMenuClose", szName ); + +private: + + Slider *m_pSlider_col; + CheckButton *m_pCheck_Depth; + + Label *m_pLabel_Info_Num_Colors; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_stdplight.cpp b/sp/src/shadereditor/properties/vsheet_stdplight.cpp new file mode 100644 index 00000000..1de051a5 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_stdplight.cpp @@ -0,0 +1,32 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Std_PLight::CSheet_Std_PLight(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCheck_StaticLighting = new CheckButton(this, "slight",""); + m_pCheck_AOTerm = new CheckButton(this, "AO",""); + m_pCheck_Halflambert = new CheckButton(this, "halfl",""); + + LoadControlSettings( "shadereditorui/vgui/sheet_std_plight.res" ); +} +CSheet_Std_PLight::~CSheet_Std_PLight() +{ +} + +void CSheet_Std_PLight::OnResetData() +{ + m_pCheck_StaticLighting->SetSelected( ( pData->GetInt( "i_plight_static" ) != 0 ) ); + m_pCheck_AOTerm->SetSelected( ( pData->GetInt( "i_plight_ao" ) != 0 ) ); + m_pCheck_Halflambert->SetSelected( ( pData->GetInt( "i_plight_hl" ) != 0 ) ); +} +void CSheet_Std_PLight::OnApplyChanges() +{ + pData->SetInt( "i_plight_static", m_pCheck_StaticLighting->IsSelected() ? 1 : 0 ); + pData->SetInt( "i_plight_ao", m_pCheck_AOTerm->IsSelected() ? 1 : 0 ); + pData->SetInt( "i_plight_hl", m_pCheck_Halflambert->IsSelected() ? 1 : 0 ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_stdplight.h b/sp/src/shadereditor/properties/vsheet_stdplight.h new file mode 100644 index 00000000..3b08eff9 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_stdplight.h @@ -0,0 +1,28 @@ +#ifndef CSHEET_STD_PLIGHT_H +#define CSHEET_STD_PLIGHT_H + +#include "vSheets.h" + + +class CSheet_Std_PLight : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Std_PLight, CSheet_Base ); + + CSheet_Std_PLight(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Std_PLight(); + + virtual const char *GetSheetTitle(){return"Pixelshader lighting";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + CheckButton *m_pCheck_StaticLighting; + CheckButton *m_pCheck_AOTerm; + CheckButton *m_pCheck_Halflambert; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_stdpspeclight.cpp b/sp/src/shadereditor/properties/vsheet_stdpspeclight.cpp new file mode 100644 index 00000000..e8e83200 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_stdpspeclight.cpp @@ -0,0 +1,26 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Std_PSpecLight::CSheet_Std_PSpecLight(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCheck_AOTerm = new CheckButton(this, "AO",""); + + LoadControlSettings( "shadereditorui/vgui/sheet_std_pspeclight.res" ); +} +CSheet_Std_PSpecLight::~CSheet_Std_PSpecLight() +{ +} + +void CSheet_Std_PSpecLight::OnResetData() +{ + m_pCheck_AOTerm->SetSelected( ( pData->GetInt( "i_plight_ao" ) != 0 ) ); +} +void CSheet_Std_PSpecLight::OnApplyChanges() +{ + pData->SetInt( "i_plight_ao", m_pCheck_AOTerm->IsSelected() ? 1 : 0 ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_stdpspeclight.h b/sp/src/shadereditor/properties/vsheet_stdpspeclight.h new file mode 100644 index 00000000..5dcf1051 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_stdpspeclight.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_STD_PSPECLIGHT_H +#define CSHEET_STD_PSPECLIGHT_H + +#include "vSheets.h" + + +class CSheet_Std_PSpecLight : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Std_PSpecLight, CSheet_Base ); + + CSheet_Std_PSpecLight(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Std_PSpecLight(); + + virtual const char *GetSheetTitle(){return"Pixelshader specular";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + CheckButton *m_pCheck_AOTerm; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_stdskinning.cpp b/sp/src/shadereditor/properties/vsheet_stdskinning.cpp new file mode 100644 index 00000000..0d846d16 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_stdskinning.cpp @@ -0,0 +1,29 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Std_Skinning::CSheet_Std_Skinning(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBoxMode = new ComboBox( this, "cbox_mode", 6, false ); + m_pCBoxMode->AddItem( "Position", NULL ); + m_pCBoxMode->AddItem( "Position and Normal", NULL ); + m_pCBoxMode->AddItem( "Pos, Normal, Tangentspace", NULL ); + + LoadControlSettings( "shadereditorui/vgui/sheet_std_skinning.res" ); +} +CSheet_Std_Skinning::~CSheet_Std_Skinning() +{ +} + +void CSheet_Std_Skinning::OnResetData() +{ + m_pCBoxMode->ActivateItem( pData->GetInt( "i_vskinning_mode" ) ); +} +void CSheet_Std_Skinning::OnApplyChanges() +{ + pData->SetInt( "i_vskinning_mode", m_pCBoxMode->GetActiveItem() ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_stdskinning.h b/sp/src/shadereditor/properties/vsheet_stdskinning.h new file mode 100644 index 00000000..6d50a7db --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_stdskinning.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_STD_SKINNING_H +#define CSHEET_STD_SKINNING_H + +#include "vSheets.h" + + +class CSheet_Std_Skinning : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Std_Skinning, CSheet_Base ); + + CSheet_Std_Skinning(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Std_Skinning(); + + //virtual const char *GetSheetTitle(){return"Skinning/ Morph";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBoxMode; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_stdvlight.cpp b/sp/src/shadereditor/properties/vsheet_stdvlight.cpp new file mode 100644 index 00000000..94dd5c08 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_stdvlight.cpp @@ -0,0 +1,42 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Std_VLight::CSheet_Std_VLight(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCheck_StaticLighting = new CheckButton(this, "slight",""); + m_pCheck_Halflambert = new CheckButton(this, "halfl",""); + + LoadControlSettings( "shadereditorui/vgui/sheet_std_vlight.res" ); +} +CSheet_Std_VLight::~CSheet_Std_VLight() +{ +} + +void CSheet_Std_VLight::OnResetData() +{ + m_pCheck_StaticLighting->SetSelected( ( pData->GetInt( "i_vlight_static" ) != 0 ) ); + m_pCheck_Halflambert->SetSelected( ( pData->GetInt( "i_vlight_hl" ) != 0 ) ); +} +void CSheet_Std_VLight::OnApplyChanges() +{ + pData->SetInt( "i_vlight_static", m_pCheck_StaticLighting->IsSelected() ? 1 : 0 ); + pData->SetInt( "i_vlight_hl", m_pCheck_Halflambert->IsSelected() ? 1 : 0 ); +} + +void CSheet_Std_VLight::OnCheckButtonChecked( KeyValues *pData ) +{ + Panel *pCaller = ((Panel*)pData->GetPtr( "panel" )); + bool bState = ( pData->GetInt( "state" ) != 0 ); + + if ( pCaller && pCaller == m_pCheck_StaticLighting ) + { + m_pCheck_Halflambert->SetEnabled( bState ); + if ( !bState ) + m_pCheck_Halflambert->SetSelected( bState ); + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_stdvlight.h b/sp/src/shadereditor/properties/vsheet_stdvlight.h new file mode 100644 index 00000000..7b4735dc --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_stdvlight.h @@ -0,0 +1,29 @@ +#ifndef CSHEET_STD_VLIGHT_H +#define CSHEET_STD_VLIGHT_H + +#include "vSheets.h" + + +class CSheet_Std_VLight : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Std_VLight, CSheet_Base ); + + CSheet_Std_VLight(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Std_VLight(); + + virtual const char *GetSheetTitle(){return"Vertex lighting";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_PARAMS( OnCheckButtonChecked, "CheckButtonChecked", pData ); + +private: + + CheckButton *m_pCheck_StaticLighting; + CheckButton *m_pCheck_Halflambert; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_swizzle.cpp b/sp/src/shadereditor/properties/vsheet_swizzle.cpp new file mode 100644 index 00000000..9b8618d1 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_swizzle.cpp @@ -0,0 +1,31 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_Swizzle::CSheet_Swizzle(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + m_pText_Values = new TextEntry(this, "name"); + + LoadControlSettings( "shadereditorui/vgui/sheet_swizzle.res" ); +} +CSheet_Swizzle::~CSheet_Swizzle() +{ +} + +void CSheet_Swizzle::OnCommand( const char *cmd ) +{ + BaseClass::OnCommand( cmd ); +} + +void CSheet_Swizzle::OnResetData() +{ + m_pText_Values->SetText( pData->GetString( "swizzleString" ) ); +} +void CSheet_Swizzle::OnApplyChanges() +{ + char name[MAX_PATH]; + m_pText_Values->GetText( name, MAX_PATH ); + pData->SetString( "swizzleString", name ); +} diff --git a/sp/src/shadereditor/properties/vsheet_swizzle.h b/sp/src/shadereditor/properties/vsheet_swizzle.h new file mode 100644 index 00000000..2c738527 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_swizzle.h @@ -0,0 +1,28 @@ +#ifndef CSHEET_SWIZZLE_H +#define CSHEET_SWIZZLE_H + +#include "vSheets.h" + + +class CSheet_Swizzle : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_Swizzle, CSheet_Base ); + + CSheet_Swizzle(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_Swizzle(); + + virtual const char *GetSheetTitle(){return"Swizzle";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + void OnCommand( const char *cmd ); + +private: + + TextEntry *m_pText_Values; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_textransform.cpp b/sp/src/shadereditor/properties/vsheet_textransform.cpp new file mode 100644 index 00000000..1d2f80eb --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_textransform.cpp @@ -0,0 +1,35 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_TexTransform::CSheet_TexTransform(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCheck_Center = new CheckButton( this, "check_center", "Custom center" ); + m_pCheck_Rotation = new CheckButton( this, "check_rot", "Rotation" ); + m_pCheck_Scale = new CheckButton( this, "check_scale", "Scale" ); + m_pCheck_Translation = new CheckButton( this, "check_translation", "Translation" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_textransform.res" ); +} +CSheet_TexTransform::~CSheet_TexTransform() +{ +} + +void CSheet_TexTransform::OnResetData() +{ + m_pCheck_Center->SetSelected( ( pData->GetInt( "iTexTrans_center" ) != 0 ) ); + m_pCheck_Rotation->SetSelected( ( pData->GetInt( "iTexTrans_rot" ) != 0 ) ); + m_pCheck_Scale->SetSelected( ( pData->GetInt( "iTexTrans_scale" ) != 0 ) ); + m_pCheck_Translation->SetSelected( ( pData->GetInt( "iTexTrans_trans" ) != 0 ) ); +} +void CSheet_TexTransform::OnApplyChanges() +{ + pData->SetInt( "iTexTrans_center", m_pCheck_Center->IsSelected() ? 1 : 0 ); + pData->SetInt( "iTexTrans_rot", m_pCheck_Rotation->IsSelected() ? 1 : 0 ); + pData->SetInt( "iTexTrans_scale", m_pCheck_Scale->IsSelected() ? 1 : 0 ); + pData->SetInt( "iTexTrans_trans", m_pCheck_Translation->IsSelected() ? 1 : 0 ); +} diff --git a/sp/src/shadereditor/properties/vsheet_textransform.h b/sp/src/shadereditor/properties/vsheet_textransform.h new file mode 100644 index 00000000..5ab0fa80 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_textransform.h @@ -0,0 +1,29 @@ +#ifndef CSHEET_TEXTRANSFORM_H +#define CSHEET_TEXTRANSFORM_H + +#include "vSheets.h" + + +class CSheet_TexTransform : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_TexTransform, CSheet_Base ); + + CSheet_TexTransform(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_TexTransform(); + + virtual const char *GetSheetTitle(){return"Texture transform";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + CheckButton *m_pCheck_Center; + CheckButton *m_pCheck_Rotation; + CheckButton *m_pCheck_Scale; + CheckButton *m_pCheck_Translation; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_texturesample.cpp b/sp/src/shadereditor/properties/vsheet_texturesample.cpp new file mode 100644 index 00000000..d677b193 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_texturesample.cpp @@ -0,0 +1,387 @@ + +#include "cbase.h" +#include "vSheets.h" + +#define TEXPATH_WHITE "white" //"Lights\\White.vtf" +#define TEXPATH_BLACK "black" //"cable\\black.vtf" +#define TEXPATH_GREY "grey" //"Dev\\bump.vtf" +#define TEXPATH_NORMAL "dev\\flat_normal.vtf" + +//int CSheet_TextureSample::m_iVguiPaint_Image= -1; + +CSheet_TextureSample::CSheet_TextureSample(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + m_bReady = false; + m_bSamplerOnly = false; + m_pParameterName = new TextEntry(this, "parameter"); + m_pCheckSRGB_Read = new CheckButton(this, "srgb",""); + + m_pComboBox_TextureType = new ComboBox( this, "textype", 7, false ); + for ( int i = 0; i <= HLSLTEXSAM_LAST_USABLE; i++ ) + { + KeyValues *pKv = new KeyValues( GetTextureTypeName( i ) ); + pKv->SetInt( "type", i ); + m_pComboBox_TextureType->AddItem( GetTextureTypeName( i ), pKv ); + pKv->deleteThis(); + } + m_pComboBox_TextureType->ActivateItem( HLSLTEX_BASETEXTURE ); + + m_szDemoTexturePath[0] = '\0'; + m_pTextEntry_DemoTexture = new TextEntry( this, "demotexname" ); + m_pButton_LoadTexture = new Button( this, "loadtexture", "", this, "" ); + + m_pTextEntry_FallbackTexture = new TextEntry( this, "fallbacktexname" ); + m_pComboBox_FallbackType = new ComboBox( this, "fallbacktype", 7, false ); + m_pComboBox_FallbackType->AddItem( "white", NULL ); + m_pComboBox_FallbackType->AddItem( "black", NULL ); + m_pComboBox_FallbackType->AddItem( "grey", NULL ); + m_pComboBox_FallbackType->AddItem( "normal", NULL ); + m_pComboBox_FallbackType->AddItem( "custom", NULL ); + m_pComboBox_FallbackType->ActivateItem( 0 ); + + m_pComboBox_LookupOverride = new ComboBox( this, "lookupoverride", 10, false ); + for ( int i = 0; i < TEXSAMP_MAX; i++ ) + m_pComboBox_LookupOverride->AddItem( ::GetSamplerData_VisualName( i ), NULL ); + + bFileIsEnvmap = false; + SetupVguiTex( m_iVguiPaint_Texture, "shadereditor/vguiTexSample" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_texsample.res" ); +} +CSheet_TextureSample::~CSheet_TextureSample() +{ + if ( m_hOpenTexture.Get() ) + m_hOpenTexture->MarkForDeletion(); +} + +void CSheet_TextureSample::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + Panel *pImgPos = FindChildByName( "imagepos" ); + if ( pImgPos ) + pImgPos->SetBorder(pScheme->GetBorder("DepressedButtonBorder")); +} + +void CSheet_TextureSample::MakeSamplerOnly() +{ + m_bSamplerOnly = true; + + Panel *pP = FindChildByName( "Label_lookup" ); + if ( pP != NULL ) + pP->SetVisible( false ); + + m_pComboBox_LookupOverride->SetVisible( false ); + m_pCheckSRGB_Read->SetVisible( false ); +} + +void CSheet_TextureSample::OnCommand( const char *cmd ) +{ + if ( !m_bReady ) + return; + bool bOpenBrowser = false; + const char *pBContext = NULL; + const char *pBPath = NULL; + if ( !Q_stricmp( cmd, "openvtf" ) ) + { + bOpenBrowser = true; + pBContext = "open_demofile"; + pBPath = "%s/materials/texture_samples"; + } + else if ( !Q_stricmp( cmd, "openfallback" ) ) + { + bOpenBrowser = true; + pBContext = "open_fallback"; + pBPath = "%s/materials"; + } + + if ( bOpenBrowser ) + { + Assert( pBContext ); + Assert( pBPath ); + + if ( m_hOpenTexture.Get() ) + m_hOpenTexture.Get()->MarkForDeletion(); + + m_hOpenTexture = new FileOpenDialog( this, "Load .vtf", FOD_OPEN, new KeyValues("FileOpenContext", "context", pBContext) ); + + if ( m_hOpenTexture.Get() ) + { + char finalPath[MAX_PATH]; + Q_snprintf( finalPath, sizeof( finalPath ), pBPath, GetGamePath() ); + + m_hOpenTexture->SetStartDirectoryContext( GetFODPathContext( FODPC_VTF ), finalPath ); + m_hOpenTexture->AddFilter( "*.vtf", "Textures", true ); + m_hOpenTexture->DoModal( true ); + } + } +} +void CSheet_TextureSample::OnFileSelected( KeyValues *pKV ) +{ + KeyValues *pContext = pKV->FindKey( "FileOpenContext" ); + if ( pContext ) + { + const bool bMainMaterial = !Q_stricmp( pContext->GetString( "context" ), "open_demofile" ); + char tmparray[MAX_PATH*4]; + char *targetarray = m_szDemoTexturePath; + if ( !bMainMaterial ) + targetarray = tmparray; + + const char *pathIn = pKV->GetString( "fullpath" ); + if ( Q_strlen( pathIn ) <= 1 ) + return; + + char tmp[MAX_PATH*4]; + char tmp2[MAX_PATH*4]; + Q_snprintf( tmp, sizeof( tmp ), "%s", pathIn ); + + bool bIsAbsPath = false; + if ( g_pFullFileSystem->FullPathToRelativePath( tmp, tmp2, sizeof(tmp2) ) ) + Q_strcpy( tmp, tmp2 ); + else if ( !g_pFullFileSystem->RelativePathToFullPath( tmp, NULL, tmp2, sizeof(tmp2) ) ) + bIsAbsPath = true; + + char *go = bIsAbsPath ? tmp : Q_StripFirstDir( tmp ); + Q_snprintf( targetarray, MAX_PATH*4, "%s", go ); + + char tmpNoExt[MAX_PATH*4]; + Q_StripExtension( targetarray, tmpNoExt, MAX_PATH*4 ); + Q_strcpy( targetarray, tmpNoExt ); + + Q_FixSlashes( targetarray ); + + if ( bMainMaterial ) + m_pTextEntry_DemoTexture->SetText( targetarray ); + else + m_pTextEntry_FallbackTexture->SetText( targetarray ); + + if ( bMainMaterial ) + LoadFile(); + } +} +void CSheet_TextureSample::LoadFile() +{ + if ( Q_strlen( m_szDemoTexturePath ) < 1 ) + return; + + bFileIsEnvmap = false; + + //{ + // unsigned char *pImgData = m_Image.GetVTF()->ImageData(); + // if ( pImgData ) + // { + // //m_iVguiPaint_Image = surface()->CreateNewTextureID( true ); + // surface()->DrawSetTextureRGBA( m_iVguiPaint_Image, pImgData, m_Image.GetVTF()->Width(), m_Image.GetVTF()->Height(), 0, true ); + // } + // m_pMat_Tex = NULL; + // m_Image.DestroyImage(); + //} + //else + + { + m_pMat_Tex = materials->FindMaterial( "shadereditor/vguiTexSample", TEXTURE_GROUP_OTHER ); + if ( !m_pMat_Tex ) + return; + bool bFound = false; + IMaterialVar *pBaseTex = m_pMat_Tex->FindVar( "$basetexture", &bFound ); + if ( !bFound ) + return; + ITexture *tex = materials->FindTexture( m_szDemoTexturePath, TEXTURE_GROUP_OTHER ); + if ( IsErrorTexture(tex) ) + return; + bFileIsEnvmap = tex->IsCubeMap(); + pBaseTex->SetTextureValue( tex ); + //tex->Download(); + //pBaseTex->SetStringValue( tmp2 ); +#ifdef SHADER_EDITOR_DLL_2006 + m_pMat_Tex->Refresh(); +#else + m_pMat_Tex->RefreshPreservingMaterialVars(); +#endif + m_pMat_Tex->RecomputeStateSnapshots(); + //( "shadereditor/vguiTexSample" ); + } +} + +void CSheet_TextureSample::OnTexturetypeSelect() +{ + int param = m_pComboBox_TextureType->GetActiveItem(); + bool bEnableCParram = param == HLSLTEX_CUSTOMPARAM; + m_pParameterName->SetEnabled( bEnableCParram ); + m_pParameterName->SetEditable( bEnableCParram ); + + const char *newTex = NULL; + bool bAllowTextureLoad = false; + bool bAllowSRGBSet = true; + + switch (param) + { + default: + case HLSLTEX_CUSTOMPARAM: + case HLSLTEX_BASETEXTURE: + case HLSLTEX_BUMPMAP: + bAllowTextureLoad = true; + break; + //case HLSLTEX_NORMAL: + // newTex = "dev\\flat_normal.vtf"; + // break; + case HLSLTEX_BLACK: + newTex = TEXPATH_BLACK; + break; + case HLSLTEX_WHITE: + newTex = TEXPATH_WHITE; + break; + case HLSLTEX_LIGHTMAP: + case HLSLTEX_LIGHTMAP_BUMPMAPPED: + bAllowSRGBSet = false; + case HLSLTEX_GREY: + newTex = TEXPATH_GREY; + break; + case HLSLTEX_FRAMEBUFFER: + newTex = "_rt_FullFrameFB"; + break; + } + + m_pButton_LoadTexture->SetEnabled( bAllowTextureLoad ); + m_pTextEntry_DemoTexture->SetEnabled( bAllowTextureLoad ); + + m_pComboBox_FallbackType->SetEnabled( bAllowTextureLoad ); + m_pTextEntry_FallbackTexture->SetEnabled( bAllowTextureLoad ); + if ( !bAllowTextureLoad ) + m_pTextEntry_DemoTexture->SetText( "" ); + + m_pCheckSRGB_Read->SetEnabled( bAllowSRGBSet ); + + if ( newTex ) + { + Q_snprintf( m_szDemoTexturePath, MAX_PATH, "%s", newTex ); + LoadFile(); + } +} + +void CSheet_TextureSample::OnMenuClose( KeyValues *pKV ) +{ + Panel *pCaller = ((Panel*)pKV->GetPtr( "panel" )); + + if ( pCaller == m_pComboBox_FallbackType ) + { + int index = m_pComboBox_FallbackType->GetActiveItem(); + const char *tgName = NULL; + switch ( index ) + { + case 0: + tgName = TEXPATH_WHITE; + break; + case 1: + tgName = TEXPATH_BLACK; + break; + case 2: + tgName = TEXPATH_GREY; + break; + case 3: + tgName = TEXPATH_NORMAL; + break; + } + if ( tgName ) + m_pTextEntry_FallbackTexture->SetText( tgName ); + else + OnCommand( "openfallback" ); + } +} +void CSheet_TextureSample::OnTextChanged( KeyValues *pKV ) +{ + Panel *pCaller = ((Panel*)pKV->GetPtr( "panel" )); + + if ( pCaller == m_pTextEntry_DemoTexture ) + { + char text[MAX_PATH]; + m_pTextEntry_DemoTexture->GetText( text, MAX_PATH ); + if ( Q_strlen( text ) < 1 ) + return; + ITexture *tex = materials->FindTexture( text, TEXTURE_GROUP_OTHER, false ); + if ( !tex ) + return; + + Q_snprintf( m_szDemoTexturePath, MAX_PATH, "%s", text ); + LoadFile(); + } + else if ( pCaller == m_pComboBox_TextureType ) + OnTexturetypeSelect(); + else if ( pCaller == m_pTextEntry_FallbackTexture ) + m_pComboBox_FallbackType->ActivateItem( 4 ); +} +void CSheet_TextureSample::Paint() +{ + BaseClass::Paint(); + + Panel *pImgPos = FindChildByName( "imagepos" ); + if ( pImgPos ) + { + int px,py,sx,sy; + pImgPos->GetBounds( px, py, sx, sy ); + + //if (m_pMat_Tex) + surface()->DrawSetTexture( m_iVguiPaint_Texture ); + //else + // surface()->DrawSetTexture( m_iVguiPaint_Image ); + surface()->DrawSetColor( Color(255,255,255,255) ); + surface()->DrawTexturedRect( px, py, px+sx, py+sy ); + } +} + +void CSheet_TextureSample::OnResetData() +{ + m_pParameterName->SetText( pData->GetString( "szParamname" ) ); + m_pCheckSRGB_Read->SetSelected( ( pData->GetInt( "iSRGB" ) != 0 ) ); + m_pComboBox_TextureType->ActivateItem( pData->GetInt( "iTextureType" ) ); + Q_snprintf( m_szDemoTexturePath, MAX_PATH, "%s", pData->GetString("szDemoTexturePath") ); + + m_pTextEntry_DemoTexture->SetText( m_szDemoTexturePath ); + + bool bEnableCParram = m_pComboBox_TextureType->GetActiveItem() == HLSLTEX_CUSTOMPARAM; + m_pParameterName->SetEnabled( bEnableCParram ); + + const char *fallbackname = pData->GetString("szFallbackTexturePath"); + int fallbackmode = pData->GetInt( "iFallbackMode"); + if ( !fallbackname || !*fallbackname ) + { + fallbackname = TEXPATH_WHITE; + fallbackmode = 0; + } + m_pTextEntry_FallbackTexture->SetText( fallbackname ); + m_pComboBox_FallbackType->ActivateItem( fallbackmode ); + + m_pComboBox_LookupOverride->ActivateItem( pData->GetInt( "iLookupoverride" ) ); + + OnTexturetypeSelect(); + LoadFile(); + + m_bReady = true; +} +void CSheet_TextureSample::OnApplyChanges() +{ + char name[MAX_PATH]; + char nameModified[MAX_PATH]; + m_pParameterName->GetText( name, MAX_PATH ); + CleanupString( name, nameModified, MAX_PATH ); + + int textype = m_pComboBox_TextureType->GetActiveItem(); + pData->SetString( "szParamname", nameModified ); + pData->SetInt( "iSRGB", m_pCheckSRGB_Read->IsSelected() ? 1 : 0 ); + pData->SetInt( "iTextureType", textype ); + pData->SetString( "szDemoTexturePath", m_szDemoTexturePath ); + + bool bCustomTexIsCubemap = bFileIsEnvmap && + (textype == HLSLTEX_CUSTOMPARAM || + textype == HLSLTEX_BASETEXTURE); + bool bCubemap = textype == HLSLTEX_ENVMAP || bCustomTexIsCubemap; + pData->SetInt( "IsCubemap", bCubemap ? 1 : 0 ); + + char tmp[MAX_PATH]; + m_pTextEntry_FallbackTexture->GetText( tmp, MAX_PATH ); + pData->SetString( "szFallbackTexturePath", tmp ); + pData->SetInt( "iFallbackMode", m_pComboBox_FallbackType->GetActiveItem() ); + + pData->SetInt( "iLookupoverride", m_pComboBox_LookupOverride->GetActiveItem() ); +} diff --git a/sp/src/shadereditor/properties/vsheet_texturesample.h b/sp/src/shadereditor/properties/vsheet_texturesample.h new file mode 100644 index 00000000..0082a53e --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_texturesample.h @@ -0,0 +1,68 @@ +#ifndef CSHEET_TEXSAMPLE_H +#define CSHEET_TEXSAMPLE_H + +#include "vSheets.h" + + +class CSheet_TextureSample : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_TextureSample, CSheet_Base ); + + CSheet_TextureSample(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_TextureSample(); + + virtual const char *GetSheetTitle(){return"Texture Sample";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_CHARPTR( OnCommand, "Command", command ); + + MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", fullpath ); + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + MESSAGE_FUNC_PARAMS( OnMenuClose, "OnMenuClose", pKV ); + + virtual void Paint(); + + void MakeSamplerOnly(); + +protected: + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + +private: + bool m_bSamplerOnly; + + bool bFileIsEnvmap; + //static int m_iVguiPaint_Image; + int m_iVguiPaint_Texture; + void LoadFile(); + + DHANDLE< FileOpenDialog > m_hOpenTexture; + char m_szDemoTexturePath[ MAX_PATH ]; + + ComboBox *m_pComboBox_TextureType; + TextEntry *m_pParameterName; + + CheckButton *m_pCheckSRGB_Read; + TextEntry *m_pTextEntry_DemoTexture; + Button *m_pButton_LoadTexture; + + + TextEntry *m_pTextEntry_FallbackTexture; + ComboBox *m_pComboBox_FallbackType; + + ComboBox *m_pComboBox_LookupOverride; + + + void OnTexturetypeSelect(); + ITexture *m_pTexture; + IMaterial *m_pMat_Tex; + KeyValues *pKV_Mat; + + bool m_bReady; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_vcompression.cpp b/sp/src/shadereditor/properties/vsheet_vcompression.cpp new file mode 100644 index 00000000..7bf38150 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_vcompression.cpp @@ -0,0 +1,39 @@ + +#include "cbase.h" +#include "vSheets.h" + +static const char *pszCModes[] = { + "Decompress normal", + "Decompress normal and tangent", +}; + +CSheet_VCompression::CSheet_VCompression(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_CompressionModes = new ComboBox( this, "cbox_modes", 10, false ); + + Assert( ARRAYSIZE( pszCModes ) == CNodeVCompression::COMPRESSION_MODE_COUNT ); + + for ( int i = 0; i < CNodeVCompression::COMPRESSION_MODE_COUNT; i++ ) + { + m_pCBox_CompressionModes->AddItem( pszCModes[i], NULL ); + } + + LoadControlSettings( "shadereditorui/vgui/sheet_vcompression.res" ); +} + +CSheet_VCompression::~CSheet_VCompression() +{ +} + +void CSheet_VCompression::OnResetData() +{ + m_pCBox_CompressionModes->ActivateItem( pData->GetInt( "iCompMode" ) ); +} + +void CSheet_VCompression::OnApplyChanges() +{ + pData->SetInt( "iCompMode", m_pCBox_CompressionModes->GetActiveItem() ); +} diff --git a/sp/src/shadereditor/properties/vsheet_vcompression.h b/sp/src/shadereditor/properties/vsheet_vcompression.h new file mode 100644 index 00000000..665f10a1 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_vcompression.h @@ -0,0 +1,26 @@ +#ifndef CSHEET_VCOMPRESSION_H +#define CSHEET_VCOMPRESSION_H + +#include "vSheets.h" + + +class CSheet_VCompression : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_VCompression, CSheet_Base ); + + CSheet_VCompression(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_VCompression(); + + virtual const char *GetSheetTitle(){return"Vertex decompress";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + ComboBox *m_pCBox_CompressionModes; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_vmtparam.cpp b/sp/src/shadereditor/properties/vsheet_vmtparam.cpp new file mode 100644 index 00000000..d1b95075 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_vmtparam.cpp @@ -0,0 +1,85 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_VParam_Mutable::CSheet_VParam_Mutable(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_Params = new ComboBox( this, "cbox_params", 10, false ); + m_pCBox_Comps = new ComboBox( this, "cbox_types", 10, false ); + + for ( int i = 0; i < AMT_VMT_MUTABLE; i++ ) + m_pCBox_Params->AddItem( VarArgs( "MUTABLE_%02i", i+1 ), NULL ); + for ( int i = 0; i < 4; i++ ) + m_pCBox_Comps->AddItem( ::GetVarTypeName( i ), NULL ); + + m_pText_Values = new TextEntry(this, "constantvalues"); + + LoadControlSettings( "shadereditorui/vgui/sheet_vparam_mutable.res" ); +} +CSheet_VParam_Mutable::~CSheet_VParam_Mutable() +{ +} + +void CSheet_VParam_Mutable::OnResetData() +{ + m_pCBox_Params->ActivateItem( pData->GetInt( "i_vp_mutable_param" ) ); + m_pCBox_Comps->ActivateItem( pData->GetInt( "i_vp_mutable_nc" ) ); + m_pText_Values->SetText( pData->GetString( "szConstantString" ) ); +} +void CSheet_VParam_Mutable::OnApplyChanges() +{ + pData->SetInt( "i_vp_mutable_param", m_pCBox_Params->GetActiveItem() ); + pData->SetInt( "i_vp_mutable_nc", m_pCBox_Comps->GetActiveItem() ); + + char tmp[MAX_PATH]; + m_pText_Values->GetText( tmp, MAX_PATH ); + pData->SetString( "szConstantString", tmp ); +} + + + + +CSheet_VParam_Static::CSheet_VParam_Static(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + SetParent( parent ); + + m_pCBox_Comps = new ComboBox( this, "cbox_types", 10, false ); + m_pTEntry_Name = new TextEntry( this, "tentry_name" ); + m_pText_Values = new TextEntry(this, "constantvalues"); + + for ( int i = 0; i < 4; i++ ) + m_pCBox_Comps->AddItem( ::GetVarTypeName( i ), NULL ); + + LoadControlSettings( "shadereditorui/vgui/sheet_vparam_static.res" ); +} +CSheet_VParam_Static::~CSheet_VParam_Static() +{ +} +void CSheet_VParam_Static::OnCommand( const char *cmd ) +{ + BaseClass::OnCommand( cmd ); +} +void CSheet_VParam_Static::OnResetData() +{ + m_pCBox_Comps->ActivateItem( pData->GetInt( "i_vp_static_nc" ) ); + m_pTEntry_Name->SetText( pData->GetString( "i_vp_static_name" ) ); + m_pText_Values->SetText( pData->GetString( "szConstantString" ) ); +} +void CSheet_VParam_Static::OnApplyChanges() +{ + pData->SetInt( "i_vp_static_nc", m_pCBox_Comps->GetActiveItem() ); + + char tmp[MAX_PATH]; + char tmp2[MAX_PATH]; + m_pTEntry_Name->GetText( tmp, MAX_PATH ); + ::CleanupString( tmp, tmp2, MAX_PATH ); + pData->SetString( "i_vp_static_name", tmp2 ); + + m_pText_Values->GetText( tmp, MAX_PATH ); + pData->SetString( "szConstantString", tmp ); +} diff --git a/sp/src/shadereditor/properties/vsheet_vmtparam.h b/sp/src/shadereditor/properties/vsheet_vmtparam.h new file mode 100644 index 00000000..41f92cfa --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_vmtparam.h @@ -0,0 +1,53 @@ +#ifndef CSHEET_VMT_PARAM_H +#define CSHEET_VMT_PARAM_H + +#include "vSheets.h" + + +class CSheet_VParam_Mutable : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_VParam_Mutable, CSheet_Base ); + + CSheet_VParam_Mutable(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_VParam_Mutable(); + + virtual const char *GetSheetTitle(){return"VParam mutable";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + +private: + + TextEntry *m_pText_Values; + + ComboBox *m_pCBox_Params; + ComboBox *m_pCBox_Comps; +}; + + +class CSheet_VParam_Static : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_VParam_Static, CSheet_Base ); + + CSheet_VParam_Static(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_VParam_Static(); + + virtual const char *GetSheetTitle(){return"VParam static";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + void OnCommand( const char *cmd ); + +private: + + TextEntry *m_pTEntry_Name; + ComboBox *m_pCBox_Comps; + + TextEntry *m_pText_Values; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_vsinput.cpp b/sp/src/shadereditor/properties/vsheet_vsinput.cpp new file mode 100644 index 00000000..1b9986e6 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_vsinput.cpp @@ -0,0 +1,119 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_VSInput::CSheet_VSInput(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + m_pCheck_flex = new CheckButton(this, "flex",""); + m_pCheck_normal = new CheckButton(this, "normal",""); + m_pCheck_normal_compression = new CheckButton(this, "normal_compression",""); + m_pCheck_tangent = new CheckButton(this, "tangent",""); + m_pCheck_blend = new CheckButton(this, "blend",""); + m_pCheck_tangent_skinable = new CheckButton(this, "tangent_skinable",""); + + m_pSlider_tex = new Slider(this, "tex" ); + m_pSlider_col = new Slider(this, "col" ); + + m_pSlider_tex->SetRange( 0, 3 ); + m_pSlider_tex->SetNumTicks( 3 ); + m_pSlider_tex->SetThumbWidth( SHEET_SLIDER_THUMB_SIZE ); + + m_pSlider_col->SetRange( 0, 2 ); + m_pSlider_col->SetNumTicks( 2 ); + m_pSlider_col->SetThumbWidth( SHEET_SLIDER_THUMB_SIZE ); + + m_pLabel_Info_Num_TexCoords = new Label( this, "info_tex", "" ); + m_pLabel_Info_Num_Colors = new Label( this, "info_col", "" ); + + for ( int i = 0; i < 3; i++ ) + m_pCBox_DType_TexCoords[i] = new ComboBox( this, VarArgs( "cbox_dtypes_texcoords_%i", i ), 10, false ); + for ( int i = 0; i < 2; i++ ) + m_pCBox_DType_Color[i] = new ComboBox( this, VarArgs( "cbox_dtypes_color_%i", i ), 10, false ); + + for ( int i = 0; i < 4; i++ ) + { + for ( int d = 0; d < 3; d++ ) + m_pCBox_DType_TexCoords[d]->AddItem( ::GetVarTypeName( i ), NULL ); + for ( int d = 0; d < 2; d++ ) + m_pCBox_DType_Color[d]->AddItem( ::GetVarTypeName( i ), NULL ); + } + + LoadControlSettings( "shadereditorui/vgui/sheet_vsinput.res" ); +} +CSheet_VSInput::~CSheet_VSInput() +{ +} + +void CSheet_VSInput::OnResetData() +{ + m_pSlider_tex->SetValue( pData->GetInt( "numTexcoords" ) ); + m_pSlider_col->SetValue( pData->GetInt( "numColor" ) ); + + m_pCheck_flex->SetSelected( ( pData->GetInt( "enable_flex" ) != 0 ) ); + m_pCheck_normal->SetSelected( ( pData->GetInt( "enable_normal" ) != 0 ) ); + m_pCheck_normal_compression->SetSelected( ( pData->GetInt( "enable_normal_compression" ) != 0 ) ); + m_pCheck_tangent->SetSelected( ( pData->GetInt( "enable_tangentspace" ) != 0 ) ); + m_pCheck_blend->SetSelected( ( pData->GetInt( "enable_blendweights" ) != 0 ) ); + m_pCheck_tangent_skinable->SetSelected( ( pData->GetInt( "enable_tangentspace_skinning" ) != 0 ) ); + + for ( int d = 0; d < 3; d++ ) + m_pCBox_DType_TexCoords[d]->ActivateItem( ::GetVarFlagsVarValue( pData->GetInt( VarArgs( "dTFlag_Texcoords_%i", d ) ) ) ); + + for ( int d = 0; d < 2; d++ ) + m_pCBox_DType_Color[d]->ActivateItem( ::GetVarFlagsVarValue( pData->GetInt( VarArgs( "dTFlag_Color_%i", d ) ) ) ); +} +void CSheet_VSInput::OnApplyChanges() +{ + pData->SetInt( "numTexcoords",m_pSlider_tex->GetValue() ); + pData->SetInt( "numColor",m_pSlider_col->GetValue() ); + + pData->SetInt( "enable_flex", m_pCheck_flex->IsSelected() ? 1 : 0 ); + pData->SetInt( "enable_normal", m_pCheck_normal->IsSelected() ? 1 : 0 ); + pData->SetInt( "enable_normal_compression", m_pCheck_normal_compression->IsSelected() ? 1 : 0 ); + pData->SetInt( "enable_tangentspace", m_pCheck_tangent->IsSelected() ? 1 : 0 ); + pData->SetInt( "enable_blendweights", m_pCheck_blend->IsSelected() ? 1 : 0 ); + pData->SetInt( "enable_tangentspace_skinning", m_pCheck_tangent_skinable->IsSelected() ? 1 : 0 ); + + for ( int d = 0; d < 3; d++ ) + pData->SetInt( VarArgs( "dTFlag_Texcoords_%i", d ), ::GetVarTypeFlag( m_pCBox_DType_TexCoords[d]->GetActiveItem() ) ); + for ( int d = 0; d < 2; d++ ) + pData->SetInt( VarArgs( "dTFlag_Color_%i", d ), ::GetVarTypeFlag( m_pCBox_DType_Color[d]->GetActiveItem() ) ); +} + +void CSheet_VSInput::OnSliderMoved( int position ) +{ + int numTex = m_pSlider_tex->GetValue(); + int numCol = m_pSlider_col->GetValue(); + + m_pLabel_Info_Num_TexCoords->SetText( VarArgs( "%1i", numTex ) ); + m_pLabel_Info_Num_Colors->SetText( VarArgs( "%1i", numCol ) ); + + for ( int d = 0; d < 3; d++ ) + m_pCBox_DType_TexCoords[d]->SetEnabled( numTex - 1 >= d ); + for ( int d = 0; d < 2; d++ ) + m_pCBox_DType_Color[d]->SetEnabled( numCol - 1 >= d ); +} + +void CSheet_VSInput::OnCheckButtonChecked( KeyValues *pData ) +{ + Panel *pCaller = ((Panel*)pData->GetPtr( "panel" )); + bool bState = ( pData->GetInt( "state" ) != 0 ); + + if ( !pCaller ) + return; + + if ( pCaller == m_pCheck_tangent ) + { + m_pCheck_tangent_skinable->SetEnabled( bState ); + if ( !bState ) + m_pCheck_tangent_skinable->SetSelected( false ); + } + else if ( pCaller == m_pCheck_normal ) + { + m_pCheck_normal_compression->SetEnabled( bState ); + if ( !bState ) + m_pCheck_normal_compression->SetSelected( false ); + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_vsinput.h b/sp/src/shadereditor/properties/vsheet_vsinput.h new file mode 100644 index 00000000..a2d60a7f --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_vsinput.h @@ -0,0 +1,42 @@ +#ifndef CSHEET_VSINPUT_H +#define CSHEET_VSINPUT_H + +#include "vSheets.h" + +class CSheet_VSInput : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_VSInput, CSheet_Base ); + + CSheet_VSInput(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_VSInput(); + + virtual const char *GetSheetTitle(){return"VS Input";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_INT( OnSliderMoved, "SliderMoved", position ); + MESSAGE_FUNC_PARAMS( OnCheckButtonChecked, "CheckButtonChecked", pData ); + +private: + + CheckButton *m_pCheck_flex; + CheckButton *m_pCheck_normal; + CheckButton *m_pCheck_normal_compression; + CheckButton *m_pCheck_tangent; + CheckButton *m_pCheck_tangent_skinable; + CheckButton *m_pCheck_blend; + + Slider *m_pSlider_tex; + Slider *m_pSlider_col; + + Label *m_pLabel_Info_Num_TexCoords; + Label *m_pLabel_Info_Num_Colors; + + ComboBox *m_pCBox_DType_TexCoords[3]; + ComboBox *m_pCBox_DType_Color[2]; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheet_vsoutpsin.cpp b/sp/src/shadereditor/properties/vsheet_vsoutpsin.cpp new file mode 100644 index 00000000..85f4db09 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_vsoutpsin.cpp @@ -0,0 +1,195 @@ + +#include "cbase.h" +#include "vSheets.h" + + +CSheet_PSInVSOut::CSheet_PSInVSOut(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ) + : BaseClass( pNode, view, data, parent ) +{ + m_pSlider_tex = new Slider(this, "tex" ); + m_pSlider_col = new Slider(this, "col" ); + + m_pSlider_tex->SetRange( 0, 8 ); + m_pSlider_tex->SetNumTicks( 8 ); + m_pSlider_tex->SetThumbWidth( SHEET_SLIDER_THUMB_SIZE ); + + m_pSlider_col->SetRange( 0, 2 ); + m_pSlider_col->SetNumTicks( 2 ); + m_pSlider_col->SetThumbWidth( SHEET_SLIDER_THUMB_SIZE ); + + m_pListTexcoords = new PanelListPanel( this, "list_data" ); + m_pListTexcoords->SetNumColumns( 2 ); + + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + m_pLabel_List[ i ] = new Label(m_pListTexcoords,VarArgs("TexCoords %i",i),VarArgs("TexCoords %i",i)); + m_pComboBox_List[ i ] = new ComboBox(m_pListTexcoords, VarArgs("entry_%i",i), 7, false); + FillComboBox( m_pComboBox_List[i], NUM_CBOX_VARTYPES ); + m_pComboBox_List[i]->ActivateItem( 0 ); + + m_pTextEntry_List[ i ] = new TextEntry( m_pListTexcoords, VarArgs( "entry_%i", i ) ); + m_pTextEntry_List[i]->SetMaximumCharCount( 18 ); + + m_pListTexcoords->AddItem( m_pLabel_List[i], m_pComboBox_List[i] ); + m_pListTexcoords->AddItem( NULL, m_pTextEntry_List[ i ] ); + } + + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + { + m_pLabel_List_Colors[ i ] = new Label(m_pListTexcoords,VarArgs("Color %i",i),VarArgs("Color %i",i)); + m_pComboBox_List_Colors[ i ] = new ComboBox(m_pListTexcoords, VarArgs("entry_%i",i), 7, false); + FillComboBox( m_pComboBox_List_Colors[i], NUM_CBOX_VARTYPES - 3 ); + m_pComboBox_List_Colors[i]->ActivateItem( 0 ); + + m_pTextEntry_List_Colors[ i ] = new TextEntry( m_pListTexcoords, VarArgs( "entry_%i", i ) ); + m_pTextEntry_List_Colors[i]->SetMaximumCharCount( 18 ); + + m_pListTexcoords->AddItem( m_pLabel_List_Colors[i], m_pComboBox_List_Colors[i] ); + m_pListTexcoords->AddItem( NULL, m_pTextEntry_List_Colors[ i ] ); + } + + m_pLabel_Info_Num_TexCoords = new Label( this, "info_tex", "" ); + m_pLabel_Info_Num_Colors = new Label( this, "info_col", "" ); + + LoadControlSettings( "shadereditorui/vgui/sheet_vsoutput_psinput.res" ); +} +CSheet_PSInVSOut::~CSheet_PSInVSOut() +{ +} + +void CSheet_PSInVSOut::FillComboBox( ComboBox *c, int numItems ) +{ + c->AddActionSignalTarget( this ); + for ( int i = 0; i < numItems; i++ ) + { + KeyValues *data = new KeyValues( VarArgs("vartype_%i",i), "vartype", i ); + c->AddItem( GetVarTypeName( i ), data ); + data->deleteThis(); + } +} +void CSheet_PSInVSOut::OnTextChanged( KeyValues *pKV ) +{ + //Panel *pCaller = ((Panel*)pKV->GetPtr( "panel" )); + int iDesiredJacks = m_pSlider_tex->GetValue(); + int iItemsToDisable = 0; + + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + ComboBox *curBox = m_pComboBox_List[ i ]; + int curItem = curBox->GetActiveItem(); + + bool bEnable = iItemsToDisable <= 0 && i < iDesiredJacks; + if ( !bEnable ) + { + curBox->ActivateItem( 0 ); + curItem = 0; + } + + int rows = GetVarTypeRowsRequired( curItem ); + + if ( rows + i > iDesiredJacks ) + { + curBox->ActivateItem( 0 ); + curItem = 0; + rows = GetVarTypeRowsRequired( curItem ); + } + + m_pLabel_List[ i ]->SetEnabled( bEnable ); + m_pComboBox_List[ i ]->SetEnabled( bEnable ); + m_pTextEntry_List[ i ]->SetEnabled( bEnable ); + + if ( bEnable ) + iItemsToDisable = rows - 1; + else + iItemsToDisable--; + } +} +void CSheet_PSInVSOut::OnSliderMoved( int position ) +{ + int numTex = m_pSlider_tex->GetValue(); + int numCol = m_pSlider_col->GetValue(); + EnableItems_Textures( numTex ); + EnableItems_Colors( numCol ); + + m_pLabel_Info_Num_TexCoords->SetText( VarArgs( "%1i", numTex ) ); + m_pLabel_Info_Num_Colors->SetText( VarArgs( "%1i", numCol ) ); + + OnTextChanged( NULL ); +} +void CSheet_PSInVSOut::EnableItems_Textures( int numTexcoords ) +{ + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + bool bEnable = numTexcoords > 0; + m_pLabel_List[ i ]->SetEnabled( bEnable ); + m_pComboBox_List[ i ]->SetEnabled( bEnable ); + m_pTextEntry_List[ i ]->SetEnabled( bEnable ); + numTexcoords--; + } +} +void CSheet_PSInVSOut::EnableItems_Colors( int numColors ) +{ + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + { + bool bEnable = numColors > 0; + m_pLabel_List_Colors[ i ]->SetEnabled( bEnable ); + m_pComboBox_List_Colors[ i ]->SetEnabled( bEnable ); + m_pTextEntry_List_Colors[ i ]->SetEnabled( bEnable ); + numColors--; + } +} + +void CSheet_PSInVSOut::OnResetData() +{ + int numTexcoordJacks = pData->GetInt( "numTexcoords" ); + int numColorJacks = pData->GetInt( "numColor" ); + + m_pSlider_tex->SetValue( numTexcoordJacks ); + m_pSlider_col->SetValue( numColorJacks ); + + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + int flag = pData->GetInt( VarArgs( "numTexcoord_Flag_%i", i ) ); + int value = GetVarFlagsVarValue( flag ); + m_pComboBox_List[ i ]->ActivateItem( value ); + m_pTextEntry_List[ i ]->SetText( pData->GetString(VarArgs( "numTexcoord_Name_%i", i )) ); + } + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + { + int flag = pData->GetInt( VarArgs( "numColor_Flag_%i", i ) ); + int value = GetVarFlagsVarValue( flag ); + m_pComboBox_List_Colors[ i ]->ActivateItem( value ); + m_pTextEntry_List_Colors[ i ]->SetText( pData->GetString(VarArgs( "numColor_Name_%i", i )) ); + } + + + EnableItems_Textures( numTexcoordJacks ); + EnableItems_Colors( numColorJacks ); + OnTextChanged( NULL ); +} +void CSheet_PSInVSOut::OnApplyChanges() +{ + pData->SetInt( "numTexcoords",m_pSlider_tex->GetValue() ); + pData->SetInt( "numColor",m_pSlider_col->GetValue() ); + + for ( int i = 0; i < VSTOPS_NUM_TEXCOORDS; i++ ) + { + ComboBox *curBox = m_pComboBox_List[ i ]; + int curItem = curBox->GetActiveItem(); + int flag = GetVarTypeFlag( curItem ); + pData->SetInt( VarArgs( "numTexcoord_Flag_%i", i ), flag ); + char tmp[32]; + m_pTextEntry_List[i]->GetText( tmp, 32 ); + pData->SetString( VarArgs( "numTexcoord_Name_%i", i ), tmp ); + } + for ( int i = 0; i < VSTOPS_NUM_COLORS; i++ ) + { + ComboBox *curBox = m_pComboBox_List_Colors[ i ]; + int curItem = curBox->GetActiveItem(); + int flag = GetVarTypeFlag( curItem ); + pData->SetInt( VarArgs( "numColor_Flag_%i", i ), flag ); + char tmp[32]; + m_pTextEntry_List_Colors[i]->GetText( tmp, 32 ); + pData->SetString( VarArgs( "numColor_Name_%i", i ), tmp ); + } +} diff --git a/sp/src/shadereditor/properties/vsheet_vsoutpsin.h b/sp/src/shadereditor/properties/vsheet_vsoutpsin.h new file mode 100644 index 00000000..0c7ed959 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheet_vsoutpsin.h @@ -0,0 +1,48 @@ +#ifndef CSHEET_PSINPUT_H +#define CSHEET_PSINPUT_H + +#include "vSheets.h" + +class CSheet_PSInVSOut : public CSheet_Base +{ +public: + DECLARE_CLASS_SIMPLE( CSheet_PSInVSOut, CSheet_Base ); + + CSheet_PSInVSOut(CBaseNode *pNode, CNodeView *view, KeyValues *data, Panel *parent ); + ~CSheet_PSInVSOut(); + + virtual const char *GetSheetTitle(){return"VS Output / PS Input";}; + + MESSAGE_FUNC( OnResetData, "ResetData" ); + MESSAGE_FUNC( OnApplyChanges, "ApplyChanges" ); + + MESSAGE_FUNC_INT( OnSliderMoved, "SliderMoved", position ); + + //MESSAGE_FUNC_CHARPTR( OnComboboxClose, "OnMenuClose", szName ); + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + +private: + + Slider *m_pSlider_tex; + Slider *m_pSlider_col; + + PanelListPanel *m_pListTexcoords; + + Label *m_pLabel_List[VSTOPS_NUM_TEXCOORDS]; + ComboBox *m_pComboBox_List[VSTOPS_NUM_TEXCOORDS]; + TextEntry *m_pTextEntry_List[VSTOPS_NUM_TEXCOORDS]; + + Label *m_pLabel_List_Colors[VSTOPS_NUM_COLORS]; + ComboBox *m_pComboBox_List_Colors[VSTOPS_NUM_COLORS]; + TextEntry *m_pTextEntry_List_Colors[VSTOPS_NUM_COLORS]; + + void FillComboBox( ComboBox *c, int numItems ); + void EnableItems_Textures( int numColors ); + void EnableItems_Colors( int numTexcoords ); + + Label *m_pLabel_Info_Num_TexCoords; + Label *m_pLabel_Info_Num_Colors; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/properties/vsheets.h b/sp/src/shadereditor/properties/vsheets.h new file mode 100644 index 00000000..30cd2074 --- /dev/null +++ b/sp/src/shadereditor/properties/vsheets.h @@ -0,0 +1,74 @@ +#ifndef VSHEETS_H +#define VSHEETS_H + +#include +#include +#include +#include +#include "ienginevgui.h" + +#include "vgui_controls/Controls.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "editorCommon.h" + +#include "vNodeProperties.h" + +#include "vCodeEditor.h" + +#include "vSheet_Base.h" +#include "vSheet_General.h" +#include "vSheet_Multiply.h" +#include "vSheet_TextureSample.h" +#include "vSheet_TexTransform.h" +#include "vSheet_Swizzle.h" +#include "vSheet_Loop.h" +#include "vSheet_Combo.h" +#include "vSheet_Constant.h" +#include "vSheet_MComp.h" +#include "vSheet_CMatrix.h" +#include "vSheet_Callback.h" +#include "vSheet_VmtParam.h" +#include "vSheet_Array.h" +#include "vSheet_Condition.h" +#include "vSheet_Custom.h" + +#include "vSheet_Parallax.h" +#include "vSheet_StdVLight.h" +#include "vSheet_StdPLight.h" +#include "vSheet_StdSkinning.h" +#include "vSheet_StdPSpecLight.h" +#include "vSheet_VCompression.h" + +#include "vSheet_Flashlight.h" +#include "vSheet_Lightscale.h" + +#include "vSheet_Final.h" + +#include "vSheet_VSInput.h" +#include "vSheet_VSOutPSIn.h" +#include "vSheet_PSOutput.h" + + + + +#include "vSheet_PP_RT.h" +#include "vSheet_PP_Mat.h" +#include "vSheet_PP_Operations.h" +#include "vSheet_PP_DrawMat.h" +#include "vSheet_PP_RenderView.h" + + + + +#include "vSheet_Comment.h" + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/shadereditor.vpc b/sp/src/shadereditor/shadereditor.vpc new file mode 100644 index 00000000..5cdfd36a --- /dev/null +++ b/sp/src/shadereditor/shadereditor.vpc @@ -0,0 +1,364 @@ +//----------------------------------------------------------------------------- +// SHADEREDITOR.VPC +// +// Project Script +//----------------------------------------------------------------------------- + +$Macro SRCDIR ".." + +$Include "$SRCDIR\shadereditor_platform.vpc" + +$Macro OUTBINNAME "shadereditor_$TARGET_PLATFORM" +$Macro OUTBINDIR "$TARGET_GAME_DIRECTORY\bin" + +$Macro GAMENAME "shader_editor" +$Macro SRCDIRSHARED "$SRCDIR\game\shared" +$Macro SRCDIRPUBLIC "$TARGET_SRC_DIRECTORY\public" +$Macro SRCDIREDITOR "$SRCDIR\shadereditor" + +$Include "$SRCDIR\vpc_scripts\source_dll_base.vpc" + +$Configuration "Debug" +{ + $General + { + $OutputDirectory ".\Debug_$GAMENAME_$TARGET_PLATFORM" + $IntermediateDirectory ".\Debug_$GAMENAME_$TARGET_PLATFORM" + } +} + +$Configuration "Release" +{ + $General + { + $OutputDirectory ".\Release_$GAMENAME_$TARGET_PLATFORM" + $IntermediateDirectory ".\Release_$GAMENAME_$TARGET_PLATFORM" + } +} + +$Configuration +{ + $General + { + $TargetName "$OUTBINNAME" + } + + $Compiler + { + $AdditionalIncludeDirectories ".\;$BASE;$SRCDIR\vgui_editor\include;$SRCDIR\vgui_editor" + $AdditionalIncludeDirectories "$BASE;$TARGET_SRC_DIRECTORY\public;$TARGET_SRC_DIRECTORY\public\tier0;$TARGET_SRC_DIRECTORY\public\tier1;$TARGET_SRC_DIRECTORY\common" + $PreprocessorDefinitions "$BASE;NO_STRING_T;CLIENT_DLL;VECTOR;VERSION_SAFE_STEAM_API_INTERFACES;PROTECTED_THINGS_ENABLE;strncpy=use_Q_strncpy_instead;_snprintf=use_Q_snprintf_instead" + $PreprocessorDefinitions "$BASE;ENABLE_CHROMEHTMLWINDOW;fopen=dont_use_fopen" [$WIN32] + $PreprocessorDefinitions "$BASE;ENABLE_CHROMEHTMLWINDOW;" [$OSXALL] + $PreprocessorDefinitions "$BASE;ENABLE_CHROMEHTMLWINDOW;" [$LINUX] + $PreprocessorDefinitions "$BASE;USE_WEBM_FOR_REPLAY" [$LINUX] + $PreprocessorDefinitions "$BASE;CURL_STATICLIB" [$WIN32 && $BUILD_REPLAY] + //$PreprocessorDefinitions "$BASE;NO_MALLOC_OVERRIDE" + $Create/UsePrecompiledHeader "Use Precompiled Header (/Yu)" + $Create/UsePCHThroughFile "cbase.h" + $PrecompiledHeaderFile "$(IntDir)/shadereditor.pch" + + $PreprocessorDefinitions "$BASE;SHADER_EDITOR_DLL;SHADER_EDITOR_DLL_$TARGET_PLATFORM" + $AdditionalIncludeDirectories "$BASE" + $AdditionalIncludeDirectories "$BASE;$SRCDIREDITOR;$SRCDIREDITOR\util;$SRCDIREDITOR\interface;$SRCDIR\..\client\shadereditor;$SRCDIREDITOR\nodes;$SRCDIREDITOR\properties;$SRCDIREDITOR\solver;$SRCDIREDITOR\threads;$SRCDIREDITOR\solver\postprocessing;$SRCDIREDITOR\properties\postprocessing;$SRCDIREDITOR\properties\smarttext;$SRCDIREDITOR\nodes\postprocessing" + $AdditionalIncludeDirectories "$BASE;$SRCDIR\materialsystem\" + } + + $Linker + { + $SystemLibraries "iconv" [$OSXALL] + $SystemFrameworks "Carbon" [$OSXALL] + $SystemLibraries "rt" [$LINUXALL] + $IgnoreImportLibrary "TRUE" + $AdditionalDependencies "$BASE winmm.lib" [$WIN32] + $AdditionalDependencies "$BASE wsock32.lib Ws2_32.lib" [$BUILD_REPLAY] + } +} + +$Configuration "Debug" +{ + $Linker + { + $AdditionalDependencies "$BASE Dbghelp.lib" [$WIN32] + } +} + +$Project "$OUTBINNAME" +{ + $Folder "Source Files" + { + $Folder "Base Files" + { + $File "$SRCDIREDITOR\util\client_factorylist.cpp" + $File "$SRCDIREDITOR\util\igamesystem.cpp" + + $File "$SRCDIRPUBLIC\collisionutils.cpp" \ + "$SRCDIR\vgui_editor\vgui_controls_editor.cpp" \ + "$SRCDIRPUBLIC\crtmemdebug.cpp" + { + $Configuration + { + $Compiler + { + $Create/UsePrecompiledHeader "Not Using Precompiled Headers" + } + } + } + } + + $File "$SRCDIREDITOR\chlsl_image.cpp" + $File "$SRCDIREDITOR\chlsl_mesh.cpp" + $File "$SRCDIREDITOR\chlsl_variable.cpp" + $File "$SRCDIREDITOR\ckvpacker.cpp" + $File "$SRCDIREDITOR\cregex.cpp" + $File "$SRCDIREDITOR\editorcommon.cpp" + $File "$SRCDIREDITOR\exported_utilities.cpp" + $File "$SRCDIREDITOR\gdirectories.cpp" + $File "$SRCDIREDITOR\gpostprocessingcache.cpp" + $File "$SRCDIREDITOR\grendertargetconfig.cpp" + $File "$SRCDIREDITOR\gshaderdumps.cpp" + $File "$SRCDIREDITOR\vbasediag.cpp" + $File "$SRCDIREDITOR\vbridge.cpp" + $File "$SRCDIREDITOR\vdialogconfig.cpp" + $File "$SRCDIREDITOR\vdialogeditorconfig.cpp" + $File "$SRCDIREDITOR\vdialognew.cpp" + $File "$SRCDIREDITOR\vdialogppeconfig.cpp" + $File "$SRCDIREDITOR\vdialogppeffectprecache.cpp" + $File "$SRCDIREDITOR\vdialogrecompileall.cpp" + $File "$SRCDIREDITOR\vdialogrtlist.cpp" + $File "$SRCDIREDITOR\vdialogsprecache.cpp" + $File "$SRCDIREDITOR\veditorflowgraphpage.cpp" + $File "$SRCDIREDITOR\veditorflowgraphsheet.cpp" + $File "$SRCDIREDITOR\veditorroot.cpp" + $File "$SRCDIREDITOR\vgui_init.cpp" + $File "$SRCDIREDITOR\vjack.cpp" + $File "$SRCDIREDITOR\vnodeview.cpp" + $File "$SRCDIREDITOR\vnodeviewerror.cpp" + $File "$SRCDIREDITOR\vpreview.cpp" + $File "$SRCDIREDITOR\vrenderpanel.cpp" + + $Folder "Interface" + { + $File "$SRCDIREDITOR\interface\dll_init.cpp" + $File "$SRCDIREDITOR\interface\editorinit.cpp" + $File "$SRCDIREDITOR\interface\ppehelper.cpp" + + $File "$SRCDIR\materialsystem\ivprocshader.cpp" + { + $Configuration + { + $Compiler + { + $Create/UsePrecompiledHeader "Not Using Precompiled Headers" + } + } + } + } + + $Folder "Nodes" + { + $File "$SRCDIREDITOR\nodes\vbasecontainer.cpp" + $File "$SRCDIREDITOR\nodes\vbasenode.cpp" + $File "$SRCDIREDITOR\nodes\vnode_add.cpp" + $File "$SRCDIREDITOR\nodes\vnode_array.cpp" + $File "$SRCDIREDITOR\nodes\vnode_baseevaluate.cpp" + $File "$SRCDIREDITOR\nodes\vnode_baserange.cpp" + $File "$SRCDIREDITOR\nodes\vnode_break.cpp" + $File "$SRCDIREDITOR\nodes\vnode_callback.cpp" + $File "$SRCDIREDITOR\nodes\vnode_combo.cpp" + $File "$SRCDIREDITOR\nodes\vnode_comment.cpp" + $File "$SRCDIREDITOR\nodes\vnode_condition.cpp" + $File "$SRCDIREDITOR\nodes\vnode_constant.cpp" + $File "$SRCDIREDITOR\nodes\vnode_cross.cpp" + $File "$SRCDIREDITOR\nodes\vnode_custom.cpp" + $File "$SRCDIREDITOR\nodes\vnode_divide.cpp" + $File "$SRCDIREDITOR\nodes\vnode_dot.cpp" + $File "$SRCDIREDITOR\nodes\vnode_envc.cpp" + $File "$SRCDIREDITOR\nodes\vnode_final.cpp" + $File "$SRCDIREDITOR\nodes\vnode_flashlight.cpp" + $File "$SRCDIREDITOR\nodes\vnode_fog.cpp" + $File "$SRCDIREDITOR\nodes\vnode_lerp.cpp" + $File "$SRCDIREDITOR\nodes\vnode_lightscale.cpp" + $File "$SRCDIREDITOR\nodes\vnode_loop.cpp" + $File "$SRCDIREDITOR\nodes\vnode_matrices.cpp" + $File "$SRCDIREDITOR\nodes\vnode_mcompose.cpp" + $File "$SRCDIREDITOR\nodes\vnode_multiply.cpp" + $File "$SRCDIREDITOR\nodes\vnode_parallax.cpp" + $File "$SRCDIREDITOR\nodes\vnode_psinput.cpp" + $File "$SRCDIREDITOR\nodes\vnode_psoutput.cpp" + $File "$SRCDIREDITOR\nodes\vnode_sampler.cpp" + $File "$SRCDIREDITOR\nodes\vnode_std_plight.cpp" + $File "$SRCDIREDITOR\nodes\vnode_std_skinning.cpp" + $File "$SRCDIREDITOR\nodes\vnode_std_vlight.cpp" + $File "$SRCDIREDITOR\nodes\vnode_subtract.cpp" + $File "$SRCDIREDITOR\nodes\vnode_swizzle.cpp" + $File "$SRCDIREDITOR\nodes\vnode_texsample.cpp" + $File "$SRCDIREDITOR\nodes\vnode_textransform.cpp" + $File "$SRCDIREDITOR\nodes\vnode_utility.cpp" + $File "$SRCDIREDITOR\nodes\vnode_vcompression.cpp" + $File "$SRCDIREDITOR\nodes\vnode_vecappend.cpp" + $File "$SRCDIREDITOR\nodes\vnode_vectorref.cpp" + $File "$SRCDIREDITOR\nodes\vnode_vmtparam.cpp" + $File "$SRCDIREDITOR\nodes\vnode_vsinput.cpp" + $File "$SRCDIREDITOR\nodes\vnode_vsoutput.cpp" + + $Folder "Post processing" + { + $File "$SRCDIREDITOR\nodes\postprocessing\vnode_pp_base.cpp" + $File "$SRCDIREDITOR\nodes\postprocessing\vnode_pp_drawmat.cpp" + $File "$SRCDIREDITOR\nodes\postprocessing\vnode_pp_mat.cpp" + $File "$SRCDIREDITOR\nodes\postprocessing\vnode_pp_operations.cpp" + $File "$SRCDIREDITOR\nodes\postprocessing\vnode_pp_renderview.cpp" + $File "$SRCDIREDITOR\nodes\postprocessing\vnode_pp_rt.cpp" + } + } + + $Folder "Properties" + { + $File "$SRCDIREDITOR\properties\vcodeeditor.cpp" + $File "$SRCDIREDITOR\properties\vnodeproperties.cpp" + $File "$SRCDIREDITOR\properties\vsheet_array.cpp" + $File "$SRCDIREDITOR\properties\vsheet_base.cpp" + $File "$SRCDIREDITOR\properties\vsheet_callback.cpp" + $File "$SRCDIREDITOR\properties\vsheet_cmatrix.cpp" + $File "$SRCDIREDITOR\properties\vsheet_combo.cpp" + $File "$SRCDIREDITOR\properties\vsheet_comment.cpp" + $File "$SRCDIREDITOR\properties\vsheet_condition.cpp" + $File "$SRCDIREDITOR\properties\vsheet_constant.cpp" + $File "$SRCDIREDITOR\properties\vsheet_custom.cpp" + $File "$SRCDIREDITOR\properties\vsheet_final.cpp" + $File "$SRCDIREDITOR\properties\vsheet_flashlight.cpp" + $File "$SRCDIREDITOR\properties\vsheet_general.cpp" + $File "$SRCDIREDITOR\properties\vsheet_lightscale.cpp" + $File "$SRCDIREDITOR\properties\vsheet_loop.cpp" + $File "$SRCDIREDITOR\properties\vsheet_mcomp.cpp" + $File "$SRCDIREDITOR\properties\vsheet_multiply.cpp" + $File "$SRCDIREDITOR\properties\vsheet_parallax.cpp" + $File "$SRCDIREDITOR\properties\vsheet_psoutput.cpp" + $File "$SRCDIREDITOR\properties\vsheet_stdplight.cpp" + $File "$SRCDIREDITOR\properties\vsheet_stdpspeclight.cpp" + $File "$SRCDIREDITOR\properties\vsheet_stdskinning.cpp" + $File "$SRCDIREDITOR\properties\vsheet_stdvlight.cpp" + $File "$SRCDIREDITOR\properties\vsheet_swizzle.cpp" + $File "$SRCDIREDITOR\properties\vsheet_textransform.cpp" + $File "$SRCDIREDITOR\properties\vsheet_texturesample.cpp" + $File "$SRCDIREDITOR\properties\vsheet_vcompression.cpp" + $File "$SRCDIREDITOR\properties\vsheet_vmtparam.cpp" + $File "$SRCDIREDITOR\properties\vsheet_vsinput.cpp" + $File "$SRCDIREDITOR\properties\vsheet_vsoutpsin.cpp" + + $Folder "Post processing" + { + $File "$SRCDIREDITOR\properties\postprocessing\vsheet_pp_drawmat.cpp" + $File "$SRCDIREDITOR\properties\postprocessing\vsheet_pp_mat.cpp" + $File "$SRCDIREDITOR\properties\postprocessing\vsheet_pp_operations.cpp" + $File "$SRCDIREDITOR\properties\postprocessing\vsheet_pp_renderview.cpp" + $File "$SRCDIREDITOR\properties\postprocessing\vsheet_pp_rt.cpp" + } + + $Folder "Smart text" + { + $File "$SRCDIREDITOR\properties\smarttext\vsmartautocomplete.cpp" + $File "$SRCDIREDITOR\properties\smarttext\vsmartobject.cpp" + $File "$SRCDIREDITOR\properties\smarttext\vsmartobjectlist.cpp" + $File "$SRCDIREDITOR\properties\smarttext\vsmartrow.cpp" + $File "$SRCDIREDITOR\properties\smarttext\vsmarttext.cpp" + $File "$SRCDIREDITOR\properties\smarttext\vsmarttooltip.cpp" + } + } + + $Folder "Solver" + { + $File "$SRCDIREDITOR\solver\chlsl_solver_add.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_append.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_array.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_baseevaluate.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_baserange.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_break.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_callback.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_constant.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_containerbasic.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_cross.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_custom.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_divide.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_dot.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_dummy.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_envc.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_final.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_flashlight.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_fog.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_lerp.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_lightscale.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_matrices.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_mcomp.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_multiply.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_parallax.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_readsemantics.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_stdplight.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_stdskinning.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_stdvlight.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_subtract.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_swizzle.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_textransform.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_texturesample.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_utility.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_vcompression.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_vecref.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_vmtparam.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solver_writesemantics.cpp" + $File "$SRCDIREDITOR\solver\chlsl_solverbase.cpp" + + $File "$SRCDIREDITOR\solver\hlsl_solver.h" + + $Folder "Post processing" + { + $File "$SRCDIREDITOR\solver\postprocessing\chlsl_solver_pp_drawmat.cpp" + $File "$SRCDIREDITOR\solver\postprocessing\chlsl_solver_pp_mat.cpp" + $File "$SRCDIREDITOR\solver\postprocessing\chlsl_solver_pp_operations.cpp" + $File "$SRCDIREDITOR\solver\postprocessing\chlsl_solver_pp_renderview.cpp" + $File "$SRCDIREDITOR\solver\postprocessing\chlsl_solver_pp_rt.cpp" + $File "$SRCDIREDITOR\solver\postprocessing\chlsl_solverpp_base.cpp" + } + } + + $Folder "Threads" + { + $File "$SRCDIREDITOR\threads\cbasethread.cpp" + $File "$SRCDIREDITOR\threads\ccompilethread.cpp" + $File "$SRCDIREDITOR\threads\csolvercallback.cpp" + $File "$SRCDIREDITOR\threads\cthreadmanager.cpp" + } + } + + $Folder "Precompiled Header" + { + $File "$SRCDIREDITOR\cbase.h" + $File "$SRCDIREDITOR\stdafx.cpp" + { + $Configuration + { + $Compiler + { + $Create/UsePrecompiledHeader "Create Precompiled Header (/Yc)" + } + } + } + } + + $Folder "Link Libraries" + { + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\bitmap.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\choreoobjects.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\dmxloader.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\mathlib.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\matsys_controls.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\particles.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\tier1.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\tier2.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\tier3.lib" + $DynamicFile "$SRCDIR\lib\public\vgui_controls_editor_$TARGET_PLATFORM.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\steam_api.lib" + $DynamicFile "$TARGET_SRC_DIRECTORY\lib\public\vtf.lib" + $DynamicFile "$SRCDIR\lib\public\jpeglib.lib" + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/solver/chlsl_solver_add.cpp b/sp/src/shadereditor/solver/chlsl_solver_add.cpp new file mode 100644 index 00000000..e9966562 --- /dev/null +++ b/sp/src/shadereditor/solver/chlsl_solver_add.cpp @@ -0,0 +1,44 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +void CHLSL_Solver_Add::OnWriteFXC( bool bIsPixelShader, WriteContext_FXC &context ) +{ + CHLSL_Var *tg = GetTargetVar( 0 ); + tg->DeclareMe(context); + CHLSL_Var *src1 = GetSourceVar( 0 ); + CHLSL_Var *src2 = GetSourceVar( 1 ); + + char tmp[MAXTARGC]; + Q_snprintf( tmp, MAXTARGC, "%s = %s + %s;\n", + tg->GetName(),src1->GetName(),src2->GetName() ); + context.buf_code.PutString( tmp ); +} + +void CHLSL_Solver_Add::Render( Preview2DContext &c ) +{ + int type0 = GetSourceVar(0)->GetType(); + int type1 = GetSourceVar(1)->GetType(); + + SetUVParamBySourceVar( NPSOP_CALC_ADD, 0, 0 ); + SetUVParamBySourceVar( NPSOP_CALC_ADD, 1, 1 ); + + IMaterialVar *var_2 = pEditorRoot->GetUVTargetParam( NPSOP_CALC_ADD, 2 ); + IMaterialVar *var_3 = pEditorRoot->GetUVTargetParam( NPSOP_CALC_ADD, 3 ); + var_2->SetVecValue( 0, 0, 0, 0 ); + var_3->SetVecValue( 0, 0, 0, 0 ); + + if ( type0 != type1 ) + { + int maxSlots = ::GetSlotsFromTypeFlag( max( type0, type1 ) ); + Assert( maxSlots > 1 ); + bool target_is_0 = ( type0 < type1 ); + + IMaterialVar *var_target = target_is_0 ? var_2 : var_3; + var_target->SetVecValue( maxSlots >= 2, maxSlots >= 3, maxSlots >= 4, 0 ); + } + + CNodeView::RenderSingleSolver( c, pEditorRoot->GetOperatorMaterial( NPSOP_CALC_ADD ) ); + UpdateTargetVarToReflectMapIndex( 0 ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/solver/chlsl_solver_add.h b/sp/src/shadereditor/solver/chlsl_solver_add.h new file mode 100644 index 00000000..8e433a12 --- /dev/null +++ b/sp/src/shadereditor/solver/chlsl_solver_add.h @@ -0,0 +1,18 @@ +#ifndef CHLSL_SOLVER_ADD_H +#define CHLSL_SOLVER_ADD_H + +#include "editorcommon.h" + +class CHLSL_Solver_Add : public CHLSL_SolverBase +{ +public: + CHLSL_Solver_Add( HNODE nodeidx ) : CHLSL_SolverBase( nodeidx ) {}; + CHLSL_SolverBase *Copy(){ + return new CHLSL_Solver_Add( *this ); }; + +protected: + virtual void OnWriteFXC( bool bIsPixelShader, WriteContext_FXC &context ); + virtual void Render( Preview2DContext &c ); +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/solver/chlsl_solver_append.cpp b/sp/src/shadereditor/solver/chlsl_solver_append.cpp new file mode 100644 index 00000000..e9532fd1 --- /dev/null +++ b/sp/src/shadereditor/solver/chlsl_solver_append.cpp @@ -0,0 +1,34 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +void CHLSL_Solver_Append::OnWriteFXC( bool bIsPixelShader, WriteContext_FXC &context ) +{ + CHLSL_Var *tg = GetTargetVar( 0 ); + tg->DeclareMe(context); + CHLSL_Var *src1 = GetSourceVar( 0 ); + CHLSL_Var *src2 = GetSourceVar( 1 ); + + const char *varCodeName = ::GetVarCodeNameFromFlag( tg->GetType() ); + + char tmp[MAXTARGC]; + Q_snprintf( tmp, MAXTARGC, "%s = %s( %s, %s );\n", + tg->GetName(), varCodeName, + src1->GetName(), src2->GetName() ); + context.buf_code.PutString( tmp ); +} + +void CHLSL_Solver_Append::Render( Preview2DContext &c ) +{ + int numcomp_0 = ::GetSlotsFromTypeFlag( GetSourceVar(0)->GetType() ); + + SetUVParamBySourceVar( NPSOP_CALC_APPEND, 0, 0 ); + SetUVParamBySourceVar( NPSOP_CALC_APPEND, 1, 1 ); + + IMaterialVar *var_2 = pEditorRoot->GetUVTargetParam( NPSOP_CALC_APPEND, 2 ); + var_2->SetVecValue( numcomp_0 == 1, numcomp_0 == 2, numcomp_0 == 3, numcomp_0 == 4 ); + + CNodeView::RenderSingleSolver( c, pEditorRoot->GetOperatorMaterial( NPSOP_CALC_APPEND ) ); + UpdateTargetVarToReflectMapIndex( 0 ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/solver/chlsl_solverbase.cpp b/sp/src/shadereditor/solver/chlsl_solverbase.cpp new file mode 100644 index 00000000..cbb0adef --- /dev/null +++ b/sp/src/shadereditor/solver/chlsl_solverbase.cpp @@ -0,0 +1,238 @@ + +#include "cbase.h" +#include "editorcommon.h" + +SolverInfo_t::SolverInfo_t() +{ + iNodeIndex = 0; + m_bValid = true; +} +SolverInfo_t::~SolverInfo_t() +{ + _IntValue_0 = _IntValue_1 = 0; +} +SolverInfo_t::SolverInfo_t( const SolverInfo_t &o ) +{ + iNodeIndex = o.iNodeIndex; + _IntValue_0 = o._IntValue_0; + _IntValue_1 = o._IntValue_1; + m_bValid = o.m_bValid; +} + +CHLSL_SolverBase::CHLSL_SolverBase( HNODE nodeidx ) +{ + m_iResourceType = RESOURCETYPE_VARIABLE; + + //pInfo = new SolverInfo_t(); + //pInfo->iNodeIndex = nodeidx; + pInfo.iNodeIndex = nodeidx; + m_iMapIndex = 0; + + AllocCheck_Alloc(); +} + +CHLSL_SolverBase::~CHLSL_SolverBase() +{ + m_hVar_SourceVars.Purge(); + m_hVar_TargetVars.Purge(); + + //delete pInfo; + + AllocCheck_Free(); +} + +CHLSL_SolverBase::CHLSL_SolverBase( const CHLSL_SolverBase& o ) +{ + m_iResourceType = o.m_iResourceType; + m_iMapIndex = 0; + + m_hVar_SourceVars.Purge(); + m_hVar_TargetVars.Purge(); + + pInfo = o.pInfo; + //pInfo = NULL; + + //if ( o.pInfo ) + // pInfo = new SolverInfo_t( *o.pInfo ); + + AllocCheck_Alloc(); +} + +void CHLSL_SolverBase::ClearInfo() +{ + //delete pInfo; + //pInfo = NULL; + pInfo.m_bValid = false; +} + +SolverInfo_t &CHLSL_SolverBase::GetData() +{ + Assert( pInfo.m_bValid ); + return pInfo; + //Assert( pInfo ); + //return *pInfo; +} + +const ResourceType_t &CHLSL_SolverBase::GetResourceType() +{ + return m_iResourceType; +} +void CHLSL_SolverBase::SetResourceType( const int &type ) +{ + m_iResourceType = ((ResourceType_t)type); +} + +void CHLSL_SolverBase::AddSourceVar( CHLSL_Var *var ) +{ + //if ( m_hVar_SourceVars.IsValidIndex( m_hVar_SourceVars.Find( var ) ) ) + // return; + + m_hVar_SourceVars.AddToTail( var ); +} +void CHLSL_SolverBase::AddTargetVar( CHLSL_Var *var ) +{ + //if ( m_hVar_TargetVars.IsValidIndex( m_hVar_TargetVars.Find( var ) ) ) + // return; + + m_hVar_TargetVars.AddToTail( var ); +} +int CHLSL_SolverBase::GetNumSourceVars() +{ + return m_hVar_SourceVars.Count(); +} +int CHLSL_SolverBase::GetNumTargetVars() +{ + return m_hVar_TargetVars.Count(); +} +CHLSL_Var *CHLSL_SolverBase::GetSourceVar( int idx ) +{ + Assert( m_hVar_SourceVars.IsValidIndex( idx ) ); + return m_hVar_SourceVars[ idx ]; +} +CHLSL_Var *CHLSL_SolverBase::GetTargetVar( int idx ) +{ + Assert( m_hVar_TargetVars.IsValidIndex( idx ) ); + return m_hVar_TargetVars[ idx ]; +} +void CHLSL_SolverBase::ReconnectVariables( CHLSL_SolverBase *shadow, + CUtlVector< CHLSL_Var* > &m_hListOld, + CUtlVector< CHLSL_Var* > &m_hListNew ) +{ + for ( int i = 0; i < shadow->m_hVar_SourceVars.Count(); i++ ) + { + int idx = m_hListOld.Find( shadow->m_hVar_SourceVars[i] ); + if ( !m_hListOld.IsValidIndex( idx ) ) + Warning("solver copy: FATAL ERROR\n"); + + m_hVar_SourceVars.AddToTail( m_hListNew[idx] ); + } + + for ( int i = 0; i < shadow->m_hVar_TargetVars.Count(); i++ ) + { + int idx = m_hListOld.Find( shadow->m_hVar_TargetVars[i] ); + if ( !m_hListOld.IsValidIndex( idx ) ) + Warning("solver copy: FATAL ERROR\n"); + + m_hVar_TargetVars.AddToTail( m_hListNew[idx] ); + } + + Assert( shadow->GetNumSourceVars() == GetNumSourceVars() ); + Assert( shadow->GetNumTargetVars() == GetNumTargetVars() ); +} + +void CHLSL_SolverBase::Invoke_VarInit( const WriteContext_FXC &context ) +{ + OnVarInit( context ); +} +void CHLSL_SolverBase::OnVarInit( const WriteContext_FXC &context ) +{ +} +void CHLSL_SolverBase::Invoke_VarInit_PostStep() +{ + OnVarInit_PostStep(); +} +void CHLSL_SolverBase::OnVarInit_PostStep() +{ +} + +void CHLSL_SolverBase::Invoke_WriteFXC( bool bIsPixelShader, WriteContext_FXC &context ) +{ + OnWriteFXC( bIsPixelShader, context ); +} +void CHLSL_SolverBase::OnWriteFXC( bool bIsPixelShader, WriteContext_FXC &context ) +{ +} + +void CHLSL_SolverBase::Invoke_Render( Preview2DContext &c ) +{ + Render( c ); + m_iMapIndex = ::GetCurrentPuzzleIndex(); +} +void CHLSL_SolverBase::Render( Preview2DContext &c ) +{ + if ( GetNumTargetVars() < 1 ) + return; + + float info_0[4] = { 1, 1, 1, 1 }; + IMaterialVar *pMatVar0 = pEditorRoot->GetUVTargetParam( NPSOP_SET_CONSTANT, 0 ); + pMatVar0->SetVecValue( info_0, 4 ); + + CNodeView::RenderSingleSolver( c, pEditorRoot->GetOperatorMaterial( NPSOP_SET_CONSTANT ) ); + UpdateTargetVarToReflectMapIndex( 0 ); +} + +void CHLSL_SolverBase::UpdateTargetVarToReflectMapIndex( int var ) +{ + if ( var > (GetNumTargetVars()-1) ) + { + //Assert( 0 ); + return; + } + + CHLSL_Var *target = GetTargetVar( var ); + target->SetMapIndex( GetCurrentPuzzleIndex() ); + //Msg( "setting idx: %i\n", GetCurrentPuzzleIndex() ); +} +void CHLSL_SolverBase::SetUVParamBySourceVar( int operatoridx, int uvparam, int sourcevar ) +{ + Assert( sourcevar < GetNumSourceVars() ); + + CHLSL_Var *src1 = GetSourceVar( sourcevar ); + IMaterialVar *pMatVar = pEditorRoot->GetUVTargetParam( operatoridx, uvparam ); + Vector2D a,b; + GetUVsForPuzzle( src1->GetMapIndex(), a, b ); + //Msg("index %i, uv coords: %f %f\n", src1->GetMapIndex(), a.x, a.y); + pMatVar->SetVecValue( a.x, a.y, b.x, b.y ); +} + +void CHLSL_SolverBase::Invoke_RenderInit() +{ + OnRenderInit(); +} +void CHLSL_SolverBase::OnRenderInit() +{ +} + +void CHLSL_SolverBase::Invoke_IdentifierAllocate( IdentifierLists_t &List ) +{ + OnIdentifierAlloc( List ); +} +void CHLSL_SolverBase::OnIdentifierAlloc( IdentifierLists_t &List ) +{ +} + +void CHLSL_SolverBase::Invoke_ExecuteCode( const RunCodeContext &context ) +{ + OnExecuteCode( context ); +} +void CHLSL_SolverBase::OnExecuteCode( const RunCodeContext &context ) +{ +} + +CHLSL_SolverBase *CHLSL_SolverBase::Copy() +{ +#if SHOW_SEDIT_ERRORS + AssertMsg( 0, "Copy called on baseSolver!!\n" ); +#endif + return NULL; +} \ No newline at end of file diff --git a/sp/src/shadereditor/solver/chlsl_solverbase.h b/sp/src/shadereditor/solver/chlsl_solverbase.h new file mode 100644 index 00000000..fd63ab2b --- /dev/null +++ b/sp/src/shadereditor/solver/chlsl_solverbase.h @@ -0,0 +1,94 @@ +#ifndef CHLSL_SOLVER_BASE_H +#define CHLSL_SOLVER_BASE_H + +#include "editorcommon.h" + +struct IdentifierLists_t; + +struct SolverInfo_t +{ + SolverInfo_t(); + ~SolverInfo_t(); + SolverInfo_t( const SolverInfo_t &o ); + + HNODE iNodeIndex; + + int _IntValue_0; + int _IntValue_1; + + bool m_bValid; +}; + +class CHLSL_SolverBase +{ +public: + CHLSL_SolverBase( HNODE nodeidx ); + virtual ~CHLSL_SolverBase(); + + CHLSL_SolverBase( const CHLSL_SolverBase& o ); + + virtual CHLSL_SolverBase *Copy(); + + virtual bool IsDummy(){ return false; }; + + const ResourceType_t &GetResourceType(); + void SetResourceType( const int &type ); + + virtual void ReconnectVariables( CHLSL_SolverBase *shadow, + CUtlVector< CHLSL_Var* > &m_hListOld, + CUtlVector< CHLSL_Var* > &m_hListNew ); + + virtual void AddSourceVar( CHLSL_Var *var ); + virtual void AddTargetVar( CHLSL_Var *var ); + + int GetNumSourceVars(); + int GetNumTargetVars(); + + CHLSL_Var *GetSourceVar( int idx ); + CHLSL_Var *GetTargetVar( int idx ); + + SolverInfo_t &GetData(); + + virtual void ClearInfo(); + + virtual void Invoke_VarInit( const WriteContext_FXC &context ); + virtual void Invoke_VarInit_PostStep(); + virtual void Invoke_WriteFXC( bool bIsPixelShader, WriteContext_FXC &context ); + + virtual void Invoke_RenderInit(); + virtual void Invoke_Render( Preview2DContext &c ); + virtual void Render( Preview2DContext &c ); + virtual bool IsRenderable(){ return true; }; + + virtual void Invoke_IdentifierAllocate( IdentifierLists_t &List ); + + virtual void Invoke_ExecuteCode( const RunCodeContext &context ); + + const int &GetMapIndex(){return m_iMapIndex;}; + +protected: + virtual void OnRenderInit(); + virtual void OnVarInit( const WriteContext_FXC &context ); + virtual void OnVarInit_PostStep(); + virtual void OnWriteFXC( bool bIsPixelShader, WriteContext_FXC &context ); + virtual void OnIdentifierAlloc( IdentifierLists_t &List ); + virtual void OnExecuteCode( const RunCodeContext &context ); + + //SolverResources *m_pCurrentSolverResource; + + //SolverInfo_t *pInfo; + SolverInfo_t pInfo; + CUtlVector< CHLSL_Var* >m_hVar_SourceVars; + CUtlVector< CHLSL_Var* >m_hVar_TargetVars; + + ResourceType_t m_iResourceType; + + void UpdateTargetVarToReflectMapIndex( int var ); + void SetUVParamBySourceVar( int operatoridx, int uvparam, int sourcevar ); + + int m_iMapIndex; +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/stdafx.cpp b/sp/src/shadereditor/stdafx.cpp new file mode 100644 index 00000000..e2eb38f6 --- /dev/null +++ b/sp/src/shadereditor/stdafx.cpp @@ -0,0 +1,11 @@ +//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// +// +// Purpose: Builds the precompiled header for the client DLL +// +// $NoKeywords: $ +//=============================================================================// + + +#include "cbase.h" + +// NOTE: DO NOT ADD ANY CODE OR HEADERS TO THIS FILE!!! diff --git a/sp/src/shadereditor/vbasediag.cpp b/sp/src/shadereditor/vbasediag.cpp new file mode 100644 index 00000000..6d0f1088 --- /dev/null +++ b/sp/src/shadereditor/vbasediag.cpp @@ -0,0 +1,109 @@ + +#include "cbase.h" +#include "editorCommon.h" +//#include "vgui_int.h" + +static CUtlVector< CBaseDiag* >hListDiags; + +CBaseDiag::CBaseDiag( vgui::Panel *parent, CNodeView *nodeview, const char *pElementName, bool bDoAutoSorting ) : BaseClass( parent, pElementName ) +{ + m_bDoAutoSorting = bDoAutoSorting; + pNodeView = nodeview; + + Activate(); + SetVisible( true ); + + SetPaintBackgroundEnabled(true); + SetPaintEnabled(true); + SetCloseButtonVisible(true); + + SetSizeable(true); + SetMoveable(true); + SetTitle("",true); + SetMinimumSize( 400, 300 ); + + SetDeleteSelfOnClose( true ); + + if ( m_bDoAutoSorting ) + hListDiags.AddToHead(this); +} +CBaseDiag::~CBaseDiag() +{ + if ( m_bDoAutoSorting ) + hListDiags.FindAndRemove(this); +} + +void CBaseDiag::OnManualCursorEntered() +{ + SetMouseInputEnabled(true); + SetKeyBoardInputEnabled(true); + + if ( m_bDoAutoSorting ) + InternalMoveToFront(); +} +void CBaseDiag::OnManualCursorExited() +{ + SetMouseInputEnabled(false); + SetKeyBoardInputEnabled(false); +} + +void CBaseDiag::InternalSort() +{ + VPANEL hfocus = g_pVGuiInput->GetFocus(); + + for ( int i = 0; i < hListDiags.Count(); i++ ) + { + CBaseDiag *d = hListDiags[i]; + const bool bFocus_is_parent = ipanel()->HasParent( d->GetVPanel(), hfocus ); + const bool bFocus_has_same_parent = d->GetParent() && ipanel()->HasParent( hfocus, d->GetParent()->GetVPanel() ); + const bool bFocus_is_child = ipanel()->HasParent( hfocus, d->GetVPanel() ); + const bool bGlobalInput = pEditorRoot && pEditorRoot->HasInputEnabled(); + + if ( ( bFocus_is_parent || bFocus_has_same_parent ) && !bFocus_is_child && !g_pVGuiInput->GetAppModalSurface() && + !IsBuildModeActive() && bGlobalInput ) + d->MoveToFront(); + } +} + +void CBaseDiag::InternalMoveToFront() +{ + hListDiags.FindAndRemove( this ); + hListDiags.AddToTail( this ); +} + +void CBaseDiag::OnThink(void) +{ + BaseClass::OnThink(); + + SetBgColor( c_1 ); + SetOutOfFocusColor( c_2 ); + + if ( m_bDoAutoSorting ) + { + int a,b,c,d,e,f; + GetBounds( a,b,c,d ); + input()->GetCursorPosition( e, f ); + ScreenToLocal( e, f ); + + const bool bGlobalInput = pEditorRoot && pEditorRoot->HasInputEnabled(); + const bool bMWasActive = IsMouseInputEnabled(); + const bool bMShouldActive = e >= 0 && e <= c && f >= 0 && f <= d && bGlobalInput && (g_pVGuiInput->GetAppModalSurface() == GetVPanel() || !g_pVGuiInput->GetAppModalSurface()); + if ( bMWasActive != bMShouldActive && !IsBuildModeActive() ) + { + if ( bMShouldActive ) + OnManualCursorEntered(); + else + OnManualCursorExited(); + } + + InternalSort(); + } +} + +void CBaseDiag::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + c_1 = pScheme->GetColor( "Grey_t", GetBgColor() ); + c_2 = pScheme->GetColor( "Grey_Faint_t", GetOutOfFocusColor() ); +} diff --git a/sp/src/shadereditor/vbasediag.h b/sp/src/shadereditor/vbasediag.h new file mode 100644 index 00000000..d99a6f81 --- /dev/null +++ b/sp/src/shadereditor/vbasediag.h @@ -0,0 +1,39 @@ +#ifndef CHLSL_BASEDIAG_H +#define CHLSL_BASEDIAG_H + +#include "cbase.h" +#include "editorCommon.h" +#include "cSolverCallback.h" + +#include "vgui_controls/html.h" + +class CBaseDiag : public vgui::Frame +{ + DECLARE_CLASS_SIMPLE( CBaseDiag, vgui::Frame ); + +public: + CBaseDiag( vgui::Panel *parent, CNodeView *nodeview, const char *pElementName, bool bDoAutoSorting = false ); + ~CBaseDiag(); + + virtual void OnThink(); + +protected: + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + + virtual void OnManualCursorEntered(); + virtual void OnManualCursorExited(); + +protected: + bool m_bDoAutoSorting; + CNodeView *pNodeView; + + Color c_1; + Color c_2; + + void InternalSort(); + void InternalMoveToFront(); +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vbridge.cpp b/sp/src/shadereditor/vbridge.cpp new file mode 100644 index 00000000..79d776e2 --- /dev/null +++ b/sp/src/shadereditor/vbridge.cpp @@ -0,0 +1,333 @@ + +#include "cbase.h" +#include "editorCommon.h" + +#define BRIDGE_DRAW_SEGMENTS_MIN 8 +#define BRIDGE_DRAW_SEGMENTS_MAX 64 + +#define BRIDGE_DRAW_ARROW_MIN 4 +#define BRIDGE_DRAW_ARROW_MAX 16 + +CBridge::CBridge( CNodeView *p ) +{ + pNodeView = p; + + pJ_Src = NULL; + pJ_Dst = NULL; + + pN_Src = NULL; + pN_Dst = NULL; + + //bDrawOrange = false; + iTempColor = TMPCOL_NONE; + + SetupVguiTex( m_iTex_Arrow, "shadereditor/arrow" ); + + start_old.Init(); + end_old.Init(); + + m_flLength = 0; + + iErrorLevel = ERRORLEVEL_NONE; +} +CBridge::~CBridge() +{ + CJack *j = pJ_Dst; + pJ_Dst = NULL; + if ( j ) + j->OnBridgeRemoved( this ); + j = pJ_Src; + pJ_Src = NULL; + if ( j ) + j->OnBridgeRemoved( this ); + pNodeView->OnBridgeRemoved( this ); +} + +void CBridge::ConnectSource( CJack *j, CBaseNode *n ) +{ + pJ_Src = j; + pN_Src = n; + + j->ConnectBridge( this ); +} + +void CBridge::ConnectDestination( CJack *j, CBaseNode *n ) +{ + pJ_Dst = j; + pN_Dst = n; + + j->ConnectBridge( this ); +} + +void CBridge::DisconnectSource() +{ + CJack *j = pJ_Src; + pJ_Src = NULL; + pN_Src = NULL; + if ( j ) + j->OnBridgeRemoved( this ); + +} +void CBridge::DisconnectDestination() +{ + CJack *j = pJ_Dst; + pJ_Dst = NULL; + pN_Dst = NULL; + if ( j ) + j->OnBridgeRemoved( this ); +} + +CBaseNode *CBridge::GetEndNode( CBaseNode *n ) +{ + if ( !n || ( pN_Src != n && pN_Dst != n ) ) + return NULL; + return (pN_Dst == n) ? pN_Src : pN_Dst; +} +CBaseNode *CBridge::GetEndNode( CJack *j ) +{ + return GetEndNode( j->GetParentNode() ); +} +CJack *CBridge::GetEndJack( CBaseNode *n ) +{ + if ( !n || ( pN_Src != n && pN_Dst != n ) ) + return NULL; + return (pN_Dst == n) ? pJ_Src : pJ_Dst; +} +CJack *CBridge::GetEndJack( CJack *j ) +{ + return GetEndJack( j->GetParentNode() ); +} + +void CBridge::SetTemporaryTarget( Vector2D tg ) +{ + tmp = tg; +} + + +inline float BSplineSingle( float start, float end, float cp1, float cp2, float fraction ) +{ + float tmp = 0; + + float hlp1, hlp2, mid; + mid = Lerp( fraction, cp1, cp2); + hlp1 = Lerp( fraction, Lerp( fraction, start, cp1), mid ); + hlp2 = Lerp( fraction, mid, Lerp( fraction, cp2, end) ); + tmp = Lerp( fraction, hlp1, hlp2 ); + return tmp; +} +inline void BSplineVector2D( Vector2D &start, Vector2D &end, Vector2D &cp1, Vector2D &cp2, + float fraction, bool autosmooth_key1, bool autosmooth_key2, Vector2D &output ) +{ + if (autosmooth_key1) + { + Vector2D dir = cp1 - start; + dir.NormalizeInPlace(); + + cp1 = start + dir * (end-start).Length() * 0.4f; + } + if (autosmooth_key2) + { + Vector2D dir = cp2 - end; + dir.NormalizeInPlace(); + + cp2 = end + dir * (end-start).Length() * 0.4f; + } + + output.Init(); + for (int i = 0; i < 2; i++) + output[i] = BSplineSingle( start[i], end[i], cp1[i], cp2[i], fraction ); +} + +void CBridge::SetTemporaryColor( int mode ) +{ + if ( iTempColor > mode ) + return; + + iTempColor = mode; +} + +void CBridge::VguiDraw( const bool bShadow ) +{ + CJack *ji = GetInputJack(); + CJack *jd = GetDestinationJack(); + + Vector2D start = ji ? ji->GetCenter() : tmp; + Vector2D end = jd ? jd->GetCenter() : tmp; + +#define BRIDGEHULLEXTRUDE 60.0f + Vector2D bounds_min = start; + Vector2D bounds_max = end; + if ( bounds_max.x < bounds_min.x ) + swap( bounds_min.x, bounds_max.x ); + if ( bounds_max.y < bounds_min.y ) + swap( bounds_min.y, bounds_max.y ); + bounds_min -= Vector2D( BRIDGEHULLEXTRUDE, BRIDGEHULLEXTRUDE ); + bounds_max += Vector2D( BRIDGEHULLEXTRUDE, BRIDGEHULLEXTRUDE ); + swap( bounds_min.y, bounds_max.y ); + if ( !::ShouldSimpleDrawObject( pNodeView, pNodeView, Vector4D( bounds_min.x, bounds_min.y, bounds_max.x, bounds_max.y ) ) ) + return; + + if ( ji ) + { + Vector2D tmpBounds = ji->GetBoundsMax(); + start.x = tmpBounds.x; + } + if ( jd ) + { + Vector2D tmpBounds = jd->GetBoundsMin(); + end.x = tmpBounds.x; + } + + if ( bShadow ) + { + start += Vector2D( NODE_DRAW_SHADOW_DELTA, -NODE_DRAW_SHADOW_DELTA ); + end += Vector2D( NODE_DRAW_SHADOW_DELTA, -NODE_DRAW_SHADOW_DELTA ); + } + + float extend = 30; + Vector2D delta = end - start; + float len = delta.Length(); + float addInverse = (delta.x < 0) ? RemapValClamped(abs(delta.x),0,100,0,0.045f) : 0; + + extend += len * ( 0.2f + addInverse ); + + addInverse = (delta.x < 0) ? RemapValClamped(abs(delta.x),0,100,0,180) : 0; + addInverse *= Sign( delta.y ) * RemapValClamped( abs(delta.y), 0, 50, 0, 1 ); + + CJack *relativeJack_1 = (delta.y>0) ? jd : ji; + CBaseNode *pN1 = relativeJack_1 ? relativeJack_1->GetParentNode() : NULL; + + float desiredMultiply1 = pN1 ? (RemapVal( abs( pN1->GetSize().y ), 0, 100, 0, 1.2f )) : 1.2f; + float desiredMultiply2 = 0.65f; + + float mulAdd_Start = (delta.y < 0) ? desiredMultiply1 : desiredMultiply2; + float mulAdd_End = (delta.y >= 0) ? desiredMultiply1 : desiredMultiply2; + + float scaleMaster = RemapValClamped( len, 0, 50, 0, 1 ); + + Vector2D cp1 = start + Vector2D( extend, addInverse * mulAdd_Start ) * scaleMaster; + Vector2D cp2 = end - Vector2D( extend, addInverse * mulAdd_End ) * scaleMaster; + + pNodeView->ToPanelSpace( start ); + pNodeView->ToPanelSpace( end ); + + pNodeView->ToPanelSpace( cp1 ); + pNodeView->ToPanelSpace( cp2 ); + + Color col = Color(0,0,0,128); + + if ( bShadow ) + col = NODE_DRAW_COLOR_SHADOW; + else + { + if ( ji && jd ) + { + if ( GetErrorLevel() == ERRORLEVEL_UNDEFINED ) + col = DRAWCOLOR_ERRORLEVEL_UNDEFINED; + else if ( GetErrorLevel() == ERRORLEVEL_FAIL ) + col = DRAWCOLOR_ERRORLEVEL_FAIL; + else + { + col = Color(0,0,0,255); + + if ( ji->GetJackType() & HLSLVAR_PP_MASTER ) + col = JACK_COLOR_PPMASTER; + } + + if ( iTempColor != TMPCOL_NONE ) + { + switch ( iTempColor ) + { + case TMPCOL_ORANGE: + col = DRAWCOLOR_BRIDGE_TMP_COL_ORANGE; + break; + case TMPCOL_TRANS: + col[3] = DRAWCOLOR_BRIDGE_TMP_COL_TRANS.a(); + break; + } + + iTempColor = TMPCOL_NONE; + } + } + } + + surface()->DrawSetColor( col ); + static IMaterial *pMatArrow = materials->FindMaterial( "shadereditor/arrow", TEXTURE_GROUP_OTHER ); + static unsigned int iVar = 0; + IMaterialVar *pVarGlowCol = pMatArrow->FindVarFast( "$glowcolor", &iVar ); + + const float scalar = 255.0f; + if ( pVarGlowCol ) + pVarGlowCol->SetVecValue( col[0] / scalar, col[1] / scalar, col[2] / scalar ); + + //if ( ( start_old != start || end_old != end ) && !bShadow ) + //{ + // double approxLength = 0; + // Vector2D append = start; + + // for ( int i = 0; i <= 1024; i++ ) + // { + // float frac = clamp( i / ( (float) 1024 ), 0, 1 ); + // Vector2D goal; + // BSplineVector2D( start, end, cp1, cp2, frac, false, false, goal ); + // approxLength += ( goal - append ).LengthSqr(); + // append = goal; + // } + + // m_flLength = FastSqrt( approxLength ); + // start_old = start; + // end_old = end; + //} + + m_flLength = (start-end).Length(); + + float arrowLength = 0.01f; + //float normalizedLength = m_flLength / pNodeView->GetZoomScalar(); + float normalizedLength = m_flLength / pNodeView->GetZoomScalar(); + if ( normalizedLength < arrowLength ) + return; + + Vertex_t vert[4]; + + Vector2D arrowStart; + BSplineVector2D( start, end, cp1, cp2, 1.0f - (arrowLength/normalizedLength), false, false, arrowStart ); + + Vector crossed3D; + Vector2D deltaArrow = end - arrowStart; + deltaArrow.NormalizeInPlace(); + deltaArrow *= 15.0f * pNodeView->GetZoomScalar(); + arrowStart = end - deltaArrow; + + Vector2D offsetX = deltaArrow * 0.15f; + + CrossProduct( Vector( deltaArrow.x, deltaArrow.y, 0 ), Vector( 0,0,1 ), crossed3D ); + Vector2D side( crossed3D.x, crossed3D.y ); + side.NormalizeInPlace(); + + side *= deltaArrow.Length(); + vert[0].Init( arrowStart + side * 0.5f + offsetX, Vector2D(0,0) ); + vert[1].Init( end + side * 0.5f + offsetX, Vector2D(1,0) ); + vert[2].Init( end - side * 0.5f + offsetX, Vector2D(1,1) ); + vert[3].Init( arrowStart - side * 0.5f + offsetX, Vector2D(0,1) ); + + surface()->DrawSetTexture( m_iTex_Arrow ); + surface()->DrawTexturedPolygon( 4, vert ); + + arrowStart = end - deltaArrow * 0.57f; + + int segments = ((int) RemapValClamped( pNodeView->GetZoomScalar(), 0, VIEWZOOM_OUT_MAX, BRIDGE_DRAW_SEGMENTS_MIN, BRIDGE_DRAW_SEGMENTS_MAX ) ); + segments -= RemapValClamped( normalizedLength, 0, 1000, max(1, segments - 10), 0 ); + + + Vector2D append = start; + for ( int i = 1; i <= segments; i++ ) + { + float frac = clamp( i / ( (float) segments ), 0, 1 ); + Vector2D goal; + BSplineVector2D( start, arrowStart, cp1, cp2, frac, false, false, goal ); + surface()->DrawLine( append.x, append.y - 1, goal.x, goal.y - 1 ); + surface()->DrawLine( append.x, append.y, goal.x, goal.y ); + surface()->DrawLine( append.x, append.y + 1, goal.x, goal.y + 1 ); + append = goal; + } +} diff --git a/sp/src/shadereditor/vbridge.h b/sp/src/shadereditor/vbridge.h new file mode 100644 index 00000000..a6c642c3 --- /dev/null +++ b/sp/src/shadereditor/vbridge.h @@ -0,0 +1,74 @@ +#ifndef CBRIDGE_H +#define CBRIDGE_H + +#include +#include +#include +#include +#include "ienginevgui.h" +#include "vgui_controls/Controls.h" + +class CJack; +class CBaseNode; +class CNodeView; + +class CBridge +{ +public: + CBridge( CNodeView *p ); + ~CBridge(); + + void ConnectSource( CJack *j, CBaseNode *n ); + void ConnectDestination( CJack *j, CBaseNode *n ); + + void DisconnectSource(); + void DisconnectDestination(); + + void SetTemporaryTarget( Vector2D tg ); + + virtual void VguiDraw( const bool bShadow = false ); + + CBaseNode *GetEndNode( CBaseNode *n ); + CBaseNode *GetEndNode( CJack *j ); + CJack *GetEndJack( CBaseNode *n ); + CJack *GetEndJack( CJack *j ); + + CJack *GetInputJack(){ return pJ_Src; }; + CJack *GetDestinationJack(){ return pJ_Dst; }; + CBaseNode *GetInputNode(){ return pN_Src; }; + CBaseNode *GetDestinationNode(){ return pN_Dst; }; + + const int GetErrorLevel(){ return iErrorLevel; }; + void SetErrorLevel(const int e){ iErrorLevel = e; }; + + //void MakeBridgeVolatile(){ bDrawOrange = true; }; + enum + { + TMPCOL_NONE = 0, + TMPCOL_TRANS, + TMPCOL_ORANGE, + }; + void SetTemporaryColor( int mode ); + +private: + Vector2D tmp; + CNodeView *pNodeView; + int iErrorLevel; + int iTempColor; + //bool bDrawOrange; + + CJack *pJ_Src; + CJack *pJ_Dst; + + CBaseNode *pN_Src; + CBaseNode *pN_Dst; + + int m_iTex_Arrow; + + float m_flLength; + Vector2D start_old; + Vector2D end_old; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogconfig.cpp b/sp/src/shadereditor/vdialogconfig.cpp new file mode 100644 index 00000000..d451ace0 --- /dev/null +++ b/sp/src/shadereditor/vdialogconfig.cpp @@ -0,0 +1,126 @@ + +#include "cbase.h" +#include "editorCommon.h" + +static const char *blendNames[] = { + "None", + "Blend enabled", + "Blend inverted", + "Blend additive", + "Alpha test", + "Alpha to coverage", +}; +static const int blendIDx[] = { + ABLEND_NONE, + ABLEND_SIMPLE, + ABLEND_SIMPLE_INVERTED, + ABLEND_ADDITIVE, + ABLEND_ALPHATEST, + ABLEND_ALPHA2COVERAGE, +}; + +const int numAblendModes = ARRAYSIZE( blendNames ); + +CDialog_GeneralConfig::CDialog_GeneralConfig( CNodeView *n, Panel *parent ) : Frame( parent, "_config" ) +{ + pNodeView = n; + GenericShaderData *setup = &n->GetDataForModify(); + + SetSizeable( false ); + SetVisible( true ); + + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + SetAutoDelete( true ); + Activate(); + + m_pRadBut_Sm2 = new RadioButton( this, "rad_1", "SM 2.0b" ); + m_pRadBut_Sm3 = new RadioButton( this, "rad_2", "SM 3.0" ); + m_pRadBut_Sm2->SetSubTabPosition( 1 ); + m_pRadBut_Sm3->SetSubTabPosition( 1 ); + + m_pCBut_DepthTest = new CheckButton( this, "depthtest", "Depth testing" ); + m_pCBut_DepthWrite = new CheckButton( this, "depthwrite", "Depth writing" ); + m_pCBut_sRGBWrite = new CheckButton( this, "srgbwrite", "write sRGB" ); + + m_pCBox_AlphaBlend = new ComboBox( this, "alphablend", numAblendModes, false ); + + for ( int i = 0; i < numAblendModes; i++ ) + m_pCBox_AlphaBlend->AddItem( blendNames[i], NULL ); + + Assert( numAblendModes == m_pCBox_AlphaBlend->GetItemCount() ); + + m_pCBox_Cullmode = new ComboBox( this, "cullmode", 5, false ); + m_pCBox_Cullmode->AddItem( "CW", NULL ); + m_pCBox_Cullmode->AddItem( "CCW", NULL ); + //m_pCBox_Cullmode->AddItem( "Double", NULL ); + m_pCBox_Cullmode->AddItem( "Off", NULL ); + + LoadControlSettings("shadereditorui/vgui/dialog_config.res"); + + if ( setup->shader->iShaderModel == SM_30 ) + m_pRadBut_Sm3->SetSelected( true ); + else + m_pRadBut_Sm2->SetSelected( true ); + + m_pCBut_DepthTest->SetSelected( setup->shader->iDepthtestmode == DEPTHTEST_NORMAL ); + m_pCBut_DepthWrite->SetSelected( setup->shader->iDepthwritemode == DEPTHWRITE_NORMAL ); + m_pCBox_Cullmode->ActivateItem( setup->shader->iCullmode ); + m_pCBut_sRGBWrite->SetSelected( setup->shader->bsRGBWrite ); + + for ( int i = 0; i < numAblendModes; i++ ) + { + if ( blendIDx[i] == setup->shader->iAlphablendmode ) + { + m_pCBox_AlphaBlend->ActivateItem( i ); + break; + } + } + + SetTitle( "Shader settings", true ); + + + DoModal(); + + SetDeleteSelfOnClose( true ); +} + +CDialog_GeneralConfig::~CDialog_GeneralConfig() +{ +} + +void CDialog_GeneralConfig::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( cmd, "save" ) ) + { + OnSave(); + Close(); + } + else if ( !Q_stricmp( cmd, "close" ) ) + { + Close(); + } +} + +void CDialog_GeneralConfig::PerformLayout() +{ + BaseClass::PerformLayout(); + SetCloseButtonVisible( false ); + + SetSize( 400, 300 ); + MoveToCenterOfScreen(); +} + +void CDialog_GeneralConfig::OnSave() +{ + Assert( numAblendModes == m_pCBox_AlphaBlend->GetItemCount() && m_pCBox_AlphaBlend->GetActiveItem() < numAblendModes ); + + GenericShaderData *setup = &pNodeView->GetDataForModify(); + setup->shader->iAlphablendmode = blendIDx[m_pCBox_AlphaBlend->GetActiveItem()]; + setup->shader->iCullmode = m_pCBox_Cullmode->GetActiveItem(); + setup->shader->iDepthtestmode = m_pCBut_DepthTest->IsSelected() ? DEPTHTEST_NORMAL : DEPTHTEST_OFF; + setup->shader->iDepthwritemode = m_pCBut_DepthWrite->IsSelected() ? DEPTHWRITE_NORMAL : DEPTHWRITE_OFF; + setup->shader->iShaderModel = m_pRadBut_Sm3->IsSelected() ? SM_30 : SM_20B; + setup->shader->bsRGBWrite = m_pCBut_sRGBWrite->IsSelected(); + pNodeView->MakeSolversDirty(); +} diff --git a/sp/src/shadereditor/vdialogconfig.h b/sp/src/shadereditor/vdialogconfig.h new file mode 100644 index 00000000..9e938df6 --- /dev/null +++ b/sp/src/shadereditor/vdialogconfig.h @@ -0,0 +1,36 @@ +#ifndef CDIALOG_CFG_H +#define CDIALOG_CFG_H + +#include "editorCommon.h" +#include "vgui_controls/controls.h" + + +class CDialog_GeneralConfig : public vgui::Frame +{ +public: + DECLARE_CLASS_SIMPLE( CDialog_GeneralConfig, Frame ); + + CDialog_GeneralConfig( CNodeView *n, Panel *parent ); + ~CDialog_GeneralConfig(); + +protected: + + void OnCommand( const char *cmd ); + + void PerformLayout(); + + CNodeView *pNodeView; + vgui::RadioButton *m_pRadBut_Sm2; + vgui::RadioButton *m_pRadBut_Sm3; + vgui::CheckButton *m_pCBut_DepthTest; + vgui::CheckButton *m_pCBut_DepthWrite; + vgui::CheckButton *m_pCBut_sRGBWrite; + vgui::ComboBox *m_pCBox_AlphaBlend; + vgui::ComboBox *m_pCBox_Cullmode; + + void OnSave(); + + //void OnDataLoaded( int mode ); +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogeditorconfig.cpp b/sp/src/shadereditor/vdialogeditorconfig.cpp new file mode 100644 index 00000000..6db7020f --- /dev/null +++ b/sp/src/shadereditor/vdialogeditorconfig.cpp @@ -0,0 +1,84 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CDialog_EditorConfig::CDialog_EditorConfig( Panel *parent ) : Frame( parent, "_editor_config" ) +{ + SetSizeable( false ); + SetVisible( true ); + + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + Activate(); + + m_pCBut_Draw_Datatypes = new CheckButton( this, "draw_datatypes", "Datatypes" ); + m_pCBut_Draw_Shadows = new CheckButton( this, "draw_shadows", "Shadows" ); + m_pCBut_Draw_Info = new CheckButton( this, "draw_info", "Additional info" ); + m_pCBut_Draw_Tooltip = new CheckButton( this, "draw_tooltip", "Show tooltips on graph" ); + + m_pCBut_Compile_Preview = new CheckButton( this, "compile_preview", "Compile enabled" ); + m_pCBut_Compile_Full = new CheckButton( this, "compile_always_full", "Always compile preview + full" ); + m_pCBut_Compile_Publish = new CheckButton( this, "compile_auto_publish", "Auto publish shaders to materials (full compile)" ); + m_pCBut_Compile_WarnOnSave = new CheckButton( this, "warn_on_close_tab", "Warn when closing a tab with unsaved changes" ); + + m_pCBut_Draw_Datatypes->SetSelected( pEditorRoot->m_bDraw_Datatypes ); + m_pCBut_Draw_Shadows->SetSelected( pEditorRoot->m_bDraw_Shadows ); + m_pCBut_Draw_Info->SetSelected( pEditorRoot->m_bDraw_AllLimits ); + m_pCBut_Draw_Tooltip->SetSelected( pEditorRoot->m_bDoTooltips ); + + m_pCBut_Compile_Preview->SetSelected( pEditorRoot->m_bAutoCompile ); + m_pCBut_Compile_Full->SetSelected( pEditorRoot->m_bAutoFullcompile ); + m_pCBut_Compile_Publish->SetSelected( pEditorRoot->m_bAutoShaderPublish ); + m_pCBut_Compile_WarnOnSave->SetSelected( pEditorRoot->m_bWarnOnClose ); + + LoadControlSettings("shadereditorui/vgui/dialog_editor_config.res"); + + SetTitle( "Editor config", true ); + + DoModal(); + SetDeleteSelfOnClose( true ); + + m_pCBut_Compile_WarnOnSave->SetEnabled( false ); +} + +CDialog_EditorConfig::~CDialog_EditorConfig() +{ +} + +void CDialog_EditorConfig::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( cmd, "save" ) ) + { + OnSave(); + Close(); + } + else if ( !Q_stricmp( cmd, "close" ) ) + { + Close(); + } +} + +void CDialog_EditorConfig::PerformLayout() +{ + BaseClass::PerformLayout(); + SetCloseButtonVisible( false ); + + SetSize( 400, 325 ); + MoveToCenterOfScreen(); +} + +void CDialog_EditorConfig::OnSave() +{ + if ( !pEditorRoot->m_bAutoCompile && m_pCBut_Compile_Preview->IsSelected() ) + pEditorRoot->GetSafeFlowgraph()->MakeSolversDirty(); + + pEditorRoot->m_bDraw_Datatypes = m_pCBut_Draw_Datatypes->IsSelected(); + pEditorRoot->m_bDraw_Shadows = m_pCBut_Draw_Shadows->IsSelected(); + pEditorRoot->m_bDraw_AllLimits = m_pCBut_Draw_Info->IsSelected(); + pEditorRoot->m_bDoTooltips = m_pCBut_Draw_Tooltip->IsSelected(); + + pEditorRoot->m_bAutoCompile = m_pCBut_Compile_Preview->IsSelected(); + pEditorRoot->m_bAutoFullcompile = m_pCBut_Compile_Full->IsSelected(); + pEditorRoot->m_bAutoShaderPublish = m_pCBut_Compile_Publish->IsSelected(); + pEditorRoot->m_bWarnOnClose = m_pCBut_Compile_WarnOnSave->IsSelected(); +} diff --git a/sp/src/shadereditor/vdialogeditorconfig.h b/sp/src/shadereditor/vdialogeditorconfig.h new file mode 100644 index 00000000..21dcfb07 --- /dev/null +++ b/sp/src/shadereditor/vdialogeditorconfig.h @@ -0,0 +1,36 @@ +#ifndef CDIALOG_EDITOR_CFG_H +#define CDIALOG_EDITOR_CFG_H + +#include "editorCommon.h" +#include "vgui_controls/controls.h" + + +class CDialog_EditorConfig : public vgui::Frame +{ +public: + DECLARE_CLASS_SIMPLE( CDialog_EditorConfig, Frame ); + + CDialog_EditorConfig( Panel *parent ); + ~CDialog_EditorConfig(); + +protected: + + void OnCommand( const char *cmd ); + + void PerformLayout(); + + CNodeView *pNodeView; + vgui::CheckButton *m_pCBut_Draw_Datatypes; + vgui::CheckButton *m_pCBut_Draw_Shadows; + vgui::CheckButton *m_pCBut_Draw_Info; + vgui::CheckButton *m_pCBut_Draw_Tooltip; + + vgui::CheckButton *m_pCBut_Compile_Preview; + vgui::CheckButton *m_pCBut_Compile_Full; + vgui::CheckButton *m_pCBut_Compile_Publish; + vgui::CheckButton *m_pCBut_Compile_WarnOnSave; + + void OnSave(); +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vdialognew.cpp b/sp/src/shadereditor/vdialognew.cpp new file mode 100644 index 00000000..03ea323c --- /dev/null +++ b/sp/src/shadereditor/vdialognew.cpp @@ -0,0 +1,78 @@ + +#include "cbase.h" +#include "editorCommon.h" +#include "vgui_controls/radiobutton.h" +#include + +CDialog_NewCanvas::CDialog_NewCanvas( CNodeView *n, Panel *parent ) : Frame( parent, "newshader" ) +{ + pNodeView = n; + + SetSizeable( false ); + SetVisible( true ); + + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + SetDeleteSelfOnClose( true ); + Activate(); + + DoModal(); + + m_pRadBut_Sm2 = new RadioButton( this, "rad_1", "SM 2.0b" ); + m_pRadBut_Sm3 = new RadioButton( this, "rad_2", "SM 3.0" ); + m_pRadBut_Sm2->SetSubTabPosition( 1 ); + m_pRadBut_Sm3->SetSubTabPosition( 1 ); + m_pRadBut_Sm3->SetSelected( true ); + + LoadControlSettings("shadereditorui/vgui/dialog_newcanvas.res"); + + SetTitle( "New shader", true ); +} +CDialog_NewCanvas::~CDialog_NewCanvas() +{ +} +void CDialog_NewCanvas::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( cmd, "scratch" ) ) + { + OnDataLoaded(CANVASINIT_SCRATCH); + } + else if ( !Q_stricmp( cmd, "postprocess" ) ) + { + OnDataLoaded(CANVASINIT_POSTPROC); + } + else if ( !Q_stricmp( cmd, "model_simple" ) ) + { + OnDataLoaded(CANVASINIT_MODEL_SIMPLE); + } + else if ( !Q_stricmp( cmd, "model_complex" ) ) + { + OnDataLoaded(CANVASINIT_MODEL_COMPLEX); + } + else if ( !Q_stricmp( cmd, "lightmapped_simple" ) ) + { + OnDataLoaded(CANVASINIT_LIGHTMAPPED_SIMPLE); + } + else if ( !Q_stricmp( cmd, "lightmapped_bump" ) ) + { + OnDataLoaded(CANVASINIT_LIGHTMAPPED_BUMP); + } + else if ( !Q_stricmp( cmd, "ppeffect" ) ) + { + OnDataLoaded(CANVASINIT_PPEFFECT); + } + else + BaseClass::OnCommand( cmd ); +} +void CDialog_NewCanvas::OnDataLoaded( int mode ) +{ + pEditorRoot->OpenShaderFlowgraph( mode, m_pRadBut_Sm2->IsSelected() ); + CloseModal(); +} +void CDialog_NewCanvas::PerformLayout() +{ + BaseClass::PerformLayout(); + + SetSize( 400, 400 ); + MoveToCenterOfScreen(); +} diff --git a/sp/src/shadereditor/vdialognew.h b/sp/src/shadereditor/vdialognew.h new file mode 100644 index 00000000..d6f415b0 --- /dev/null +++ b/sp/src/shadereditor/vdialognew.h @@ -0,0 +1,44 @@ +#ifndef CDIALOG_NEW_H +#define CDIALOG_NEW_H + +#include "editorCommon.h" +#include "vgui_controls/controls.h" + +enum +{ + CANVASINIT_SCRATCH = 0, + CANVASINIT_LIGHTMAPPED_SIMPLE, + CANVASINIT_LIGHTMAPPED_BUMP, + CANVASINIT_MODEL_SIMPLE, + CANVASINIT_MODEL_COMPLEX, + CANVASINIT_POSTPROC, + CANVASINIT_PPEFFECT, + CANVASINIT_, +}; + +class CDialog_NewCanvas : public vgui::Frame +{ +public: + DECLARE_CLASS_SIMPLE( CDialog_NewCanvas, Frame ); + + CDialog_NewCanvas( CNodeView *n, Panel *parent ); + ~CDialog_NewCanvas(); + +protected: + + void OnCommand( const char *cmd ); + + void PerformLayout(); + + CNodeView *pNodeView; + vgui::RadioButton *m_pRadBut_Sm2; + vgui::RadioButton *m_pRadBut_Sm3; + + //vgui::TextEntry *m_pShaderName; + + void OnDataLoaded( int mode ); + + //char shadername[MAX_PATH]; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogppeconfig.cpp b/sp/src/shadereditor/vdialogppeconfig.cpp new file mode 100644 index 00000000..c4c26601 --- /dev/null +++ b/sp/src/shadereditor/vdialogppeconfig.cpp @@ -0,0 +1,50 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CDialog_PPEConfig::CDialog_PPEConfig( Panel *parent, CNodeView *pNodeView ) : Frame( parent, "ppe_config" ) +{ + m_pNodeView = pNodeView; + SetSizeable( false ); + SetVisible( true ); + + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + Activate(); + + m_pCheck_AutoUpdateFBCopy = new CheckButton( this, "autoupdatefb", "Auto update FB copy tex" ); + + LoadControlSettings("shadereditorui/vgui/dialog_ppe_config.res"); + + m_pCheck_AutoUpdateFBCopy->SetSelected( pNodeView->AccessPPEConfig()->bDoAutoUpdateFBCopy ); + + SetSize( 280, 220 ); + SetTitle( "PPE settings", true ); + + DoModal(); + + SetDeleteSelfOnClose( true ); +} + +CDialog_PPEConfig::~CDialog_PPEConfig() +{ +} + +void CDialog_PPEConfig::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( cmd, "save" ) ) + { + OnSave(); + Close(); + } + else if ( !Q_stricmp( cmd, "close" ) ) + { + Close(); + } +} + +void CDialog_PPEConfig::OnSave() +{ + m_pNodeView->AccessPPEConfig()->bDoAutoUpdateFBCopy = m_pCheck_AutoUpdateFBCopy->IsSelected(); +} \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogppeconfig.h b/sp/src/shadereditor/vdialogppeconfig.h new file mode 100644 index 00000000..9b453707 --- /dev/null +++ b/sp/src/shadereditor/vdialogppeconfig.h @@ -0,0 +1,31 @@ +#ifndef CDIALOG_PPE_CFG_H +#define CDIALOG_PPE_CFG_H + +#include "editorCommon.h" +#include "vgui_controls/controls.h" + + +class CDialog_PPEConfig : public vgui::Frame +{ +public: + DECLARE_CLASS_SIMPLE( CDialog_PPEConfig, Frame ); + + CDialog_PPEConfig( Panel *parent, CNodeView *pNodeView ); + ~CDialog_PPEConfig(); + +protected: + + void OnCommand( const char *cmd ); + + //void PerformLayout(); + +private: + + void OnSave(); + + vgui::CheckButton *m_pCheck_AutoUpdateFBCopy; + + CNodeView *m_pNodeView; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogppeffectprecache.cpp b/sp/src/shadereditor/vdialogppeffectprecache.cpp new file mode 100644 index 00000000..b9f2e259 --- /dev/null +++ b/sp/src/shadereditor/vdialogppeffectprecache.cpp @@ -0,0 +1,192 @@ + +#include "cbase.h" +#include "editorCommon.h" + + +CDialog_PPEPrecache::CDialog_PPEPrecache( Panel *parent ) : BaseClass( parent, NULL, "dialog_precache_ppeffect" ) +{ + SetSizeable( false ); + SetVisible( true ); + + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + Activate(); + + m_pList_Effects = new PanelListPanel( this, "effect_list" ); + m_pList_Effects->SetNumColumns( 4 ); + m_pList_Effects->SetFirstColumnWidth( 200 ); + + FillList(); + + LoadControlSettings( "shadereditorui/vgui/dialog_ppe_precache_list.res" ); + + SetTitle( "Post processing precache", true ); + + DoModal(); + SetDeleteSelfOnClose( true ); + MoveToCenterOfScreen(); +} + +CDialog_PPEPrecache::~CDialog_PPEPrecache() +{ + if ( m_hEffectBrowser.Get() ) + m_hEffectBrowser.Get()->MarkForDeletion(); +} + + +void CDialog_PPEPrecache::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( "add_effect", cmd ) ) + { + OpenFiledialog(); + } + else if ( Q_stristr( cmd, "del_effect_" ) == cmd ) + { + const char *pszIdStart = cmd + 11; + const int index = atoi( pszIdStart ); + + Assert( index >= 0 && index < GetPPCache()->GetNumPostProcessingEffects() ); + + GetPPCache()->DeletePostProcessingEffect( index ); + + FillList(); + } + else if ( Q_stristr( cmd, "movedown_effect_" ) == cmd ) + { + const char *pszIdStart = cmd + 16; + const int index = atoi( pszIdStart ); + + Assert( index >= 0 && index < GetPPCache()->GetNumPostProcessingEffects() ); + + GetPPCache()->MoveEffectAlongList( index, false ); + + FillList(); + } + else if ( Q_stristr( cmd, "moveup_effect_" ) == cmd ) + { + const char *pszIdStart = cmd + 14; + const int index = atoi( pszIdStart ); + + Assert( index >= 0 && index < GetPPCache()->GetNumPostProcessingEffects() ); + + GetPPCache()->MoveEffectAlongList( index, true ); + + FillList(); + } + else + { + GetPPCache()->SavePrecacheFile(); + + BaseClass::OnCommand( cmd ); + } +} + +void CDialog_PPEPrecache::FillList() +{ + ScrollBar *pScroll = m_pList_Effects->GetScrollbar(); + int scrollValue = pScroll ? pScroll->GetValue() : 0; + + m_pList_Effects->DeleteAllItems(); + + GetPPCache()->ClearInvalidEntries(); + + HFont fontMarlett = scheme()->GetIScheme( GetScheme() )->GetFont( "Marlett", false ); + + for ( int i = 0; i < GetPPCache()->GetNumPostProcessingEffects(); i++ ) + { + EditorPostProcessingEffect *effect = GetPPCache()->GetPostProcessingEffect( i ); + + Label *pL = new Label( m_pList_Effects, "", effect->pszName ); + Button *pDel = new Button( m_pList_Effects, "", "Delete", this, VarArgs("del_effect_%i",i) ); + CheckButton *pCheck = new CheckButton( m_pList_Effects, effect->pszName, "" ); + + pCheck->AddActionSignalTarget( this ); + pCheck->SetSelected( effect->bStartEnabled ); + + Button *pDown = new Button( m_pList_Effects, "", "u", this, VarArgs("movedown_effect_%i",i) ); + Button *pUp = new Button( m_pList_Effects, "", "t", this, VarArgs("moveup_effect_%i",i) ); + + pDown->SetFont( fontMarlett ); + pUp->SetFont( fontMarlett ); + + pDel->SetContentAlignment( Label::a_center ); + pDown->SetContentAlignment( Label::a_center ); + pUp->SetContentAlignment( Label::a_center ); + + m_pList_Effects->AddItem( NULL, pCheck ); + m_pList_Effects->AddItem( NULL, pDown ); + m_pList_Effects->AddItem( NULL, pUp ); + m_pList_Effects->AddItem( pL, pDel ); + } + + if ( pScroll ) + pScroll->SetValue( scrollValue ); +} + +void CDialog_PPEPrecache::CheckButtonChecked( KeyValues *pKV ) +{ + bool bChecked = pKV->GetInt( "state" ) != 0; + Panel *p = (Panel*)pKV->GetPtr( "panel" ); + Assert( p ); + + int index = GetPPCache()->FindPostProcessingEffect( p->GetName() ); + Assert( index >= 0 && index < GetPPCache()->GetNumPostProcessingEffects() ); + + GetPPCache()->GetPostProcessingEffect( index )->bStartEnabled = bChecked; + GetPPCache()->GetPostProcessingEffect( index )->bIsEnabled = bChecked; + + if ( pEditorRoot->GetSafeFlowgraph()->GetFlowgraphType() == CNodeView::FLOWGRAPH_POSTPROC ) + pEditorRoot->GetSafeFlowgraph()->UpdatePPECache(); +} + +void CDialog_PPEPrecache::OnFileSelected( KeyValues *pKV ) +{ + const char *pathIn = pKV->GetString( "fullpath" ); + if ( Q_strlen( pathIn ) <= 1 ) + return; + + char tmp[MAX_PATH*4]; + if ( !g_pFullFileSystem->FullPathToRelativePath( pathIn, tmp, sizeof( tmp ) ) ) + Q_snprintf( tmp, sizeof(tmp), "%s", pathIn ); + + CPostProcessingCache::PPE_Error error = GetPPCache()->LoadPostProcessingEffect( tmp, false ); + + if ( error != CPostProcessingCache::PPE_OKAY ) + { + PromptSimple *prompt = new PromptSimple( this, "Error" ); + prompt->MoveToCenterOfScreen(); + switch ( error ) + { + case CPostProcessingCache::PPE_INVALID_INPUT: + prompt->SetText( "Unable to load file." ); + break; + case CPostProcessingCache::PPE_INVALID_GRAPH_TYPE: + prompt->SetText( "This file is not a post processing graph!" ); + break; + case CPostProcessingCache::PPE_GRAPH_NOT_VALID: + prompt->SetText( "This graph is not valid, open the file and fix it!" ); + break; + } + prompt->AddButton( "Ok" ); + } + else if ( pEditorRoot->GetSafeFlowgraph()->GetFlowgraphType() == CNodeView::FLOWGRAPH_POSTPROC ) + pEditorRoot->GetSafeFlowgraph()->UpdatePPECache(); + + FillList(); +} + +void CDialog_PPEPrecache::OpenFiledialog() +{ + if ( m_hEffectBrowser.Get() ) + m_hEffectBrowser.Get()->MarkForDeletion(); + + m_hEffectBrowser = new FileOpenDialog( this, "Select post processing effect", + FOD_OPEN, NULL ); + + if ( m_hEffectBrowser.Get() ) + { + m_hEffectBrowser->SetStartDirectoryContext( GetFODPathContext( FODPC_CANVAS ), GetCanvasDirectory() ); + m_hEffectBrowser->AddFilter( "*.txt", "Canvas", true ); + m_hEffectBrowser->DoModal( true ); + } +} diff --git a/sp/src/shadereditor/vdialogppeffectprecache.h b/sp/src/shadereditor/vdialogppeffectprecache.h new file mode 100644 index 00000000..deace3c0 --- /dev/null +++ b/sp/src/shadereditor/vdialogppeffectprecache.h @@ -0,0 +1,33 @@ +#ifndef DIALOG_PPE_PRECACHE_H +#define DIALOG_PPE_PRECACHE_H + +#include "cbase.h" +#include "editorCommon.h" + +class CDialog_PPEPrecache : public CBaseDiag +{ +public: + DECLARE_CLASS_SIMPLE( CDialog_PPEPrecache, CBaseDiag ); + + CDialog_PPEPrecache( Panel *parent ); + ~CDialog_PPEPrecache(); + +protected: + + MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", pKV ); + MESSAGE_FUNC_PARAMS( CheckButtonChecked, "CheckButtonChecked", pKV ); + + virtual void OnCommand( const char *cmd ); + +private: + + void FillList(); + void OpenFiledialog(); + + DHANDLE< FileOpenDialog > m_hEffectBrowser; + PanelListPanel *m_pList_Effects; + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogrecompileall.cpp b/sp/src/shadereditor/vdialogrecompileall.cpp new file mode 100644 index 00000000..6aadd3c0 --- /dev/null +++ b/sp/src/shadereditor/vdialogrecompileall.cpp @@ -0,0 +1,422 @@ + +#include "cbase.h" +#include "editorCommon.h" + +enum +{ + _CSTEP_INITIAL = 0, + _CSTEP_SOLVE_GRAPH, + _CSTEP_COMPILE_SHADER_WAIT, + _CSTEP_FINISHED_SUCCESS, + _CSTEP_FINISHED_ERROR, + _CSTEP_, +}; + +DumpCompileHelper_t::DumpCompileHelper_t() +{ + shaderDump = NULL; + iCompileStep = _CSTEP_INITIAL; +} +DumpCompileHelper_t::~DumpCompileHelper_t() +{ + delete shaderDump; +} + +#ifdef COLOR_GREY +#undef COLOR_GREY +#endif + +#define DEFAULT_LOG_COLOR Color( 255,255,255,255 ) +#define ERROR_LOG_COLOR Color( 255,64,64,255 ) +#define ERROR_LOG_COLOR_LIGHT Color( 255,96,96,255 ) +#define ERROR_LOG_COLOR_DARK Color( 255,32,32,255 ) +#define SUCCESS_LOG_COLOR Color( 64,255,64,255 ) +#define COLOR_WHITE Color(255,255,255,255) +#define COLOR_GREY Color(164,164,164,255) +#define COLOR_INVIS Color(0,0,0,0) + +CDialogRecompileAll::CDialogRecompileAll( vgui::Panel *parent ) : BaseClass( parent, NULL, "diag_recompileall" ) +{ + m_pRichText_Log = new RichText( this, "rtext_log" ); + m_pClose = new Button( this, "button_close", "", this, "close" ); + m_pProgressPos = new Panel( this, "progress_pos" ); + + LoadControlSettings("shadereditorui/vgui/shadereditor_diag_recompileall.res"); + + SetButtonState( false ); + + SetTitle("Recompile all",true); + + //SetSizeable(false); + + int sx, sy; + surface()->GetScreenSize( sx, sy ); + SetSize( 560, sy * 0.7f ); + + CUtlVector hDumpList; + ReadGameShaders( hDumpList ); + + for ( int i = 0; i < hDumpList.Count(); i++ ) + { + DumpCompileHelper_t *pC = new DumpCompileHelper_t(); + pC->shaderDump = hDumpList[i]; + hCompileList.AddToTail( pC ); + } + + hDumpList.Purge(); + + m_pView = new CNodeView( NULL, pEditorRoot, "compileallhelper" ); + + LogMsg( "Found %i shaders marked for precaching:\n", hCompileList.Count() ); + + m_bCompilerRunning = true; + + char tmp[MAX_PATH*4]; + for ( int i = 0; i < hCompileList.Count(); i++ ) + { + BasicShaderCfg_t *p = hCompileList[i]->shaderDump; + if ( !p->Filename || !p->Filename ) + continue; + + for ( int n = 0; n < pEditorRoot->GetNumFlowGraphs(); n++ ) + { + CNodeView *pV = pEditorRoot->GetFlowGraph(n); + + if ( pV->GetFlowgraphType() != CNodeView::FLOWGRAPH_HLSL ) + continue; + + if ( !pV->GetShadername() || !*pV->GetShadername() ) + continue; + + if ( !g_pFullFileSystem->FullPathToRelativePath( pV->GetShadername(), tmp, sizeof( tmp ) ) ) + Q_snprintf( tmp, sizeof( tmp ), "%s", pV->GetShadername() ); + Q_FixSlashes( tmp ); + + if ( Q_stricmp( tmp, p->Filename ) ) + continue; + + if ( !pV->IsSaveDirty() ) + continue; + + m_bCompilerRunning = false; + break; + } + } + + DoModal(); + + if ( !m_bCompilerRunning ) + { + PromptSimple *prompt = new PromptSimple( this, "Warning" ); + prompt->MoveToCenterOfScreen(); + prompt->SetText( "It appears that you have unsaved changes in some shaders which are selected for precaching. Save them now?" ); + prompt->AddButton( "Yes", "continuecompile_dosave" ); + prompt->AddButton( "No", "continuecompile" ); + prompt->InvalidateLayout( true, true ); + } + + m_bAutoInjectOld = pEditorRoot->m_bAutoShaderPublish; + pEditorRoot->m_bAutoShaderPublish = true; + + SetDeleteSelfOnClose( true ); +} + +CDialogRecompileAll::~CDialogRecompileAll() +{ + pEditorRoot->m_bAutoShaderPublish = m_bAutoInjectOld; + delete m_pView; + hCompileList.PurgeAndDeleteElements(); +} + +void CDialogRecompileAll::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( "continuecompile_dosave", cmd ) ) + { + pEditorRoot->SaveAllGraphs(); + m_bCompilerRunning = true; + + InvalidateLayout(); + } + else if ( !Q_stricmp( "continuecompile", cmd ) ) + { + m_bCompilerRunning = true; + + InvalidateLayout(); + } + else if ( !Q_stricmp( "close", cmd ) ) + { + if ( m_bCompilerRunning ) + { + m_bCompilerRunning = false; + + InvalidateLayout(); + + ForceTerminateCompilers(); + LogMsg( ERROR_LOG_COLOR, "\n\nCOMPILER TERMINATED\n" ); + } + else + { + DeletePanel(); + } + } +} + +void CDialogRecompileAll::SetButtonState( bool bShowClose ) +{ + if ( bShowClose ) + { + m_pClose->SetText( "Close" ); + m_pClose->InvalidateLayout( true, true ); + } + else + { + m_pClose->SetText( "Terminate" ); + m_pClose->SetDefaultColor( COLOR_WHITE, ERROR_LOG_COLOR ); + m_pClose->SetArmedColor( COLOR_WHITE, ERROR_LOG_COLOR_LIGHT ); + m_pClose->SetDepressedColor( COLOR_WHITE, ERROR_LOG_COLOR_DARK ); + //m_pClose->SetPaintBackgroundEnabled( true ); + } +} + +void CDialogRecompileAll::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + m_pRichText_Log->SetBorder( pScheme->GetBorder("DepressedButtonBorder") ); + m_pRichText_Log->SetVerticalScrollbar( true ); + m_pRichText_Log->SetUnusedScrollbarInvisible( false ); + m_pRichText_Log->SetPanelInteractive( true ); + m_pRichText_Log->InsertColorChange( DEFAULT_LOG_COLOR ); +} + +void CDialogRecompileAll::PerformLayout() +{ + BaseClass::PerformLayout(); + + SetButtonState( !m_bCompilerRunning ); + m_pProgressPos->SetPaintBackgroundEnabled( false ); + + SetDeleteSelfOnClose( true ); +} + +void CDialogRecompileAll::Paint() +{ + BaseClass::Paint(); + + int x,y,sx,sy; + m_pProgressPos->GetBounds( x, y, sx, sy ); + const int iExtrude = 2; + const int iThick = 3; + + surface()->DrawSetColor( COLOR_GREY ); + surface()->DrawFilledRect( x - iExtrude - iThick, + y - iExtrude - iThick, + x + sx + iExtrude + iThick, + y - iExtrude ); + surface()->DrawFilledRect( x - iExtrude - iThick, + y + sy + iExtrude, + x + sx + iExtrude + iThick, + y + sy + iExtrude + iThick ); + surface()->DrawFilledRect( x - iExtrude - iThick, + y - iExtrude, + x - iExtrude, + y + sy + iExtrude ); + surface()->DrawFilledRect( x + sx + iExtrude, + y - iExtrude, + x + sx + iExtrude + iThick, + y + sy + iExtrude ); + + if ( hCompileList.Count() > 0 ) + { + //const int iStep = sx / (float)hCompileList.Count(); + + const float flStep = sx / (float)hCompileList.Count(); + int iLastX1 = x; + + for ( int i = 0; i < hCompileList.Count(); i++ ) + { + const int cur = hCompileList[i]->iCompileStep; + bool bStop = false; + + switch ( cur ) + { + case _CSTEP_FINISHED_ERROR: + surface()->DrawSetColor( ERROR_LOG_COLOR_DARK ); + break; + case _CSTEP_FINISHED_SUCCESS: + surface()->DrawSetColor( COLOR_GREY ); + break; + default: + bStop = true; + break; + } + + if ( bStop ) + break; + + //const int lx0 = x + iStep * i; + //const int lx1 = (i < hCompileList.Count() - 1) ? lx0 + iStep : x + sx; + + const int lx0 = iLastX1; + const int lx1 = (i < hCompileList.Count() - 1) ? lx0 + flStep : x + sx; + iLastX1 = lx1; + + surface()->DrawFilledRect( lx0, y, lx1, y + sy ); + } + } +} + +void CDialogRecompileAll::OnThink() +{ + if ( m_bCompilerRunning ) + { + int cur = -1; + for ( int i = 0; i < hCompileList.Count() && cur < 0; i++ ) + { + if ( hCompileList[i]->iCompileStep < _CSTEP_FINISHED_SUCCESS ) + cur = i; + } + + if ( cur < 0 ) + { + m_bCompilerRunning = false; + LogMsg( "\nFinished. Processed %i dumps", hCompileList.Count() ); + + int success = 0; + int error = 0; + + for ( int i = 0; i < hCompileList.Count(); i++ ) + { + if ( hCompileList[i]->iCompileStep == _CSTEP_FINISHED_SUCCESS ) + success++; + else + error++; + } + + if ( success != 0 || error != 0 ) + { + LogMsg( " - %i successfully compiled, ", success ); + LogMsg( ((error>0) ? ERROR_LOG_COLOR : DEFAULT_LOG_COLOR), "%i errored", error ); + LogMsg( "." ); + } + + LogMsg( "\n" ); + + InvalidateLayout(); + return; + } + + Assert( cur >= 0 && cur < hCompileList.Count() ); + DumpCompileHelper_t *cmd = hCompileList[cur]; + + switch ( cmd->iCompileStep ) + { + case _CSTEP_INITIAL: + { + LogMsg( "\nProcessing %s:\n", ( cmd->shaderDump->CanvasName ? cmd->shaderDump->CanvasName : "MISSING_CANVAS_NAME" ) ); + + LogMsg( "Loading file... " ); + if ( !cmd->shaderDump->Filename || !*cmd->shaderDump->Filename ) + { + LogMsg( ERROR_LOG_COLOR, "ERROR (no filepath in dump -> try manual full compile!)" ); + LogMsg( ".\n" ); + cmd->iCompileStep = _CSTEP_FINISHED_ERROR; + } + else if ( !m_pView->LoadFromFile( cmd->shaderDump->Filename, true ) ) + { + LogMsg( ERROR_LOG_COLOR, "ERROR (unable to open file)" ); + LogMsg( ".\n" ); + cmd->iCompileStep = _CSTEP_FINISHED_ERROR; + } + else + { + m_pView->SetShadername( cmd->shaderDump->Filename ); + + LogMsg( SUCCESS_LOG_COLOR, "finished" ); + LogMsg( ".\n" ); + cmd->iCompileStep = _CSTEP_SOLVE_GRAPH; + } + } + break; + case _CSTEP_SOLVE_GRAPH: + { + LogMsg( "Solving graph... " ); + + if ( m_pView->GetFlowgraphType() != CNodeView::FLOWGRAPH_HLSL ) + { + cmd->iCompileStep = _CSTEP_FINISHED_ERROR; + LogMsg( ERROR_LOG_COLOR, "ERROR (graph is not a compilable shader!)" ); + LogMsg( ".\n" ); + } + else + { + m_pView->UpdateSolvers(); + + CBaseNode *pVSOut = m_pView->GetNodeFromType( HLSLNODE_VS_OUT ); + CBaseNode *pPSOut = m_pView->GetNodeFromType( HLSLNODE_PS_OUT ); + + if ( !pVSOut || !pPSOut || + pVSOut->GetErrorLevel() != ERRORLEVEL_NONE || pPSOut->GetErrorLevel() != ERRORLEVEL_NONE ) + { + cmd->iCompileStep = _CSTEP_FINISHED_ERROR; + LogMsg( ERROR_LOG_COLOR, "ERROR (graph not solvable, go check for errors)" ); + LogMsg( ".\n" ); + } + else + { + LogMsg( SUCCESS_LOG_COLOR, "finished" ); + LogMsg( ".\n" ); + + LogMsg( "Running compiler... " ); + cmd->iCompileStep = _CSTEP_COMPILE_SHADER_WAIT; + } + } + } + break; + case _CSTEP_COMPILE_SHADER_WAIT: + { + if ( m_pView->GetCompiledStackIndex() == m_pView->GetStackIndex() ) + { + if ( m_pView->IsLastCompileSuccessful() ) + { + LogMsg( SUCCESS_LOG_COLOR, "finished" ); + LogMsg( ".\n" ); + cmd->iCompileStep = _CSTEP_FINISHED_SUCCESS; + } + else + { + LogMsg( ERROR_LOG_COLOR, "ERROR" ); + LogMsg( ".\n" ); + cmd->iCompileStep = _CSTEP_FINISHED_ERROR; + } + } + } + break; + } + } +} + +static char __string[1024]; + +void CDialogRecompileAll::LogMsg( const char *msg, ... ) +{ + va_list argptr; + va_start (argptr, msg); + Q_vsnprintf (__string, sizeof( __string ), msg, argptr); + va_end (argptr); + + m_pRichText_Log->InsertString( __string ); +} +void CDialogRecompileAll::LogMsg( Color textCol, const char *msg, ... ) +{ + m_pRichText_Log->InsertColorChange( textCol ); + + va_list argptr; + va_start (argptr, msg); + Q_vsnprintf (__string, sizeof( __string ), msg, argptr); + va_end (argptr); + + m_pRichText_Log->InsertString( __string ); + + m_pRichText_Log->InsertColorChange( DEFAULT_LOG_COLOR ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogrecompileall.h b/sp/src/shadereditor/vdialogrecompileall.h new file mode 100644 index 00000000..aa249a18 --- /dev/null +++ b/sp/src/shadereditor/vdialogrecompileall.h @@ -0,0 +1,55 @@ +#ifndef C_DIALOG_RECOMPILE_ALL_H +#define C_DIALOG_RECOMPILE_ALL_H + +#include "cbase.h" +#include "editorCommon.h" + +struct DumpCompileHelper_t +{ +public: + + DumpCompileHelper_t(); + ~DumpCompileHelper_t(); + + BasicShaderCfg_t *shaderDump; + int iCompileStep; + +private: + DumpCompileHelper_t( const DumpCompileHelper_t &o ); +}; + +class CDialogRecompileAll : public CBaseDiag +{ + DECLARE_CLASS_SIMPLE( CDialogRecompileAll, CBaseDiag ); + +public: + CDialogRecompileAll( vgui::Panel *parent ); + ~CDialogRecompileAll(); + +protected: + void OnCommand( const char *cmd ); + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void PerformLayout(); + + void Paint(); + + void OnThink(); + +private: + CUtlVector hCompileList; + bool m_bCompilerRunning; + + void LogMsg( const char *msg, ... ); + void LogMsg( Color textCol, const char *msg, ... ); + RichText *m_pRichText_Log; + + Button *m_pClose; + void SetButtonState( bool bShowClose ); + + CNodeView *m_pView; + Panel *m_pProgressPos; + bool m_bAutoInjectOld; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogrtlist.cpp b/sp/src/shadereditor/vdialogrtlist.cpp new file mode 100644 index 00000000..ce201c7b --- /dev/null +++ b/sp/src/shadereditor/vdialogrtlist.cpp @@ -0,0 +1,502 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CDialog_RendertargetList::CDialog_RendertargetList( Panel *parent ) : CBaseDiag( parent, NULL, "_rt_list" ) +{ + SetSizeable( false ); + SetVisible( true ); + + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + Activate(); + + + + m_pList_RT = new PanelListPanel( this, "rtlist" ); + m_pList_RT->SetNumColumns( 2 ); + m_pList_RT->SetFirstColumnWidth( 200 ); + + FillList(); + + + LoadControlSettings( "shadereditorui/vgui/dialog_rendertarget_list.res" ); + + SetTitle( "Rendertarget manager", true ); + + DoModal(); + SetDeleteSelfOnClose( true ); + MoveToCenterOfScreen(); +} + +CDialog_RendertargetList::~CDialog_RendertargetList() +{ +} + +void CDialog_RendertargetList::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( cmd, "new_rt" ) ) + { + CDialog_RendertargetSettings *pEditDiag = new CDialog_RendertargetSettings( this ); + pEditDiag->AddActionSignalTarget( this ); + pEditDiag->SetDefaults(); + } + else if ( Q_stristr( cmd, "del_rt_" ) == cmd ) + { + const char *pszNum = cmd + 7; + int index = atoi( pszNum ); + + Assert( index >= 0 && index < GetRTManager()->GetNumRTs() ); + + GetRTManager()->GetRT( index )->FlagForDeletion(); + + FillList(); + } + else if ( Q_stristr( cmd, "edit_rt_" ) == cmd ) + { + const char *pszNum = cmd + 8; + int index = atoi( pszNum ); + + Assert( index >= 0 && index < GetRTManager()->GetNumRTs() ); + + CDialog_RendertargetSettings *pEditDiag = new CDialog_RendertargetSettings( this ); + pEditDiag->AddActionSignalTarget( this ); + pEditDiag->InitFromRT( GetRTManager()->GetRT( index ) ); + } + else if ( !Q_stricmp( cmd, "apply" ) ) + { + GetRTManager()->UpdateRTsToMatSys(); + GetRTManager()->SaveRTsToFile(); + } + else + { + GetRTManager()->UpdateRTsToMatSys(); + GetRTManager()->SaveRTsToFile(); + + BaseClass::OnCommand( cmd ); + } +} + +void CDialog_RendertargetList::PerformLayout() +{ + BaseClass::PerformLayout(); +} + +void CDialog_RendertargetList::FillList() +{ + ScrollBar *pScroll = m_pList_RT->GetScrollbar(); + int scrollValue = pScroll ? pScroll->GetValue() : 0; + + m_pList_RT->DeleteAllItems(); + + GetRTManager()->SortRTsByName(); + for ( int i = 0; i < GetRTManager()->GetNumRTs(); i++ ) + { + RTDef *rt = GetRTManager()->GetRT( i ); + + if ( rt->IsFlaggedForDeletion() ) + continue; + + Label *pL = new Label( m_pList_RT, "", rt->GetName() ); + Button *pBDel = new Button( m_pList_RT, "", "Delete", this, VarArgs("del_rt_%i",i) ); + Button *pBEdit = new Button( m_pList_RT, "", "Edit", this, VarArgs("edit_rt_%i",i) ); + + pBDel->SetContentAlignment( Label::a_center ); + pBEdit->SetContentAlignment( Label::a_center ); + + m_pList_RT->AddItem( pL, pBDel ); + m_pList_RT->AddItem( NULL, pBEdit ); + } + + if ( pScroll ) + pScroll->SetValue( scrollValue ); +} +void CDialog_RendertargetList::OnUpdateList() +{ + FillList(); +} + + +// quick access to files with all these constants +#include "bitmap/imageformat.h" +#include "vtf/vtf.h" +#include "materialsystem/imaterialsystem.h" + +static const char *pszImgFormatNames[] = { + "RGBA8888", // 0 + "ABGR8888", + "RGB888", + "BGR888", + "RGB565", + "I8", + "IA88", + "P8", + "A8", + "RGB888_BLUESCREEN", + "BGR888_BLUESCREEN", + "ARGB8888", + "BGRA8888", + "DXT1", + "DXT3", + "DXT5", + "BGRX8888", + "BGR565", + "BGRX5551", + "BGRA4444", + "DXT1_ONEBITALPHA", // 20 + "BGRA5551", + "UV88", + "UVWQ8888", + "RGBA16161616F", + "RGBA16161616", + "UVLX8888", + "R32F", + "RGB323232F", + "RGBA32323232F", // 29 + +#ifdef SHADER_EDITOR_DLL_SWARM + "RG1616F", + "RG3232F", + "RGBX8888", +#endif +}; +static const int iNumImgFormatNames = ARRAYSIZE( pszImgFormatNames ); + + +const char *pszRTSizeModes[] = { + "NO_CHANGE", // 0 + "DEFAULT (<= FB)", + "PICMIP", + "HDR (QUARTER FB)", + "FULL_FRAME_BUFFER (ROUND DOWN)", + "OFFSCREEN", + "FULL_FRAME_BUFFER (ROUND UP)", +#ifdef SHADER_EDITOR_DLL_2013 + "REPLAY SCREENSHOT", +#endif + "HALF FRAME BUFFER", +}; +static const int iNumRTSizeModes = ARRAYSIZE( pszRTSizeModes ); + + +const char *pszRTDepthModes[] = { + "SHARED", + "SEPARATE", + "NONE", + "ONLY", +}; +static const int iNumRTDepthModes = ARRAYSIZE( pszRTDepthModes ); + +const char *pszVTFFlags[] = { + "POINTSAMPLE", + "TRILINEAR", + "CLAMPS", + "CLAMPT", + "ANISOTROPIC", + "HINT_DXT5", +#ifdef SHADER_EDITOR_DLL_SWARM + "PWL_CORRECTED", +#else + "SRGB", +#endif + "NORMAL", + "NOMIP", + "NOLOD", + "ALL_MIPS", + "PROCEDURAL", + "ONEBITALPHA", + "EIGHTBITALPHA", + "ENVMAP", + "RENDERTARGET", + "DEPTHRENDERTARGET", + "NODEBUGOVERRIDE", + "SINGLECOPY", +#ifdef SHADER_EDITOR_DLL_SWARM + "PRE_SRGB", +#else + "UNUSED_00080000", +#endif + "UNUSED_00100000", + "UNUSED_00200000", + "UNUSED_00400000", + "NODEPTHBUFFER", + "UNUSED_01000000", + "CLAMPU", + "VERTEXTEXTURE", + "SSBUMP", + "UNUSED_10000000", + "BORDER", + "UNUSED_40000000", + "UNUSED_80000000", +}; +static const int iNumVTFFlags = ARRAYSIZE( pszVTFFlags ); + + +CDialog_RendertargetSettings::CDialog_RendertargetSettings( Panel *parent ) : CBaseDiag( parent, NULL, "rtsettings" ) //BaseClass( parent, "rtsettings" ) +{ + m_pRTTarget = NULL; + + SetMouseInputEnabled( true ); + SetKeyBoardInputEnabled( true ); + + m_pText_RTName = new TextEntry( this, "rt_name" ); + + m_pText_SizeX = new TextEntry( this, "rt_size_x" ); + m_pText_SizeY = new TextEntry( this, "rt_size_y" ); + + m_pList_Flags = new PanelListPanel( this, "rtlist" ); + m_pList_Flags->SetNumColumns( 1 ); + m_pList_Flags->SetFirstColumnWidth( 0 ); + m_pList_Flags->SetVerticalBufferPixels( 0 ); + + for ( int i = 0; i < iNumVTFFlags; i++ ) + { + CheckButton *pCBut = new CheckButton( m_pList_Flags, "", pszVTFFlags[i] ); + m_pList_Flags->AddItem( NULL, pCBut ); + m_hFlag_Buttons.AddToTail( pCBut ); + } + + m_pCBox_ImgFormat = new ComboBox( this, "cbox_format", 20, false ); + for ( int i = 0; i < iNumImgFormatNames; i++ ) + m_pCBox_ImgFormat->AddItem( pszImgFormatNames[i], NULL ); + + m_pCBox_SizeMode = new ComboBox( this, "cbox_sizemode", 20, false ); + for ( int i = 0; i < iNumRTSizeModes; i++ ) + m_pCBox_SizeMode->AddItem( pszRTSizeModes[i], NULL ); + + m_pCBox_DepthMode = new ComboBox( this, "cbox_depthmode", 20, false ); + for ( int i = 0; i < iNumRTDepthModes; i++ ) + m_pCBox_DepthMode->AddItem( pszRTDepthModes[i], NULL ); + + LoadControlSettings( "shadereditorui/vgui/dialog_rendertarget_settings.res" ); + + SetSizeable( false ); + SetTitle( "Rendertarget properties", true ); + + SetCloseButtonVisible( false ); + + DoModal(); + MoveToCenterOfScreen(); +} + +CDialog_RendertargetSettings::~CDialog_RendertargetSettings() +{ + m_hFlag_Buttons.Purge(); +} + +bool CDialog_RendertargetSettings::DoesRTExist( const char *name ) +{ + if ( !name || !*name ) + return false; + + ITexture *pTex = materials->FindTexture( name, TEXTURE_GROUP_OTHER, false ); + RTDef *rt = GetRTManager()->FindRTByName( name, true ); + + if ( rt && rt->IsFlaggedForDeletion() ) + return false; + + return rt != NULL || + !IsErrorTexture( pTex ); +} + +void CDialog_RendertargetSettings::ShowErrorDiag( const char *name ) +{ + bool bEngineTex = GetRTManager()->FindRTByName( name, true ) == NULL; + + PromptSimple *prompt = new PromptSimple( this, "Error" ); + prompt->MoveToCenterOfScreen(); + if ( !bEngineTex ) + { + prompt->SetText( "Rendertarget of specified name exists already, override?" ); + prompt->AddButton( "Ok", "onerror_override" ); + prompt->AddButton( "Cancel", "onerror_cancel" ); + } + else + { + prompt->SetText( VarArgs( "'%s' is a texture defined elsewhere, you can't use this name!", name ) ); + prompt->AddButton( "Cancel", "onerror_cancel" ); + } +} + +void CDialog_RendertargetSettings::OnCommand( const char *cmd ) +{ + if ( !Q_stricmp( cmd, "Ok" ) ) + { + if ( m_pText_RTName->GetTextLength() < 1 ) + { + PromptSimple *prompt = new PromptSimple( this, "Error" ); + prompt->MoveToCenterOfScreen(); + prompt->SetText( "You must specify a name for the RT!" ); + prompt->AddButton( "Ok" ); + return; + } + + if ( m_pRTTarget != NULL ) + { + RTDef tmpRT = *m_pRTTarget; + WriteToRT( &tmpRT ); + + RTDef *pFound = GetRTManager()->FindRTByName( tmpRT.GetName(), true ); + if ( pFound != NULL && pFound != m_pRTTarget ) + { + ShowErrorDiag( tmpRT.GetName() ); + return; + } + + m_pRTTarget->Modify( tmpRT ); + } + else + { + RTDef newRT; + WriteToRT( &newRT ); + + int oldIndex = GetRTManager()->FindRTIndexByName(newRT.GetName()); + + if ( oldIndex >= 0 && GetRTManager()->GetRT( oldIndex )->IsFlaggedForDeletion() ) + { + GetRTManager()->RemoveRT( oldIndex ); + GetRTManager()->AddRT( newRT ); + } + else if ( DoesRTExist( newRT.GetName() ) ) + { + ShowErrorDiag( newRT.GetName() ); + return; + } + else + GetRTManager()->AddRT( newRT ); + } + + CloseModal(); + } + else if ( !Q_stricmp( cmd, "Close" ) ) + { + CloseModal(); + } + else if ( !Q_stricmp( cmd, "onerror_override" ) ) + { + RTDef newRT; + WriteToRT( &newRT ); + + for ( int i = 0; i < GetRTManager()->GetNumRTs(); i++ ) + { + RTDef *pold = GetRTManager()->GetRT( i ); + if ( Q_stricmp( pold->GetName(), newRT.GetName() ) ) + continue; + pold->FlagForDeletion(); + } + + if ( m_pRTTarget != NULL ) + m_pRTTarget->Modify( newRT ); + else + GetRTManager()->AddRT( newRT ); + + CloseModal(); + } + else if ( !Q_stricmp( cmd, "onerror_cancel" ) ) + { + } +} + +void CDialog_RendertargetSettings::CloseModal() +{ + PostActionSignal( new KeyValues( "UpdateList" ) ); + BaseClass::CloseModal(); +} + +void CDialog_RendertargetSettings::PerformLayout() +{ + BaseClass::PerformLayout(); +} + +void CDialog_RendertargetSettings::SetDefaults() +{ + m_pText_RTName->SetText( "" ); + m_pText_SizeX->SetText( VarArgs( "%i", RT_DEFAULT_SIZE ) ); + m_pText_SizeY->SetText( VarArgs( "%i", RT_DEFAULT_SIZE ) ); + + m_pCBox_ImgFormat->ActivateItem( 0 ); + m_pCBox_SizeMode->ActivateItem( 0 ); + m_pCBox_DepthMode->ActivateItem( 2 ); + + for ( int i = 0; i < m_hFlag_Buttons.Count(); i++ ) + { + m_hFlag_Buttons[i]->SetSelected( (TEXTUREFLAGS_RENDERTARGET & ( 1 << i )) != 0 ); + } +} + +void CDialog_RendertargetSettings::InitFromRT( RTDef *rt ) +{ + m_pRTTarget = rt; + + m_pText_RTName->SetText( rt->GetName() ); + m_pText_SizeX->SetText( VarArgs( "%i", rt->GetSizeX() ) ); + m_pText_SizeY->SetText( VarArgs( "%i", rt->GetSizeY() ) ); + + m_pCBox_ImgFormat->ActivateItem( rt->GetImgFormat() ); + m_pCBox_SizeMode->ActivateItem( rt->GetSizeMode() ); + m_pCBox_DepthMode->ActivateItem( rt->GetDepthMode() ); + + unsigned int flags = rt->GetFlags(); + Assert( m_hFlag_Buttons.Count() == iNumVTFFlags ); + + for ( int i = 0; i < m_hFlag_Buttons.Count(); i++ ) + { + m_hFlag_Buttons[i]->SetSelected( !!(flags & ( 1 << i )) ); + } +} + +void CDialog_RendertargetSettings::WriteToRT( RTDef *rt ) +{ + char name_dirty[MAX_PATH]; + char name[MAX_PATH]; + char tmp[MAX_PATH]; + + m_pText_RTName->GetText( name_dirty, sizeof(name_dirty) ); + CleanupString( name_dirty, name, sizeof( name ) ); + + if ( Q_strlen( name ) < 1 ) + Q_snprintf( name, sizeof( name ), "_rt_unnamed" ); + + m_pText_SizeX->GetText( tmp, sizeof(tmp) ); + int x = atoi( tmp ); + m_pText_SizeY->GetText( tmp, sizeof(tmp) ); + int y = atoi( tmp ); + + if ( x < 1 ) + x = RT_DEFAULT_SIZE; + if ( y < 1 ) + y = RT_DEFAULT_SIZE; + + x = min( RT_MAX_SIZE, x ); + y = min( RT_MAX_SIZE, y ); + + unsigned int flags = 0; + for ( int i = 0; i < m_hFlag_Buttons.Count(); i++ ) + if ( m_hFlag_Buttons[i]->IsSelected() ) + flags |= ( 1 << i ); + + ImageFormat f = (ImageFormat)m_pCBox_ImgFormat->GetActiveItem(); + RenderTargetSizeMode_t sm = (RenderTargetSizeMode_t)m_pCBox_SizeMode->GetActiveItem(); + MaterialRenderTargetDepth_t dm = (MaterialRenderTargetDepth_t)m_pCBox_DepthMode->GetActiveItem(); + + rt->Modify( (Q_strlen(name)) ? name : NULL, + &f, &sm, &dm, + &x, &y, &flags ); +} + +void CDialog_RendertargetSettings::OnTextChanged( KeyValues *pKV ) +{ + Panel *p = (Panel*)pKV->GetPtr("panel"); + + if ( p == m_pCBox_SizeMode ) + { + const int sizemode = m_pCBox_SizeMode->GetActiveItem(); + const bool bEnableSizing = sizemode != RT_SIZE_HALF_FRAME_BUFFER && + sizemode != RT_SIZE_HDR && + sizemode != RT_SIZE_FULL_FRAME_BUFFER && + sizemode != RT_SIZE_FULL_FRAME_BUFFER_ROUNDED_UP; + + m_pText_SizeX->SetEnabled( bEnableSizing ); + m_pText_SizeY->SetEnabled( bEnableSizing ); + } +} \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogrtlist.h b/sp/src/shadereditor/vdialogrtlist.h new file mode 100644 index 00000000..48b3db84 --- /dev/null +++ b/sp/src/shadereditor/vdialogrtlist.h @@ -0,0 +1,77 @@ +#ifndef DIALOG_RT_LIST_H +#define DIALOG_RT_LIST_H + +#include "editorCommon.h" +#include "vgui_controls/controls.h" + + +class CDialog_RendertargetList : public CBaseDiag +{ +public: + DECLARE_CLASS_SIMPLE( CDialog_RendertargetList, CBaseDiag ); + + CDialog_RendertargetList( Panel *parent ); + ~CDialog_RendertargetList(); + +protected: + + void OnCommand( const char *cmd ); + + void PerformLayout(); + + MESSAGE_FUNC( OnUpdateList, "UpdateList" ); + +private: + + PanelListPanel *m_pList_RT; + + void FillList(); + +}; + + +class CDialog_RendertargetSettings : public CBaseDiag //vgui::Frame +{ +public: + DECLARE_CLASS_SIMPLE( CDialog_RendertargetSettings, CBaseDiag ); + + CDialog_RendertargetSettings( Panel *parent ); + ~CDialog_RendertargetSettings(); + + void InitFromRT( RTDef *rt ); + void WriteToRT( RTDef *rt ); + void SetDefaults(); + +protected: + + void OnCommand( const char *cmd ); + + void PerformLayout(); + + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + + virtual void CloseModal(); + + bool DoesRTExist( const char *name ); + void ShowErrorDiag( const char *name ); + +private: + + TextEntry *m_pText_RTName; + TextEntry *m_pText_SizeX; + TextEntry *m_pText_SizeY; + + PanelListPanel *m_pList_Flags; + + ComboBox *m_pCBox_ImgFormat; + ComboBox *m_pCBox_SizeMode; + ComboBox *m_pCBox_DepthMode; + + CUtlVector< CheckButton* > m_hFlag_Buttons; + + RTDef *m_pRTTarget; +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogsprecache.cpp b/sp/src/shadereditor/vdialogsprecache.cpp new file mode 100644 index 00000000..85a7dcc6 --- /dev/null +++ b/sp/src/shadereditor/vdialogsprecache.cpp @@ -0,0 +1,196 @@ + +#include "cbase.h" +#include "editorCommon.h" + +CShaderPrecache::CShaderPrecache( vgui::Panel *parent, CNodeView *nodeview ) : BaseClass( parent, nodeview, "shaderpreview" ) +{ + m_pPanelList_Shader = new PanelListPanel( this, "shaderlist" ); + m_pPanelList_Shader->SetFirstColumnWidth( 300 ); + + m_pCheck_ReloadCache = new CheckButton( this, "check_reloadcache", "Reload cache on close" ); + + LoadControlSettings("shadereditorui/vgui/shadereditor_shaderprecache.res"); + + SetTitle("Shader precache",true); + + SetAutoDelete( true ); + SetSizeable(false); + + int sx, sy; + surface()->GetScreenSize( sx, sy ); + SetSize( 480, sy * 0.8f ); + + DoModal(); + + LoadList(); +} + +CShaderPrecache::~CShaderPrecache() +{ + m_pPanelList.Purge(); +} + +void CShaderPrecache::Activate() +{ + BaseClass::Activate(); +} + +void CShaderPrecache::Paint() +{ + BaseClass::Paint(); +} + +void CShaderPrecache::OnCommand(const char* pcCommand) +{ + if ( !Q_stricmp( pcCommand, "addshader" ) ) + { + OpenFileBrowser(); + return; + } + else if ( !Q_stricmp( pcCommand, "close" ) ) + { + SaveList(); + + pEditorRoot->m_bAutoPrecacheUpdate = m_pCheck_ReloadCache->IsSelected(); + + if ( pEditorRoot->ShouldAutoUpdatePrecache() ) + { + LoadGameShaders(); + QuickRefreshEditorShader(); + + GetPPCache()->RefreshAllPPEMaterials(); + } + } + BaseClass::OnCommand(pcCommand); +} + +void CShaderPrecache::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); +} + +void CShaderPrecache::PerformLayout() +{ + BaseClass::PerformLayout(); + + m_pCheck_ReloadCache->SetSelected( pEditorRoot->ShouldAutoUpdatePrecache() ); +} + +void CShaderPrecache::LoadList() +{ + KeyValues *pKV = df_LoadDump_List(); + KeyValues *pKey = pKV->GetFirstValue(); + while ( pKey ) + { + AddEntry( pKey->GetString() ); + pKey = pKey->GetNextValue(); + } + + pKV->deleteThis(); +} +void CShaderPrecache::AddEntry( const char *name ) +{ + char szFullpath[MAX_PATH]; + Q_snprintf( szFullpath, MAX_PATH, "%s\\%s.dump", ::GetDumpDirectory(), name ); + Q_FixSlashes( szFullpath ); + + if ( !g_pFullFileSystem->FileExists( szFullpath, "MOD" ) ) + return; + + for ( int i = 0; i < m_pPanelList.Count(); i++ ) + { + char tmp[MAX_PATH]; + m_pPanelList[i].L->GetText( tmp, MAX_PATH ); + if ( !Q_stricmp( tmp, name ) ) + return; + } + + Label *pL = new Label( m_pPanelList_Shader, "", name ); + Button *pB = new Button( m_pPanelList_Shader, "", "Remove" ); + pB->AddActionSignalTarget( this ); + pB->SetContentAlignment( Label::a_center ); + + m_pPanelList.AddToTail(); + m_pPanelList.Tail().L = pL; + m_pPanelList.Tail().B = pB; + + SortAllEntries(); +} +int PEntrySort( PListEntry_t const *p1, PListEntry_t const *p2 ) +{ + char sz1[ MAX_PATH ]; + char sz2[ MAX_PATH ]; + ( *p1 ).L->GetText( sz1, sizeof( sz1 ) ); + ( *p2 ).L->GetText( sz2, sizeof( sz2 ) ); + return Q_stricmp( sz1, sz2 ); +} +void CShaderPrecache::SortAllEntries() +{ + m_pPanelList.Sort( PEntrySort ); + m_pPanelList_Shader->RemoveAll(); + for ( int i = 0; i < m_pPanelList.Count(); i++ ) + m_pPanelList_Shader->AddItem( m_pPanelList[i].L, m_pPanelList[i].B ); + UpdateAllButtonCmds(); +} +void CShaderPrecache::SetButtonCmd( Button *b ) +{ + Assert( PListEntry_t::HasElement( m_pPanelList, b ) ); + + int idx = PListEntry_t::FindEntry( m_pPanelList, b ); + b->SetCommand( new KeyValues( "shaderremove", "index", idx ) ); +} +void CShaderPrecache::SaveList() +{ + KeyValues *pKV = new KeyValues( "shaderlist" ); + + for ( int i = 0; i < m_pPanelList.Count(); i++ ) + { + char name[MAX_PATH]; + m_pPanelList[i].L->GetText( name, MAX_PATH ); + pKV->SetString( VarArgs( "shader_%03i", i ), name ); + } + + df_SaveDump_List( pKV ); +} +void CShaderPrecache::OnRemovePressed( int index ) +{ + m_pPanelList.Remove( index ); + m_pPanelList_Shader->RemoveItem( m_pPanelList_Shader->GetItemIDFromRow( index ) ); + SortAllEntries(); +} +void CShaderPrecache::UpdateAllButtonCmds() +{ + Assert( m_pPanelList.Count() == m_pPanelList_Shader->GetItemCount() ); + + for ( int i = 0; i < m_pPanelList.Count(); i++ ) + SetButtonCmd( m_pPanelList[i].B ); +} + + +void CShaderPrecache::OpenFileBrowser() +{ + if ( m_hDumpBrowser.Get() ) + m_hDumpBrowser.Get()->MarkForDeletion(); + + m_hDumpBrowser = new FileOpenDialog( this, + "Load shader info", + FOD_OPEN, + new KeyValues("FileOpenContext", "context", "open_si" ) ); + + if ( m_hDumpBrowser.Get() ) + { + m_hDumpBrowser->SetStartDirectoryContext( GetFODPathContext( FODPC_DUMPFILE ), ::GetDumpDirectory() ); + m_hDumpBrowser->AddFilter( "*.dump", "ShaderInfo", true ); + m_hDumpBrowser->DoModal(); + } +} +void CShaderPrecache::OnFileSelected( KeyValues *pKV ) +{ + const char *pathIn = pKV->GetString( "fullpath" ); + if ( Q_strlen( pathIn ) <= 1 ) + return; + + char dumpname[MAX_PATH]; + Q_FileBase( pathIn, dumpname, MAX_PATH ); + AddEntry( dumpname ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/vdialogsprecache.h b/sp/src/shadereditor/vdialogsprecache.h new file mode 100644 index 00000000..18786200 --- /dev/null +++ b/sp/src/shadereditor/vdialogsprecache.h @@ -0,0 +1,80 @@ +#ifndef CHLSL_SHADERPRECACHE_H +#define CHLSL_SHADERPRECACHE_H + +#include "cbase.h" +#include "editorCommon.h" + +using namespace vgui; + +struct PListEntry_t +{ + Label *L; + Button *B; + + static int FindEntry( const CUtlVector< PListEntry_t > &list, const Label* L ) + { + for ( int i = 0; i < list.Count(); i++ ) + if ( list[i].L == L ) + return i; + return -1; + } + static int FindEntry( const CUtlVector< PListEntry_t > &list, const Button* B ) + { + for ( int i = 0; i < list.Count(); i++ ) + if ( list[i].B == B ) + return i; + return -1; + } + static bool HasElement( const CUtlVector< PListEntry_t > &list, const Label* L ) + { + return FindEntry( list, L ) >= 0; + } + static bool HasElement( const CUtlVector< PListEntry_t > &list, const Button* B ) + { + return FindEntry( list, B ) >= 0; + } +}; + +class CShaderPrecache : public CBaseDiag +{ + DECLARE_CLASS_SIMPLE( CShaderPrecache, CBaseDiag ); + +public: + CShaderPrecache( vgui::Panel *parent, CNodeView *nodeview ); + ~CShaderPrecache(); + + virtual void Activate(); + + void AddEntry( const char *name ); + void LoadList(); + + void SetButtonCmd( Button *b ); + void UpdateAllButtonCmds(); + void SaveList(); + + MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", fullpath ); + +protected: + virtual void Paint(); + + void OpenFileBrowser(); + + void OnCommand(const char* pcCommand); + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void PerformLayout(); + + MESSAGE_FUNC_INT( OnRemovePressed, "shaderremove", index ); + +private: + DHANDLE< FileOpenDialog > m_hDumpBrowser; + + PanelListPanel *m_pPanelList_Shader; + + CUtlVector< PListEntry_t >m_pPanelList; + void SortAllEntries(); + + CheckButton *m_pCheck_ReloadCache; +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/veditorflowgraphpage.cpp b/sp/src/shadereditor/veditorflowgraphpage.cpp new file mode 100644 index 00000000..6da31711 --- /dev/null +++ b/sp/src/shadereditor/veditorflowgraphpage.cpp @@ -0,0 +1,25 @@ + +#include "cbase.h" +#include "editorcommon.h" + + +CFlowGraphPage::CFlowGraphPage( Panel *parent ) : PropertyPage( parent, "" ) +{ + pGraph = NULL; +} + +CFlowGraphPage::~CFlowGraphPage() +{ +} + +void CFlowGraphPage::SetFlowGraph( CNodeView *p ) +{ + pGraph = p; + p->InvalidateLayout( true ); +} + +void CFlowGraphPage::PageShow() +{ + Assert( pGraph ); + pGraph->UploadPreviewData(); +} \ No newline at end of file diff --git a/sp/src/shadereditor/veditorflowgraphpage.h b/sp/src/shadereditor/veditorflowgraphpage.h new file mode 100644 index 00000000..80375069 --- /dev/null +++ b/sp/src/shadereditor/veditorflowgraphpage.h @@ -0,0 +1,26 @@ +#ifndef C_EDITOR_FG_PAGE_H +#define C_EDITOR_FG_PAGE_H + +#include "vSheets.h" + + +class CFlowGraphPage : public PropertyPage +{ +public: + DECLARE_CLASS_SIMPLE( CFlowGraphPage, PropertyPage ); + + CFlowGraphPage( Panel *parent ); + ~CFlowGraphPage(); + + void SetFlowGraph( CNodeView *p ); + CNodeView *GetFlowGraph(){ return pGraph; }; + + MESSAGE_FUNC( PageShow, "PageShow" ); + +protected: + + CNodeView *pGraph; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/veditorflowgraphsheet.cpp b/sp/src/shadereditor/veditorflowgraphsheet.cpp new file mode 100644 index 00000000..c202f2a4 --- /dev/null +++ b/sp/src/shadereditor/veditorflowgraphsheet.cpp @@ -0,0 +1,28 @@ + +#include "cbase.h" +#include "editorcommon.h" + + +CFlowGraphSheet::CFlowGraphSheet( Panel *parent, const char *panelName, bool draggableTabs, bool closeableTabs ) + : BaseClass( parent, panelName, draggableTabs, closeableTabs ) +{ + SetTabPosition( 1 ); +} + +CFlowGraphSheet::~CFlowGraphSheet() +{ +} + + +void CFlowGraphSheet::PerformLayout() +{ + BaseClass::PerformLayout(); + + int viewer_inset = 22; + int viewer_inset_y = 45; + int w,t; + //engine->GetScreenSize( w, t ); + GetParent()->GetSize( w, t ); + SetPos( viewer_inset, viewer_inset_y ); + SetSize( w - viewer_inset * 2, t - viewer_inset - viewer_inset_y ); +} diff --git a/sp/src/shadereditor/veditorflowgraphsheet.h b/sp/src/shadereditor/veditorflowgraphsheet.h new file mode 100644 index 00000000..b18e6550 --- /dev/null +++ b/sp/src/shadereditor/veditorflowgraphsheet.h @@ -0,0 +1,30 @@ +#ifndef C_EDITOR_FG_SHEET_H +#define C_EDITOR_FG_SHEET_H + +#include "vSheets.h" + +#include "vgui_controls/Controls.h" +#include +#include +#include +#include +#include +#include +#include +#include + +class CFlowGraphSheet : public PropertySheet +{ +public: + DECLARE_CLASS_SIMPLE( CFlowGraphSheet, PropertySheet ); + + CFlowGraphSheet( Panel *parent, const char *panelName, bool draggableTabs, bool closeableTabs ); + ~CFlowGraphSheet(); + +protected: + virtual void PerformLayout(); + +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/veditorroot.cpp b/sp/src/shadereditor/veditorroot.cpp new file mode 100644 index 00000000..be52d489 --- /dev/null +++ b/sp/src/shadereditor/veditorroot.cpp @@ -0,0 +1,1544 @@ +#include "cbase.h" +#include +#include +#include "vgui/ISurface.h" +#include "ienginevgui.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "materialsystem/imesh.h" +#include "materialsystem/ITexture.h" +#include "materialsystem/IMaterial.h" +#include "materialsystem/IMaterialVar.h" +#include "materialsystem/imaterialsystem.h" + +#include "editorCommon.h" +#include "vEditorRoot.h" +#include "vNodeView.h" + +//#include "vgui_int.h" + +CEditorRoot *pEditorRoot = NULL; + + + +enum ERoot_FileMenu_t +{ + ER_FMENU_NEW = 0, + ER_FMENU_OPEN, + ER_FMENU_SAVE, + ER_FMENU_SAVE_AS, + ER_FMENU_SAVE_ALL, + ER_FMENU_SCREENSHOT, + ER_FMENU_ECONFIG, + ER_FMENU_UNDO, + ER_FMENU_REDO, +}; +enum ERoot_ShaderMenu_t +{ + ER_SMENU_SCONFIG = 0, + ER_SMENU_FULLCOMPILE, + ER_SMENU_ALLCOMPILE, + ER_SMENU_KILLCOMPILER, + ER_SMENU_SPRECACHE, + ER_SMENU_INJECT, + ER_SMENU_PAINT, +}; +enum ERoot_PostProcMenu_t +{ + ER_PMENU_PCONFIG = 0, + ER_PMENU_PPRECACHE, + ER_PMENU_RTS, + ER_PMENU_, +}; + +CEditorRoot::CEditorRoot( const char *pElementName ) : BaseClass( NULL, "editor" ) +{ + pEditorRoot = this; + Q_memset( hFonts, 0, sizeof(hFonts) ); + Q_memset( hFonts2, 0, sizeof(hFonts2) ); +// m_pKV_MainPreviewMat = NULL; + //m_pMat_MainPreview = NULL; +// m_pKV_BGPreviewMat = NULL; + //m_pMat_BGPreview = NULL; + m_bPainting = false; + m_bAutoCompile = true; + m_bAutoFullcompile = false; + m_bAutoShaderPublish = true; + m_bAutoPrecacheUpdate = true; + m_bWarnOnClose = true; + + InitColors(); + + pPreview = NULL; + m_pKV_NodeHelp = NULL; + + m_iNumMaterials = 0; + m_pszMaterialList = NULL; + + m_pLastFullCompiledShader = NULL; + + //vgui::VPANEL GameUIRoot = enginevgui->GetPanel( PANEL_GAMEUIDLL ); + vgui::VPANEL EngineRoot = enginevgui->GetPanel( PANEL_ROOT ); + //vgui::VPANEL DLLRoot = VGui_GetClientDLLRootPanel(); + + vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SourceScheme.res", "SourceScheme"); + SetScheme( scheme ); + + m_pLabelTitle = new Label( this, "title_label", "" ); + + pNodeSheet = new CFlowGraphSheet( this, "flowgraphsheets", true, true ); + pNodeSheet->AddActionSignalTarget( this ); + pNodeSheet->SetAddTabButtonEnabled( true ); + //pNodeSheet->ShowContextButtons(true); + /*pNodeView =*/ + AddNewTab(); + + //CFlowGraphPage *page = new CFlowGraphPage( this ); + //m_hFlowGraphPages.AddToTail( page ); + //CNodeView *view = new CNodeView( page, this, "main_nodeview" ); + //m_hNodeViews.AddToTail( pNodeView ); + //page->SetFlowGraph( pNodeView ); + //pNodeSheet->AddPage( page, GetDefaultTabName() ); + + m_pLabel_Coords = new Label( this, "mouse_node_coords", "" ); + m_pLabel_FrameTime = new Label( this, "framespeed", "" ); + + + m_pMenuBar = new MenuBar( this, "menu_bar" ); + m_pMBut_File = new MenuButton( this, "mbut_file", "File" ); + m_pMBut_File->AddActionSignalTarget( this ); + Menu *pMenu_File = new Menu( m_pMBut_File, "" ); + pMenu_File->AddMenuItem( "New", new KeyValues("onmenufile","entry",ER_FMENU_NEW), this ); + pMenu_File->AddSeparator(); + pMenu_File->AddMenuItem( "Open", new KeyValues("onmenufile","entry",ER_FMENU_OPEN), this ); + pMenu_File->AddSeparator(); + pMenu_File->AddMenuItem( "Save", new KeyValues("onmenufile","entry",ER_FMENU_SAVE), this ); + pMenu_File->AddMenuItem( "Save as", new KeyValues("onmenufile","entry",ER_FMENU_SAVE_AS), this ); + pMenu_File->AddMenuItem( "Save all", new KeyValues("onmenufile","entry",ER_FMENU_SAVE_ALL), this ); + pMenu_File->AddSeparator(); + pMenu_File->AddMenuItem( "Undo", new KeyValues("onmenufile","entry",ER_FMENU_UNDO), this ); + pMenu_File->AddMenuItem( "Redo", new KeyValues("onmenufile","entry",ER_FMENU_REDO), this ); + pMenu_File->AddSeparator(); + pMenu_File->AddMenuItem( "Take screenshot", new KeyValues("onmenufile","entry",ER_FMENU_SCREENSHOT), this ); + pMenu_File->AddMenuItem( "Editor config", new KeyValues("onmenufile","entry",ER_FMENU_ECONFIG), this ); + m_pMBut_File->SetMenu( pMenu_File ); + m_pMenuBar->AddButton( m_pMBut_File ); + + m_pMBut_Shader = new MenuButton( this, "mbut_shader", "Shader" ); + Menu *pMenu_Shader = new Menu( m_pMBut_Shader, "" ); + pMenu_Shader->AddMenuItem( "Shader settings", new KeyValues("onmenushader","entry",ER_SMENU_SCONFIG), this ); + pMenu_Shader->AddMenuItem( "Shader precache", new KeyValues("onmenushader","entry",ER_SMENU_SPRECACHE), this ); + pMenu_Shader->AddSeparator(); + pMenu_Shader->AddMenuItem( "Full compile", new KeyValues("onmenushader","entry",ER_SMENU_FULLCOMPILE), this ); + pMenu_Shader->AddMenuItem( "Compile all precached", new KeyValues("onmenushader","entry",ER_SMENU_ALLCOMPILE), this ); + pMenu_Shader->AddMenuItem( "Terminate compilers", new KeyValues("onmenushader","entry",ER_SMENU_KILLCOMPILER), this ); + pMenu_Shader->AddSeparator(); + pMenu_Shader->AddMenuItem( "Inject shader into world", new KeyValues("onmenushader","entry",ER_SMENU_INJECT), this ); + pMenu_Shader->AddMenuItem( "Paint world", new KeyValues("onmenushader","entry",ER_SMENU_PAINT), this ); + m_pMBut_Shader->SetMenu( pMenu_Shader ); + m_pMenuBar->AddButton( m_pMBut_Shader ); + + m_pMBut_PostProc = new MenuButton( this, "mbut_postproc", "Post processing" ); + Menu *pMenu_PostProc = new Menu( m_pMBut_PostProc, "" ); + pMenu_PostProc->AddMenuItem( "Effect settings", new KeyValues("onmenupostprocessing","entry",ER_PMENU_PCONFIG), this ); + pMenu_PostProc->AddMenuItem( "Effect precache", new KeyValues("onmenupostprocessing","entry",ER_PMENU_PPRECACHE), this ); + pMenu_PostProc->AddMenuItem( "Manage rendertargets", new KeyValues("onmenupostprocessing","entry",ER_PMENU_RTS), this ); + m_pMBut_PostProc->SetMenu( pMenu_PostProc ); + m_pMenuBar->AddButton( m_pMBut_PostProc ); + + //m_pLabel_CurrentFileName = new Label( this, "filename", "-" ); + + LoadControlSettings("shadereditorui/vgui/shadereditor_root.res"); + OnShaderNameChanged(); + + Activate(); + SetVisible( true ); + SetPaintBorderEnabled( false ); + SetPaintBackgroundEnabled( true ); + SetPaintEnabled( true ); + SetParent( EngineRoot ); + + m_pKV_SelectionCopy = NULL; + bFontsLoaded = false; + + m_bHalfView = false; + m_bHasInput = true; + //m_bNeedsButtonPush = false; + + m_bDraw_Datatypes = true; + m_bDraw_Shadows = true; + m_bDraw_AllLimits = true; + m_bDoTooltips = true; + + //m_szShaderName[0] = '\0'; + px = py = psx = psy = 0; + cedit_x = cedit_y = cedit_sx = cedit_sy = -1; + //m_flErrorTime = 0; + + AllocProceduralMaterials(); + UpdateVariablePointer(); + + //m_iLastCompileIndex = GetSafeFlowgraph()->GetStackIndex(); +} +CEditorRoot::~CEditorRoot() +{ + if ( m_pszMaterialList ) + { + sEditMRender->DestroyCharPtrList( &m_pszMaterialList ); + m_pszMaterialList = NULL; + m_iNumMaterials = 0; + } + + DeleteProceduralMaterials(); + + SendCopyNodes( NULL ); + //m_hFlowGraphPages.Purge(); + //m_hNodeViews.Purge(); + + if ( pPreview ) + { + pPreview->SetParent( (Panel*)NULL ); + delete pPreview; + pPreview = NULL; + } + + delete m_pLastFullCompiledShader; + + if ( m_pKV_NodeHelp ) + m_pKV_NodeHelp->deleteThis(); + m_pKV_NodeHelp = NULL; +} + +KeyValues *CEditorRoot::GetNodeHelpContainer() +{ + if ( !m_pKV_NodeHelp ) + { + m_pKV_NodeHelp = new KeyValues( "node_help" ); + char tmp[MAX_PATH*4]; + Q_snprintf( tmp, sizeof(tmp), "%s/node_help.txt", GetEditorRootDirectory() ); + if ( !m_pKV_NodeHelp->LoadFromFile( g_pFullFileSystem, tmp ) ) + { + m_pKV_NodeHelp->deleteThis(); + m_pKV_NodeHelp = NULL; + } + } + + return m_pKV_NodeHelp; +} + +void CEditorRoot::PageChanged() +{ + SortButtons(); + + CNodeView *pView = GetSafeFlowgraph(); + const char *pszShaderName = pView->GetShadername(); + + m_pMBut_File->GetMenu()->SetItemEnabled( 2, pszShaderName != NULL ); + + const bool bIsShader = pView->GetFlowgraphType() == CNodeView::FLOWGRAPH_HLSL || + pView->GetFlowgraphType() == CNodeView::FLOWGRAPH_HLSL_TEMPLATE; + m_pMBut_Shader->GetMenu()->SetItemEnabled( 0, bIsShader ); + m_pMBut_Shader->GetMenu()->SetItemEnabled( 2, bIsShader ); + m_pMBut_Shader->GetMenu()->SetItemEnabled( 4, bIsShader ); + m_pMBut_Shader->GetMenu()->SetItemEnabled( 5, bIsShader ); + m_pMBut_Shader->GetMenu()->SetItemEnabled( 6, bIsShader ); + + const bool bIsPPEffect = pView->GetFlowgraphType() == CNodeView::FLOWGRAPH_POSTPROC; + m_pMBut_PostProc->GetMenu()->SetItemEnabled( 0, bIsPPEffect ); + + if ( pPreview ) + { + pPreview->UpdateLayout(); + } +} + +void CEditorRoot::OnAskPageClose( KeyValues *pKV ) +{ + Panel *pPageTab = (Panel*)pKV->GetPtr( "PageTab" ); + CNodeView *pGraph = GetFlowGraph( pKV->GetInt( "TabIndex" ) ); + + if ( pPageTab == NULL || + pGraph == NULL ) + { + Assert( 0 ); + return; + } + + ConfirmTabClose( pPageTab->GetVPanel() ); + +#if 0 + if ( !m_bWarnOnClose || !pGraph->IsSaveDirty() ) + ConfirmTabClose( pPageTab->GetVPanel() ); + else + { + const char *pszShadername = pGraph->GetShadername(); + + char shortName[MAX_PATH*4]; + + KeyValues *pKVResponse_Yes = new KeyValues( "ResponseGraphSave", "DoSave", 1 ); + KeyValues *pKVResponse_No = new KeyValues( "ResponseGraphSave", "DoSave", 0 ); + + if ( pszShadername == NULL ) + { + pKVResponse_No->deleteThis(); + pKVResponse_No = new KeyValues( "ResponseGraphSave", "DoSave", 2 ); + } + else + { + Q_FileBase( pszShadername, shortName, sizeof( shortName ) ); + } + + pKVResponse_Yes->SetPtr( "PageTab", pPageTab ); + pKVResponse_No->SetPtr( "PageTab", pPageTab ); + pKVResponse_Yes->SetPtr( "Graph", pGraph ); + pKVResponse_No->SetPtr( "Graph", pGraph ); + + vgui::PromptSimple *prompt = new vgui::PromptSimple( this, "Unsaved changes" ); + prompt->MoveToCenterOfScreen(); + + if ( pszShadername != NULL ) + prompt->SetText( VarArgs( "The graph %s has unsaved changes. Save now?", shortName ) ); + else + prompt->SetText( "This graph has not been saved yet, are you sure that you want to close it?" ); + + prompt->AddButton( "Yes", pKVResponse_Yes ); + prompt->AddButton( "No", pKVResponse_No ); + prompt->MakeReadyForUse(); + prompt->InvalidateLayout( true, true ); + } +#endif +} + +void CEditorRoot::OnResponseGraphSave( KeyValues *pKV ) +{ + int iResponse = pKV->GetInt( "DoSave" ); + const bool bSave = iResponse == 1; + const bool bAbort = iResponse == 2; + + if ( bAbort ) + return; + + Panel *pPageTab = (Panel*)pKV->GetPtr( "PageTab" ); + CNodeView *pGraph = (CNodeView*)pKV->GetPtr( "Graph" ); + + if ( bSave && pGraph != NULL ) + pGraph->SaveToFile(); + + ConfirmTabClose( pPageTab->GetVPanel() ); +} + +void CEditorRoot::ConfirmTabClose( vgui::VPANEL panel ) +{ + ivgui()->PostMessage( panel, new KeyValues("OnCloseConfirmed"), GetVPanel() ); +} + +void CEditorRoot::PageClosed( int pagenum ) +{ + //m_bNeedsButtonPush = true; +} + +void CEditorRoot::RequestAddTab() +{ + int mode = ( input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ) || + input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ) ) ? + CANVASINIT_PPEFFECT : CANVASINIT_SCRATCH; + + OpenShaderFlowgraph( mode, false, true ); +} + +void CEditorRoot::SortButtons() +{ + //m_bNeedsButtonPush = false; + + Panel *pViewReset = FindChildByName( "button_viewreset" ); + + if ( pViewReset ) + { + pViewReset->MoveToFront(); + pViewReset->SetBgColor( Color( 127,127,127,127) ); + } +} +void CEditorRoot::OnSceneRender() +{ + if ( pPreview ) + pPreview->OnSceneRender(); +} +void CEditorRoot::OnPostRender() +{ + if ( pPreview ) + pPreview->OnPostRender(); +} +void CEditorRoot::AllocProceduralMaterials() +{ + for ( int i = 0; i < NPSOP_CALC_LAST; i++ ) + { + m_pKV_NodePreview[ i ] = new KeyValues( "NODE_CALC" ); + m_pKV_NodePreview[ i ]->SetInt( "$OPERATION", i ); + m_pMat_NodePreview[ i ] = materials->CreateMaterial( VarArgs( "__node_pv_op_%i", i ), m_pKV_NodePreview[ i ] ); + m_pMat_NodePreview[ i ]->Refresh(); + //m_pKV_NodePreview[ i ]->Clear(); + } + + //KeyValues* m_pKV_MainPreviewMat = new KeyValues( "EDITOR_SHADER" ); + //Assert( !m_pMat_MainPreview ); + //m_pMat_MainPreview = materials->CreateMaterial( "__main_preview", m_pKV_MainPreviewMat ); + //m_pMat_MainPreview->Refresh(); + + //KeyValues* m_pKV_BGPreviewMat = new KeyValues( "BACKGROUND_PREV" ); + //Assert( !m_pMat_BGPreview ); + //m_pMat_BGPreview = materials->CreateMaterial( "__bg_preview", m_pKV_BGPreviewMat ); + //m_pMat_BGPreview->Refresh(); +} +void CEditorRoot::UpdateVariablePointer() +{ + bool bFound = false; + for ( int i = 0; i < NPSOP_CALC_LAST; i++ ) + { + for ( int a = 0; a < 6; a++ ) + { + m_pMatVar_NodePv_UVs[ i ][ a ] = m_pMat_NodePreview[ i ]->FindVar( VarArgs( "$INPUT_UVS_%i", a ), &bFound ); + Assert( bFound ); + } + } + + for ( int i = 0; i < pNodeSheet->GetNumPages(); i++ ) + ((CFlowGraphPage*)pNodeSheet->GetPage(i))->GetFlowGraph()->UpdatePsinMaterialVar(); + + //for ( int i = 0; i < m_hNodeViews.Count(); i++ ) + //{ + // m_hNodeViews[i]->UpdatePsinMaterialVar(); + //} +} + +IMaterial *CEditorRoot::GetMainPreviewMat() +{ + CNodeView *pView = GetActiveFlowGraph(); + Assert( pView ); + return pView->GetPreviewMeshMaterial(); +} + +IMaterial *CEditorRoot::GetBGPreviewMat() +{ + CNodeView *pView = GetActiveFlowGraph(); + Assert( pView ); + return pView->GetPreviewBackgroundMaterial(); +} + +KeyValues *CEditorRoot::GetMainPreviewKV() +{ + CNodeView *pView = GetActiveFlowGraph(); + Assert( pView ); + return pView->GetKVMeshMaterial(); +} + +KeyValues *CEditorRoot::GetBGPreviewKV() +{ + CNodeView *pView = GetActiveFlowGraph(); + Assert( pView ); + return pView->GetKVBackgroundMaterial(); +} + +IMaterial *CEditorRoot::GetOperatorMaterial( int i ) +{ + Assert( m_pMat_NodePreview[i] ); + return m_pMat_NodePreview[i]; +} +IMaterialVar *CEditorRoot::GetUVTargetParam( int i, int num ) +{ + Assert( m_pMatVar_NodePv_UVs[i][num] ); + return m_pMatVar_NodePv_UVs[i][num]; +} +//IMaterialVar *CEditorRoot::GetOperatorParam( int i ) +//{ +// Assert( m_pMatVar_NodePv_OP[i] ); +// return m_pMatVar_NodePv_OP[i]; +//} +void CEditorRoot::DeleteProceduralMaterials() +{ + for ( int i = 0; i < NPSOP_CALC_LAST; i++ ) + { + m_pKV_NodePreview[ i ]->Clear(); + ForceDeleteMaterial( &m_pMat_NodePreview[i] ); + m_pKV_NodePreview[ i ] = NULL; + //m_pKV_NodePreview[i]->deleteThis(); + } + + //ForceDeleteMaterial( &m_pMat_MainPreview ); + //ForceDeleteMaterial( &m_pMat_BGPreview ); + + //m_pMat_MainPreview->Release(); + //m_pMat_MainPreview->DeleteIfUnreferenced(); + + //m_pMat_BGPreview->Release(); + //m_pMat_BGPreview->DeleteIfUnreferenced(); +} + +void CEditorRoot::SendFullyCompiledShader( GenericShaderData* data ) +{ + delete m_pLastFullCompiledShader; + m_pLastFullCompiledShader = new GenericShaderData( *data ); + + if ( ShouldAutoPublish() ) + InvokeShaderToScene(); +} +void CEditorRoot::InvokeShaderToScene( GenericShaderData *pShader ) +{ + if ( pShader == NULL ) + pShader = m_pLastFullCompiledShader; + + if ( pShader == NULL ) + return; + + ReloadGameShaders( pShader ); + + for ( int i = 0; i < GetNumFlowGraphs(); i++ ) + { + if ( GetFlowGraph(i)->GetFlowgraphType() == CNodeView::FLOWGRAPH_POSTPROC ) + GetFlowGraph(i)->MakeSolversDirty(); + } +} + +void CEditorRoot::BeginPaintWorld() +{ + m_bPainting = true; + input()->SetMouseCapture( GetVPanel() ); +} + +void CEditorRoot::EndPaintWorld( bool bValid ) +{ + input()->SetMouseCapture( NULL ); + input()->SetCursorOveride( dc_user ); + m_bPainting = false; + + if ( bValid && !m_pLastFullCompiledShader ) + return; + + if ( input()->GetMouseOver() && + ( input()->GetMouseOver() == GetVPanel() || + ipanel()->HasParent( input()->GetMouseOver(), GetVPanel() ) ) ) + return; + + if ( !sEditMRender ) + return; + + sEditMRender->DestroyCharPtrList( &m_pszMaterialList ); + m_iNumMaterials = sEditMRender->MaterialPicker( &m_pszMaterialList ); + + gShaderEditorSystem->BeginMaterialReload( !bValid ); + //ReloadGameShaders( m_pLastFullCompiledShader, m_pszMaterialList, m_iNumMaterials ); +} +void CEditorRoot::OnMouseCaptureLost() +{ + if ( m_bPainting ) + { + m_bPainting = false; + input()->SetCursorOveride( dc_user ); + } +} +void CEditorRoot::OnMousePressed(MouseCode code) +{ + if ( m_bPainting ) + { + EndPaintWorld( code == MOUSE_LEFT ); + return; + } + BaseClass::OnMousePressed( code ); +} + +CNodeView *CEditorRoot::GetMainFlowgraph() +{ + return NULL; //pNodeView; +} + +CNodeView *CEditorRoot::GetSafeFlowgraph() +{ + CNodeView *pCur = GetActiveFlowGraph(); + Assert( pCur ); + return (pCur) ? pCur : GetMainFlowgraph(); +} + +const int CEditorRoot::GetNumFlowGraphs() +{ + return pNodeSheet->GetNumPages(); +} + +CNodeView *CEditorRoot::GetFlowGraph( int i ) +{ + CFlowGraphPage *page = (CFlowGraphPage*)pNodeSheet->GetPage( i ); + CNodeView *pView = page ? page->GetFlowGraph() : NULL; + return pView; +} + +CNodeView *CEditorRoot::GetActiveFlowGraph() +{ + CFlowGraphPage *page = GetActiveFlowgraphPage(); //(CFlowGraphPage*)pNodeSheet->GetActivePage(); + CNodeView *pView = page ? page->GetFlowGraph() : NULL; + return pView; +} + +CFlowGraphPage *CEditorRoot::GetActiveFlowgraphPage() +{ + return (CFlowGraphPage*)pNodeSheet->GetActivePage(); +} + +const bool CEditorRoot::ShouldDraw_Datatypes() +{ + return sedit_draw_datatypes.GetBool() && m_bDraw_Datatypes; +} +const bool CEditorRoot::ShouldDraw_Shadows() +{ + return sedit_draw_shadows.GetBool() && m_bDraw_Shadows; +} +const bool CEditorRoot::ShouldDraw_Nodes() +{ + return sedit_draw_nodes.GetBool(); +} +const bool CEditorRoot::ShouldDraw_Jacks() +{ + return sedit_draw_jacks.GetBool(); +} +const bool CEditorRoot::ShouldDraw_Bridges() +{ + return sedit_draw_bridges.GetBool(); +} +const bool CEditorRoot::ShouldDraw_AllLimits() +{ + return m_bDraw_AllLimits; +} +void CEditorRoot::SendCopyNodes( KeyValues *pKV ) +{ + if ( m_pKV_SelectionCopy ) + m_pKV_SelectionCopy->deleteThis(); + if ( pKV ) + m_pKV_SelectionCopy = pKV; + else + m_pKV_SelectionCopy = NULL; +} +KeyValues *CEditorRoot::GetCopyNodes() +{ + return m_pKV_SelectionCopy; +} + +void CEditorRoot::OnThink(void) +{ + BaseClass::OnThink(); + + if ( IsBuildModeActive() ) + { + Panel *pBuild = FindChildByName( "BuildModeDialog" ); + if ( pBuild && !pBuild->IsCursorOver() && input()->IsKeyDown( KEY_LCONTROL ) ) + pBuild->MoveToFront(); + } + + input()->GetCursorPosition( Mx, My ); + ScreenToLocal(Mx,My); + + Vector2D mCoords = GetSafeFlowgraph()->GetMousePosInNodeSpace(); + m_pLabel_Coords->SetText( VarArgs( "position: %10.1f / %10.1f", mCoords.x, mCoords.y ) ); + + static CFastTimer _timer; + _timer.End(); + double _frametime = _timer.GetDuration().GetSeconds(); + _timer.Start(); + m_pLabel_FrameTime->SetText( VarArgs( "fps: %4.1f, ms: %8.7f", 1.0f/max( 0.00001f, _frametime ), _frametime ) ); + + if ( m_bPainting ) + input()->SetCursorOveride( dc_hand ); + + // FML + SortButtons(); + //if ( m_bNeedsButtonPush ) + // SortButtons(); + +#ifdef SHADER_EDITOR_DLL_SWARM + VPANEL modal = input()->GetAppModalSurface(); + static bool bFailed = false; + + if ( !bFailed && modal > 0 && modal != GetVPanel() ) + { + if ( !m_bHalfView && IsVisible() && !ipanel()->HasParent( modal, GetVPanel() ) ) + { + const char *pszModalName = ipanel()->GetName( modal ); + const char *names[] = { + "SteamCloudConfirmation", + "AddonAssociation", + }; + + const int numnames = ARRAYSIZE( names ); + for ( int i = 0; i < numnames; i++ ) + { + if ( !Q_stricmp( names[i], pszModalName ) ) + { + ToggleVisible(); + return; + } + } + + bFailed = true; + } + } +#endif +} +bool CEditorRoot::ShouldDraw( void ) +{ + return true; +} +void CEditorRoot::Init(void) +{ +} +void CEditorRoot::LevelInit( void ) +{ +} +void CEditorRoot::LevelShutdown() +{ +} +void CEditorRoot::SetVisible(bool state) +{ + BaseClass::SetVisible(state); +} + +//void CEditorRoot::CompileCallback( bool bError, HCURSTACKIDX idx ) +//{ +// if (bError) +// m_flErrorTime = 1; +// else +// m_iLastCompileIndex = idx; +//} + +void CEditorRoot::InitColors() +{ +} + +void CEditorRoot::Paint() +{ + BaseClass::Paint(); +} + +void CEditorRoot::OnMenuFile( int entry ) +{ + switch ( entry ) + { + case ER_FMENU_NEW: // new + new CDialog_NewCanvas( GetSafeFlowgraph(), this ); + break; + case ER_FMENU_OPEN: // open + OpenFileDialog( false ); + break; + case ER_FMENU_SAVE: // save + GetSafeFlowgraph()->SaveToFile(); + break; + case ER_FMENU_SAVE_AS: // save as + OpenFileDialog( true ); + break; + case ER_FMENU_SAVE_ALL: + SaveAllGraphs(); + break; + case ER_FMENU_SCREENSHOT: // screenshot + TakeScreenshot(); + break; + case ER_FMENU_ECONFIG: // editor config + new CDialog_EditorConfig( this ); + break; + case ER_FMENU_UNDO: + { + CNodeView *pView = GetActiveFlowGraph(); + if ( !pView ) break; + pView->HistoryAction( CNodeView::HACT_UNDO ); + } + break; + case ER_FMENU_REDO: + { + CNodeView *pView = GetActiveFlowGraph(); + if ( !pView ) break; + pView->HistoryAction( CNodeView::HACT_REDO ); + } + break; + } +} +void CEditorRoot::OnMenuShader( int entry ) +{ + switch ( entry ) + { + case ER_SMENU_SCONFIG: // settings + new CDialog_GeneralConfig( GetSafeFlowgraph(), this ); + break; + case ER_SMENU_FULLCOMPILE: // compile + if ( !GetSafeFlowgraph() ) + return; + GetSafeFlowgraph()->SetPreviewMode( false ); + GetSafeFlowgraph()->MakeSolversDirty(); + GetSafeFlowgraph()->UpdateSolvers(); + GetSafeFlowgraph()->SetPreviewMode( true ); + break; + case ER_SMENU_ALLCOMPILE: + new CDialogRecompileAll( this ); + break; + case ER_SMENU_SPRECACHE: // shader precache + new CShaderPrecache( this, GetSafeFlowgraph() ); + break; + case ER_SMENU_KILLCOMPILER: // terminate compiler + ForceTerminateCompilers(); + break; + case ER_SMENU_INJECT: // inject shader to scene + InvokeShaderToScene(); + break; + case ER_SMENU_PAINT: // paint world + BeginPaintWorld(); + break; + } +} +void CEditorRoot::OnMenuPostProcessing( int entry ) +{ + switch ( entry ) + { + case ER_PMENU_PCONFIG: + new CDialog_PPEConfig( this, GetSafeFlowgraph() ); + break; + case ER_PMENU_PPRECACHE: + new CDialog_PPEPrecache( this ); + break; + case ER_PMENU_RTS: // settings + new CDialog_RendertargetList( this ); + break; + } +} + +void CEditorRoot::TakeScreenshot() +{ + CNodeView *pView = GetActiveFlowGraph(); + if ( !pView ) + return; + + char _path[MAX_PATH*4]; + Q_snprintf( _path, sizeof(_path), "%s\\screenshots", ::GetGamePath() ); + + if ( !g_pFullFileSystem->IsDirectory( _path, "MOD" ) ) + g_pFullFileSystem->CreateDirHierarchy( _path, "MOD" ); + + int idx = 0; + Q_snprintf( _path, sizeof(_path), "%s\\screenshots\\nodeview_%03i.jpg", ::GetGamePath(), idx ); + + while ( g_pFullFileSystem->FileExists( _path ) ) + { + idx++; + Q_snprintf( _path, sizeof(_path), "%s\\screenshots\\nodeview_%03i.jpg", ::GetGamePath(), idx ); + } + + Q_snprintf( _path, sizeof(_path), "%s\\screenshots\\nodeview_%03i.jpg", ::GetGamePath(), idx ); + CHLSL_Image::CreateScreenshot( pView, _path ); +} + +void CEditorRoot::SaveAllGraphs() +{ + for ( int i = 0; i < GetNumFlowGraphs(); i++ ) + { + if ( GetFlowGraph( i )->GetShadername() ) + GetFlowGraph(i)->SaveToFile( GetFlowGraph(i)->GetShadername() ); + } +} +void CEditorRoot::OnShaderNameChanged() +{ + CNodeView *pView = GetSafeFlowgraph(); + const char *pszShaderName = pView->GetShadername(); + + m_pMBut_File->GetMenu()->SetItemEnabled( 2, pszShaderName != NULL ); + + Label *pTab = (Label*)pNodeSheet->GetActiveTab(); + Assert( pTab && GetActiveFlowgraphPage() ); + + if ( pszShaderName == NULL ) + { + //m_pLabel_CurrentFileName->SetText( "-" ); + //pView->SetShadername( NULL ); + + pTab->SetText( GetDefaultTabName( pView ) ); + //GetActiveFlowgraphPage()->sett + } + else + { + char tmp[MAX_PATH]; + Q_FileBase( pszShaderName, tmp, sizeof( tmp ) ); + + //m_pLabel_CurrentFileName->SetText( tmp ); + pTab->SetText( tmp ); + } + + for ( int i = 0; i < pNodeSheet->GetNumPages(); i++ ) + ((Panel*)pNodeSheet->GetTab(i))->InvalidateLayout(true); + + pNodeSheet->InvalidateLayout( true, true ); +} +void CEditorRoot::SetCurrentShaderName( const char *n ) +{ + CNodeView *pView = GetSafeFlowgraph(); + pView->SetShadername( n ); + //Q_memset( m_szShaderName, 0, sizeof(m_szShaderName) ); + //if ( n ) + // Q_snprintf( m_szShaderName, sizeof(m_szShaderName), "%s", n ); + OnShaderNameChanged(); +} + +const char *CEditorRoot::GetCurrentShaderName() +{ + CNodeView *pView = GetSafeFlowgraph(); + return pView->GetShadername(); +} + +void CEditorRoot::OnMenuOpen( KeyValues *pKV ) +{ + Panel *pP = (Panel*)pKV->GetPtr( "panel" ); + if ( pP == m_pMBut_File ) + { + CNodeView *pView = GetActiveFlowGraph(); + const bool bAllowUndo = pView && pView->GetNumHistoryEntires_Undo() > 1; + const bool bAllowRedo = pView && pView->GetNumHistoryEntires_Redo() > 0; + m_pMBut_File->GetMenu()->SetItemEnabled( 5, bAllowUndo ); + m_pMBut_File->GetMenu()->SetItemEnabled( 6, bAllowRedo ); + } +} +void CEditorRoot::OpenFileDialog( bool bSave ) +{ + if ( m_hShaderBrowser.Get() ) + m_hShaderBrowser.Get()->MarkForDeletion(); + + m_hShaderBrowser = new FileOpenDialog( this, + bSave ? "Save canvas" : "Load canvas", + bSave ? FOD_SAVE : FOD_OPEN, + new KeyValues("FileOpenContext", "context", + bSave ? "savec" : "openc" ) + ); + + if ( m_hShaderBrowser.Get() ) + { + //m_hShaderBrowser->SetStartDirectory( GetCanvasDirectory() ); + m_hShaderBrowser->SetStartDirectoryContext( GetFODPathContext( FODPC_CANVAS ), GetCanvasDirectory() ); + m_hShaderBrowser->AddFilter( "*.txt", "Canvas", true ); +#if MAKE_DEFAULT_CANVAS_EDITABLE + m_hShaderBrowser->AddFilter( "*.def", "Default canvas", true ); +#endif + m_hShaderBrowser->DoModal( true ); + } +} +void CEditorRoot::OnFileSelected( KeyValues *pKV ) +{ + KeyValues *pContext = pKV->FindKey( "FileOpenContext" ); + if ( !pContext ) + return; + const char *__c = pContext->GetString( "context" ); + bool bSaving = true; + if ( !Q_stricmp( __c, "openc" ) ) + bSaving = false; + + const char *pathIn = pKV->GetString( "fullpath" ); + if ( Q_strlen( pathIn ) <= 1 ) + return; + + bool bDoViewReset = false; + + if ( !bSaving ) + { + int iPageIndex = -1; + for ( int i = 0; i < pNodeSheet->GetNumPages(); i++ ) + { + const char *pszShadername = ((CFlowGraphPage*)pNodeSheet->GetPage(i))->GetFlowGraph()->GetShadername(); + if ( pszShadername && !Q_stricmp( pszShadername, pathIn ) ) + iPageIndex = i; + } + bool bExists = iPageIndex >= 0; + + if ( bExists ) + { + pNodeSheet->SetActivePage( pNodeSheet->GetPage( iPageIndex ) ); + //return; + } + else if ( ( input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ) ) ) + { + AddNewTab(); + bDoViewReset = true; + } + } + else + { + Panel *p = pNodeSheet->GetActivePage(); + for ( int i = 0; i < pNodeSheet->GetNumPages(); i++ ) + { + Panel *pCur = pNodeSheet->GetPage(i); + if (pCur == p) + continue; + + const char *pszShadername = ((CFlowGraphPage*)pCur)->GetFlowGraph()->GetShadername(); + if ( pszShadername && !Q_stricmp( pszShadername, pathIn ) ) + { + pNodeSheet->DeletePage(pCur); + i--; + } + } + } + + SetCurrentShaderName( pathIn ); + CNodeView *pView = GetSafeFlowgraph(); + + if ( bSaving ) + pView->SaveToFile( pView->GetShadername() ); //m_szShaderName ); + else + { + pView->LoadFromFile( pView->GetShadername() ); //m_szShaderName ); + + if ( bDoViewReset ) + { + pView->InvalidateLayout( true, true ); + pView->ResetView_User( false ); + } + + PageChanged(); + } + + pView->RequestFocus(); +} + +void CEditorRoot::OpenShaderFlowgraph( int mode, bool bSM20, bool bForceNewTab ) +{ + //CNodeView::FlowGraphType_t curType = GetSafeFlowgraph()->GetFlowgraphType(); + + CNodeView::FlowGraphType_t targetType = CNodeView::FLOWGRAPH_HLSL; + switch (mode) + { + case CANVASINIT_PPEFFECT: + targetType = CNodeView::FLOWGRAPH_POSTPROC; + break; + } + + bool bPushHistory = false; + + if ( bForceNewTab || + input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ) ) + AddNewTab(targetType); + else + bPushHistory = true; + + OnNewFile(); + + CNodeView *pView = GetSafeFlowgraph(); + pView->PurgeCanvas(); + + const char *FileToLoad = NULL; + + switch (mode) + { + default: + case CANVASINIT_SCRATCH: + { + GenericShaderData *data = new GenericShaderData(); + if ( bSM20 ) + data->shader->iShaderModel = SM_20B; + + pView->InitCanvas(targetType,data); + delete data; + } + break; + + case CANVASINIT_MODEL_SIMPLE: +#ifdef SHADER_EDITOR_DLL_SWARM + FileToLoad = "def_model_simple_swarm.def"; +#else + FileToLoad = "def_model_simple.def"; +#endif + break; + + case CANVASINIT_MODEL_COMPLEX: +#ifdef SHADER_EDITOR_DLL_SWARM + FileToLoad = "def_model_complex_swarm.def"; +#else + FileToLoad = "def_model_complex.def"; +#endif + break; + + case CANVASINIT_POSTPROC: + FileToLoad = "def_pp.def"; + break; + + case CANVASINIT_LIGHTMAPPED_SIMPLE: +#ifdef SHADER_EDITOR_DLL_SWARM + FileToLoad = "def_lightmap_simple_swarm.def"; +#else + FileToLoad = "def_lightmap_simple.def"; +#endif + break; + + case CANVASINIT_LIGHTMAPPED_BUMP: +#ifdef SHADER_EDITOR_DLL_SWARM + FileToLoad = "def_lightmap_bump_swarm.def"; +#else + FileToLoad = "def_lightmap_bump.def"; +#endif + break; + case CANVASINIT_PPEFFECT: + pView->InitCanvas(targetType); + break; + } + + if ( FileToLoad ) + { + char fPath[ MAX_PATH ]; + Q_snprintf( fPath, MAX_PATH, "%s/shadereditorui/canvas_default/%s", GetGamePath(), FileToLoad ); + pView->LoadFromFile( fPath ); + } + + OnShaderNameChanged(); + UpdateTabColor( pView ); + + pView->InvalidateLayout( true, true ); + pView->ResetView_User( false ); + + if ( bPushHistory ) + pView->MakeHistoryDirty(); + + PageChanged(); + + pView->UnDirtySave(); +} + +CNodeView *CEditorRoot::AddNewTab( CNodeView::FlowGraphType_t mode, bool bActivate ) +{ + CFlowGraphPage *page = new CFlowGraphPage( this ); + //m_hFlowGraphPages.AddToTail( page ); + + CNodeView *pView = new CNodeView( page, this, /*mode,*/ "nodeview_panel" ); + //m_hNodeViews.AddToTail( pView ); + pView->SetFlowgraphType( mode ); + pView->ResetView(); + + page->SetFlowGraph( pView ); + pNodeSheet->AddPage( page, GetDefaultTabName( pView ) ); + + if ( bActivate ) + pNodeSheet->SetActivePage( page ); + + UpdateTabColor( pView ); + + return pView; +} + +const char *CEditorRoot::GetDefaultTabName( CNodeView *pView ) +{ + Assert( pView ); + switch ( pView->GetFlowgraphType() ) + { + default: + case CNodeView::FLOWGRAPH_HLSL: + return "Unknown shader"; + case CNodeView::FLOWGRAPH_POSTPROC: + return "Unknown post processing effect"; + case CNodeView::FLOWGRAPH_HLSL_TEMPLATE: + return "Unknown template graph"; + } +} + +void CEditorRoot::UpdateTabColor( CNodeView *pView ) +{ + if ( !pView ) + pView = GetSafeFlowgraph(); + + CNodeView::FlowGraphType_t mode = pView->GetFlowgraphType(); + + Color col( 127, 127, 127, 255 ); + + switch ( mode ) + { + case CNodeView::FLOWGRAPH_HLSL: + col.SetColor( 100, 108, 102, 255 ); + break; + case CNodeView::FLOWGRAPH_POSTPROC: + col.SetColor( 108, 104, 100, 255 ); + break; + default: + Assert(0); + break; + } + + int pageIndex = -1; + for ( int i = 0; i < pNodeSheet->GetNumPages() && pageIndex < 0; i++ ) + if ( GetFlowGraph( i ) == pView ) + pageIndex = i; + + Assert( pageIndex >= 0 && pageIndex < pNodeSheet->GetNumPages() ); + pNodeSheet->SetTabColor( pageIndex, col ); +} + +void CEditorRoot::RefreshNodeInstances( int iNodeType, KeyValues *pParams ) +{ + const char *pszParam_Path = pParams->GetString( "filepath" ); + + for ( int i = 0; i < pNodeSheet->GetNumPages(); i++ ) + { + CNodeView *pView = GetFlowGraph( i ); + + for ( int n = 0; n < pView->GetNumNodes(); n++ ) + { + CBaseNode *pNode = pView->GetNode( n ); + + if ( pNode->GetNodeType() != iNodeType ) + continue; + + switch ( iNodeType ) + { + case HLSLNODE_UTILITY_CUSTOMCODE: + { + CNodeCustom *pCustomNode = (CNodeCustom*)pNode; + if ( pCustomNode->IsUsingInlineCode() || Q_stricmp( pCustomNode->GetFilePath(), pszParam_Path ) ) + break; + + pCustomNode->UpdateFromFile(); + } + break; + } + } + } + + pParams->deleteThis(); +} + +void CEditorRoot::CreatePreview() +{ + if ( !pPreview ) + { + pPreview = new CPreview( this, NULL ); //pNodeView ); + pPreview->MoveToCenterOfScreen(); + if ( psx > 0 && psy > 0 ) + { + ClipToScreenBounds( px, py, psx, psy ); + pPreview->SetBounds( px, py, psx, psy ); + } + else + pPreview->GetBounds(px,py,psx,psy); + + pPreview->RememberPosition(); + } + else + { + if ( !pPreview->IsVisible() ) + pPreview->Activate(); + else + pPreview->Close(); + return; + } + + //int mx, my; + //pPreview->GetMinimumSize( mx, my ); + //pPreview->SetSize( mx, my ); + pPreview->MakeReadyForUse(); + pPreview->InvalidateLayout( true, true ); +} +const char *CEditorRoot::GetEnvmapOverride() +{ + if ( !pPreview ) + return NULL; + + const char *pEnv = pPreview->GetEnvmap(); + if ( !pEnv || !*pEnv ) + return NULL; + + return pEnv; +} +void CEditorRoot::OnNewFile() +{ + //m_szShaderName[0] = '\0'; + CNodeView *pView = GetSafeFlowgraph(); + pView->SetShadername(NULL); + OnShaderNameChanged(); +} +void CEditorRoot::LoadLayout() +{ + KeyValues *pKV = new KeyValues( "config" ); + bool bPreview = false; + if ( pKV->LoadFromFile( filesystem, VarArgs( "%s/shadereditorui/editor_config.txt", engine->GetGameDirectory()), "MOD" ) ) + { + px = pKV->GetInt( "p_x" ); + py = pKV->GetInt( "p_y" ); + psx = pKV->GetInt( "p_sx" ); + psy = pKV->GetInt( "p_sy" ); + if ( pKV->GetInt( "preview_visible" ) ) + bPreview = true; + } + else + { + px=py=psx=psy=0; + } + + m_bDraw_Datatypes = !!pKV->GetInt( "draw_datatypes", 1 ); + m_bDraw_Shadows = !!pKV->GetInt( "draw_shadows", 1 ); + m_bDraw_AllLimits = !!pKV->GetInt( "draw_all_limits", 0 ); + m_bAutoCompile = !!pKV->GetInt( "compile_preview", 1 ); + m_bAutoFullcompile = !!pKV->GetInt( "compile_always_full", 0 ); + m_bAutoShaderPublish = !!pKV->GetInt( "compile_auto_publish_to_materials", 1 ); + m_bDoTooltips = !!pKV->GetInt( "enable_nodeview_tooltips", 1 ); + m_bAutoPrecacheUpdate = !!pKV->GetInt( "precache_auto_reload", 1 ); + m_bWarnOnClose = !!pKV->GetInt( "warn_unsaved_changes", 1 ); + + cedit_x = pKV->GetInt( "cedit_x", -1 ); + cedit_y = pKV->GetInt( "cedit_y", -1 ); + cedit_sx = pKV->GetInt( "cedit_sx", -1 ); + cedit_sy = pKV->GetInt( "cedit_sy", -1 ); + + pKV->deleteThis(); + + if ( bPreview ) + CreatePreview(); +} +void CEditorRoot::SaveLayout() +{ + KeyValues *pKV = new KeyValues( "config" ); + + pKV->SetInt( "preview_visible", (pPreview && pPreview->IsVisible()) ); + if ( pPreview ) + pPreview->GetBounds( px, py, psx, psy ); + + pKV->SetInt( "p_x", px ); + pKV->SetInt( "p_y", py ); + pKV->SetInt( "p_sx", psx ); + pKV->SetInt( "p_sy", psy ); + + pKV->SetInt( "draw_datatypes", m_bDraw_Datatypes ? 1 : 0 ); + pKV->SetInt( "draw_shadows", m_bDraw_Shadows ? 1 : 0 ); + pKV->SetInt( "draw_all_limits", m_bDraw_AllLimits ? 1 : 0 ); + pKV->SetInt( "compile_preview", m_bAutoCompile ? 1 : 0 ); + pKV->SetInt( "enable_nodeview_tooltips", m_bDoTooltips ? 1 : 0 ); + pKV->SetInt( "compile_always_full", m_bAutoFullcompile ? 1 : 0 ); + pKV->SetInt( "compile_auto_publish_to_materials", m_bAutoShaderPublish ? 1 : 0 ); + pKV->SetInt( "precache_auto_reload", m_bAutoPrecacheUpdate ? 1 : 0 ); + pKV->SetInt( "warn_unsaved_changes", m_bWarnOnClose ? 1 : 0 ); + + pKV->SetInt( "cedit_x", cedit_x ); + pKV->SetInt( "cedit_y", cedit_y ); + pKV->SetInt( "cedit_sx", cedit_sx ); + pKV->SetInt( "cedit_sy", cedit_sy ); + + pKV->SaveToFile( filesystem, VarArgs( "%s/shadereditorui/editor_config.txt", engine->GetGameDirectory()), "MOD" ); + pKV->deleteThis(); + + //DeallocPingPongRTs(); +} + +bool CEditorRoot::GetCodeEditorBounds( int &x, int &y, int &sx, int &sy ) +{ + x = y = sx = sy = 50; + + if ( cedit_x < 0 || cedit_y < 0 || cedit_sx < 0 || cedit_sy < 0 ) + return false; + + ClipToScreenBounds( cedit_x, cedit_y, cedit_sx, cedit_sy ); + + x = cedit_x; + y = cedit_y; + sx = cedit_sx; + sy = cedit_sy; + return true; +} + +void CEditorRoot::SetCodeEditorBounds( int x, int y, int sx, int sy ) +{ + cedit_x = x; + cedit_y = y; + cedit_sx = sx; + cedit_sy = sy; +} + +void CEditorRoot::OnCommand(const char* pcCommand) +{ + if( !Q_stricmp(pcCommand, "quit") ) + { + engine->ClientCmd( "quit" ); + return; + } + if( !Q_stricmp(pcCommand, "resetview") ) + { + CNodeView *pView = GetActiveFlowGraph(); + if ( pView ) + pView->ResetView_User(); + return; + } + if( !Q_stricmp(pcCommand, "options") ) + { + if ( !enginevgui->IsGameUIVisible() ) + { + vgui::VPANEL GameUIRoot = enginevgui->GetPanel( PANEL_GAMEUIDLL ); + ipanel()->SetVisible( GameUIRoot, true ); + } + engine->ClientCmd( "gamemenucommand OpenOptionsDialog" ); + return; + } + if( !Q_stricmp(pcCommand, "preview") ) + { + CreatePreview(); + return; + } + if( !Q_stricmp(pcCommand, "pv_closed") ) + { + if (pPreview) + pPreview->GetBounds( px, py, psx, psy ); + return; + } + BaseClass::OnCommand( pcCommand ); +} + +void CEditorRoot::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + SetPaintBackgroundEnabled(true); + SetPaintBorderEnabled(false); + SetPaintEnabled(true); + SetCloseButtonVisible(false); + SetSizeable(false); + SetMoveable(false); + + InitColors(); + + SetTitle( "", true ); + SetTitleBarVisible( false ); + m_pLabelTitle->SetText( GetEditorTitle() ); + m_pLabelTitle->SetFont( pScheme->GetFont( "UiBold", false ) ); + + SetPaintBackgroundType( 0 ); + OnShaderNameChanged(); + GenerateFonts(pScheme); +} +void CEditorRoot::PerformLayout() +{ + BaseClass::PerformLayout(); + + SetZPos(0); + int wide,tall; + surface()->GetScreenSize(wide, tall); + if ( m_bHalfView ) + wide /= 2; + SetPos(0,0); + SetSize(wide,tall); + + SetMouseInputEnabled(m_bHasInput); + SetKeyBoardInputEnabled(m_bHasInput); + + m_pLabelTitle->SetVisible( !m_bHalfView ); +} +void CEditorRoot::OnKeyCodeTyped(KeyCode code) +{ + BaseClass::OnKeyCodeTyped( code ); + + CNodeView *pView = GetActiveFlowGraph(); + if ( pView ) + pView->OnParentKeyCodeTyped( code ); +} +void CEditorRoot::OnKeyCodePressed ( vgui::KeyCode code ) +{ + BaseClass::OnKeyCodePressed( code ); + + CNodeView *pView = GetActiveFlowGraph(); + if ( pView ) + pView->OnParentKeyCodePressed( code ); +} +void CEditorRoot::OnKeyCodeReleased( vgui::KeyCode code ) +{ + BaseClass::OnKeyCodeReleased( code ); + + CNodeView *pView = GetActiveFlowGraph(); + if ( pView ) + pView->OnParentKeyCodeReleased( code ); +} + +void CEditorRoot::GenerateFonts(vgui::IScheme *pScheme) +{ + //if ( bFontsLoaded ) + // return; + + GetFontCacheHandle()->InvalidateFonts(); + GetFontCacheHandle()->AllocFonts(); + + for ( int i = 0; i < MAX_ZOOM_FONTS; i++ ) + { + if ( !bFontsLoaded ) + hFonts[i] = surface()->CreateFont(); + bool bSuccess = surface()->SetFontGlyphSet( hFonts[i], "Tahoma", 1 + i, 1, 0, 0, + +#ifndef SHADER_EDITOR_DLL_SWARM + ISurface::FONTFLAG_CUSTOM | + ISurface::FONTFLAG_DROPSHADOW | + ISurface::FONTFLAG_ANTIALIAS +#else + FONTFLAG_CUSTOM | + FONTFLAG_DROPSHADOW | + FONTFLAG_ANTIALIAS +#endif + + ); + if ( !bSuccess ) + hFonts[i] = 0; + /* + if ( !bFontsLoaded ) + hFonts2[i] = surface()->CreateFont(); + bSuccess = surface()->SetFontGlyphSet( hFonts2[i], "Tahoma", 1 + i, 1, 0, 0, ISurface::FONTFLAG_CUSTOM + //| ISurface::FONTFLAG_OUTLINE + //| ISurface::FONTFLAG_ANTIALIAS + //| ISurface::FONTFLAG_GAUSSIANBLUR + ); + if ( !bSuccess ) + hFonts2[i] = 0; + */ + } + _Font_Marlett = pScheme->GetFont( "Marlett", false ); + + bFontsLoaded = true; +} + +void CEditorRoot::ToggleFullScreen() +{ + if ( !pEditorRoot->IsVisible() ) + return; + + m_bHalfView = !m_bHalfView; + if ( !m_bHalfView ) + m_bHasInput = true; + + if ( pPreview ) + pPreview->RememberPosition(); + + InvalidateLayout( true ); + + if ( pPreview ) + pPreview->RestorePosition(); + + if ( pNodeSheet ) + { + pNodeSheet->InvalidateLayout(); + pNodeSheet->ScrollToActivePage(); + } +} +void CEditorRoot::ToggleVisible() +{ + SetVisible( !IsVisible() ); + + if ( IsVisible() ) + MoveToFront(); +} +void CEditorRoot::ToggleInput() +{ + if ( !pEditorRoot->IsVisible() ) + return; + + m_bHasInput = !m_bHasInput; + if ( !m_bHalfView ) + m_bHasInput = true; + + if ( pPreview ) + pPreview->RememberPosition(); + InvalidateLayout(); + if ( pPreview ) + pPreview->RestorePosition(); +} \ No newline at end of file diff --git a/sp/src/shadereditor/veditorroot.h b/sp/src/shadereditor/veditorroot.h new file mode 100644 index 00000000..4dc54b3e --- /dev/null +++ b/sp/src/shadereditor/veditorroot.h @@ -0,0 +1,247 @@ +#ifndef CEditorRoot_H +#define CEditorRoot_H + +#include "cbase.h" +using namespace vgui; + +#include +#include +#include +#include "editorCommon.h" +#include +#include "cSolverCallback.h" + +class CNodeView; +class CPreview; + +class CEditorRoot : public vgui::Frame, public CAutoSolverCallback +{ + DECLARE_CLASS_SIMPLE( CEditorRoot, vgui::Frame ); + + friend class CDialog_EditorConfig; + friend class CDialogRecompileAll; + friend class CShaderPrecache; + +public: + CEditorRoot( const char *pElementName ); + ~CEditorRoot(); + + virtual void OnThink(); + virtual bool ShouldDraw( void ); + void Init( void ); + void LevelInit( void ); + void LevelShutdown(); + void OnSceneRender(); + void OnPostRender(); + void SetVisible(bool state); + + void OnNewFile(); + + virtual bool IsOpaque(){ return true; }; + + virtual void OnKeyCodeTyped(KeyCode code); + virtual void OnKeyCodePressed ( vgui::KeyCode code ); + virtual void OnKeyCodeReleased( vgui::KeyCode code ); + + virtual void OnMousePressed(MouseCode code); + + virtual void OnMouseCaptureLost(); + + const HFont &GetFont1( int idx ){ + Assert(bFontsLoaded); + return hFonts[idx]; + }; + const HFont &GetFont2( int idx ){ + Assert(0); + static HFont NullHFont = 0; + return NullHFont; + //Assert(bFontsLoaded); + //return hFonts2[idx]; + }; + const HFont &GetMarlettFont(){ return _Font_Marlett; }; + + const bool ShouldDraw_Datatypes(); + const bool ShouldDraw_Shadows(); + const bool ShouldDraw_Nodes(); + const bool ShouldDraw_Jacks(); + const bool ShouldDraw_Bridges(); + const bool ShouldDraw_AllLimits(); + const bool ShouldAutoCompile(){ return m_bAutoCompile; }; + const bool ShouldAutoFullcompile(){ return m_bAutoFullcompile; }; + const bool ShouldAutoPublish(){ return m_bAutoShaderPublish; }; + const bool ShouldAutoUpdatePrecache(){ return m_bAutoPrecacheUpdate; }; + const bool ShouldShowTooltips(){ return m_bDoTooltips; }; + + void SendCopyNodes( KeyValues *pKV ); + KeyValues *GetCopyNodes(); + + void ToggleFullScreen(); + void ToggleVisible(); + void ToggleInput(); + + const bool HasInputEnabled(){ return m_bHasInput; }; + + void LoadLayout(); + void SaveLayout(); + + void SaveAllGraphs(); + CNodeView *GetMainFlowgraph(); + CNodeView *GetSafeFlowgraph(); + + const int GetNumFlowGraphs(); + CNodeView *GetFlowGraph( int i ); + CNodeView *GetActiveFlowGraph(); + CFlowGraphPage *GetActiveFlowgraphPage(); + + MESSAGE_FUNC_INT( OnMenuFile, "onmenufile", entry ); + MESSAGE_FUNC_INT( OnMenuShader, "onmenushader", entry ); + MESSAGE_FUNC_INT( OnMenuPostProcessing, "onmenupostprocessing", entry ); + + MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", pKV ); + MESSAGE_FUNC_PARAMS( OnMenuOpen, "MenuOpen", pKV ); + + MESSAGE_FUNC( PageChanged, "PageChanged" ); + MESSAGE_FUNC_PARAMS( OnAskPageClose, "AskPageClose", pKV ); + MESSAGE_FUNC_PARAMS( OnResponseGraphSave, "ResponseGraphSave", pKV ); + MESSAGE_FUNC_INT( PageClosed, "PageClosed", pagenum ); + MESSAGE_FUNC( RequestAddTab, "RequestAddTab" ); + + const char *GetCurrentShaderName(); //{ return m_szShaderName; }; + void SetCurrentShaderName( const char *n ); + const char *GetDefaultTabName( CNodeView *pView ); + + void OpenShaderFlowgraph( int mode, bool bSM20, bool bForceNewTab = false ); + void UpdateTabColor( CNodeView *pView = NULL ); + + //void CompileCallback( bool bError, HCURSTACKIDX idx ); + + void RefreshNodeInstances( int iNodeType, KeyValues *pParams ); + + KeyValues *GetNodeHelpContainer(); + +protected: + + virtual void Paint(); + void OnCommand(const char* pcCommand); + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void PerformLayout(); + + void GenerateFonts( vgui::IScheme *pScheme ); + +private: + CNodeView *AddNewTab( CNodeView::FlowGraphType_t mode = CNodeView::FLOWGRAPH_HLSL, bool bActivate = true ); + void ConfirmTabClose( vgui::VPANEL panel ); + + void InitColors(); + + + Label *m_pLabelTitle; + + void SortButtons(); + //bool m_bNeedsButtonPush; + void TakeScreenshot(); + + bool m_bHalfView; + bool m_bHasInput; + int Mx, My; + vgui::MenuBar *m_pMenuBar; + vgui::MenuButton *m_pMBut_File; + vgui::MenuButton *m_pMBut_Shader; + vgui::MenuButton *m_pMBut_PostProc; + DHANDLE< FileOpenDialog > m_hShaderBrowser; + + //HCURSTACKIDX m_iLastCompileIndex; + + KeyValues *m_pKV_NodeHelp; + + //CUtlVector< CFlowGraphPage* > m_hFlowGraphPages; + CFlowGraphSheet *pNodeSheet; + //CFlowGraphPage *pPageMain; + //CNodeView *pNodeView; + CPreview *pPreview; + //CUtlVector< CNodeView* >m_hNodeViews; + + void OpenFileDialog( bool bSave ); + void CreatePreview(); + + Label *m_pLabel_Coords; + Label *m_pLabel_FrameTime; + //Label *m_pLabel_CurrentFileName; + + bool bFontsLoaded; + HFont hFonts[MAX_ZOOM_FONTS]; + HFont hFonts2[MAX_ZOOM_FONTS]; + HFont _Font_Marlett; + //char m_szShaderName[MAX_PATH]; + void OnShaderNameChanged(); + + KeyValues *m_pKV_SelectionCopy; + int px, py, psx, psy; + int cedit_x, cedit_y, cedit_sx, cedit_sy; + + bool m_bDraw_Datatypes; + bool m_bDraw_Shadows; + bool m_bDraw_AllLimits; + bool m_bAutoCompile; + bool m_bAutoFullcompile; + bool m_bAutoShaderPublish; + bool m_bAutoPrecacheUpdate; + bool m_bDoTooltips; + bool m_bWarnOnClose; + +public: + + bool GetCodeEditorBounds( int &x, int &y, int &sx, int &sy ); + void SetCodeEditorBounds( int x, int y, int sx, int sy ); + + IMaterial *GetOperatorMaterial( int i ); + IMaterialVar *GetUVTargetParam( int i, int num ); + //IMaterialVar *GetOperatorParam( int i ); + + void AllocProceduralMaterials(); + void UpdateVariablePointer(); + void DeleteProceduralMaterials(); + + IMaterial *GetMainPreviewMat(); //{ Assert(m_pMat_MainPreview); return m_pMat_MainPreview; }; + IMaterial *GetBGPreviewMat(); //{ Assert(m_pMat_BGPreview); return m_pMat_BGPreview; }; + + KeyValues *GetMainPreviewKV(); //{ Assert(m_pKV_MainPreviewMat); return m_pKV_MainPreviewMat; }; + KeyValues *GetBGPreviewKV(); //{ Assert(m_pKV_BGPreviewMat); return m_pKV_BGPreviewMat; }; + + const char *GetEnvmapOverride(); + + void SendFullyCompiledShader( GenericShaderData* data ); + GenericShaderData *GetLastFullyCompiledShader(){ return m_pLastFullCompiledShader; }; + void InvokeShaderToScene( GenericShaderData *pShader = NULL ); + + void BeginPaintWorld(); + void EndPaintWorld( bool bValid = false ); + const bool IsPainting(){ return m_bPainting; }; + + const int &GetNumReloadMaterials(){ return m_iNumMaterials; }; + char **GetReloadMaterialList(){ return m_pszMaterialList; }; + +private: + + bool m_bPainting; + + int m_iNumMaterials; + char **m_pszMaterialList; + + KeyValues *m_pKV_NodePreview[NPSOP_CALC_LAST]; + IMaterial *m_pMat_NodePreview[NPSOP_CALC_LAST]; + + IMaterialVar *m_pMatVar_NodePv_UVs[NPSOP_CALC_LAST][6]; + + //KeyValues *m_pKV_MainPreviewMat; + //IMaterial *m_pMat_MainPreview; + //KeyValues *m_pKV_BGPreviewMat; + //IMaterial *m_pMat_BGPreview; + + ::GenericShaderData *m_pLastFullCompiledShader; +}; + + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vgui_init.cpp b/sp/src/shadereditor/vgui_init.cpp new file mode 100644 index 00000000..5f58b1f6 --- /dev/null +++ b/sp/src/shadereditor/vgui_init.cpp @@ -0,0 +1,160 @@ + +#include "cbase.h" +//#include "vgui_int.h" +#include "ienginevgui.h" +#include +#include +#include +#include "tier0/vprof.h" +#include +#include +#include "FileSystem.h" +#ifndef SHADER_EDITOR_DLL_2006 +#include "matsys_controls/matsyscontrols.h" +#endif +#include "vguimatsurface/IMatSystemSurface.h" +#include "vgui/isystem.h" +#include +#include +#include +#include "vgui_controls/animationcontroller.h" + +#include "vEditorRoot.h" +#include "editorCommon.h" + +using namespace vgui; + +#include +#include + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +vgui::IInputInternal *g_InputInternal = NULL; +CEditorRoot *pShaderEditor = NULL; + +bool VGui_Editor_Startup( CreateInterfaceFn appSystemFactory ) +{ + enginevgui = (IEngineVGui *)appSystemFactory( VENGINE_VGUI_VERSION, NULL ); + if ( !enginevgui ) + return false; + +#if 0 + g_pVGuiSurface = (vgui::ISurface*)appSystemFactory( VGUI_SURFACE_INTERFACE_VERSION, NULL ); + if ( !g_pVGuiSurface ) + return false; + g_pVGuiSurface->Connect( appSystemFactory ); + + g_pMatSystemSurface = (IMatSystemSurface *)appSystemFactory(MAT_SYSTEM_SURFACE_INTERFACE_VERSION, NULL); + if ( !g_pMatSystemSurface ) + return false; + g_pMatSystemSurface->Connect( appSystemFactory ); + + g_pVGuiInput = (IInput *)appSystemFactory(VGUI_INPUT_INTERFACE_VERSION, NULL); + if ( !g_pVGuiInput ) + return false; + + g_pVGui = (IVGui *)appSystemFactory(VGUI_IVGUI_INTERFACE_VERSION, NULL); + if ( !g_pVGui ) + return false; + g_pVGui->Connect( appSystemFactory ); + + g_pVGuiPanel = (IPanel *)appSystemFactory(VGUI_PANEL_INTERFACE_VERSION, NULL); + if ( !g_pVGuiPanel ) + return false; + +#ifndef SHADER_EDITOR_DLL_SWARM + g_pVGuiLocalize = ( vgui::ILocalize *)appSystemFactory(VGUI_LOCALIZE_INTERFACE_VERSION, NULL); + if ( !g_pVGuiLocalize ) + return false; +#endif + + g_pVGuiSchemeManager = (ISchemeManager *)appSystemFactory(VGUI_SCHEME_INTERFACE_VERSION, NULL); + if ( !g_pVGuiSchemeManager ) + return false; + + g_pVGuiSystem = (ISystem *)appSystemFactory(VGUI_SYSTEM_INTERFACE_VERSION, NULL); + if ( !g_pVGuiSystem ) + return false; + + //g_InputInternal = (IInputInternal *)appSystemFactory( VGUI_INPUTINTERNAL_INTERFACE_VERSION, NULL ); + //if ( !g_InputInternal ) + // return false; +#endif + + if ( !vgui::VGui_InitInterfacesList( "ShaderEditorUI", &appSystemFactory, 1 ) ) + return false; + + if ( g_pVGuiSurface == NULL || + g_pMatSystemSurface == NULL || + g_pVGuiInput == NULL || + g_pVGui == NULL || + g_pVGuiPanel == NULL || + g_pVGuiLocalize == NULL || + g_pVGuiSchemeManager == NULL || + g_pVGuiSystem == NULL ) + return false; + +#ifndef SHADER_EDITOR_DLL_2006 + if ( !vgui::VGui_InitMatSysInterfacesList( "ShaderEditorUI", &appSystemFactory, 1 ) ) + return false; +#endif + + return true; +} + +#define SEDITSCHEME_PATH "shadereditorui/ShaderEditorScheme.res" +#define SEDITSCHEME_TAG "ShaderEditorScheme" + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void VGui_Editor_CreateGlobalPanels( bool bEditingMode ) +{ + //char animFileName[MAX_PATH]; + //Q_snprintf( animFileName, MAX_PATH, "%s\\shadereditorui\\SEditUI.txt" ); + //::GetAnimationController()->SetScriptFile( pShaderEditor->GetVPanel(), animFileName ); + + if ( bEditingMode ) + { + HScheme seditScheme = g_pVGuiSchemeManager->LoadSchemeFromFile( SEDITSCHEME_PATH, SEDITSCHEME_TAG ); + + if ( !pShaderEditor ) + pShaderEditor = new CEditorRoot("editor"); + if ( pShaderEditor ) + { + pShaderEditor->SetScheme( seditScheme ); + pShaderEditor->MakeReadyForUse(); + pShaderEditor->InvalidateLayout( true, true ); + + Assert( pShaderEditor->GetSafeFlowgraph() ); + + pShaderEditor->GetSafeFlowgraph()->InitCanvas(); + pShaderEditor->GetSafeFlowgraph()->ResetView_User( true ); + + pShaderEditor->LoadLayout(); + + pShaderEditor->GetSafeFlowgraph()->FlushHistory(); + pShaderEditor->GetSafeFlowgraph()->UnDirtySave(); + } + } +} + +void VGui_Editor_Shutdown() +{ + if ( pShaderEditor ) + { + pShaderEditor->SaveLayout(); + pShaderEditor->SetParent( (Panel*)NULL ); + delete pShaderEditor; + pShaderEditor = NULL; + } + + DestroyDirectoryStrings(); + + vgui::ivgui()->RunFrame(); + + //g_pVGui->Disconnect(); + //g_pMatSystemSurface->Disconnect(); + //g_pVGuiSurface->Disconnect(); +} \ No newline at end of file diff --git a/sp/src/shadereditor/vgui_init.h b/sp/src/shadereditor/vgui_init.h new file mode 100644 index 00000000..25f89f7e --- /dev/null +++ b/sp/src/shadereditor/vgui_init.h @@ -0,0 +1,19 @@ +#ifndef VGUI_EDITOR_INIT +#define VGUI_EDITOR_INIT +#ifdef _WIN32 +#pragma once +#endif + +#include "interface.h" +#include + +namespace vgui +{ + class Panel; +} + +bool VGui_Editor_Startup( CreateInterfaceFn appSystemFactory ); +void VGui_Editor_Shutdown( void ); +void VGui_Editor_CreateGlobalPanels( bool bEditingMode ); + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vjack.cpp b/sp/src/shadereditor/vjack.cpp new file mode 100644 index 00000000..55083790 --- /dev/null +++ b/sp/src/shadereditor/vjack.cpp @@ -0,0 +1,521 @@ +#include "cbase.h" +#include +#include +#include "vgui/ISurface.h" +#include "ienginevgui.h" +#include +#include +#include + +#include "materialsystem/imesh.h" +#include "materialsystem/ITexture.h" +#include "materialsystem/IMaterial.h" +#include "materialsystem/IMaterialVar.h" +#include "materialsystem/imaterialsystem.h" + +#include + +#include "editorCommon.h" +#include "vJack.h" +#include "vBaseNode.h" + + + +CJack::CJack( CBaseNode *p, int slot, bool input ) +{ + pNode = p; + pNodeView = p->GetParent(); + + m_iJackType = 0; + m_iJackColorCode = HLSLJACK_COLOR_NORM; + + m_vecPosition.Init(); + m_vecSize.Init( JACK_SIZE_X, JACK_SIZE_Y ); + + bHasFocus = false; + m_bInput = input; + m_iSlot = slot; + + m_iSmartType = -1; + bLockSmartType = false; + + m_pVolatileVar = NULL; + m_iResourceType = RESOURCETYPE_VARIABLE; + szName[0] = '\0'; +} +CJack::~CJack() +{ + delete m_pVolatileVar; + + pNodeView->OnJackRemoved( this ); + PurgeBridges(); +} + +void CJack::ConnectBridge( CBridge *b ) +{ + m_hBridgeList.AddToTail( b ); + pNode->UpdatePreviewAllowed(); + + const bool bConnected = b->GetEndJack( this ) && b->GetEndNode( this ); + if ( !bConnected ) + return; + + UpdateSmartType( b ); + + pNode->OnUpdateHierachy( b, this ); + + CBaseNode *pOtherNode = b->GetEndNode( this ); + pOtherNode->OnUpdateHierachy( b, b->GetEndJack( this ) ); + pOtherNode->UpdatePreviewAllowed(); +} +void CJack::OnBridgeRemoved( CBridge *b ) +{ + CBaseNode *pOtherNode = b->GetEndNode( this ); + CJack *pOtherJack = b->GetEndJack( this ); + + m_hBridgeList.FindAndRemove( b ); + + if ( IsInput() ) + { + UpdateSmartType( NULL ); + pNode->OnUpdateHierachy( NULL, this ); + } + + if ( IsOutput() && pOtherNode && pOtherJack ) + pOtherNode->OnUpdateHierachy( NULL, pOtherJack ); + + pNode->UpdatePreviewAllowed(); + if ( pOtherNode ) + pOtherNode->UpdatePreviewAllowed(); +} + +void CJack::PurgeBridges() +{ + SaveDeleteVector( m_hBridgeList ); +} +void CJack::DisconnectBridges() +{ + PurgeBridges(); + //for ( int b = 0; b < m_hBridgeList.Count(); b++ ) + //{ + // CBridge *pB = m_hBridgeList[ b ]; + // if ( this == pB->GetDestinationJack() ) + // pB->DisconnectDestination(); + // else + // pB->DisconnectSource(); + //} +} +const int CJack::GetNumBridges() +{ + return m_hBridgeList.Count(); +} +int CJack::GetNumBridgesConnected() +{ + int b = 0; + for ( int i = 0; i < m_hBridgeList.Count(); i++ ) + { + if ( m_hBridgeList[i]->GetEndJack( this ) && m_hBridgeList[i]->GetEndNode( this ) ) + b++; + } + return b; +} +CBridge *CJack::BridgeBeginBuild() +{ + CBridge *b = new CBridge(pNodeView); + if ( !IsInput() ) + b->ConnectSource( this, GetParentNode() ); + else + b->ConnectDestination( this, GetParentNode() ); + return b; +} +void CJack::BridgeEndBuild( CBridge *pBridge ) +{ + if ( !IsInput() ) + pBridge->ConnectSource( this, GetParentNode() ); + else + pBridge->ConnectDestination( this, GetParentNode() ); + pNodeView->AddBridgeToList( pBridge ); + + CJack *pJSrc = pBridge->GetInputJack(); + if ( !pJSrc ) + return; + + if ( GetSmartType() == HLSLVAR_PP_MASTER ) + { + for ( int i = 0; i < pJSrc->GetNumBridges(); i++ ) + { + CBridge *pB = pJSrc->GetBridge( i ); + if ( pB == pBridge ) + continue; + + delete pB; + i--; + } + } +} + +void CJack::UpdateSmartType( CBridge *b ) +{ + if ( IsOutput() ) + return; + + if ( !b || !b->GetEndJack( this ) ) + return SetSmartType( -1 ); + + //SetSmartType( b->GetEndJack( this )->GetSmartType() ); +} +void CJack::SetSmartTypeLocked( const bool b ) +{ + bLockSmartType = b; +} + +//void CJack::SetSmartTypeFromFlag( const int flag ) +//{ +//} +void CJack::SetSmartType( const int t ) +{ + if ( IsSmartTypeLocked() ) + return; + + m_iSmartType = t; +} + +const ResourceType_t &CJack::GetResourceType() +{ + return m_iResourceType; +} +void CJack::SetResourceType( const int &type ) +{ + m_iResourceType = ((ResourceType_t)type); +} +CHLSL_Var *CJack::AllocateVarFromSmartType( bool bAssigntoSelf ) +{ +#if SHOW_SEDIT_ERRORS + AssertMsg( (GetSmartType() >= 0), "jack not ready!!\n" ); + Assert( IsOutput() ); +#endif + + CHLSL_Var *var = new CHLSL_Var( ((HLSLVariableTypes)GetSmartType()) ); + if ( bAssigntoSelf ) + SetTemporaryVarTarget( var ); + return var; +} +void CJack::SetTemporaryVarTarget( CHLSL_Var *var ) +{ + m_pVolatileVar = var; +} +CHLSL_Var *CJack::GetTemporaryVarTarget() +{ +//#if SHOW_SEDIT_ERRORS +// Assert(!!m_pVolatileVar); +//#endif + return m_pVolatileVar; +} +CHLSL_Var *CJack::GetTemporaryVarTarget_End() +{ +#if SHOW_SEDIT_ERRORS + Assert(!!GetNumBridges()); +#endif + return GetBridge(0)->GetEndJack(this)->GetTemporaryVarTarget(); +} +CHLSL_Var *CJack::GetTemporaryVarTarget_End_Smart( int varTypes, bool bAllowOverwrite ) +{ +#if SHOW_SEDIT_ERRORS + Assert(!!GetNumBridges()); + Assert(IsInput()); +#endif + for ( int i = 0; i < GetNumBridges(); i++ ) + { + CBridge *pBridge = GetBridge( i ); + CJack *pEndJack = pBridge->GetEndJack( this ); + if ( !pEndJack ) + continue; + + CHLSL_Var *potentialVar = pEndJack->GetTemporaryVarTarget(); + if ( !potentialVar ) + continue; + if ( !(potentialVar->GetType() & varTypes) ) + continue; + + int numPartnerBridges = pEndJack->GetNumBridges(); + if ( numPartnerBridges < 2 ) + return potentialVar; + + bool bTakeThis = true; + if ( !bAllowOverwrite ) + { + for ( int a = 0; a < numPartnerBridges; a++ ) + { + CBridge *pPartnerBridge = pEndJack->GetBridge( a ); + if ( pPartnerBridge->GetEndNode( pEndJack ) != GetParentNode() ) + bTakeThis = false; + } + } + if ( bTakeThis ) + return pEndJack->GetTemporaryVarTarget(); + } + return NULL; +} +void CJack::ClearTemporaryVarTarget() +{ + m_pVolatileVar = NULL; +} + +void CJack::ClearVarFlags() +{ + m_iJackType = 0; +} +void CJack::AddVarFlags( int f ) +{ + m_iJackType |= f; +} +void CJack::RemoveVarFlags( int f ) +{ + m_iJackType &= ~f; +} +bool CJack::HasVarFlag( int f ) +{ + return ( ( m_iJackType & f ) != 0 ); +} +void CJack::SetName( const char *name ) +{ + if ( Q_strlen( name ) < 1 ) + return; + Q_snprintf( szName, sizeof(szName), "%s", name ); + pNode->UpdateSize(); +} + +Vector2D CJack::GetBoundsMin() +{ + return m_vecPosition; +} +Vector2D CJack::GetBoundsMax() +{ + return m_vecPosition + m_vecSize; +} +Vector2D CJack::GetCenter() +{ + return GetBoundsMin() + ( GetBoundsMax() - GetBoundsMin() ) * 0.5f; +} +Vector2D CJack::GetBoundsMinPanelSpace() +{ + Vector2D _min( GetBoundsMin().x, GetBoundsMax().y ); + pNodeView->ToPanelSpace( _min ); + return _min; +} +Vector2D CJack::GetBoundsMaxPanelSpace() +{ + Vector2D _max( GetBoundsMax().x, GetBoundsMin().y ); + pNodeView->ToPanelSpace( _max ); + return _max; +} +Vector2D CJack::GetCenterPanelSpace() +{ + Vector2D pos = GetCenter(); + pNodeView->ToPanelSpace( pos ); + return pos; +} +bool CJack::IsWithinBounds_Base( Vector2D pos ) +{ + Vector2D _min, _max; + _min = GetBoundsMin(); + _max = GetBoundsMax(); + + if ( pos.x >= _min.x && pos.y >= _min.y && + pos.x <= _max.x && pos.y <= _max.y ) + return true; + return false; +} + +void CJack::SetPosition( Vector2D vec, bool bCenter ) +{ + if ( bCenter ) + { + Vector2D delta = GetBoundsMin() + ( GetBoundsMax() - GetBoundsMin() ) * 0.5f; + vec -= delta; + } + m_vecPosition = vec; +} +void CJack::UpdatePosition() +{ + Vector2D parentBoxStart = pNode->GetBoundsBoxMin(); + Vector2D parentBoxEnd = pNode->GetBoundsBoxMax(); + const bool bContainer = !!pNode->GetAsContainer(); + + float x = m_bInput ? parentBoxStart.x : (parentBoxEnd.x + (bContainer?CBORDER_SIZE:0)); + x += (m_bInput ? -JACK_SIZE_X : 0); + float y = parentBoxStart.y - ( JACK_SIZE_Y + JACK_DELTA_Y ) * (m_iSlot) - JACK_SIZE_Y * 2; + + SetPosition( Vector2D( x, y ) ); +} +void CJack::UpdatePositionData() +{ + UpdatePosition(); +} +Vector2D CJack::GetPosition() +{ + return m_vecPosition; +} +void CJack::OnParentMoved() +{ + UpdatePosition(); +} + +void CJack::VguiDraw( bool bShadow ) +{ + if ( !pNodeView->ShouldDraw_Jacks() ) + return; + + Vector2D panelMin = GetBoundsMinPanelSpace(); + Vector2D panelMax = GetBoundsMaxPanelSpace(); + + float flZoom = pNodeView->GetZoomScalar(); + if ( bShadow ) + { + float flO = NODE_DRAW_SHADOW_DELTA * flZoom; + Vector2D offset( flO, flO ); + panelMin += offset; + panelMax += offset; + } + + Color colText = JACK_COLOR_DATATYPE; + + switch ( m_iJackColorCode ) + { + case HLSLJACK_COLOR_NORM: + surface()->DrawSetColor( JACK_COLOR_NORM ); + break; + case HLSLJACK_COLOR_RGB: + case HLSLJACK_COLOR_R: + surface()->DrawSetColor( JACK_COLOR_R ); + break; + case HLSLJACK_COLOR_G: + surface()->DrawSetColor( JACK_COLOR_G ); + break; + case HLSLJACK_COLOR_B: + surface()->DrawSetColor( JACK_COLOR_B ); + break; + case HLSLJACK_COLOR_A: + surface()->DrawSetColor( JACK_COLOR_A ); + break; + case HLSLJACK_COLOR_PPMASTER: + surface()->DrawSetColor( JACK_COLOR_PPMASTER ); + colText = JACK_COLOR_DATATYPE_DARK; + break; + } + + if ( HasFocus() ) + surface()->DrawSetColor( JACK_COLOR_FOCUS ); + + if ( bShadow ) + surface()->DrawSetColor( NODE_DRAW_COLOR_SHADOW ); + else + VguiDrawName(); + + if ( m_iJackColorCode != HLSLJACK_COLOR_RGB || bShadow || HasFocus() ) + { + surface()->DrawFilledRect( panelMin.x, panelMin.y, panelMax.x, panelMax.y ); + } + else + { + float deltax = panelMax.x - panelMin.x; + deltax /= 3; + + surface()->DrawSetColor( JACK_COLOR_R ); + surface()->DrawFilledRect( panelMin.x, panelMin.y, panelMin.x + deltax, panelMax.y ); + surface()->DrawSetColor( JACK_COLOR_G ); + surface()->DrawFilledRect( panelMin.x + deltax, panelMin.y, panelMin.x + deltax * 2, panelMax.y ); + surface()->DrawSetColor( JACK_COLOR_B ); + surface()->DrawFilledRect( panelMin.x + deltax * 2, panelMin.y, panelMin.x + deltax * 3, panelMax.y ); + } + + if ( pNodeView->ShouldDraw_Datatypes() ) + { + wchar_t szconverted[ 1024 ]; + int fontWide, fontTall; + + if ( !bShadow ) + { + bool bDraw; + vgui::HFont hFont_Small = pNodeView->GetFontScaled(3,bDraw); + if ( bDraw ) + { + int smartType = GetSmartType(); + if ( smartType >= 0 ) + { + smartType = GetVarFlagsVarValue( smartType ); + g_pVGuiLocalize->ConvertANSIToUnicode( GetVarTypeName( smartType ), szconverted, sizeof(szconverted) ); + surface()->DrawSetTextColor( colText ); + } + else + { + g_pVGuiLocalize->ConvertANSIToUnicode( "NONE", szconverted, sizeof(szconverted) ); + surface()->DrawSetTextColor( JACK_COLOR_DATATYPE_UNDEFINED ); + } + + surface()->DrawSetTextFont( hFont_Small ); + surface()->GetTextSize( hFont_Small, szconverted, fontWide, fontTall ); + + Vector2D mid = panelMin + ( panelMax - panelMin ) * 0.5f; + surface()->DrawSetTextPos( mid.x - fontWide * 0.5f, mid.y - fontTall * 0.5f ); + + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } + } + } +} +void CJack::VguiDrawName() +{ + if ( Q_strlen(szName) < 1 ) + return; + + Vector2D _min = GetBoundsMinPanelSpace(); + Vector2D _max = GetBoundsMaxPanelSpace(); + + Vector2D drawpos( _min + ( _max - _min ) * 0.5f ); + + bool bDraw; + HFont font = pNodeView->GetFontScaled( 9, bDraw ); + if ( !bDraw ) + return; + + wchar_t szconverted[ 1024 ]; + g_pVGuiLocalize->ConvertANSIToUnicode( szName, szconverted, sizeof(szconverted) ); + + int fontWide, fontTall; + surface()->DrawSetTextFont( font ); + surface()->GetTextSize( font, szconverted, fontWide, fontTall ); + + Vector2D edge = m_bInput ? GetBoundsMax() : GetBoundsMin(); + edge.x = edge.x + ( m_bInput ? JACK_TEXT_INSET : -JACK_TEXT_INSET ); + pNodeView->ToPanelSpace( edge ); + if ( !m_bInput ) + edge.x -= fontWide; + + surface()->DrawSetTextPos( edge.x, drawpos.y - fontTall * 0.5f ); + + surface()->DrawSetTextColor( HasFocus() ? JACK_COLOR_NAME_FOCUS : JACK_COLOR_NAME ); + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); +} +int CJack::GetFinalTextInset() +{ + int i = 0; + if ( Q_strlen(szName) >= 1 ) + { + float z = 1.15f; + bool bDraw; + HFont font = pNodeView->GetFontScaled( 9, bDraw, &z ); + Assert( bDraw ); + + wchar_t szconverted[ 1024 ]; + Q_memset( szconverted, 0, sizeof( szconverted ) ); + g_pVGuiLocalize->ConvertANSIToUnicode( szName, szconverted, sizeof(szconverted) ); + + int fontWide, fontTall; + surface()->DrawSetTextFont( font ); + surface()->GetTextSize( font, szconverted, fontWide, fontTall ); + + i = fontWide + JACK_TEXT_INSET + 3; + } + return i; +} diff --git a/sp/src/shadereditor/vjack.h b/sp/src/shadereditor/vjack.h new file mode 100644 index 00000000..7e291691 --- /dev/null +++ b/sp/src/shadereditor/vjack.h @@ -0,0 +1,122 @@ +#ifndef CJACK_H +#define CJACK_H + +#include +#include +#include +#include +#include "ienginevgui.h" +#include "vgui_controls/Controls.h" + +class CBridge; +class CBaseNode; +class CNodeView; +class CHLSL_Var; + +#define JACK_SIZE_Y 6 +#define JACK_SIZE_X 8 +#define JACK_DELTA_Y 5 + +class CJack +{ +public: + CJack( CBaseNode *p, int slot, bool input ); + ~CJack(); + + virtual void SetName( const char *name ); + const char *GetName(){ return szName; }; + CBaseNode *GetParentNode(){ return pNode; }; + + const ResourceType_t &GetResourceType(); + void SetResourceType( const int &type ); + CHLSL_Var *AllocateVarFromSmartType( bool bAssigntoSelf = true ); + + void ConnectBridge( CBridge *b ); + void OnBridgeRemoved( CBridge *b ); + void PurgeBridges(); + + virtual void ClearVarFlags(); + virtual void AddVarFlags( int f ); + virtual void RemoveVarFlags( int f ); + virtual bool HasVarFlag( int f ); + + virtual int GetSmartType(){ return m_iSmartType; }; + virtual void SetSmartType( const int t ); + //virtual void SetSmartTypeFromFlag( const int flag ); + virtual void SetSmartTypeLocked( const bool b ); + virtual const bool IsSmartTypeLocked(){ return bLockSmartType; }; + virtual void UpdateSmartType( CBridge *b ); + + virtual void SetJackType( const int t ){ m_iJackType = t; }; + virtual const int GetJackType(){ return m_iJackType; }; + virtual void SetJackColorCode( int t ){ m_iJackColorCode = t; }; + virtual const int GetJackColorCode(){ return m_iJackColorCode; }; + + virtual void VguiDraw( bool bShadow = false ); + virtual void VguiDrawName(); + + virtual Vector2D GetBoundsMin(); + virtual Vector2D GetBoundsMax(); + virtual Vector2D GetCenter(); + virtual Vector2D GetBoundsMinPanelSpace(); + virtual Vector2D GetBoundsMaxPanelSpace(); + virtual Vector2D GetCenterPanelSpace(); + virtual bool IsWithinBounds_Base( Vector2D pos ); + + virtual void UpdatePositionData(); + virtual void UpdatePosition(); + virtual void SetPosition( Vector2D vec, bool bCenter = false ); + virtual Vector2D GetPosition(); + + virtual const bool IsInput(){ return m_bInput; }; + virtual const bool IsOutput(){ return !m_bInput; }; + virtual const int GetSlot(){ return m_iSlot; }; + + virtual void OnParentMoved(); + + virtual const bool HasFocus(){ return bHasFocus; }; + virtual void SetFocus( const bool b ){ bHasFocus = b; }; + + virtual int GetFinalTextInset(); + + const int GetNumBridges(); + int GetNumBridgesConnected(); + CBridge *GetBridge( const int idx ){ return m_hBridgeList[idx]; }; + CBridge *BridgeBeginBuild(); + void BridgeEndBuild( CBridge *pBridge ); + void DisconnectBridges(); + + void SetTemporaryVarTarget( CHLSL_Var *var ); + CHLSL_Var *GetTemporaryVarTarget(); + //// for inputs! + CHLSL_Var *GetTemporaryVarTarget_End(); + CHLSL_Var *GetTemporaryVarTarget_End_Smart( int varTypes, bool bAllowOverwrite = false ); + //// + void ClearTemporaryVarTarget(); + +protected: + char szName[MAX_PATH]; + + int m_iJackType; + int m_iJackColorCode; + int m_iSmartType; + bool bLockSmartType; + + Vector2D m_vecPosition; + Vector2D m_vecSize; + + CBaseNode *pNode; + CNodeView *pNodeView; + CUtlVector< CBridge* >m_hBridgeList; + CHLSL_Var *m_pVolatileVar; + + bool bHasFocus; + + bool m_bInput; + int m_iSlot; + ResourceType_t m_iResourceType; +}; + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vnodeview.cpp b/sp/src/shadereditor/vnodeview.cpp new file mode 100644 index 00000000..97d5099f --- /dev/null +++ b/sp/src/shadereditor/vnodeview.cpp @@ -0,0 +1,4421 @@ +#include "cbase.h" +#include +#include +#include "vgui/ISurface.h" +#include "ienginevgui.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "materialsystem/imesh.h" +#include "materialsystem/ITexture.h" +#include "materialsystem/IMaterial.h" +#include "materialsystem/IMaterialVar.h" +#include "materialsystem/imaterialsystem.h" + +#include "collisionutils.h" +#include "vgui_controls/animationcontroller.h" + +#include "editorCommon.h" +#include "vNodeView.h" +#include "vSmartObject.h" +#include "vSmartTooltip.h" +#include "vSheets.h" + +//#include "memtrack.h" + +bool CNodeView::bRenderingScreenShot = false; +Vector4D CNodeView::vecScreenshotBounds = Vector4D( 0,0,0,0 ); + +#define VIEWSPEED_PAN editor_movespeed.GetFloat() +#define VIEWSPEED_ZOOM editor_movespeed.GetFloat() + +#define BRIDGE_DRAG_TOLERANCE 10 + +#define VIEWZOOM_SPEED editor_zoomspeed.GetFloat() + +#define GRID_CELL_SIZE 100.0f + +CNodeView::CNodeView( Panel *parent, CEditorRoot *root, /*FlowGraphType_t type,*/ const char *pElementName ) : BaseClass( parent, pElementName ) +{ + m_FlowGraphType = FLOWGRAPH_HLSL; + InitColors(); + + m_bPreviewMode = root != NULL && parent != NULL; + //vgui::HScheme scheme = vgui::scheme()->LoadSchemeFromFile("resource/SourceScheme.res", "SourceScheme"); + //SetScheme( scheme ); + pEditorRoot = root; + //LoadControlSettings("resource/shadereditor_root.res"); + SetProportional(false); + + m_flZoom = 8; + m_flZoomGoal = 8; + m_vecPosition.Init(); + m_vecPositionGoal.Init(); + + m_bHistoryDirty = false; + m_lTime_MouseLastMoved = 0.0f; + m_flErrorTime = 0; + + SetupVguiTex( m_iTex_Darken, "shadereditor/darken" ); + + pJackLast = NULL; + m_pCurBridge = NULL; + m_pLastPreviewData = NULL; + m_pTooltip = NULL; + m_iLastPreviewFlags = 0; + + m_bDirtySolvers = false; + //ClearCurrentSolverResource(); + + m_ShaderData = NULL; + m_PPEData = NULL; + //if ( m_FlowGraphType == FLOWGRAPH_HLSL ) + // m_ShaderData = new GenericShaderData(); + + m_StackIndex = 0; + m_StackIndex_LastCompiled = 0; + m_HistoryIndex = 0; + m_HistoryIndex_LastSaved = 0; + m_bLastCompileSuccessFull = false; + + pKV_Mat_PsIn = NULL; + m_pMat_PsIn = NULL; + m_pPreview_Material = NULL; + m_pPreview_KV = NULL; + m_pPrevBackground_Material = NULL; + m_pPrevBackground_KV = NULL; + + m_szEnvmap[0] = '\0'; + //m_pTexCubemap = NULL; + m_szShaderName[0] = '\0'; + m_bRenderBackground = false; + + CAutoSolverCallback::Startup(); + AddSolverClient( this ); + + m_iCursorLast = dc_user; + + UpdatePsinMaterial(NULL); + InitPreviewMaterials(); + + SetupVguiTex( m_iTex_BusyIco, "shadereditor/busy" ); + + Init(); +} +CNodeView::~CNodeView() +{ + FlushHistory(); + + RemoveSolverClient( this ); + CAutoSolverCallback::Shutdown(); + //ClearCurrentSolverResource(); + PurgeCanvas( true ); + PurgeSolverClients(); + + ClearShaderData(); + delete m_pLastPreviewData; + ClearPPEData(); + + if (m_pMat_PsIn) + { + pKV_Mat_PsIn->Clear(); + //m_pMat_PsIn->Release(); + //m_pMat_PsIn->DeleteIfUnreferenced(); + //pKV_Mat_PsIn = NULL; + ForceDeleteMaterial( &m_pMat_PsIn ); + } + + DestroyPreviewMaterials(); + + KillDragBridge(); + //if ( pKV_Mat_PsIn ) + //{ + // delete ((void*)pKV_Mat_PsIn); + // pKV_Mat_PsIn = NULL; + //} + + DestroyTooltip(); +} + +CNodeView::FlowGraphType_t CNodeView::GetFlowgraphType() +{ + return m_FlowGraphType; +} +void CNodeView::SetFlowgraphType( FlowGraphType_t type, bool bValidateGraphData ) +{ + if ( bValidateGraphData ) + { + if ( type == FLOWGRAPH_HLSL ) + GenerateShaderData(); + else + ClearShaderData(); + + if ( type == FLOWGRAPH_POSTPROC ) + GeneratePPEData(); + else + ClearPPEData(); + } + + m_FlowGraphType = type; +} + +void CNodeView::ClearShaderData() +{ + delete m_ShaderData; + m_ShaderData = NULL; +} +GenericShaderData &CNodeView::GetDataForModify() +{ + Assert( m_ShaderData && GetFlowgraphType() == FLOWGRAPH_HLSL ); + return *m_ShaderData; +} +void CNodeView::GenerateShaderData() +{ + if ( !m_ShaderData ) + m_ShaderData = new GenericShaderData(); +} + +void CNodeView::ClearPPEData() +{ + delete m_PPEData; + m_PPEData = NULL; +} +void CNodeView::GeneratePPEData() +{ + if ( !m_PPEData ) + m_PPEData = new GenericPPEData(); +} + + +void CNodeView::InitPreviewMaterials() +{ + if ( !m_pPreview_Material ) + { + Assert( !m_pPreview_KV ); + + m_pPreview_KV = new KeyValues( "EDITOR_SHADER" ); + m_pPreview_Material = materials->CreateMaterial( "__main_preview", m_pPreview_KV ); + Assert( m_pPreview_Material ); + + m_pPreview_Material->Refresh(); + } + + if ( !m_pPrevBackground_Material ) + { + Assert( !m_pPrevBackground_KV ); + + m_pPrevBackground_KV = new KeyValues( "BACKGROUND_PREV" ); + m_pPrevBackground_Material = materials->CreateMaterial( "__bg_preview", m_pPrevBackground_KV ); + Assert( m_pPrevBackground_Material ); + + m_pPrevBackground_Material->Refresh(); + } +} + +void CNodeView::DestroyPreviewMaterials() +{ + if ( m_pPreview_Material ) + { + m_pPreview_KV->Clear(); + ForceDeleteMaterial( &m_pPreview_Material ); + m_pPreview_KV = NULL; + } + + if ( m_pPrevBackground_Material ) + { + m_pPrevBackground_KV->Clear(); + ForceDeleteMaterial( &m_pPrevBackground_Material ); + m_pPrevBackground_KV = NULL; + } +} + +void CNodeView::SetEnvmap( const char *pszPath ) +{ + //m_pTexCubemap = NULL; + if ( pszPath ) + { + Q_snprintf( m_szEnvmap, sizeof(m_szEnvmap), "%s", pszPath ); + //m_pTexCubemap = materials->FindTexture( m_szEnvmap, TEXTURE_GROUP_CUBE_MAP, false ); + + //if ( IsErrorTexture( m_pTexCubemap ) ) + // m_pTexCubemap = NULL; + } + else + m_szEnvmap[0] = '\0'; +} + +const char *CNodeView::GetEnvmap() +{ + if ( Q_strlen(m_szEnvmap) ) + return m_szEnvmap; + return NULL; +} + +//ITexture *CNodeView::GetEnvmapTexture() +//{ +// return m_pTexCubemap; +//} + +void CNodeView::SetShadername( const char *pszPath ) +{ + if ( pszPath ) + Q_snprintf( m_szShaderName, sizeof(m_szShaderName), "%s", pszPath ); + else + m_szShaderName[0] = '\0'; +} + +const char *CNodeView::GetShadername() +{ + if ( Q_strlen(m_szShaderName) ) + return m_szShaderName; + return NULL; +} + +void CNodeView::SetUsingBackgroundMaterial( bool bUse ) +{ + m_bRenderBackground = bUse; +} + +const bool CNodeView::IsUsingBackgroundMaterial() +{ + return m_bRenderBackground; +} + +IMaterial *CNodeView::GetPreviewMeshMaterial() +{ + return m_pPreview_Material; +} + +IMaterial *CNodeView::GetPreviewBackgroundMaterial() +{ + return m_pPrevBackground_Material; +} + +KeyValues *CNodeView::GetKVMeshMaterial() +{ + return m_pPreview_KV; +} + +KeyValues *CNodeView::GetKVBackgroundMaterial() +{ + return m_pPrevBackground_KV; +} + +GenericShaderData *CNodeView::GetPreviewData() +{ + return m_pLastPreviewData; +} + +void CNodeView::PurgeSolverClients() +{ + m_hSolverClients.Purge(); +} +void CNodeView::AddSolverClient( ISolverRequester *client ) +{ + if ( m_hSolverClients.IsValidIndex( m_hSolverClients.Find( client ) ) ) + return; + m_hSolverClients.AddToTail( client ); + MakeSolversDirty(); +} +void CNodeView::RemoveSolverClient( ISolverRequester *client ) +{ + m_hSolverClients.FindAndRemove( client ); +} +void CNodeView::PrepShaderData() +{ + Assert( m_ShaderData ); + + CNodeVSInput *pVS_IN = (CNodeVSInput*)GetNodeFromType( HLSLNODE_VS_IN ); + CNodeVSOutput *pVS_OUT = (CNodeVSOutput*)GetNodeFromType( HLSLNODE_VS_OUT ); + CNodePSOutput *pPS_OUT = (CNodePSOutput*)GetNodeFromType( HLSLNODE_PS_OUT ); + + const bool bIsPreview = m_ShaderData->shader->bPreviewMode; //IsPreviewModeEnabled(); + + //m_ShaderData->shader->bPreviewMode = bIsPreview; + if ( pVS_IN ) + m_ShaderData->VS_IN = pVS_IN->GetSetup(); + if ( pVS_OUT ) + m_ShaderData->VS_to_PS = pVS_OUT->GetSetup(); + if ( pPS_OUT ) + m_ShaderData->PS_OUT = pPS_OUT->GetSetup(); + + if ( bIsPreview ) + DoEnvmapOverride(); + + const char *shaderName = GetShadername(); //pEditorRoot->GetCurrentShaderName(); + char *tmpName = new char[ MAX_PATH ]; + + if ( shaderName ) + { + Q_FileBase( shaderName, tmpName, MAX_PATH + 1 ); + + Assert( m_ShaderData->shader->Filename == NULL ); + char tmp[MAX_PATH*4]; + if ( g_pFullFileSystem->FullPathToRelativePath( shaderName, tmp, sizeof( tmp ) ) ) + { + int len = Q_strlen( tmp ) + 1; + m_ShaderData->shader->Filename = new char[len]; + Q_strcpy( m_ShaderData->shader->Filename, tmp ); + } + else + AutoCopyStringPtr( shaderName, &m_ShaderData->shader->Filename ); + } + + if ( !shaderName || Q_strlen( tmpName ) < 1 ) + Q_snprintf( tmpName, MAX_PATH, "UNNAMEDSHADER" ); + + m_ShaderData->name = tmpName; + m_ShaderData->iStackIdx = GetStackIndex(); +} +void CNodeView::CleanupShaderData() +{ + Assert( m_ShaderData ); + + delete [] m_ShaderData->name; + m_ShaderData->name = NULL; + + delete [] m_ShaderData->shader->Filename; + m_ShaderData->shader->Filename = NULL; +} +void CNodeView::CleanupNodes() +{ + CUtlVector< CHLSL_Var* >hVarGarbage; + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *pN = m_hNodeList[ i ]; + + for ( int j = 0; j < pN->GetNumJacks_Out(); j++ ) + { + CJack *pJ = pN->GetJack_Out( j ); + CHLSL_Var *var = pJ->GetTemporaryVarTarget(); + + if ( !var ) + continue; + + if ( !hVarGarbage.HasElement( var ) ) + hVarGarbage.AddToTail( var ); + } + for ( int j = 0; j < pN->GetNumJacks_In(); j++ ) + { + CJack *pJ = pN->GetJack_In( j ); + CHLSL_Var *var = pJ->GetTemporaryVarTarget(); + + if ( !var ) + continue; + + if ( !hVarGarbage.HasElement( var ) ) + hVarGarbage.AddToTail( var ); + } + } + + hVarGarbage.PurgeAndDeleteElements(); + + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[ i ]; + //n->RemoveSolvers(); + n->SweepJackHlslCache(); + } +} + +void CNodeView::SetPreviewMode( bool bEnabled ) +{ + m_bPreviewMode = bEnabled; +} + +bool CNodeView::IsPreviewModeEnabled() +{ + return m_bPreviewMode; +} + +void CNodeView::UpdateSolverClients() +{ + Assert( m_ShaderData ); + + CNodeVSOutput *pVS_OUT = (CNodeVSOutput*)GetNodeFromType( HLSLNODE_VS_OUT ); + CNodePSOutput *pPS_OUT = (CNodePSOutput*)GetNodeFromType( HLSLNODE_PS_OUT ); + const bool bVertexShaderReady = pVS_OUT && pVS_OUT->GetErrorLevel() == ERRORLEVEL_NONE; + const bool bPixelShaderReady = pPS_OUT && pPS_OUT->GetErrorLevel() == ERRORLEVEL_NONE; + + PrepShaderData(); + +#if DEBUG + for ( int i = 0; i < hErrorList.Count(); i++ ) + AllocCheck_FreeS("LimitReport_t"); +#endif + hErrorList.PurgeAndDeleteElements(); + + if ( + !ReportErrors( m_ShaderData, hErrorList ) && + ( !m_ShaderData->IsPreview() || pEditorRoot->ShouldAutoCompile() ) + ) + { + for ( int i = 0; i < m_hSolverClients.Count(); i++ ) + { + ISolverRequester *c = m_hSolverClients[ i ]; + c->OnSolverUpdated( this, m_ShaderData, bVertexShaderReady, bPixelShaderReady ); + } + } + + CleanupShaderData(); +} +void CNodeView::UpdatePPECache() +{ + if ( m_hSolverStack_PostProcessing.Count() < 1 ) + return; + + const char *pszShaderName = GetShadername(); + if ( !pszShaderName ) + return; + + char tmp[MAX_PATH*4]; + Q_FileBase( pszShaderName, tmp, sizeof(tmp) ); + + int index = GetPPCache()->FindPostProcessingEffect( tmp ); + + if ( index < 0 ) + return; + + EditorPostProcessingEffect *fx = GetPPCache()->GetPostProcessingEffect( index ); + Assert( fx ); + fx->ReplacePostProcessingChain( m_hSolverStack_PostProcessing ); + fx->bIsEnabled = true; + + DestroySolverStack( m_hSolverStack_PostProcessing ); +} +void CNodeView::OnSolvingFinsihed() +{ + if ( ShouldCallCompiler() ) + { + UpdateSolverClients(); + + if ( IsPreviewModeEnabled() && pEditorRoot->ShouldAutoFullcompile() ) + { + SetPreviewMode( false ); + UpdateSolverClients(); + SetPreviewMode( true ); + } + } + else if ( GetFlowgraphType() == FLOWGRAPH_POSTPROC ) + UpdatePPECache(); +} +void CNodeView::OnCompilationEnd( int flags, int exitcode, GenericShaderData *data ) +{ + //Assert( GetFlowgraphType() == FLOWGRAPH_HLSL ); + + const bool bError = exitcode != 0; + m_StackIndex_LastCompiled = data->iStackIdx; + m_bLastCompileSuccessFull = !bError; + + //if ( pEditorRoot != NULL ) + //{ + // pEditorRoot->CompileCallback( bError, data->iStackIdx ); + //} + + //if ( !data->bPreview && !bError ) + // df_SaveDump_File( data->name, *data->shader ); + + //CopyShaders( flags, data ); + + if ( bError ) + { + m_flErrorTime = 1; + return; + } + + if ( data->IsPreview() ) + { + CAutoSolverCallback::CopyShaders( flags, data ); + + delete m_pLastPreviewData; + m_pLastPreviewData = NULL; + + //if ( !bError ) + { + m_iLastPreviewFlags = flags; + m_pLastPreviewData = new GenericShaderData( *data ); + } + //else + // m_iLastPreviewFlags = 0; + + UploadPreviewData(); + } + else + { + //if ( flags & ACTIVEFLAG_VS && flags & ACTIVEFLAG_PS ) + // pEditorRoot->SendFullyCompiledShader( data ); + } + + //delete data; +} + +void CNodeView::UploadPreviewData() +{ + if ( pEditorRoot->GetSafeFlowgraph() != this ) + return; + + if ( !m_iLastPreviewFlags || !m_pLastPreviewData ) + { + Update3DPrevMaterial( NULL ); + Update3DPrevMaterial( NULL, 1 ); + return; + } + + if ( m_iLastPreviewFlags & ACTIVEFLAG_VS_POS ) + { + char _vs_pos[MAX_PATH]; + ComposeShaderName_Compiled( m_pLastPreviewData, false, false, _vs_pos, MAX_PATH, true ); + UpdatePsinMaterial( _vs_pos, m_pLastPreviewData ); + } + else + UpdatePsinMaterial( NULL ); + + if ( m_iLastPreviewFlags & ACTIVEFLAG_VS && m_iLastPreviewFlags & ACTIVEFLAG_PS ) + Update3DPrevMaterial( m_pLastPreviewData ); + if ( m_iLastPreviewFlags & ACTIVEFLAG_VS ) + Update3DPrevMaterial( m_pLastPreviewData, 1 ); +} + +void CNodeView::UpdatePsinMaterial( const char *vsName, GenericShaderData *data ) +{ + if ( !m_pMat_PsIn ) + { + Assert( !pKV_Mat_PsIn ); + /*KeyValues **/ pKV_Mat_PsIn = new KeyValues( "NODE_PSIN" ); + //pKV_Mat_PsIn = new KeyValues( "NODE_PSIN" ); +// ::gProcShaderCTRL->SendTempPsInputShaderName( "psin_vs20" ); + m_pMat_PsIn = materials->CreateMaterial( "__npv_psin", pKV_Mat_PsIn ); + //pKV_Mat_PsIn->Clear(); + + pKV_Mat_PsIn->SetString( "$VSNAME", "psin_vs20" ); + m_pMat_PsIn->Refresh(); + //SetMaterialVar_String( m_pMat_PsIn, "$VSNAME", "psin_vs20" ); + //m_pMat_PsIn->Refresh(); + //IMaterialVar *VS = m_pMat_PsIn->FindVar( "$VSNAME", &bFound2 ); + //VS->SetStringValue( "psin_vs20" ); + UpdatePsinMaterialVar(); + Assert(m_pMat_PsIn); + return; + } + //IMaterialVar *pVSName = m_pMat_PsIn->FindVar( "$VSNAME", &bFound ); + //Assert(bFound); + //Assert(pKV_Mat_PsIn); + Assert(m_pMat_PsIn); + Assert( !IsErrorMaterial( m_pMat_PsIn ) ); + + const char *pDefault = "psin_vs20"; + const char *szTmp = pDefault; + if ( vsName && Q_strlen( vsName ) ) + szTmp = vsName; + + //SetMaterialVar_String( m_pMat_PsIn, "$VSNAME", szTmp ); + pKV_Mat_PsIn->SetString( "$VSNAME", szTmp ); + + if ( data ) + { + //SetMaterialVar_Int( m_pMat_PsIn, "$VFMT_FLAGS", data->shader->iVFMT_flags ); + //SetMaterialVar_Int( m_pMat_PsIn, "$VFMT_NUMTEXCOORDS", data->shader->iVFMT_numTexcoords ); + //SetMaterialVar_Int( m_pMat_PsIn, "$VFMT_USERDATA", data->shader->iVFMT_numUserData ); + pKV_Mat_PsIn->SetInt( "$VFMT_FLAGS", data->shader->iVFMT_flags ); + pKV_Mat_PsIn->SetInt( "$VFMT_NUMTEXCOORDS", data->shader->iVFMT_numTexcoords ); + pKV_Mat_PsIn->SetInt( "$VFMT_USERDATA", data->shader->iVFMT_numUserData ); + pKV_Mat_PsIn->SetInt( "$VFMT_TEXCOORDDIM_0", data->shader->iVFMT_texDim[0] ); + pKV_Mat_PsIn->SetInt( "$VFMT_TEXCOORDDIM_1", data->shader->iVFMT_texDim[1] ); + pKV_Mat_PsIn->SetInt( "$VFMT_TEXCOORDDIM_2", data->shader->iVFMT_texDim[2] ); + } + + m_pMat_PsIn->Refresh(); + m_pMat_PsIn->RecomputeStateSnapshots(); + UpdatePsinMaterialVar(); +} + +void CNodeView::UpdatePsinMaterialVar() +{ + bool bFound = false; + m_pMatVar_PsIn_Operation = m_pMat_PsIn->FindVar( "$OPERATION", &bFound ); + Assert(bFound); +} + +void CNodeView::OnContainerRemoved( CBaseContainerNode *container ) +{ + int idx = m_hContainerNodes.Find( container ); + if ( !m_hContainerNodes.IsValidIndex(idx) ) + return; + m_hContainerNodes.Remove( idx ); + + Assert( !m_hContainerNodes.IsValidIndex( m_hContainerNodes.Find( container ) ) ); +} +void CNodeView::OnContainerAdded( CBaseContainerNode *container ) +{ + Assert( !m_hContainerNodes.IsValidIndex( m_hContainerNodes.Find( container ) ) ); + m_hContainerNodes.AddToTail( container ); +} +void CNodeView::ListContainerAtPos( Vector2D &pos, CUtlVector< CBaseContainerNode* > &hList ) +{ + hList.Purge(); + for ( int i = 0; i < m_hContainerNodes.Count(); i++ ) + { + if ( m_hContainerNodes[i]->IsInContainerBounds( pos ) ) + hList.AddToTail( m_hContainerNodes[i] ); + } +} + +void CNodeView::PurgeCanvas( bool OnShutdown ) +{ + if ( m_pCurBridge ) + { + delete m_pCurBridge; + m_pCurBridge = NULL; + } + DestroyAllSolvers(); + SaveDeleteVector( m_hBridgeList ); + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + m_hNodeList[ i ]->MarkForDeletion(); + SaveDeleteVector( m_hNodeList ); + m_hNodesInMove.Purge(); + m_hTmpNodeIndex.Purge(); + + m_hContainerNodes.Purge(); + if ( !OnShutdown ) + UpdatePsinMaterial( NULL ); + +#if DEBUG + for ( int i = 0; i < hErrorList.Count(); i++ ) + AllocCheck_FreeS("LimitReport_t"); +#endif + hErrorList.PurgeAndDeleteElements(); +} + +void CNodeView::InitCanvas( FlowGraphType_t type, GenericShaderData *newData ) +{ + PurgeCanvas(); + + SetFlowgraphType( type ); + + if ( type == FLOWGRAPH_HLSL ) + { + CBaseNode *n = SpawnNode( HLSLNODE_VS_IN ); + n->SetPosition( Vector2D( -CRUCIALNODE_CANVAS_BASE_X, CRUCIALNODE_CANVAS_BASE_Y + CRUCIALNODE_CANVAS_OFFSET_Y ) ); + + n = SpawnNode( HLSLNODE_VS_OUT ); + n->SetPosition( Vector2D( CRUCIALNODE_CANVAS_BASE_X - CRUCIALNODE_MIN_SIZE_X, CRUCIALNODE_CANVAS_BASE_Y + CRUCIALNODE_CANVAS_OFFSET_Y ) ); + + n = SpawnNode( HLSLNODE_PS_IN ); + n->SetPosition( Vector2D( -CRUCIALNODE_CANVAS_BASE_X, -CRUCIALNODE_CANVAS_BASE_Y + CRUCIALNODE_CANVAS_OFFSET_Y ) ); + + n = SpawnNode( HLSLNODE_PS_OUT ); + n->SetPosition( Vector2D( CRUCIALNODE_CANVAS_BASE_X - CRUCIALNODE_MIN_SIZE_X, -CRUCIALNODE_CANVAS_BASE_Y + CRUCIALNODE_CANVAS_OFFSET_Y ) ); + + if ( newData ) + { + ClearShaderData(); + + Assert( !m_ShaderData ); + m_ShaderData = new GenericShaderData( *newData ); + } + + Assert( m_ShaderData ); + } + else if ( type == FLOWGRAPH_POSTPROC ) + { + CBaseNode *n = SpawnNode( HLSLNODE_POSTPROCESSING_INPUT ); + n->SetPosition( Vector2D( -CRUCIALNODE_CANVAS_BASE_X, CRUCIALNODE_CANVAS_OFFSET_Y / 2 ) ); + + n = SpawnNode( HLSLNODE_POSTPROCESSING_OUTPUT ); + n->SetPosition( Vector2D( CRUCIALNODE_CANVAS_BASE_X - CRUCIALNODE_MIN_SIZE_X, CRUCIALNODE_CANVAS_OFFSET_Y / 2 ) ); + } +} +void CNodeView::Init(void) +{ + ResetView(); + PurgeCanvas(); +} + +void CNodeView::OnBridgeRemoved( CBridge *b ) +{ + if ( b == m_pCurBridge ) + { + m_pCurBridge = NULL; + } + m_hBridgeList.FindAndRemove( b ); + + OnHierachyChanged(); +} +void CNodeView::OnJackRemoved( const CJack *j ) +{ + if ( pJackLast == j ) + { + pJackLast = NULL; + } + + OnHierachyChanged(); +} + +void CNodeView::UpdateRTs() +{ + if ( CNodeView::bRenderingScreenShot ) + return; + + if ( GetFlowgraphType() != FLOWGRAPH_HLSL ) + return; + + CViewSetup setup; + setup.origin = Vector( 0, 0, 0.5f ); + setup.angles = QAngle( 90, 0, 0 ); + setup.m_bOrtho = true; + setup.x = 0; + setup.y = 0; + setup.width = GetRTSize(); + setup.height = GetRTSize(); + setup.m_OrthoTop = -0.5f; + setup.m_OrthoLeft = -0.5f; + setup.m_OrthoBottom = 0.5f; + setup.m_OrthoRight = 0.5f; + setup.zNear = 0; + setup.zFar = 1.0f; + + ResetTileInfo(); + + int numSolvers_P = m_hSolverStack_PixelShader.Count(); + int numSolvers_U = m_hSolverStack_NoHierachy.Count(); + + CMatRenderContextPtr pRenderContext( materials ); + + CalcPuzzleSize( numSolvers_P + numSolvers_U ); + + pRenderContext->ClearColor4ub( 0, 0, 0, 255 ); + pRenderContext->PushRenderTargetAndViewport( GetPingPongRT(0) ); + pRenderContext->ClearBuffers( true, false ); +#ifndef SHADER_EDITOR_DLL_2006 + pRenderContext.SafeRelease(); +#endif + + Frustum tmp; +#ifdef SHADER_EDITOR_DLL_2006 + render->Push3DView( setup, 0, true, GetPingPongRT( 0 ), tmp ); +#else + render->Push3DView( setup, 0, GetPingPongRT( 0 ), tmp ); +#endif + //pRenderContext->PushRenderTargetAndViewport( GetPingPongRT( 0 ) ); + + gShaderEditorSystem->UpdateConstants( &setup ); + if ( numSolvers_P ) + RenderSolvers( m_hSolverStack_PixelShader ); + if ( numSolvers_U ) + RenderSolvers( m_hSolverStack_NoHierachy ); + gShaderEditorSystem->UpdateConstants(); + +#ifndef SHADER_EDITOR_DLL_2006 + pRenderContext.GetFrom( materials ); +#endif + pRenderContext->PopRenderTargetAndViewport(); + render->PopView( tmp ); +} +void CNodeView::RenderSolvers( CUtlVector< CHLSL_SolverBase* > &hSolvers ) +{ + CMatRenderContextPtr pRenderContext( materials ); + + Preview2DContext context; + context.pRenderContext = pRenderContext; + + context.pMat_PsIn = m_pMat_PsIn; + context.pMat_PsInOP = m_pMatVar_PsIn_Operation; + + ResetVariableIndices( hSolvers ); + int x,y,w,t; + for ( int i = 0; i < hSolvers.Count(); i++ ) + { + if ( !hSolvers[i]->IsRenderable() ) + continue; + GetCurPuzzleView( x, y, w, t ); + pRenderContext->Viewport( x, y, w, t ); + + hSolvers[ i ]->Invoke_Render( context ); + pRenderContext->CopyRenderTargetToTexture( GetPingPongRT(1) ); + OnPuzzleDrawn(); + } +} +void CNodeView::RenderSingleSolver( Preview2DContext &c, IMaterial *pMat ) +{ + CMeshBuilder pMeshBuilder; + IMesh *pMesh = c.pRenderContext->GetDynamicMesh( true, 0, 0, pMat ); + pMeshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); +#ifndef SHADER_EDITOR_DLL_2006 + pMeshBuilder.SetCompressionType( VERTEX_COMPRESSION_NONE ); +#endif + + float norm[3] = { 0, 0, 1 }; + float tan_s[3] = { 0, -1, 0 }; + float tan_t[3] = { 1, 0, 0 }; + float tan_s_u[4] = { 0, -1, 0, 1 }; + + pMeshBuilder.Position3f( 0.5f, 0.5f, 0 ); + pMeshBuilder.Normal3fv( norm ); + pMeshBuilder.TangentS3fv( tan_s ); + pMeshBuilder.TangentT3fv( tan_t ); + pMeshBuilder.UserData( tan_s_u ); + for ( int i = 0; i < 3; i++ ) + pMeshBuilder.TexCoord2f( i, 0, 0 ); + pMeshBuilder.Color4f( 1, 1, 1, 1 ); + pMeshBuilder.AdvanceVertex(); + + pMeshBuilder.Position3f( 0.5f, -0.5f, 0 ); + pMeshBuilder.Normal3fv( norm ); + pMeshBuilder.TangentS3fv( tan_s ); + pMeshBuilder.TangentT3fv( tan_t ); + pMeshBuilder.UserData( tan_s_u ); + for ( int i = 0; i < 3; i++ ) + pMeshBuilder.TexCoord2f( i, 1, 0 ); + pMeshBuilder.Color4f( 1, 1, 1, 1 ); + pMeshBuilder.AdvanceVertex(); + + pMeshBuilder.Position3f( -0.5f, -0.5f, 0 ); + pMeshBuilder.Normal3fv( norm ); + pMeshBuilder.TangentS3fv( tan_s ); + pMeshBuilder.TangentT3fv( tan_t ); + pMeshBuilder.UserData( tan_s_u ); + for ( int i = 0; i < 3; i++ ) + pMeshBuilder.TexCoord2f( i, 1, 1 ); + pMeshBuilder.Color4f( 1, 1, 1, 1 ); + pMeshBuilder.AdvanceVertex(); + + pMeshBuilder.Position3f( -0.5f, 0.5f, 0 ); + pMeshBuilder.Normal3fv( norm ); + pMeshBuilder.TangentS3fv( tan_s ); + pMeshBuilder.TangentT3fv( tan_t ); + pMeshBuilder.UserData( tan_s_u ); + for ( int i = 0; i < 3; i++ ) + pMeshBuilder.TexCoord2f( i, 0, 1 ); + pMeshBuilder.Color4f( 1, 1, 1, 1 ); + pMeshBuilder.AdvanceVertex(); + + pMeshBuilder.End(); + pMesh->Draw(); +} + +void CNodeView::MakeSolversDirty() +{ + m_bDirtySolvers = true; + m_StackIndex++; +} +void CNodeView::OnHierachyChanged() +{ + MakeSolversDirty(); +} +void CNodeView::DoFullHierachyUpdate() +{ + CUtlVector< CBaseNode* > m_hList_Bottom; + CUtlVector< CBaseNode* > m_hList_Top; + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[ i ]; + n->Recursive_AddTailNodes( m_hList_Bottom, false ); + } + for ( int i = 0; i < m_hList_Bottom.Count(); i++ ) + { + CBaseNode *n = m_hList_Bottom[ i ]; + n->Recursive_AddTailNodes( m_hList_Top, true ); + } + for ( int i = 0; i < m_hList_Top.Count(); i++ ) + m_hList_Top[i]->OnUpdateHierachy( NULL, NULL ); + m_hList_Top.Purge(); + m_hList_Bottom.Purge(); +} +void CNodeView::ResetTempHierachy() +{ + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + m_hNodeList[ i ]->SetTempHierachyType( HLSLHIERACHY_PENDING ); +} +bool CNodeView::ShouldCallCompiler() +{ + if ( m_ShaderData == NULL ) + return false; + + if ( GetFlowgraphType() == FLOWGRAPH_HLSL ) + return true; + + return false; +} + +void CNodeView::UpdateUserErrors() +{ + const FlowGraphType_t type = GetFlowgraphType(); + CUtlVector< int > hActiveErrors; + CUtlVector< char* > hErrorParams; + + if ( type == FLOWGRAPH_HLSL ) + { + Assert( m_ShaderData != NULL ); + + bool bShowTextureMismatchError = false; + char paramName[MAX_PATH]; + paramName[0] = '\0'; + //const CUtlVector< SimpleTexture* > &hTextures = m_ShaderData->shader->pPS_Identifiers->hList_Textures; + CUtlVector< SimpleTexture* > hTextures; + hTextures.AddVectorToTail( m_ShaderData->shader->pPS_Identifiers->hList_Textures ); + hTextures.AddVectorToTail( m_ShaderData->shader->pVS_Identifiers->hList_Textures ); + + for ( int i = 0; i < hTextures.Count() && !bShowTextureMismatchError; i++ ) + { + const int baseMode = hTextures[i]->iTextureMode; + + if ( !IS_TEXTURE_SAMPLER_USING_CUSTOM_TEXTURE( baseMode ) ) + continue; + + for ( int t = 0; t < hTextures.Count() && !bShowTextureMismatchError; t++ ) + { + if ( t == i ) + continue; + + const int childMode = hTextures[t]->iTextureMode; + + if ( baseMode != childMode ) + continue; + + const bool bCustomParam = baseMode == HLSLTEX_CUSTOMPARAM; + + if ( bCustomParam ) + { + Assert( hTextures[i]->szParamName && hTextures[t]->szParamName ); + + if ( hTextures[i]->szParamName && hTextures[t]->szParamName && + Q_stricmp( hTextures[i]->szParamName, hTextures[t]->szParamName ) ) + continue; + } + + const bool bHasTex_fb_0 = hTextures[i]->szFallbackName != NULL; + const bool bHasTex_fb_1 = hTextures[t]->szFallbackName != NULL; + const bool bHasTex_prev_0 = hTextures[i]->szTextureName != NULL; + const bool bHasTex_prev_1 = hTextures[t]->szTextureName != NULL; + + if ( bHasTex_fb_0 != bHasTex_fb_1 || bHasTex_prev_0 != bHasTex_prev_1 ) + bShowTextureMismatchError = true; + else if ( bHasTex_fb_0 && Q_stricmp( hTextures[i]->szFallbackName, hTextures[t]->szFallbackName ) || + bHasTex_prev_0 && Q_stricmp( hTextures[i]->szTextureName, hTextures[t]->szTextureName ) ) + bShowTextureMismatchError = true; + + if ( bShowTextureMismatchError ) + { + if ( bCustomParam ) + { + if ( hTextures[i]->szParamName != NULL ) + Q_snprintf( paramName, sizeof(paramName), "%s", hTextures[i]->szParamName ); + else + Q_snprintf( paramName, sizeof(paramName), "unnamed custom param" ); + } + else + Q_snprintf( paramName, sizeof(paramName), "%s", GetTextureTypeName( baseMode ) ); + } + } + } + + if ( bShowTextureMismatchError ) + { + int len = Q_strlen( paramName ) + 1; + char *pErrorParam = (len > 1) ? new char[len] : NULL; + if ( pErrorParam != NULL ) + Q_strcpy( pErrorParam, paramName ); + + hActiveErrors.AddToTail( CNodeViewError::NVERROR_TEXTURE_SAMPLER_PARAM_MISMATCH ); + hErrorParams.AddToTail( pErrorParam ); + } + } + else if ( type == FLOWGRAPH_POSTPROC ) + { + CNodePP_Base *pNodeStart = (CNodePP_Base*)GetNodeFromType( HLSLNODE_POSTPROCESSING_INPUT ); + if ( pNodeStart ) + { + bool bGotNonScene = false; + bool bGotError = false; + for ( CNodePP_Base *pNext = pNodeStart->GetNextPPNode(); pNext && !bGotError; pNext = pNext->GetNextPPNode() ) + { + const bool bScene = pNext->IsSceneNode(); + if ( bGotNonScene && bScene ) + bGotError = true; + else if ( !bScene ) + bGotNonScene = true; + } + + if ( bGotError ) + { + hActiveErrors.AddToTail( CNodeViewError::NVERROR_RENDER_VIEW_SCENE_NOT_AT_START ); + hErrorParams.AddToTail( NULL ); + } + } + } + +#ifdef SHADER_EDITOR_DLL_2006 + char nodeName[MAX_PATH]; + bool bShowUnsupportedError = false; + + const int unsupportedList[] = { + HLSLNODE_STUDIO_VERTEXLIGHTING, + HLSLNODE_STUDIO_PIXELSHADER_LIGHTING, + HLSLNODE_STUDIO_PIXELSHADER_SPECLIGHTING, + HLSLNODE_STUDIO_SKINNING, + HLSLNODE_STUDIO_MORPH, + + HLSLNODE_CONSTANT_LIGHTSCALE, + + HLSLNODE_MATRIX_FLASHLIGHT, + HLSLNODE_UTILITY_FLASHLIGHT, + HLSLNODE_CONSTANT_FLASHLIGHTPOS, + + HLSLNODE_STUDIO_VCOMPRESSION, + + HLSLNODE_POSTPROCESSING_RENDER_VIEW, + }; + const int unsupportedList_size = ARRAYSIZE( unsupportedList ); + + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[i]; + int t = n->GetNodeType(); + + for ( int list = 0; list < unsupportedList_size; list++ ) + { + if ( unsupportedList[list] == t ) + { + bShowUnsupportedError = true; + Q_snprintf( nodeName, sizeof( nodeName ), "%s", n->GetName() ); + } + } + + } + + if ( bShowUnsupportedError ) + { + char *unsupportedName = NULL; + AutoCopyStringPtr( nodeName, &unsupportedName ); + + hActiveErrors.AddToTail( CNodeViewError::NVERROR_UNSUPPORTED_BY_2006 ); + hErrorParams.AddToTail( unsupportedName ); + } +#endif + + Assert( hErrorParams.Count() == hActiveErrors.Count() ); + + // close all messages that are not triggered anymore + for ( int a = 0; a < m_hUserErrorLabels.Count(); a++ ) + { + if ( m_hUserErrorLabels[a]->IsClosing() ) + continue; + + const int labelErrorType = m_hUserErrorLabels[a]->GetErrorType(); + + if ( !hActiveErrors.HasElement( labelErrorType ) ) + m_hUserErrorLabels[a]->DoClose(); + } + + // remove all errors that are existing already + for ( int i = 0; i < hActiveErrors.Count(); i++ ) + { + const int requestedError = hActiveErrors[i]; + for ( int a = 0; a < m_hUserErrorLabels.Count(); a++ ) + { + const int labelErrorType = m_hUserErrorLabels[a]->GetErrorType(); + if ( labelErrorType == requestedError ) + { + m_hUserErrorLabels[a]->SetText( hErrorParams[i] ); + if ( m_hUserErrorLabels[a]->IsClosing() ) + m_hUserErrorLabels[a]->DoOpen(); + + hActiveErrors.Remove(i); + delete [] hErrorParams[i]; + hErrorParams.Remove(i); + i--; + break; + } + } + } + + // finally, create new missing errors + for ( int i = 0; i < hActiveErrors.Count(); i++ ) + { + const int requestedError = hActiveErrors[i]; + + CNodeViewError *pError = new CNodeViewError( this, requestedError ); //, hErrorParams[i] ); + pError->SetText( hErrorParams[i] ); + m_hUserErrorLabels.AddToTail( pError ); + } + + for (int i = 0; i < hErrorParams.Count(); i++ ) + delete [] hErrorParams[i]; + hErrorParams.Purge(); +} + +const int CNodeView::GetNumUserErrorLabels() +{ + return m_hUserErrorLabels.Count(); +} + +CNodeViewError *CNodeView::GetUserErrorLabel( int index ) +{ + return m_hUserErrorLabels[index]; +} + +void CNodeView::OnDestroyUserError( KeyValues *pKV ) +{ + CNodeViewError *p = dynamic_cast( ((Panel*)pKV->GetPtr( "panel" )) ); + + if ( !p || !m_hUserErrorLabels.HasElement(p) ) + { + Assert( 0 ); + return; + } + + m_hUserErrorLabels.FindAndRemove( p ); + + p->MarkForDeletion(); +} + +void CNodeView::UpdateUserErrorLayouts() +{ + bool bGotAnimating = false; + + for ( int i = m_hUserErrorLabels.Count() - 1; i >= 0; i-- ) + { + bGotAnimating = bGotAnimating || m_hUserErrorLabels[i]->IsAnimating(); + + if ( bGotAnimating ) + m_hUserErrorLabels[i]->InvalidateLayout( true ); + } +} + +void CNodeView::Think_UpdateSolvers() +{ + UpdateSolvers(); +} + +bool CNodeView::UpdateSolvers() +{ + if ( !m_bDirtySolvers ) //|| m_hNodeList.Count() < 1 ) + return false; + + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + m_hNodeList[ i ]->PreSolverUpdated(); + + for ( int i = 0; i < m_hContainerNodes.Count(); i++ ) + { + m_hContainerNodes[ i ]->FullHierachyUpdate(); + } + + const bool bUsesShaderData = ShouldCallCompiler(); + + if ( bUsesShaderData ) + { + m_ShaderData->shader->iVFMT_texDim[0] = 2; + m_ShaderData->shader->iVFMT_texDim[1] = 2; + m_ShaderData->shader->iVFMT_texDim[2] = 2; + + ClearIdentifiers( *m_ShaderData ); + } + +#if PSIN_ERROR_WHEN_VSOUT_ERROR + CBaseNode *pPS_In = GetNodeFromType( HLSLNODE_PS_IN ); + if ( pPS_In ) + { + pPS_In->SetErrorLevel( pPS_In->PerNodeErrorLevel() ); + pPS_In->JackHierachyUpdate_Out(); + } +#endif + + const FlowGraphType_t type = GetFlowgraphType(); + + struct solverInstruction + { + public: + solverInstruction( int iHierachy, CUtlVector< CHLSL_SolverBase* > *phSolver_Output ) + { + this->iHierachy = iHierachy; + this->phSolver_Output = phSolver_Output; + }; + ~solverInstruction() + { + // explicit, although it's unnecessary + hList_Source.Purge(); + hList_Solved.Purge(); + hList_Bottom.Purge(); + }; + + int iHierachy; + CUtlVector< CHLSL_SolverBase* > *phSolver_Output; + + CUtlVector< CBaseNode* > hList_Source; + CUtlVector< CBaseNode* > hList_Solved; + CUtlVector< CBaseNode* > hList_Bottom; + }; + + CUtlVector< solverInstruction* >hSolverCmds; + + if ( type == FLOWGRAPH_HLSL ) + { + hSolverCmds.AddToTail( new solverInstruction( HLSLHIERACHY_VS, &m_hSolverStack_VertexShader ) ); + hSolverCmds.AddToTail( new solverInstruction( HLSLHIERACHY_PS, &m_hSolverStack_PixelShader ) ); + } + else if ( type == FLOWGRAPH_POSTPROC ) + { + CBaseNode *pPPEOut = GetNodeFromType( HLSLNODE_POSTPROCESSING_OUTPUT ); + + if ( pPPEOut && pPPEOut->GetErrorLevel() == ERRORLEVEL_NONE ) + hSolverCmds.AddToTail( new solverInstruction( HLSLHIERACHY_POST_PROCESS, &m_hSolverStack_PostProcessing ) ); + } + + // 'no hierachy' must be last. + hSolverCmds.AddToTail( new solverInstruction( HLSLHIERACHY_NONE, &m_hSolverStack_NoHierachy ) ); + +#if DO_SOLVING + DestroyAllSolvers(); +#endif + + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[ i ]; + n->RemoveSolvers(); + n->SweepJackHlslCache(); + + if ( n->GetAsContainer() ) + continue; + + int tmpHierachy = n->GetTempHierachyType(); + if ( tmpHierachy == HLSLHIERACHY_PENDING ) + { + tmpHierachy = n->GetHierachyTypeIterateFullyRecursive(); + n->SetTempHierachyTypeFullyRecursive( tmpHierachy ); + } + + for ( int s = 0; s < hSolverCmds.Count(); s++ ) + { + solverInstruction *pCmd = hSolverCmds[s]; + if ( tmpHierachy & pCmd->iHierachy || + s == hSolverCmds.Count() - 1 ) + { + pCmd->hList_Source.AddToTail( n ); + break; + } + } + } + + ResetTempHierachy(); + + CUtlVector< CBaseContainerNode* >m_hContainerStack; + +#if DO_SOLVING + for ( int s = 0; s < hSolverCmds.Count(); s++ ) + { + solverInstruction *pCmd = hSolverCmds[s]; + + //CUtlVector< CBaseNode* > m_hList_VertexShader_Bottom; + for ( int i = 0; i < pCmd->hList_Source.Count(); i++ ) + { + CBaseNode *n = pCmd->hList_Source[ i ]; + n->Recursive_AddTailNodes( pCmd->hList_Bottom, false, false, NULL, true ); + } + InvokeCreateSolvers( pCmd->hList_Bottom, pCmd->hList_Solved, m_hContainerStack, m_ShaderData ); + Assert( !m_hContainerStack.Count() ); + m_hContainerStack.Purge(); + + Assert( pCmd->phSolver_Output ); + + CopySolvers( pCmd->hList_Solved, *pCmd->phSolver_Output ); + ResetVariables( *pCmd->phSolver_Output ); + } +#endif + + CleanupNodes(); + + //SetupForRendering( m_hSolverStack_VertexShader ); +#if DO_SOLVING + SetupForRendering( m_hSolverStack_PixelShader ); + SetupForRendering( m_hSolverStack_NoHierachy ); +#endif + + if ( bUsesShaderData ) + { + AllocateIdentifiers( *m_ShaderData->shader->pVS_Identifiers, m_hSolverStack_VertexShader ); + AllocateIdentifiers( *m_ShaderData->shader->pPS_Identifiers, m_hSolverStack_PixelShader ); + AllocateIdentifiers( *m_ShaderData->pUNDEF_Identifiers, m_hSolverStack_NoHierachy ); + } + + UpdateUserErrors(); + + if ( bUsesShaderData ) + { + UniquifyIdentifiers( false, *m_ShaderData->shader->pVS_Identifiers ); + UniquifyIdentifiers( true, *m_ShaderData->shader->pPS_Identifiers ); + UniquifyIdentifiers( true, *m_ShaderData->pUNDEF_Identifiers ); + + BuildFormatFlags( *m_ShaderData->shader, m_hSolverStack_VertexShader, m_hSolverStack_PixelShader ); + + const bool bIsPreview = IsPreviewModeEnabled(); + m_ShaderData->shader->bPreviewMode = bIsPreview; + + CalcNumDynamicCombos( *m_ShaderData->shader->pVS_Identifiers, bIsPreview ); + CalcNumDynamicCombos( *m_ShaderData->shader->pPS_Identifiers, bIsPreview ); + CalcNumDynamicCombos( *m_ShaderData->pUNDEF_Identifiers, bIsPreview ); + } + +#if SHOW_SEDIT_ERRORS + if ( bUsesShaderData ) + { + bool bHasLookupSolver = false; + bool bHasTextureIdentifier = !!m_ShaderData->shader->pPS_Identifiers->hList_Textures.Count(); + for ( int i = 0; i < m_hSolverStack_PixelShader.Count(); i++ ) + { + if ( dynamic_cast< CHLSL_Solver_TextureSample* >( m_hSolverStack_PixelShader[i] ) ) + bHasLookupSolver = true; + else if ( dynamic_cast< CHLSL_Solver_Flashlight* >( m_hSolverStack_PixelShader[i] ) ) + bHasLookupSolver = true; + } + Assert( bHasLookupSolver == bHasTextureIdentifier ); + } +#endif + + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + m_hNodeList[ i ]->PostSolverUpdated(); + +#if DO_SOLVING + OnSolvingFinsihed(); +#endif + + m_bDirtySolvers = false; + + MakeHistoryDirty(); + + hSolverCmds.PurgeAndDeleteElements(); + + return true; +} + +void CNodeView::InvokeCreateSolvers( CUtlVector< CBaseNode* > &m_hNodeBottomList, + CUtlVector< CBaseNode* > &m_hNodeOutList, + CUtlVector< CBaseContainerNode* > &m_hContainerStack, + GenericShaderData *ShaderData ) +{ + CUtlVector< CBaseNode* > m_hList_Shader_Top; + CBaseContainerNode *activeContainer = NULL; + if ( m_hContainerStack.Count() ) + activeContainer = m_hContainerStack.Tail(); + + for (;;) + { + bool bEarlyOut = false; // avoid one sort of limbo + for ( int i = 0; i < m_hNodeBottomList.Count(); i++ ) + { + CBaseNode *n_SHADER_Bottom = m_hNodeBottomList[ i ]; + n_SHADER_Bottom->Recursive_AddTailNodes( m_hList_Shader_Top, true, true, activeContainer ); + } + + if ( activeContainer != NULL ) + { + bool bHasPriorityNodes = false; + CUtlVector< CBaseNode* >hDirectChildren; + for ( int i = 0; i < m_hList_Shader_Top.Count(); i++ ) + { + CBaseNode *pContainerTop = m_hList_Shader_Top[ i ]; + bool bIsSubChild = false; + for ( int c = 0; c < activeContainer->GetNumChildren(); c++ ) + { + CBaseContainerNode *pCCCHild = activeContainer->GetChild(c)->GetAsContainer(); + if ( !pCCCHild ) + continue; + if ( pCCCHild->HasChild( pContainerTop ) ) + bIsSubChild = true; + } + if ( !bIsSubChild ) + { + bHasPriorityNodes = true; + hDirectChildren.AddToTail( pContainerTop ); + } + } + if ( bHasPriorityNodes ) + { + m_hList_Shader_Top.Purge(); + m_hList_Shader_Top.AddVectorToTail( hDirectChildren ); + hDirectChildren.Purge(); + } + } + + //Msg( "::::: input TOP nodes %i\n", m_hList_VertexShader_Top.Count() ); + bool bProcessedContainer = false; + for ( int i = 0; i < m_hList_Shader_Top.Count(); i++ ) + { + CBaseNode *n_SHADER_Top = m_hList_Shader_Top[ i ]; + //Assert( !n_SHADER_Top->GetAsContainer() ); + + CUtlVector< CBaseContainerNode* > curContainers; + + n_SHADER_Top->ListContainersChronologically( curContainers ); + + CBaseContainerNode *pCurContainer = n_SHADER_Top->GetAsContainer(); + //if ( pCurContainer != NULL && + // pCurContainer->GetNumSolvers() ) + // pCurContainer = NULL; + + if ( pCurContainer != NULL && + !curContainers.HasElement( pCurContainer) ) + curContainers.AddToTail( pCurContainer ); + + if ( n_SHADER_Top->GetErrorLevel() == ERRORLEVEL_NONE || + pCurContainer != NULL ) + { + for ( int c = 0; c < curContainers.Count(); c++ ) + { + CBaseContainerNode *pC = curContainers[c]; + Assert( pC->GetAsContainer() ); + if ( m_hContainerStack.HasElement( pC ) ) + continue; + if ( !pC->IsSolvable( true ) ) + continue; + bool bIsCond = dynamic_cast< CNodeCondition* >( pC ) != NULL; + if ( !bIsCond && pC->GetNumSolvers() > 0 ) + continue; + + m_hContainerStack.AddToTail( pC ); + pC->Solve_ContainerEntered(); + //pC->Solve_ContainerCreateVariables(); + m_hNodeOutList.AddToTail( pC ); + + //int TargetHierachy = n_SHADER_Top->GetHierachyTypeIterateFullyRecursive(); + + CUtlVector< CBaseNode* > hContainerBottom; + Assert( pC->HasChild( n_SHADER_Top ) || pC == n_SHADER_Top ); + for ( int iChild = 0; iChild < pC->GetNumChildren(); iChild++ ) + { + CBaseNode *pChild = pC->GetChild(iChild); + m_hList_Shader_Top.FindAndRemove( pChild ); + + //if ( pChild->GetHierachyTypeIterateFullyRecursive() != TargetHierachy ) + // continue; + pChild->Recursive_AddTailNodes( hContainerBottom, false, false, pC, true ); + } + //i--; + InvokeCreateSolvers( hContainerBottom, m_hNodeOutList, m_hContainerStack, ShaderData ); + hContainerBottom.Purge(); + + m_hNodeOutList.AddToTail( pC ); + pC->Solve_ContainerLeft(); + m_hContainerStack.FindAndRemove( pC ); + + bProcessedContainer = true; + } + + //if ( pCurContainer ) + // bProcessedContainer = true; + } + + curContainers.Purge(); + + if ( bProcessedContainer ) + continue; + //Msg( "::::::: calling solve on: %i\n", n_VS_Top->GetNodeType() ); + if ( n_SHADER_Top->InvokeCreateSolvers(ShaderData) ) + { +#if SHOW_SEDIT_ERRORS + Assert( !m_hNodeOutList.IsValidIndex( m_hNodeOutList.Find( n_SHADER_Top ) ) ); +#endif + m_hNodeOutList.AddToTail( n_SHADER_Top ); + } + else + { + bEarlyOut = true; + break; + } + } + + if ( ( !m_hList_Shader_Top.Count() || bEarlyOut ) && !bProcessedContainer ) + break; + + m_hList_Shader_Top.Purge(); + } + //Msg( "- nodes solved created: %i\n", solvers ); + + m_hList_Shader_Top.Purge(); +} + +int CNodeView::CreatePPSolversFromFile( const char *fileName, CUtlVector &hOutput, GenericPPEData &config ) +{ + int iError = CPostProcessingCache::PPE_OKAY; + //CNodeView *pCalcView = new CNodeView( NULL, ::pEditorRoot, "" ); + CNodeView *pCalcView = new CNodeView( NULL, NULL, "" ); + const bool bOpenSuccessful = pCalcView->LoadFromFile( fileName, true ); + + if ( !bOpenSuccessful || pCalcView->GetNumNodes() < 1 ) + iError = CPostProcessingCache::PPE_INVALID_INPUT; + else if ( pCalcView->GetFlowgraphType() == CNodeView::FLOWGRAPH_POSTPROC ) + { + CBaseNode *pn_IN = pCalcView->GetNodeFromType( HLSLNODE_POSTPROCESSING_INPUT ); + CBaseNode *pn_OUT = pCalcView->GetNodeFromType( HLSLNODE_POSTPROCESSING_OUTPUT ); + + //pn_IN->OnUpdateHierachy( NULL, NULL ); + pCalcView->DoFullHierachyUpdate(); + //for ( int i = 0; i < pCalcView->GetNumNodes(); i++ ) + //{ + // if ( pCalcView->GetNode(i)->GetErrorLevel() != errorl + //} + + if ( !pn_IN || !pn_OUT || + pn_IN->GetErrorLevel() != ERRORLEVEL_NONE || + pn_OUT->GetErrorLevel() != ERRORLEVEL_NONE ) + iError = CPostProcessingCache::PPE_GRAPH_NOT_VALID; + else + { + pCalcView->Think_UpdateSolvers(); + CopySolvers( pCalcView->AccessSolverStack_POSTPROC(), hOutput ); + + Assert( pCalcView->m_PPEData ); + + config = *pCalcView->m_PPEData; + } + } + else + iError = CPostProcessingCache::PPE_INVALID_GRAPH_TYPE; + + delete pCalcView; + return iError; +} + +GenericPPEData *CNodeView::AccessPPEConfig() +{ + Assert( m_PPEData ); + return m_PPEData; +} + +void CNodeView::DoEnvmapOverride() +{ + if ( !m_ShaderData ) + return; + + if ( !m_ShaderData->IsPreview() || !pEditorRoot ) + return; + + if ( !m_ShaderData->shader || + !m_ShaderData->shader->pPS_Identifiers ) + return; + + const char *destTex = pEditorRoot->GetEnvmapOverride(); + if ( !destTex ) + return; + + for ( int i = 0; i < m_ShaderData->shader->pPS_Identifiers->hList_Textures.Count(); i++ ) + { + SimpleTexture *tex = m_ShaderData->shader->pPS_Identifiers->hList_Textures[i]; + if ( tex->iTextureMode != HLSLTEX_ENVMAP ) + continue; + + if ( tex->szTextureName != NULL ) + AllocCheck_FreeS( "szTextureName" ); + + delete [] tex->szTextureName; + tex->szTextureName = new char[ Q_strlen( destTex ) + 1 ]; + Q_strcpy( tex->szTextureName, destTex ); + AllocCheck_AllocS( "szTextureName" ); + } +} + + +void CNodeView::DestroyAllSolvers() +{ + DestroySolverStack(m_hSolverStack_VertexShader); + DestroySolverStack(m_hSolverStack_PixelShader); + DestroySolverStack(m_hSolverStack_NoHierachy); + DestroySolverStack(m_hSolverStack_PostProcessing); +} +CUtlVector< CHLSL_SolverBase* > &CNodeView::AccessSolverStack_VS() +{ + return m_hSolverStack_VertexShader; +} +CUtlVector< CHLSL_SolverBase* > &CNodeView::AccessSolverStack_PS() +{ + return m_hSolverStack_PixelShader; +} +CUtlVector< CHLSL_SolverBase* > &CNodeView::AccessSolverStack_UNDEFINED() +{ + return m_hSolverStack_NoHierachy; +} +CUtlVector< CHLSL_SolverBase* > &CNodeView::AccessSolverStack_POSTPROC() +{ + return m_hSolverStack_PostProcessing; +} + +bool CNodeView::IsMouseOver() +{ + //int sx,sy; + //GetSize( sx, sy ); + //UpdateMousePos(); + //int px = Mx; + //int py = My; + //ScreenToLocal( px, py ); + //return px >= 0 && py >= 0 && px <= sx && py <= sy; + + return GetVPanel() == input()->GetMouseOver(); +} + +void CNodeView::ResetView() +{ + m_vecMenuCreationPosition.Init(); + + ResetView_User(); + + m_vecPosition.Init(); + m_flZoom = m_flZoomGoal; + + StopDrag( iArmDrag == DRAG_NODES ); + iArmDrag = DRAG_NONE; + + UpdateMousePos(); + MxOld = Mx; + MyOld = My; + MxDelta = MyDelta = 0; + + if ( pJackLast ) + pJackLast->SetFocus( false ); + pJackLast = NULL; + bOverrideNodeIndices = false; +} +void CNodeView::ResetView_User( bool bInitial ) +{ + if ( bInitial ) + { + int x,y; + engine->GetScreenSize(x,y); + float relative = 592.0f / y; + m_flZoomGoal = clamp( relative * 1.0f, VIEWZOOM_IN_MAX, VIEWZOOM_OUT_MAX ); + m_vecPositionGoal.Init(); + + m_flZoom = VIEWZOOM_OUT_MAX; + return; + } + + int nsx, nsy; + GetSize( nsx, nsy ); + Vector4D bounds; + GetGraphBoundaries( bounds ); + + Assert( bounds.z > bounds.x ); + Assert( bounds.w > bounds.y ); + + m_vecPositionGoal.Init( -1.0f * bounds.x, bounds.y ); + m_vecPositionGoal.x -= (bounds.z - bounds.x) * 0.5f; + m_vecPositionGoal.y += (bounds.w - bounds.y) * 0.5f; + + float delta_horizontal = (bounds.z - bounds.x) / nsx; + float delta_vertical = (bounds.w - bounds.y) / nsy; + m_flZoomGoal = max( delta_horizontal, delta_vertical ) + 0.2f; + m_flZoomGoal = clamp( m_flZoomGoal, VIEWZOOM_IN_MAX, VIEWZOOM_OUT_MAX ); +} +bool CNodeView::IsCursorOutOfBounds( Vector2D *delta ) +{ + UpdateMousePos(); + + int w,t; + GetSize(w,t); + + if ( delta ) + { + delta->Init(); + + Vector2D mid( w * 0.5f, t * 0.5f ); + Vector2D cur( Mx, My ); + + Vector2D _min( 0, t ); + Vector2D _max( w, 0 ); + + ToNodeSpace( mid ); + ToNodeSpace( cur ); + ToNodeSpace( _min ); + ToNodeSpace( _max ); + + Vector rstart( mid.x, mid.y, 0 ); + Vector rend( cur.x, cur.y, 0 ); + Ray_t ray; + ray.Init( rstart, rend ); + + Vector bmin( _min.x, _min.y, -10 ); + Vector bmax( _max.x, _max.y, 10 ); + + float out = 0; + CBaseTrace tr; + if ( IntersectRayWithBox( ray, bmin, bmax, 1.0f, &tr, &out ) ) + { + Vector intersect = rstart + (rend - rstart) * out; + rend -= intersect; + + delta->Init( rend.x, rend.y ); + } + } + + if ( Mx < 0 || My < 0 ) + return true; + if ( Mx > w || My > t ) + return true; + + if ( delta ) + delta->Init(); + + return false; +} + +float CNodeView::GetZoomScalar() +{ + return 1.0f / max( 0.001f, m_flZoom ); +} +void CNodeView::SetZoomScalar( float zoom ) +{ + m_flZoom = zoom; +} +void CNodeView::ToNodeSpace( Vector2D &pos ) +{ + Vector2D panelMid( GetWide() * 0.5f, GetTall() * 0.5f ); + Vector2D origin = panelMid + m_vecPosition; + + pos -= origin; + + Vector2D panelMidNodeSpace = panelMid - origin; + Vector2D delta( pos - panelMidNodeSpace ); + + delta *= m_flZoom; + + pos = panelMidNodeSpace + delta; + pos.y *= -1.0f; +} +void CNodeView::ToPanelSpace( Vector2D &pos ) +{ +#if 1 + Vector2D panelMid( GetWide(), GetTall() ); + panelMid *= 0.5f * m_flZoom; + Vector2D origin = panelMid + m_vecPosition; + + Vector2D MidPanelSpace = panelMid; + //ToNodeSpace( MidPanelSpace ); + + Vector2D delta( pos - MidPanelSpace ); + //delta *= 1.0f / max( 0.001f, m_flZoom ); + pos = MidPanelSpace + delta; + + pos.x += origin.x; + pos.y -= origin.y; + pos.y *= -1.0f; + pos *= 1.0f / max( 0.001f, m_flZoom ); +#else + Vector2D panelMid( 0.5f * GetWide(), 0.5f * GetTall() ); + Vector2D origin = panelMid + m_vecPosition; + + Vector2D MidPanelSpace = panelMid; + ToNodeSpace( MidPanelSpace ); + + Vector2D delta( pos - MidPanelSpace ); + delta *= 1.0f / max( 0.001f, m_flZoom ); + pos = MidPanelSpace + delta; + + pos.x += origin.x; + pos.y -= origin.y; + pos.y *= -1.0f; +#endif +} +void CNodeView::GetGraphBoundaries( Vector4D &out ) +{ + if ( !GetNumNodes() ) + out.Init( -100, -100, 100, 100 ); + else + { + CBaseNode *node = GetNode( 0 ); + Vector2D local_min = node->GetBoundsMinNodeSpace(); + Vector2D local_max = node->GetBoundsMaxNodeSpace(); + out.Init( local_min.x, local_min.y, local_max.x, local_max.y ); + } + + for ( int i = 1; i < GetNumNodes(); i++ ) + { + CBaseNode *node = GetNode( i ); + + Vector2D local_min = node->GetBoundsMinNodeSpace(); + Vector2D local_max = node->GetBoundsMaxNodeSpace(); + + out.x = min( out.x, local_min.x ); + out.y = min( out.y, local_min.y ); + out.z = max( out.z, local_max.x ); + out.w = max( out.w, local_max.y ); + } +} +Vector2D CNodeView::GetMousePosInNodeSpace() +{ + UpdateMousePos(); + Vector2D mN( Mx, My ); + ToNodeSpace(mN); + return mN; +} + +void CNodeView::OnThink(void) +{ + UpdateMousePos(); + AccumulateMouseMove(); + + BaseClass::OnThink(); + + Think_HighlightJacks(); + Think_UpdateCursorIcon(); + Think_SmoothView(); + Think_Drag(); + + Think_UpdateSolvers(); + Think_UpdateHistory(); + + Think_CreateTooltip(); + SaveMousePos(); + + UpdateUserErrorLayouts(); +} +void CNodeView::Think_SmoothView() +{ + for ( int i = 0; i < 2; i++ ) + { + float delta = ( m_vecPositionGoal[i] - m_vecPosition[i] ); + float move = delta * gpGlobals->frametime * VIEWSPEED_PAN; + if ( abs(move) > abs(delta) ) + move = delta; + m_vecPosition[i] += move; + } + float delta = ( m_flZoomGoal - m_flZoom ); + float move = delta * gpGlobals->frametime * VIEWSPEED_ZOOM; + if ( abs(move) > abs(delta) ) + move = delta; + m_flZoom += move; +} +void CNodeView::Think_Drag() +{ + if ( !IsInDrag() ) + return; + + bool bNodeDrag = iArmDrag == DRAG_NODES; + bool bSBoxDrag = iArmDrag == DRAG_SBOX; + bool bBridgeDrag = iArmDrag == DRAG_BRDIGE; + + if ( bBridgeDrag && m_pCurBridge ) + { + Vector2D target = GetMousePosInNodeSpace(); + CJack *curJack = GetBridgeSnapJack(); + if ( curJack ) + { + target = curJack->GetCenter(); + if ( !curJack->IsInput() ) + target.x = curJack->GetBoundsMax().x; + else + target.x = curJack->GetBoundsMin().x; + } + + m_pCurBridge->SetTemporaryTarget( target ); + } + + if ( bSBoxDrag || bBridgeDrag ) + { + Think_PullView(); + return; + } + + Vector2D curpos( Mx, My ); + Vector2D oldpos( MxOld, MyOld ); + + ToNodeSpace(curpos); + ToNodeSpace(oldpos); + + Vector2D delta = curpos - oldpos; + + if ( bNodeDrag ) + { + Vector2D d = Think_PullView(); + DragSelection( delta + d ); + return; + } + + delta.y *= -1.0f; + + m_vecPositionGoal += delta; +} +Vector2D CNodeView::Think_PullView() +{ + Vector2D delta; + if ( !IsCursorOutOfBounds( &delta ) ) + return Vector2D(0,0); + + float len = delta.NormalizeInPlace(); + len = min( editor_pull_speed_max.GetFloat() / GetZoomScalar(), len ); + delta *= len; + + delta *= gpGlobals->frametime * editor_pull_speed_mul.GetFloat(); + + m_vecPositionGoal -= Vector2D( delta.x, -delta.y ); + return delta; +} +void CNodeView::Think_HighlightJacks() +{ + CJack *cur = NULL; + if ( !IsInDrag() || iArmDrag != DRAG_BRDIGE ) + { + float t = BRIDGE_DRAG_TOLERANCE; + cur = GetJackUnderCursor(&t); + } + else + cur = GetBridgeSnapJack(); + + if ( IsInDrag() && iArmDrag != DRAG_BRDIGE ) + cur = NULL; + + for ( int i = 0; cur != NULL && i < cur->GetNumBridges(); i++ ) + cur->GetBridge(i)->SetTemporaryColor( CBridge::TMPCOL_TRANS ); + + if ( cur == pJackLast ) + return; + + if ( pJackLast ) + pJackLast->SetFocus( false ); + + if ( cur ) + cur->SetFocus( true ); + + pJackLast = cur; +} +void CNodeView::Think_UpdateCursorIcon() +{ + int hoverCursor = 0; + int dcTarget = dc_user; + + Vector2D mPos( Mx, My ); + ToNodeSpace( mPos ); + + if ( !pJackLast && IsMouseOver() && !pEditorRoot->IsPainting() ) + { + if ( IsInDrag() && iArmDrag == DRAG_NODES ) + { + dcTarget = m_iCursorLast; + } + else + { + for ( int i = 0; i < m_hContainerNodes.Count(); i++ ) + { + hoverCursor = m_hContainerNodes[i]->IsInBorderBounds( mPos ); + if ( hoverCursor ) + break; + } + } + } + + switch ( hoverCursor ) + { + default: + break; + case CBORDER_TOP_LEFT: + case CBORDER_BOTTOM_RIGHT: + dcTarget = dc_sizenwse; + break; + case CBORDER_TOP_RIGHT: + case CBORDER_BOTTOM_LEFT: + dcTarget = dc_sizenesw; + break; + case CBORDER_TOP: + case CBORDER_BOTTOM: + dcTarget = dc_sizens; + break; + case CBORDER_RIGHT: + case CBORDER_LEFT: + dcTarget = dc_sizewe; + break; + } + if ( m_iCursorLast == dcTarget ) + return; + + m_iCursorLast = dcTarget; + input()->SetCursorOveride( dcTarget ); +} + +void CNodeView::Think_CreateTooltip() +{ + if ( m_pTooltip ) + return; + + if ( m_ContextMenu && m_ContextMenu->IsVisible() ) + return; + + if ( m_lTime_MouseLastMoved <= 0 ) + return; + + long curTime = system()->GetTimeMillis(); + bool bShouldCreateTooltip = curTime - m_lTime_MouseLastMoved > 1000 && pEditorRoot->ShouldShowTooltips(); + + if ( bShouldCreateTooltip ) + { + CBaseNode *pNode = GetNodeUnderCursor(); + if ( pNode ) + CreateTooltip( pNode->GetNodeType() ); + } +} + +void CNodeView::UpdateMousePos() +{ + input()->GetCursorPosition( Mx, My ); + ScreenToLocal(Mx,My); +} +void CNodeView::AccumulateMouseMove() +{ + MxDelta = Mx - MxOld; + MyDelta = My - MyOld; +} +void CNodeView::SaveMousePos() +{ + MxOld = Mx; + MyOld = My; +} + +void CNodeView::ForceFocus() +{ + input()->SetMouseFocus( GetVPanel() ); + if ( m_ContextMenu.Get() ) + m_ContextMenu->OnKillFocus(); +} +void CNodeView::OnKeyCodeTyped(KeyCode code) +{ + DestroyTooltip(); + + OnParentKeyCodeTyped( code ); +} +void CNodeView::OnKeyCodePressed ( vgui::KeyCode code ) +{ + OnParentKeyCodePressed( code ); +} +void CNodeView::OnKeyCodeReleased( vgui::KeyCode code ) +{ + OnParentKeyCodeReleased( code ); +} +void CNodeView::OnParentKeyCodeTyped(KeyCode code) +{ + if ( !AllowKeyInput() ) return; +} +void CNodeView::OnParentKeyCodePressed ( vgui::KeyCode code ) +{ + if ( !AllowKeyInput() ) return; + + if ( input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ) ) + { + if ( code == KEY_C ) + CopySelection(); + else if ( code == KEY_V ) + { + Vector2D pos( Mx, My ); + ToNodeSpace( pos ); + PasteNodes( pEditorRoot->GetCopyNodes(), true, &pos ); + } + else if ( code == KEY_X ) + { + CopySelection(); + DeleteSelection(); + } + else if ( code == KEY_Z ) + { + const bool bShiftDown = input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ); + HistoryAction( bShiftDown ? HACT_REDO : HACT_UNDO ); + } + return; + } + + switch ( code ) + { + case KEY_DELETE: + DeleteSelection(); + return; + } +} +void CNodeView::OnParentKeyCodeReleased( vgui::KeyCode code ) +{ + if ( !AllowKeyInput() ) return; +} +void CNodeView::OnMousePressed ( vgui::MouseCode code ) +{ + DestroyTooltip(); + ForceFocus(); + + BaseClass::OnMousePressed( code ); + + if ( code == MOUSE_RIGHT ) + { + iArmDrag = DRAG_VIEW; + } + else if ( code == MOUSE_LEFT ) + { + CBaseNode *cur = GetNodeUnderCursor(); + float t = BRIDGE_DRAG_TOLERANCE; + CJack *curJack = GetJackUnderCursor(&t); + + HandleSelectionInputPressed( cur ); + + if ( curJack && ( !cur || cur == curJack->GetParentNode() ) ) + { + CBaseNode *n = curJack->GetParentNode(); + if ( n ) + { + bool bReArrange = curJack->IsInput() && curJack->GetNumBridges(); + iArmDrag = DRAG_BRDIGE; + + if ( !bReArrange ) + CreateDragBridge( curJack ); + else + UpdateDragBridge( curJack, n ); + } + } + else if ( cur ) + { + if ( cur->IsSelected() ) + { + iArmDrag = DRAG_NODES; + Vector2D mPos( Mx, My ); + ToNodeSpace( mPos ); + cur->OnLeftClick( mPos ); + } + } + else + { + m_vecSelectionBoxStart = GetMousePosInNodeSpace(); + iArmDrag = DRAG_SBOX; + } + } +} + +void CNodeView::OnMouseDoublePressed(MouseCode code) +{ + ForceFocus(); + + BaseClass::OnMouseDoublePressed( code ); + + if ( code == MOUSE_LEFT ) + { + CBaseNode *cur = GetNodeUnderCursor(); + if ( cur ) + { + CreatePropertyDialog( cur ); + } + } +} +void CNodeView::OnMouseReleased( vgui::MouseCode code ) +{ + BaseClass::OnMouseReleased( code ); + + const bool bNodeDrag = iArmDrag == DRAG_NODES; + const bool bSBoxDrag = iArmDrag == DRAG_SBOX; + const bool bBridgeDrag = iArmDrag == DRAG_BRDIGE; + + iArmDrag = DRAG_NONE; + + if ( IsInDrag() ) + { + if ( bSBoxDrag ) + { + HandleSelectionInputReleasedBox(); + } + else if ( bBridgeDrag && m_pCurBridge ) + { + CJack *tJ = GetBridgeSnapJack(); + + if ( tJ && tJ->GetParentNode() ) + { + if ( tJ->IsInput() && tJ->GetNumBridges() ) + { + Assert( tJ->GetNumBridges() == 1 ); + tJ->DisconnectBridges(); + } + FinishDragBridge( tJ ); + } + else + KillDragBridge(); + } + + StopDrag( bNodeDrag ); + return; + } + else if ( m_pCurBridge ) + { + KillDragBridge(); + } + + if ( code == MOUSE_RIGHT ) + { + CBaseNode *cur = GetNodeUnderCursor(); + float t = BRIDGE_DRAG_TOLERANCE; + CJack *curJack = GetJackUnderCursor(&t); + + if ( curJack && ( !cur || cur == curJack->GetParentNode() ) ) + { + curJack->PurgeBridges(); + return; + } + else if ( cur ) + { + if ( !cur->IsSelected() ) + { + DeselectAllNodes( cur ); + cur->SetSelected( true ); + } + } + else + DeselectAllNodes(); + + CreateContextMenu( GetFirstSelectedNode() ); + } + if ( code == MOUSE_LEFT ) + { + CBaseNode *cur = GetNodeUnderCursor(); + + HandleSelectionInputReleased( cur ); + } +} +void CNodeView::OnCursorMoved( int x, int y ) +{ + BaseClass::OnCursorMoved(x,y); + + DestroyTooltip(); + + m_lTime_MouseLastMoved = system()->GetTimeMillis(); + + if ( iArmDrag && ( x || y ) && !IsInDrag() ) + { + bool bNodeDrag = iArmDrag == DRAG_NODES; + BeginDrag( bNodeDrag ); + } +} +void CNodeView::OnMouseWheeled( int delta ) +{ + if ( !IsMouseOver() ) + return; + + DestroyTooltip(); + + BaseClass::OnMouseWheeled(delta); + + if ( IsInDrag() && iArmDrag == DRAG_NODES ) + return; + + Vector2D oldPos = GetMousePosInNodeSpace(); + + float flZoomDelta = delta * VIEWZOOM_SPEED * Bias( RemapValClamped(m_flZoom,0,VIEWZOOM_OUT_MAX,0,1), 0.6f ); + float flZoomOld = m_flZoom; + + m_flZoom -= flZoomDelta; + m_flZoomGoal -= flZoomDelta; + m_flZoom = clamp( m_flZoom, VIEWZOOM_IN_MAX, VIEWZOOM_OUT_MAX ); + m_flZoomGoal = clamp( m_flZoomGoal, VIEWZOOM_IN_MAX, VIEWZOOM_OUT_MAX ); + + Vector2D newPos = GetMousePosInNodeSpace(); + + m_flZoom = flZoomOld; + + Vector2D deltaPos = newPos - oldPos; + + if ( delta < 0 ) + deltaPos *= -1.0f; + + deltaPos.y *= -1.0f; + + m_vecPositionGoal += deltaPos; +} + +void CNodeView::OnCursorEntered() +{ + m_lTime_MouseLastMoved = 0; + DestroyTooltip(); +} +void CNodeView::OnCursorExited() +{ + m_lTime_MouseLastMoved = 0; + DestroyTooltip(); +} + +void CNodeView::CreateTooltip( int iNodeIndex ) +{ + DestroyTooltip(); + + KeyValues *pNodeHelp = pEditorRoot->GetNodeHelpContainer(); + if ( !pNodeHelp ) + return; + + KeyValues *pInfo = pNodeHelp->FindKey( VarArgs( "%i", iNodeIndex ) ); + if ( !pInfo ) + return; + + char *pszName = CKVPacker::ConvertKVSafeString( pInfo->GetString( "name" ), false ); + char *pszInfo = CKVPacker::ConvertKVSafeString( pInfo->GetString( "info" ), false ); + char *pszCode = CKVPacker::ConvertKVSafeString( pInfo->GetString( "code" ), false ); + + if ( !pszName && !pszInfo && !pszCode ) + return; + + CSmartObject *pO = new CSmartObject( ACOMP_VAR, pszName, NULL, NULL ); + AutoCopyStringPtr( pszInfo, &pO->m_pszHelptext ); + if ( pszCode && Q_strlen(pszCode) ) + AutoCopyStringPtr( VarArgs("Example: %s",pszCode), &pO->m_pszSourceFile ); + + delete [] pszName; + delete [] pszInfo; + delete [] pszCode; + + m_pTooltip = new CSmartTooltip( this, "nodetooltip" ); + m_pTooltip->Init( pO ); + m_pTooltip->InvalidateLayout( true ); + + int mx, my, sx, sy, tsx, tsy; + input()->GetCursorPosition( mx, my ); + mx += 16; + + surface()->GetScreenSize( sx, sy ); + m_pTooltip->GetSize( tsx, tsy ); + + mx -= max( 0, tsx + mx - sx ); + my -= max( 0, tsy + my - sy ); + + //ScreenToLocal( mx, my ); + m_pTooltip->SetPos( mx, my ); + + delete pO; +} + +void CNodeView::DestroyTooltip() +{ + if ( !m_pTooltip ) + return; + + m_pTooltip->MarkForDeletion(); + m_pTooltip = NULL; + + m_lTime_MouseLastMoved = 0; +} + +void CNodeView::BeginDrag( bool bNodes ) +{ + bInDrag = true; + input()->SetMouseCapture( GetVPanel() ); + + Assert( !m_hNodesInMove.Count() ); + if ( bNodes ) + { + m_hNodesInMove.Purge(); + Vector2D mouseInNodeSpace( MxOld, MyOld ); + ToNodeSpace( mouseInNodeSpace ); + CBaseNode *cur = GetNodeUnderPos( mouseInNodeSpace ); + + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + if ( m_hNodeList[i]->IsSelected() ) + m_hNodesInMove.AddToTail( m_hNodeList[i] ); + for ( int i = 0; i < m_hNodesInMove.Count(); i++ ) + if ( m_hNodesInMove[i]->MustDragAlone() ) + { + if ( cur == m_hNodesInMove[i] ) + { + CBaseNode *SingleNode = m_hNodesInMove[i]; + DeselectAllNodes( SingleNode ); + m_hNodesInMove.Purge(); + m_hNodesInMove.AddToTail( SingleNode ); + break; + } + else + { + m_hNodesInMove[ i ]->SetSelected( false ); + m_hNodesInMove.Remove( i ); + i--; + } + } + for ( int i = 0; i < m_hNodesInMove.Count(); i++ ) + m_hNodesInMove[i]->OnDragStart(); + } +} +bool CNodeView::IsInDrag() +{ + return bInDrag; +} +void CNodeView::StopDrag( bool bNodes ) +{ + bInDrag = false; + input()->SetMouseCapture( NULL ); + + if ( bNodes ) + { + for ( int i = 0; i < m_hNodesInMove.Count(); i++ ) + m_hNodesInMove[i]->OnDragEnd(); + m_hNodesInMove.Purge(); + + MakeHistoryDirty(); + } +} +void CNodeView::HandleSelectionInputPressed( CBaseNode *pNode ) +{ + bool bToggle = input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ); + bool bAdd = input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ); + if ( bAdd ) + bToggle = false; + bool bAccum = bAdd || bToggle; + + if ( pNode ) + { + CBaseContainerNode *pContainer = pNode->GetAsContainer(); + + bool bWasSelected = pNode->IsSelected(); + if ( !bWasSelected && !bAccum ) + DeselectAllNodes( pNode ); + + if ( pContainer != NULL ) + { + pContainer->UpdateOnMove(); + + if ( pContainer->ShouldSelectChildrenOnClick() ) + pContainer->SelectAllInBounds(); + } + + if ( bToggle ) + pNode->ToggleSelection(); + else + pNode->SetSelected( true ); + + MoveNodeToFront( pNode ); + } +} +void CNodeView::HandleSelectionInputReleased( CBaseNode *pNode ) +{ + bool bToggle = input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ); + bool bAdd = input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ); + if ( bAdd ) + bToggle = false; + bool bAccum = bAdd || bToggle; + + if ( pNode ) + { + CBaseContainerNode *pContainer = pNode->GetAsContainer(); + + if ( !bAccum ) + DeselectAllNodes( pNode ); + + if ( pContainer != NULL ) + { + pContainer->UpdateOnMove(); + + if ( pContainer->ShouldSelectChildrenOnClick() ) + pContainer->SelectAllInBounds(); + } + } + else if ( !bAccum ) + DeselectAllNodes(); +} +void CNodeView::HandleSelectionInputReleasedBox() +{ + bool bToggle = input()->IsKeyDown( KEY_LCONTROL ) || input()->IsKeyDown( KEY_RCONTROL ); + bool bAdd = input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ); + if ( bAdd ) + bToggle = false; + bool bAccum = bAdd || bToggle; + + Vector2D sstart = m_vecSelectionBoxStart; + Vector2D ssend = GetMousePosInNodeSpace(); + Vector smin( min( sstart.x, ssend.x ), + min( sstart.y, ssend.y ), -10 ); + Vector smax( max( sstart.x, ssend.x ), + max( sstart.y, ssend.y ), 10 ); + + CUtlVector< CBaseNode* >m_hSelection; + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[i]; + + Vector2D nmin = n->GetSelectionBoundsMinNodeSpace(); //GetBoundsMinNodeSpace(); + Vector2D nmax = n->GetSelectionBoundsMaxNodeSpace(); //GetBoundsMaxNodeSpace(); + Vector n1( nmin.x, nmin.y, -10 ); + Vector n2( nmax.x, nmax.y, 10 ); + + if ( IsBoxIntersectingBox( smin, smax, n1, n2 ) ) + { + m_hSelection.AddToTail( n ); + } + } + + if ( !bAccum ) + DeselectAllNodes(); + for ( int i = 0; i < m_hSelection.Count(); i++ ) + { + CBaseNode *n = m_hSelection[i]; + if ( bToggle ) + n->ToggleSelection(); + else + n->SetSelected( true ); + } + + m_hSelection.Purge(); +} + +CBaseNode *CNodeView::GetNodeUnderCursor() +{ + UpdateMousePos(); + Vector2D mouseInNodeSpace( Mx, My ); + ToNodeSpace( mouseInNodeSpace ); + return GetNodeUnderPos( mouseInNodeSpace ); +} +CBaseNode *CNodeView::GetNodeUnderPos(Vector2D pos) +{ + CBaseNode *p = NULL; + + for ( int i = m_hNodeList.Count() - 1; i >= 0 ; i-- ) + { + CBaseNode *n = m_hNodeList[i]; + if ( n->IsWithinBounds_Base( pos ) ) + { + p = n; + break; + } + } + + return p; +} +CJack *CNodeView::GetJackUnderCursor( float *tolerance, bool bInputs, bool bOutputs ) +{ + UpdateMousePos(); + Vector2D mouseInNodeSpace( Mx, My ); + ToNodeSpace( mouseInNodeSpace ); + return GetJackUnderPos( mouseInNodeSpace, tolerance, bInputs, bOutputs ); +} +CJack *CNodeView::GetJackUnderPos(Vector2D pos, float *tolerance, bool bInputs, bool bOutputs ) +{ + if ( !IsMouseOver() ) + return NULL; + + CJack *j = NULL; + for ( int i = m_hNodeList.Count() - 1; i >= 0 ; i-- ) + { + CBaseNode *n = m_hNodeList[i]; + float bestdist = 99999; + CJack *bestJack = NULL; + + if ( bOutputs ) + { + for ( int x = 0; x < n->GetNumJacks_Out(); x++ ) + { + CJack *tmp = n->GetJack_Out(x); + if ( tmp->IsWithinBounds_Base( pos ) ) + { + j = tmp; + break; + } + if (tolerance) + { + Vector2D c = tmp->GetCenter(); + c -= pos; + float dist = c.Length(); + if ( dist < *tolerance && dist < bestdist ) + { + bestdist = dist; + bestJack = tmp; + } + } + } + } + if ( bInputs ) + { + for ( int x = 0; x < n->GetNumJacks_In(); x++ ) + { + CJack *tmp = n->GetJack_In(x); + if ( tmp->IsWithinBounds_Base( pos ) ) + { + j = tmp; + break; + } + if (tolerance) + { + Vector2D c = tmp->GetCenter(); + c -= pos; + float dist = c.Length(); + if ( dist < *tolerance && dist < bestdist ) + { + bestdist = dist; + bestJack = tmp; + } + } + } + } + + if ( bestJack && !j ) + j = bestJack; + + if ( j ) + break; + } + return j; +} +void CNodeView::DeselectAllNodes( CBaseNode *pIgnore ) +{ + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[i]; + if ( n == pIgnore ) + continue; + n->SetSelected( false ); + } +} +void CNodeView::SelectNodes( CUtlVector< CBaseNode* > &m_hNodes, bool bAdd ) +{ + if ( !bAdd ) + DeselectAllNodes(); + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[i]; + if ( m_hNodes.Find( n ) != m_hNodes.InvalidIndex() ) + n->SetSelected( true ); + } +} +bool CNodeView::IsSelectionBiggerThanOne() +{ + int num = 0; + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[i]; + if ( n->IsSelected() ) + num++; + } + return num > 1; +} +CBaseNode *CNodeView::GetFirstSelectedNode() +{ + for ( int i = m_hNodeList.Count()-1; i >= 0; i-- ) + { + CBaseNode *n = m_hNodeList[i]; + if ( n->IsSelected() ) + return n; + } + return NULL; +} +void CNodeView::DragSelection( Vector2D delta ) +{ + //CUtlVector< CBaseNode* >hSelection; + //for ( int i = 0; i < m_hNodeList.Count(); i++ ) + // if ( m_hNodeList[i] ) + // hSelection.AddToTail( m_hNodeList[i] ); + + //for ( int i = 0; i < hSelection.Count(); i++ ) + // if ( hSelection[i]->MustDragAlone() ) + // { + // CBaseNode *SingleNode = hSelection[i]; + // DeselectAllNodes( SingleNode ); + // hSelection.Purge(); + // hSelection.AddToTail( SingleNode ); + // break; + // } + + //for ( int i = 0; i < hSelection.Count(); i++ ) + for ( int i = 0; i < m_hNodesInMove.Count(); i++ ) + { + //CBaseNode *n = m_hNodeList[i]; + CBaseNode *n = m_hNodesInMove[i]; + //if ( !n->IsSelected() ) + // continue; + + n->OnDrag( delta ); + + //Vector2D pos = n->GetPosition(); + //pos += delta; + //n->SetPosition( pos ); + } + //hSelection.Purge(); +} +void CNodeView::MoveNodeToFront( CBaseNode *p ) +{ + if ( p == m_hNodeList.Tail() ) + return; + + int idx = m_hNodeList.Find( p ); + m_hNodeList.Remove( idx ); + m_hNodeList.AddToTail( p ); +} +void CNodeView::CopySelection() +{ + if ( !AllowKeyInput() ) return; + + CUtlVector< CBaseNode* > m_hCopy; + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + if ( !m_hNodeList[i]->IsSelected() ) + continue; + if ( m_hNodeList[i]->IsNodeCrucial() ) + continue; + m_hCopy.AddToTail( m_hNodeList[i] ); + } + + pEditorRoot->SendCopyNodes( CopyNodes( m_hCopy ) ); + m_hCopy.Purge(); +} +void CNodeView::PasteSelection() +{ + if ( !AllowKeyInput() ) return; + //KeyValues *pKV = pEditorRoot->GetCopyNodes(); + //if ( !pKV ) + // return; + + PasteNodes( pEditorRoot->GetCopyNodes(), true, &m_vecMenuCreationPosition ); + + //CUtlVector< CBaseNode* > m_hPasted; + //PasteNodes( m_vecMenuCreationPosition, pKV, &m_hPasted ); + //SelectNodes( m_hPasted, false ); +} +void CNodeView::DeleteSelection() +{ + if ( !AllowKeyInput() ) return; + + CUtlVector< CBaseNode* > m_hDeleteThese; + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[i]; + if ( !n->IsSelected() ) + continue; + if ( n->IsNodeCrucial() ) + continue; + + m_hNodesInMove.FindAndRemove( m_hNodeList[i] ); + m_hNodeList.Remove( i ); + n->MarkForDeletion(); + m_hDeleteThese.AddToTail( n ); + i--; + } + SaveDeleteVector( m_hDeleteThese ); +} +void CNodeView::DisconnectSelection() +{ + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *n = m_hNodeList[i]; + if ( !n->IsSelected() ) + continue; + + n->PurgeBridges(); + } +} + +bool CNodeView::AllowKeyInput() +{ + if ( input()->GetAppModalSurface() ) + return false; + if ( m_Properties.Get() ) + return false; + + return true; +} + +void CNodeView::StartOverrideIndices( CUtlVector< CBaseNode* > &m_hNodes ) +{ + bOverrideNodeIndices = true; + m_hTmpNodeIndex.Purge(); + m_hTmpNodeIndex.AddVectorToTail( m_hNodes ); +} +void CNodeView::FinishOverrideIndices() +{ + bOverrideNodeIndices = false; + m_hTmpNodeIndex.Purge(); +} +KeyValues *CNodeView::CopyNodes( CUtlVector< CBaseNode* > &m_hNodesToCopy, bool bCenterNodes ) +{ + if ( m_hNodesToCopy.Count() < 1 ) + return NULL; + Vector2D groupMin = m_hNodesToCopy[0]->GetBoundsMinNodeSpace(); + Vector2D groupMax = m_hNodesToCopy[0]->GetBoundsMaxNodeSpace(); + Vector2D groupMid; + + for ( int i = 1; i < m_hNodesToCopy.Count(); i++ ) + { + Vector2D curmin = m_hNodesToCopy[i]->GetBoundsMinNodeSpace(); + Vector2D curmax = m_hNodesToCopy[i]->GetBoundsMaxNodeSpace(); + if ( curmin.x < groupMin.x ) + groupMin.x = curmin.x; + if ( curmin.y < groupMin.y ) + groupMin.y = curmin.y; + + if ( curmax.x > groupMax.x ) + groupMax.x = curmax.x; + if ( curmax.y > groupMax.y ) + groupMax.y = curmax.y; + } + + groupMid = groupMin + ( groupMax - groupMin ) * 0.5f; + + StartOverrideIndices( m_hNodesToCopy ); + + KeyValues *pKV = new KeyValues("Nodes"); + for ( int i = 0; i < m_hNodesToCopy.Count(); i++ ) + { + pKV->AddSubKey( m_hNodesToCopy[i]->AllocateKeyValues( i ) ); + } + if ( bCenterNodes ) + MoveNodes( -groupMid, pKV ); + + FinishOverrideIndices(); + + return pKV; +} +CBaseNode *CNodeView::AllocateSingleNode( KeyValues *pKV ) +{ + int type = pKV->GetInt( "iType" ); + CBaseNode *pNode = SpawnNode( type ); + if ( !pNode ) + return NULL; + + Assert( pNode ); + pNode->RestoreFromKeyValues( pKV ); + return pNode; +} +void CNodeView::ConnectBridges( CUtlVector< CBaseNode* > &m_hInstantiatedNodes, KeyValues *pKV ) +{ + StartOverrideIndices( m_hInstantiatedNodes ); + for ( int i = 0; i < m_hInstantiatedNodes.Count(); i++ ) + { + CBaseNode *n = m_hInstantiatedNodes[i]; + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "Node_%03i", i ); + KeyValues *data = pKV->FindKey( tmp ); + if ( !data ) + { + Warning( "no bridge info on instantiated node!\n" ); + continue; + } + n->RestoreFromKeyValues_CreateBridges( data ); + } + FinishOverrideIndices(); +} +void CNodeView::PasteNodes( KeyValues *pKV, bool bAutoSelect, Vector2D *origin, CUtlVector< CBaseNode* > *m_hNewNodes ) +{ + if ( !pKV ) + return; + + int idx = 0; + CUtlVector< CBaseNode* >m_hInstantiatedNodes; + + for (;;) + { + char tmp[MAX_PATH]; + Q_snprintf( tmp, MAX_PATH, "Node_%03i", idx ); + KeyValues *pKVNode = pKV->FindKey( tmp ); + idx++; + if ( !pKVNode ) + break; + + CBaseNode *pNode = AllocateSingleNode( pKVNode ); + if ( !pNode ) + continue; + + if ( origin ) + MoveNodes( *origin, pNode ); + + m_hInstantiatedNodes.AddToTail( pNode ); + } + + ConnectBridges( m_hInstantiatedNodes, pKV ); + + if ( m_hNewNodes ) + m_hNewNodes->AddVectorToTail( m_hInstantiatedNodes ); + + if ( bAutoSelect ) + SelectNodes( m_hInstantiatedNodes, false ); + + m_hInstantiatedNodes.Purge(); +} +KeyValues *CNodeView::BuildFullCanvas() +{ + KeyValues *pNodes = CopyNodes( m_hNodeList, false ); + if ( !pNodes ) + return NULL; + + FlowGraphType_t type = GetFlowgraphType(); + + KeyValues *pCanvas = new KeyValues("canvas"); + // data version + pCanvas->SetString( GetCanvasVersion_KeyName(), GetCanvasVersion_Current() ); + + // graphtype + pCanvas->SetInt( "flowgraph_type", type ); + + // main config + if ( type == FLOWGRAPH_HLSL ) + { + KeyValues *pConfig = new KeyValues("config"); + pConfig->SetInt( "shadermodel", m_ShaderData->shader->iShaderModel ); + pConfig->SetInt( "cull_mode", m_ShaderData->shader->iCullmode ); + pConfig->SetInt( "alpha_blending", m_ShaderData->shader->iAlphablendmode ); + pConfig->SetInt( "depth_test", m_ShaderData->shader->iDepthtestmode ); + pConfig->SetInt( "depth_write", m_ShaderData->shader->iDepthwritemode ); + pConfig->SetInt( "srgb_write", m_ShaderData->shader->bsRGBWrite ? 1 : 0 ); + pCanvas->AddSubKey( pConfig ); + } + else if ( type == FLOWGRAPH_POSTPROC ) + { + KeyValues *pConfig = new KeyValues("config_ppe"); + pConfig->SetInt( "updatefbcopy", m_PPEData->bDoAutoUpdateFBCopy ); + pCanvas->AddSubKey( pConfig ); + } + + // nodes + pCanvas->AddSubKey( pNodes ); + + return pCanvas; +} +void CNodeView::RestoreFullCanvas( KeyValues *pCanvas ) +{ + PurgeCanvas(); + + FlowGraphType_t type = (FlowGraphType_t)pCanvas->GetInt( "flowgraph_type", FLOWGRAPH_HLSL ); + + SetFlowgraphType( type ); + + KeyValues *pNodes = pCanvas->FindKey( "nodes" ); + if ( pNodes ) + PasteNodes( pNodes, false ); + + if ( type == FLOWGRAPH_HLSL ) + { + KeyValues *pConfig = pCanvas->FindKey( "config" ); + if ( pConfig ) + { + Assert( m_ShaderData ); + m_ShaderData->shader->iShaderModel = pConfig->GetInt( "shadermodel" ); + m_ShaderData->shader->iCullmode = pConfig->GetInt( "cull_mode" ); + m_ShaderData->shader->iAlphablendmode = pConfig->GetInt( "alpha_blending" ); + m_ShaderData->shader->iDepthtestmode = pConfig->GetInt( "depth_test" ); + m_ShaderData->shader->iDepthwritemode = pConfig->GetInt( "depth_write" ); + m_ShaderData->shader->bsRGBWrite = !!pConfig->GetInt( "srgb_write" ); + } + } + else if ( type == FLOWGRAPH_POSTPROC ) + { + KeyValues *pConfig = pCanvas->FindKey( "config_ppe" ); + if ( pConfig ) + { + m_PPEData->bDoAutoUpdateFBCopy = !!pConfig->GetInt( "updatefbcopy" ); + } + } + + DoFullHierachyUpdate(); + + if ( GetParent() != NULL ) + pEditorRoot->UpdateTabColor( this ); +} +void CNodeView::SaveToFile( const char *fullpath ) +{ + if ( fullpath == NULL ) + fullpath = GetShadername(); + + if ( fullpath == NULL ) + return; + + KeyValues *pCanvas = BuildFullCanvas(); + if ( !pCanvas ) + return; + + pCanvas->SaveToFile( g_pFullFileSystem, fullpath, "MOD" ); + + pCanvas->deleteThis(); + + m_HistoryIndex_LastSaved = m_HistoryIndex; +} +bool CNodeView::LoadFromFile( const char *fullpath, bool bSuppressError ) +{ + bool bSuccess = false; + KeyValues *pCanvas = new KeyValues("canvas"); + + if ( pCanvas->LoadFromFile( g_pFullFileSystem, fullpath, "MOD" ) ) + { + const char *pCVName = pCanvas->GetString( GetCanvasVersion_KeyName() ); //, GetCanvasVersion_Current() ); + bool bAllowLoad = true; + + if ( pCVName && Q_strlen( pCVName ) > 0 ) + { + bAllowLoad = false; + for ( int i = 0; i < GetCanvasVersion_Amt(); i++ ) + { + if ( !Q_stricmp( GetCanvasVersion( i ), pCVName ) ) + { + bAllowLoad = true; + UpgradeFromVersion( pCanvas, pCVName ); + } + } + } + else + UpgradeFromVersion( pCanvas, NULL ); + + if ( bAllowLoad ) + { + RestoreFullCanvas( pCanvas ); + bSuccess = true; + } + else if ( !bSuppressError ) + { + vgui::PromptSimple *prompt = new vgui::PromptSimple( pEditorRoot, "ERROR" ); + prompt->MoveToCenterOfScreen(); + prompt->SetText( VarArgs( "Canvas version '%s' unsupported!", pCVName ) ); + prompt->AddButton( "Ok" ); + prompt->MakeReadyForUse(); + prompt->InvalidateLayout( true, true ); + } + } + + UnDirtySave(); + + pCanvas->deleteThis(); + return bSuccess; +} + +void CNodeView::MoveNodes( Vector2D offset, KeyValues *pKV ) +{ + int idx = 0; + for (;;) + { + KeyValues *pNode = pKV->FindKey( VarArgs("Node_%03i", idx) ); + idx++; + if ( !pNode ) + break; + + Vector2D pos( pNode->GetFloat( "pos_x" ), pNode->GetFloat( "pos_y" ) ); + pos += offset; + pNode->SetFloat( "pos_x", pos.x ); + pNode->SetFloat( "pos_y", pos.y ); + } +} +void CNodeView::MoveNodes( Vector2D offset, CBaseNode *n ) +{ + Vector2D pos = n->GetPosition(); + pos += offset; + n->SetPosition( pos ); +} +void CNodeView::MoveNodes( Vector2D offset, CUtlVector< CBaseNode* > &m_hList ) +{ + for ( int i = 0; i < m_hList.Count(); i++ ) + MoveNodes( offset, m_hList[i] ); +} +int CNodeView::GetNodeIndex( CBaseNode *n ) +{ + if ( bOverrideNodeIndices ) + return m_hTmpNodeIndex.Find( n ); + return m_hNodeList.Find( n ); +} +CBaseNode *CNodeView::GetNodeFromIndex( int idx ) +{ + if ( bOverrideNodeIndices ) + { + if ( !m_hTmpNodeIndex.IsValidIndex(idx) ) + return NULL; + return m_hTmpNodeIndex[idx]; + } + + if ( !m_hNodeList.IsValidIndex(idx) ) + return NULL; + return m_hNodeList[idx]; +} +CBaseNode *CNodeView::GetNodeFromType( int type ) +{ + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + if ( m_hNodeList[i]->GetNodeType() == type ) + return m_hNodeList[i]; + } + return NULL; +} + +void CNodeView::CreateDragBridge( CJack *j ) +{ + KillDragBridge(); + CBridge *b = j->BridgeBeginBuild(); + + m_pCurBridge = b; + m_pCurBridge->SetTemporaryTarget( GetMousePosInNodeSpace() ); +} +void CNodeView::UpdateDragBridge( CJack *j, CBaseNode *n ) +{ + KillDragBridge(); + m_pCurBridge = j->GetBridge( 0 ); + m_hBridgeList.FindAndRemove( m_pCurBridge ); + + if ( !j->IsInput() ) + m_pCurBridge->DisconnectSource(); + else + m_pCurBridge->DisconnectDestination(); + + BeginDrag( false ); + + m_pCurBridge->SetTemporaryTarget( GetMousePosInNodeSpace() ); +} +void CNodeView::FinishDragBridge( CJack *j ) +{ + if ( !m_pCurBridge ) + return; + + j->BridgeEndBuild( m_pCurBridge ); + + m_pCurBridge = NULL; +} +void CNodeView::AddBridgeToList( CBridge *b ) +{ + m_hBridgeList.AddToTail( b ); +} +void CNodeView::KillDragBridge() +{ + if ( m_pCurBridge ) + { + delete m_pCurBridge; + m_pCurBridge = NULL; + } +} +CJack *CNodeView::GetBridgeSnapJack() +{ + if ( !m_pCurBridge ) + return NULL; + + bool bHasInputDefined = !!m_pCurBridge->GetInputJack(); + float t = BRIDGE_DRAG_TOLERANCE; + CJack *curJack = GetJackUnderCursor( &t, bHasInputDefined, !bHasInputDefined ); + CBaseNode *n = curJack ? curJack->GetParentNode() : NULL; + + const bool bHasVolatileBridges = curJack != NULL && curJack->IsInput() && curJack->GetNumBridges(); + bool bSameNode = n && ( m_pCurBridge->GetInputNode() == n || m_pCurBridge->GetDestinationNode() == n ) && + !bHasVolatileBridges; + + if ( curJack && n && + ( curJack->IsInput() == bHasInputDefined ) && + !bSameNode + ) + { + //if ( curJack->IsInput() && curJack->GetNumBridges() ) + // return NULL; + + CJack *potentialInput = m_pCurBridge->GetInputJack() ? m_pCurBridge->GetInputJack() : curJack; + CJack *potentialDest = m_pCurBridge->GetDestinationJack() ? m_pCurBridge->GetDestinationJack() : curJack; + for ( int i = 0; i < m_hBridgeList.Count(); i++ ) + { + CBridge *b = m_hBridgeList[ i ]; + + if ( potentialInput == b->GetInputJack() && + potentialDest == b->GetDestinationJack() ) + return NULL; + } + + CBaseNode *origNode = bHasInputDefined ? m_pCurBridge->GetInputNode() : m_pCurBridge->GetDestinationNode(); + if ( n->RecursiveFindNode( origNode, !curJack->IsInput() ) ) + return NULL; + + if ( n == origNode ) + return NULL; + + int allowances_l, allowances_j; + int LocalHierachy = origNode->GetHierachyTypeIterateFullyRecursive(&allowances_l); + int JackHierachy = n->GetHierachyTypeIterateFullyRecursive(&allowances_j); + + if ( LocalHierachy == HLSLHIERACHY_MULTIPLE || + JackHierachy == HLSLHIERACHY_MULTIPLE ) + return NULL; + + if ( LocalHierachy != HLSLHIERACHY_NONE && + JackHierachy != HLSLHIERACHY_NONE && + JackHierachy != LocalHierachy ) + return NULL; + + if ( ( LocalHierachy > 0 && !( allowances_j & LocalHierachy ) ) || + ( JackHierachy > 0 && !( allowances_l & JackHierachy ) ) ) + return NULL; + + if ( bHasVolatileBridges ) + curJack->GetBridge( 0 )->SetTemporaryColor( CBridge::TMPCOL_ORANGE ); + + return curJack; + } + return NULL; +} +const bool CNodeView::ShouldDraw_Datatypes() +{ + return pEditorRoot->ShouldDraw_Datatypes(); +} +const bool CNodeView::ShouldDraw_Shadows() +{ + return pEditorRoot->ShouldDraw_Shadows(); +} +const bool CNodeView::ShouldDraw_Nodes() +{ + return pEditorRoot->ShouldDraw_Nodes(); +} +const bool CNodeView::ShouldDraw_Jacks() +{ + return pEditorRoot->ShouldDraw_Jacks(); +} +const bool CNodeView::ShouldDraw_Bridges() +{ + return pEditorRoot->ShouldDraw_Bridges(); +} + +void CNodeView::Paint() +{ + BaseClass::Paint(); + + if ( sedit_2dprev_Enable.GetInt() ) + UpdateRTs(); + + int wide, tall; + GetSize( wide, tall ); + + Paint_Grid(); + if ( ShouldDraw_Shadows() ) + { + if ( ShouldDraw_Nodes() ) + Paint_Nodes(true); + if ( ShouldDraw_Bridges() ) + Paint_Bridges(true); + } + if ( ShouldDraw_Nodes() ) + Paint_Nodes(false); + if ( ShouldDraw_Bridges() ) + Paint_Bridges(false); + + Paint_SelectionBox(); + + if ( bRenderingScreenShot ) + { + int inset; + inset = min( vecScreenshotBounds.z - vecScreenshotBounds.x, vecScreenshotBounds.w - vecScreenshotBounds.y ); + inset *= 0.3f; + + Vector2D top_left( vecScreenshotBounds.x, vecScreenshotBounds.w ); + Vector2D bottom_right( vecScreenshotBounds.z, vecScreenshotBounds.y ); + + ToPanelSpace( top_left ); + ToPanelSpace( bottom_right ); + + surface()->DrawSetTexture( m_iTex_Darken ); + surface()->DrawSetColor( Color( 0,0,0,96 ) ); + surface()->DrawTexturedSubRect( top_left.x, top_left.y, top_left.x + inset, bottom_right.y, 0, 0, 1, 1 ); + surface()->DrawTexturedSubRect( bottom_right.x - inset, top_left.y, bottom_right.x, bottom_right.y, 1, 0, 0, 1 ); + + Vertex_t points[4]; + points[0].Init( Vector2D( top_left.x, top_left.y ), Vector2D( 0, 1 ) ); + points[1].Init( Vector2D( bottom_right.x, top_left.y ), Vector2D( 0, 0 ) ); + points[2].Init( Vector2D( bottom_right.x, top_left.y + inset ), Vector2D( 1, 0 ) ); + points[3].Init( Vector2D( top_left.x, top_left.y + inset ), Vector2D( 1, 1 ) ); + surface()->DrawTexturedPolygon( 4, points ); + + points[0].Init( Vector2D( top_left.x, bottom_right.y - inset ), Vector2D( 1, 0 ) ); + points[1].Init( Vector2D( bottom_right.x, bottom_right.y - inset ), Vector2D( 1, 1 ) ); + points[2].Init( Vector2D( bottom_right.x, bottom_right.y ), Vector2D( 0, 1 ) ); + points[3].Init( Vector2D( top_left.x, bottom_right.y ), Vector2D( 0, 0 ) ); + surface()->DrawTexturedPolygon( 4, points ); + + surface()->DrawSetTextPos( top_left.x + 15, top_left.y + 15 ); + surface()->DrawSetTextFont( pEditorRoot->GetFont1( MAX_ZOOM_FONTS - 1 ) ); + surface()->DrawSetTextColor( NODE_DRAW_COLOR_TEXT_OP ); + + char name[MAX_PATH]; + if ( pEditorRoot->GetCurrentShaderName() != NULL ) + Q_FileBase( pEditorRoot->GetCurrentShaderName(), name, MAX_PATH ); + else + Q_snprintf( name, sizeof(name), "Unnamed shader" ); + wchar_t szconverted[ 256 ]; + g_pVGuiLocalize->ConvertANSIToUnicode( name, szconverted, sizeof(szconverted) ); + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } + else + { + int inset = 256; + + surface()->DrawSetTexture( m_iTex_Darken ); + surface()->DrawSetColor( Color( 0,0,0,96 ) ); + surface()->DrawTexturedSubRect( 0, 0, inset, tall, 0, 0, 1, 1 ); + surface()->DrawTexturedSubRect( wide - inset, 0, wide, tall, 1, 0, 0, 1 ); + + Vertex_t points[4]; + points[0].Init( Vector2D( 0, 0 ), Vector2D( 0, 1 ) ); + points[1].Init( Vector2D( wide, 0 ), Vector2D( 0, 0 ) ); + points[2].Init( Vector2D( wide, inset ), Vector2D( 1, 0 ) ); + points[3].Init( Vector2D( 0, inset ), Vector2D( 1, 1 ) ); + surface()->DrawTexturedPolygon( 4, points ); + + points[0].Init( Vector2D( 0, tall - inset ), Vector2D( 1, 0 ) ); + points[1].Init( Vector2D( wide, tall - inset ), Vector2D( 1, 1 ) ); + points[2].Init( Vector2D( wide, tall ), Vector2D( 0, 1 ) ); + points[3].Init( Vector2D( 0, tall ), Vector2D( 0, 0 ) ); + surface()->DrawTexturedPolygon( 4, points ); + + Paint_StatusBar(); + Paint_CompilerIcon(); + Paint_PreCompilerErrors(); + } +} +void CNodeView::Paint_StatusBar() +{ + if ( GetStackIndex() == GetCompiledStackIndex() && !m_flErrorTime ) + return; + + Vector4D col( _col_OutOfDate[0] / 255.0f, + _col_OutOfDate[1] / 255.0f, + _col_OutOfDate[2] / 255.0f, + _col_OutOfDate[3] / 255.0f ); + + bool bOutofDate = GetStackIndex() != GetCompiledStackIndex(); + if ( !bOutofDate ) + col.w = 0; + + if ( m_flErrorTime ) + { + col.x = _col_Error[0] / 255.0f; + col.y = _col_Error[1] / 255.0f; + col.z = _col_Error[2] / 255.0f; + col.w = abs( sin( m_flErrorTime * M_PI * 4 ) ) * m_flErrorTime; + m_flErrorTime -= gpGlobals->frametime; + if ( m_flErrorTime < 0 ) + m_flErrorTime = 0; + } + + if ( col.w < 0.025f ) + return; + +#define ERRORBORDER_EXTRUDE 5 + + int sx,sy; + GetSize( sx, sy ); + + surface()->DrawSetColor( Color( col.x * 255, col.y * 255, col.z * 255, col.w * 255 ) ); + + surface()->DrawFilledRect( 0, 0, ERRORBORDER_EXTRUDE, sy ); + surface()->DrawFilledRect( sx - ERRORBORDER_EXTRUDE, 0, sx, sy ); + surface()->DrawFilledRect( ERRORBORDER_EXTRUDE, 0, sx - ERRORBORDER_EXTRUDE, ERRORBORDER_EXTRUDE ); + surface()->DrawFilledRect( ERRORBORDER_EXTRUDE, sy - ERRORBORDER_EXTRUDE, sx - ERRORBORDER_EXTRUDE, sy ); +} +void CNodeView::Paint_CompilerIcon() +{ + if ( !gShaderEditorSystem->IsCompilerRunning() ) + return; + + int sx, sy; + GetSize( sx, sy ); + + int size = scheme()->GetProportionalScaledValue( 20 ); + int offset = scheme()->GetProportionalScaledValue( 1 ); + + DynRenderHelper info; + + info.Size = size * 1.5f; + info.Orig.x = sx - size; + info.Orig.y = size; + info.Rotation = -45.0f * floor( 10.0f * gpGlobals->curtime ); + + surface()->DrawSetTexture( m_iTex_BusyIco ); + surface()->DrawSetColor( Color( 32, 32, 32, 255 ) ); + ::PaintDynamicRotationStructure( info ); + + info.Orig -= Vector2D( offset, offset ); + surface()->DrawSetColor( Color( 200, 200, 200, 255 ) ); + ::PaintDynamicRotationStructure( info ); +} +void CNodeView::Paint_PreCompilerErrors() +{ + const int ypos_delta = 10; + int ypos_current = 5; + const bool bDrawAll = pEditorRoot->ShouldDraw_AllLimits(); + + const Color collist[ 3 ] = { + Color( 200, 200, 200, 255 ), // normal + Color( 180, 180, 60, 255 ), // limit + Color( 140, 50, 50, 255 ), // error + }; + + HFont font = pEditorRoot->GetFont1( 12 ); + surface()->DrawSetTextFont( font ); + + for ( int i = 0; i < hErrorList.Count(); i++ ) + { + LimitReport_t *pE = hErrorList[i]; + const bool bIsError = pE->i_cur > pE->i_max; + const bool bIsLimit = pE->i_cur == pE->i_max; + if ( !bDrawAll && !bIsError ) + continue; + + int textColor = bIsError ? 2 : ( bIsLimit ? 1 : 0 ); + surface()->DrawSetTextPos( 8, ypos_current ); + ypos_current += ypos_delta; + surface()->DrawSetTextColor( collist[ textColor ] ); + + char szText[ 1024 ]; + Q_snprintf( szText, sizeof(szText), "%s: %i / %i", pE->sz_name, pE->i_cur, pE->i_max ); + + wchar_t szconverted[ 1024 ]; + g_pVGuiLocalize->ConvertANSIToUnicode( szText, szconverted, sizeof(szconverted) ); + surface()->DrawPrintText( szconverted, wcslen( szconverted ) ); + } +} +void CNodeView::Paint_Grid() +{ + //const float zoomOld = m_flZoom; + + //const Vector4D gridSteps[] = { + // // zoom cellsize thickness colormult + // Vector4D( 2.0f, 4.5f, 14.0f, 0.25f ), + // Vector4D( 1.0f, 1.0f, 2.5f, 1.0f ), + //}; + + //for ( int i = 1; i < 2; i++ ) + { + //m_flZoom = zoomOld * gridSteps[i].x; + + //const int flCellSize = GRID_CELL_SIZE; // * gridSteps[i].y; + + float alpha = Bias( RemapValClamped( m_flZoom, 0.5f, VIEWZOOM_OUT_MAX - 2, 1.0f, 0 ), 0.4f ); + Color bg = GetBgColor(); + //float intensity = bg.r() - 15.0f * alpha; // * gridSteps[i].w; + Color col = Lerp( alpha, bg, _col_Grid ); + surface()->DrawSetColor( col ); //Color( intensity, intensity, intensity, 255 ) ); + + int sx,sy; + GetSize(sx,sy); + + Vector2D pos_min( 0, 0 ); + Vector2D pos_max( sx, sy ); + Vector2D tmp1,tmp2; + + ToNodeSpace( pos_min ); + ToNodeSpace( pos_max ); + + Vector2D delta = pos_max - pos_min; + delta.y *= -1.0f; + + int num_vertical = max( 1, ceil( abs(delta.x) / GRID_CELL_SIZE ) ) + 1; + int num_horizontal = max( 1, ceil( abs(delta.y) / GRID_CELL_SIZE ) ) + 1; + + float startx = ceil( pos_min.x / GRID_CELL_SIZE ) * GRID_CELL_SIZE; + float starty = floor( pos_min.y / GRID_CELL_SIZE ) * GRID_CELL_SIZE; + + tmp1.Init( startx, starty ); + tmp2.Init( startx+GRID_CELL_SIZE, starty-GRID_CELL_SIZE ); + + ToPanelSpace( tmp1 ); + ToPanelSpace( tmp2 ); + + tmp2 = tmp2 - tmp1; + + Vector2D orig( 0, 0 ); + Vector2D thickness( 2.5f, 0 ); + ToPanelSpace( orig ); + ToPanelSpace( thickness ); + thickness.x = max( 1, thickness.x - orig.x ) * 0.5f; + + tmp1 -= tmp2; + + for ( int i = 0; i < num_vertical; i++ ) + { + surface()->DrawFilledRect( tmp1.x + tmp2.x * i - thickness.x, 0, + tmp1.x + tmp2.x * i + thickness.x, sy ); + } + for ( int i = 0; i < num_horizontal; i++ ) + { + surface()->DrawFilledRect( 0, tmp1.y + tmp2.y * i - thickness.x, + sx, tmp1.y + tmp2.y * i + thickness.x ); + } + } + + //m_flZoom = zoomOld; +} +void CNodeView::Paint_Nodes( bool bShadow ) +{ + for ( int i = 0; i < m_hNodeList.Count(); i++ ) + { + CBaseNode *p = m_hNodeList[i]; + p->VguiDraw( bShadow ); + } +} +void CNodeView::Paint_Bridges( bool bShadow ) +{ + for ( int i = 0; i < m_hBridgeList.Count(); i++ ) + { + CBridge *p = m_hBridgeList[i]; + p->VguiDraw( bShadow ); + } + + if ( m_pCurBridge ) + { + m_pCurBridge->VguiDraw( bShadow ); + } +} +void CNodeView::Paint_SelectionBox() +{ + if ( !IsInDrag() ) + return; + if ( iArmDrag != DRAG_SBOX ) + return; + + Vector2D curpos = GetMousePosInNodeSpace(); + Vector2D oldpos = m_vecSelectionBoxStart; + + ToPanelSpace( curpos ); + ToPanelSpace( oldpos ); + surface()->DrawSetColor( Color( 128, 128, 164, 128 ) ); + + Vector2D _min = Vector2D( min( curpos.x, oldpos.x ), + min( curpos.y, oldpos.y ) ); + Vector2D _max = Vector2D( max( curpos.x, oldpos.x ), + max( curpos.y, oldpos.y ) ); + + surface()->DrawFilledRect( _min.x, _min.y, _max.x, _max.y ); + + surface()->DrawSetColor( Color( 48, 48, 96, 196 ) ); + surface()->DrawLine( _min.x-1, _min.y-1, _max.x, _min.y-1 ); + surface()->DrawLine( _min.x-1, _max.y, _max.x, _max.y ); + surface()->DrawLine( _min.x-1, _min.y-1, _min.x-1, _max.y ); + surface()->DrawLine( _max.x, _min.y-1, _max.x, _max.y ); +} + +void CNodeView::InitColors() +{ + _col_Grid = Color( 148, 148, 148, 255 ); + _col_Vignette = Color( 0, 0, 0, 96 ); + + _col_OutOfDate.SetColor( 50, 50, 62, 0 ); + _col_Error.SetColor( 180, 50, 62, 0 ); +} + +void CNodeView::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + SetPaintBackgroundEnabled(true); + SetPaintBorderEnabled(true); + + SetPaintBackgroundType( 0 ); + //SetBorder(pScheme->GetBorder("BaseBorder")); + + SetMouseInputEnabled(true); + SetKeyBoardInputEnabled(true); + + SetBgColor( pScheme->GetColor( "NodeView.Bg", GetBgColor() ) ); + + InitColors(); + _col_Grid = pScheme->GetColor( "NodeView.Grid", _col_Grid ); + _col_Vignette = pScheme->GetColor( "NodeView.Vignette", _col_Vignette ); + + _col_OutOfDate = pScheme->GetColor( "EditorRoot.OutOfDate", _col_OutOfDate ); + _col_Error = pScheme->GetColor( "EditorRoot.Error", _col_Error ); +} +void CNodeView::PerformLayout() +{ + BaseClass::PerformLayout(); + +#if 0 + int viewer_inset = 22; + int viewer_inset_y = 90; + int w,t; + //engine->GetScreenSize( w, t ); + GetParent()->GetSize( w, t ); + SetPos( viewer_inset, viewer_inset_y ); + SetSize( w - viewer_inset * 2, t - viewer_inset - viewer_inset_y ); +#else + int w,t; + GetParent()->GetSize( w, t ); + SetPos( 0, 0 ); + SetSize( w, t ); +#endif +} +HFont CNodeView::GetFontScaled( float Scale, bool &bVis, float *zoom ) +{ + if ( !pEditorRoot ) + { + bVis = true; + return 0; + } + + int maxFonts = MAX_ZOOM_FONTS - 1; + Scale *= zoom ? *zoom : GetZoomScalar(); + bVis = ( Scale > 2.0f ) ? true : false; + HFont tmp = pEditorRoot->GetFont1( clamp(((int)Scale)-1,0,maxFonts)); + return tmp; +} +HFont CNodeView::GetFontScaledNoOutline( float Scale, bool &bVis, float *zoom ) +{ + return 0; + //int maxFonts = MAX_ZOOM_FONTS - 1; + //Scale *= zoom ? *zoom : GetZoomScalar(); + //bVis = ( Scale > 2.0f ) ? true : false; + //HFont tmp = pEditorRoot->GetFont2(clamp(((int)Scale)-1,0,maxFonts)); + //return tmp; +} + +void CNodeView::OnCommand( const char *command ) +{ + BaseClass::OnCommand( command ); + + if ( !Q_stricmp( command, "node_delete" ) ) + DeleteSelection(); + if ( !Q_stricmp( command, "node_disconnect" ) ) + DisconnectSelection(); + if ( !Q_stricmp( command, "node_copy" ) ) + CopySelection(); + if ( !Q_stricmp( command, "node_paste" ) ) + PasteSelection(); + if ( !Q_stricmp( command, "node_cut" ) ) + { + CopySelection(); + DeleteSelection(); + } +} + +#define NODESWITCH( nodeType, nodeClass ) case nodeType:\ + pNode = new nodeClass(this);\ + break; + +CBaseNode *CNodeView::SpawnNode( int type ) +{ + CBaseNode *pNode = NULL; + switch ( type ) + { + default: + Warning( "node type %i not implemented!\n", type ); + break; +// SHADER STRUCTS + case HLSLNODE_VS_IN: + pNode = new CNodeVSInput(this); + break; + case HLSLNODE_VS_OUT: + pNode = new CNodeVSOutput(this); + break; + case HLSLNODE_PS_IN: + pNode = new CNodePSInput(this); + break; + case HLSLNODE_PS_OUT: + pNode = new CNodePSOutput(this); + break; + +// MATRICES + case HLSLNODE_MATRIX_MODELVIEWPROJ: + pNode = new CNodeMatrix_MVP(this); + break; + case HLSLNODE_MATRIX_VIEWPROJ: + pNode = new CNodeMatrix_VP(this); + break; + case HLSLNODE_MATRIX_MODEL: + pNode = new CNodeMatrix_M(this); + break; + case HLSLNODE_MATRIX_VIEWMODEL: + pNode = new CNodeMatrix_VM(this); + break; + + NODESWITCH( HLSLNODE_MATRIX_FLASHLIGHT, CNodeMatrix_FVP ); + NODESWITCH( HLSLNODE_MATRIX_COMPOSE, CNodeMCompose ); + NODESWITCH( HLSLNODE_MATRIX_CUSTOM, CNodeMatrix_Custom ); + +// MATH + case HLSLNODE_MATH_ADD: + pNode = new CNodeAdd(this); + break; + case HLSLNODE_MATH_SUBTRACT: + pNode = new CNodeSubtract(this); + break; + case HLSLNODE_MATH_MULTIPLY: + pNode = new CNodeMultiply(this); + break; + case HLSLNODE_MATH_DIVIDE: + pNode = new CNodeDivide(this); + break; + + NODESWITCH( HLSLNODE_MATH_LERP, CNodeLerp ); + NODESWITCH( HLSLNODE_MATH_SMOOTHSTEP, CNodeSmoothstep ); + NODESWITCH( HLSLNODE_MATH_STEP, CNodeStep ); + NODESWITCH( HLSLNODE_MATH_CLAMP, CNodeClamp ); + NODESWITCH( HLSLNODE_MATH_POW, CNodePower ); + NODESWITCH( HLSLNODE_MATH_ROUND, CNodeRound ); + NODESWITCH( HLSLNODE_MATH_FRAC, CNodeFraction ); + NODESWITCH( HLSLNODE_MATH_FLOOR, CNodeFloor ); + NODESWITCH( HLSLNODE_MATH_CEIL, CNodeCeil ); + NODESWITCH( HLSLNODE_MATH_ABS, CNodeAbs ); + NODESWITCH( HLSLNODE_MATH_MIN, CNodeMin ); + NODESWITCH( HLSLNODE_MATH_MAX, CNodeMax ); + NODESWITCH( HLSLNODE_MATH_FMOD, CNodeFMod ); + + NODESWITCH( HLSLNODE_MATH_SIN, CNodeSin ); + NODESWITCH( HLSLNODE_MATH_ASIN, CNodeASin ); + NODESWITCH( HLSLNODE_MATH_SINH, CNodeSinH ); + NODESWITCH( HLSLNODE_MATH_COS, CNodeCos ); + NODESWITCH( HLSLNODE_MATH_ACOS, CNodeACos ); + NODESWITCH( HLSLNODE_MATH_COSH, CNodeCosH ); + NODESWITCH( HLSLNODE_MATH_TAN, CNodeTan ); + NODESWITCH( HLSLNODE_MATH_ATAN, CNodeATan ); + NODESWITCH( HLSLNODE_MATH_TANH, CNodeTanH ); + NODESWITCH( HLSLNODE_MATH_ATAN2, CNodeATan2 ); + + NODESWITCH( HLSLNODE_MATH_DEGREES, CNodeDegrees ); + NODESWITCH( HLSLNODE_MATH_RADIANS, CNodeRadians ); + NODESWITCH( HLSLNODE_MATH_SATURATE, CNodeSaturate ); + NODESWITCH( HLSLNODE_MATH_INVERT, CNodeInvert ); + NODESWITCH( HLSLNODE_MATH_SIGN, CNodeSign ); + NODESWITCH( HLSLNODE_MATH_SQRT, CNodeRoot ); + + NODESWITCH( HLSLNODE_MATH_LOG, CNodeLog ); + NODESWITCH( HLSLNODE_MATH_LOG2, CNodeLog2 ); + NODESWITCH( HLSLNODE_MATH_LOG10, CNodeLog10 ); + NODESWITCH( HLSLNODE_MATH_EXP, CNodeExp ); + NODESWITCH( HLSLNODE_MATH_EXP2, CNodeExp2 ); + + NODESWITCH( HLSLNODE_MATH_DDX, CNodeddx ); + NODESWITCH( HLSLNODE_MATH_DDY, CNodeddy ); + +// VECTORS + case HLSLNODE_MATH_SWIZZLE: + pNode = new CNodeSwizzle(this); + break; + case HLSLNODE_MATH_DOT: + pNode = new CNodeDot(this); + break; + case HLSLNODE_MATH_NORMALIZE: + pNode = new CNodeNormalize(this); + break; + case HLSLNODE_MATH_LENGTH: + pNode = new CNodeLength(this); + break; + + NODESWITCH( HLSLNODE_VECTOR_REFLECT, CNodeVectorReflect ); + NODESWITCH( HLSLNODE_VECTOR_REFRACT, CNodeVectorRefract ); + NODESWITCH( HLSLNODE_MATH_APPEND, CNodeAppend ); + NODESWITCH( HLSLNODE_VECTOR_CROSS, CNodeCross ); + NODESWITCH( HLSLNODE_VECTOR_DISTANCE, CNodeDistance ); + +// CONSTANTS + case HLSLNODE_CONSTANT_LOCAL: + pNode = new CNodeConstant(this); + break; + case HLSLNODE_CONSTANT_VIEW_ORIGIN: + case HLSLNODE_CONSTANT_VIEW_FORWARD: + case HLSLNODE_CONSTANT_VIEW_UP: + case HLSLNODE_CONSTANT_VIEW_RIGHT: + case HLSLNODE_CONSTANT_VIEW_WORLDSPACE_DEPTH: + case HLSLNODE_CONSTANT_FB_PIXELSIZE: + case HLSLNODE_CONSTANT_FOGPARAMS: + case HLSLNODE_CONSTANT_TIME: + { + int targetIdx = HLSLENV_TIME; + float defSmartVal0 = 0.0f; + + if ( type < HLSLNODE_CONSTANT_TIME ) + targetIdx = (type - HLSLNODE_CONSTANT_VIEW_ORIGIN) + HLSLENV_VIEW_ORIGIN; + else + { + switch ( type ) + { + case HLSLNODE_CONSTANT_FB_PIXELSIZE: + targetIdx = HLSLENV_PIXEL_SIZE; + defSmartVal0 = 1.0f; + break; + case HLSLNODE_CONSTANT_FOGPARAMS: + targetIdx = HLSLENV_FOG_PARAMS; + break; + } + } + CNodeEnvC *pCastedNode = new CNodeEnvC(this,defSmartVal0); + pCastedNode->SetEnvCType( targetIdx ); + pNode = pCastedNode; + } + break; + NODESWITCH( HLSLNODE_CONSTANT_CALLBACK, CNodeCallback ); + NODESWITCH( HLSLNODE_CONSTANT_VP_MUTABLE, CNodeVmtParam_Mutable ); + NODESWITCH( HLSLNODE_CONSTANT_VP_STATIC, CNodeVmtParam_Static ); + NODESWITCH( HLSLNODE_CONSTANT_LIGHTSCALE, CNodeLightscale ); + NODESWITCH( HLSLNODE_CONSTANT_RANDOM, CNodeRandom ); + NODESWITCH( HLSLNODE_CONSTANT_BUMPBASIS, CNodeBumpBasis ); + NODESWITCH( HLSLNODE_CONSTANT_ARRAY, CNodeArray ); + NODESWITCH( HLSLNODE_CONSTANT_FLASHLIGHTPOS, CNodeFlashlight_Position ); + +// TEXTURE + case HLSLNODE_TEXTURE_SAMPLER: + pNode = new CNodeTexSample(this); + break; + NODESWITCH( HLSLNODE_TEXTURE_TRANSFORM, CNodeTexTransform ); + NODESWITCH( HLSLNODE_TEXTURE_SAMPLEROBJECT, CNodeSampler ); + NODESWITCH( HLSLNODE_TEXTURE_PARALLAX, CNodeParallax ); + NODESWITCH( HLSLNODE_TEXTURE_PARALLAX_SHADOW, CNodeParallax_StdShadow ); + +// CONTROLFLOW + case HLSLNODE_CONTROLFLOW_LOOP: + pNode = new CNodeLoop(this); + break; + NODESWITCH( HLSLNODE_CONTROLFLOW_COMBO, CNodeCombo ); + NODESWITCH( HLSLNODE_CONTROLFLOW_CONDITION, CNodeCondition ); + NODESWITCH( HLSLNODE_CONTROLFLOW_BREAK, CNodeBreak ); + NODESWITCH( HLSLNODE_CONTROLFLOW_CLIP, CNodeClip ); + +// UTILITY + case HLSLNODE_UTILITY_DECLARE: + pNode = new CNodeUtility_Declare(this); + break; + case HLSLNODE_UTILITY_ASSIGN: + pNode = new CNodeUtility_Assign(this); + break; + + NODESWITCH( HLSLNODE_STUDIO_VERTEXLIGHTING, CNodeStdVLight ); + NODESWITCH( HLSLNODE_STUDIO_PIXELSHADER_LIGHTING, CNodeStdPLight ); + NODESWITCH( HLSLNODE_STUDIO_PIXELSHADER_SPECLIGHTING, CNodeStdPSpecLight ); + NODESWITCH( HLSLNODE_STUDIO_SKINNING, CNodeStdSkinning ); + NODESWITCH( HLSLNODE_STUDIO_MORPH, CNodeStdMorph ); + NODESWITCH( HLSLNODE_STUDIO_VCOMPRESSION, CNodeVCompression ); + NODESWITCH( HLSLNODE_UTILITY_FOG, CNodeFog ); + NODESWITCH( HLSLNODE_UTILITY_FINAL, CNodeFinal ); + NODESWITCH( HLSLNODE_UTILITY_FLASHLIGHT, CNodeFlashlight ); + NODESWITCH( HLSLNODE_UTILITY_CUSTOMCODE, CNodeCustom ); + +// POST PROCESSING EFFECTS + NODESWITCH( HLSLNODE_POSTPROCESSING_INPUT, CNodePP_Input ); + NODESWITCH( HLSLNODE_POSTPROCESSING_OUTPUT, CNodePP_Output ); + + NODESWITCH( HLSLNODE_POSTPROCESSING_CREATE_RT, CNodePP_RT ); + NODESWITCH( HLSLNODE_POSTPROCESSING_CREATE_MAT, CNodePP_Mat ); + NODESWITCH( HLSLNODE_POSTPROCESSING_COPY_RT, CNodePP_CopyRT ); + + NODESWITCH( HLSLNODE_POSTPROCESSING_PUSH_VP, CNodePP_VP_Push ); + NODESWITCH( HLSLNODE_POSTPROCESSING_POP_VP, CNodePP_VP_Pop ); + NODESWITCH( HLSLNODE_POSTPROCESSING_SET_RT, CNodePP_VP_SetRT ); + + NODESWITCH( HLSLNODE_POSTPROCESSING_CLEAR_BUFFERS, CNodePP_ClearBuffers ); + NODESWITCH( HLSLNODE_POSTPROCESSING_DRAW_MATERIAL, CNodePP_DrawMat ); + NODESWITCH( HLSLNODE_POSTPROCESSING_UPDATE_FB, CNodePP_UpdateFB ); + NODESWITCH( HLSLNODE_POSTPROCESSING_RENDER_VIEW, CNodePP_RenderView ); + +// MISC + NODESWITCH( HLSLNODE_OTHER_COMMENT, CNodeComment ); + } + + if ( !pNode ) + return NULL; + + if ( !( GetFlowgraphType() & pNode->GetAllowedFlowgraphTypes() ) ) + { + delete pNode; + return NULL; + } + + pNode->Spawn(); + + OnHierachyChanged(); + m_hNodeList.AddToTail( pNode ); + return pNode; +} +void CNodeView::OnSpawnNode( int type ) +{ + CBaseNode *pNode = SpawnNode( type ); + if ( !pNode ) + return; + + pNode->SetPosition( m_vecMenuCreationPosition, true ); +} + +void CNodeView::OnMenuClosed( KeyValues *pData ) +{ + Panel *pMenu = ((Panel*)pData->GetPtr( "panel" )); + if ( pMenu == m_ContextMenu.Get() ) + { + delete m_ContextMenu.Get(); + m_ContextMenu = NULL; + } +} +void CNodeView::CreateContextMenu( CBaseNode *pMouseOverNode ) +{ + if ( m_ContextMenu.Get() ) + { + delete m_ContextMenu.Get(); + m_ContextMenu = NULL; + } + + UpdateMousePos(); + m_vecMenuCreationPosition.Init( Mx, My ); + ToNodeSpace( m_vecMenuCreationPosition ); + + bool bMouseOverNode = pMouseOverNode != NULL; + bool bOtherNodesSelected = IsSelectionBiggerThanOne(); + bool bAnyNodesSelected = bMouseOverNode || bOtherNodesSelected; + + bool bCrucialNode = bMouseOverNode && pMouseOverNode->IsNodeCrucial(); + bool bBlockOnSingleCrucialNode = bCrucialNode && !bOtherNodesSelected; + bool bNodesInCopySlot = !!pEditorRoot->GetCopyNodes(); + + Panel *pMenuParent = this; + + Menu *m = new Menu( pMenuParent, "contextmenu" ); + Menu *padd = new Menu( m, "addmenu" ); + + AddNodesToContextMenu( padd ); + + m->AddCascadingMenuItem( "New node", this, padd ); + + int tmp; + tmp = m->AddMenuItem( "Copy", "node_copy", this ); + if ( !bAnyNodesSelected || bBlockOnSingleCrucialNode ) + m->GetMenuItem( tmp )->SetEnabled( false ); + + tmp = m->AddMenuItem( "Cut", "node_cut", this ); + if ( !bAnyNodesSelected || bBlockOnSingleCrucialNode ) + m->GetMenuItem( tmp )->SetEnabled( false ); + + tmp = m->AddMenuItem( "Paste", "node_paste", this ); + if ( !bNodesInCopySlot ) + m->GetMenuItem( tmp )->SetEnabled( false ); + + tmp = m->AddMenuItem( "Delete", "node_delete", this ); + if ( !bAnyNodesSelected || bBlockOnSingleCrucialNode ) + m->GetMenuItem( tmp )->SetEnabled( false ); + + tmp = m->AddMenuItem( "Disconnect", "node_disconnect", this ); + if ( !bAnyNodesSelected ) + m->GetMenuItem( tmp )->SetEnabled( false ); + + KeyValues *pKV_P = new KeyValues("OpenProperties"); + pKV_P->SetPtr( "pNode", pMouseOverNode ); + tmp = m->AddMenuItem( "Properties", pKV_P, this ); + if ( ( bOtherNodesSelected || !bAnyNodesSelected ) || !bMouseOverNode ) m->GetMenuItem( tmp )->SetEnabled( false ); + + m_ContextMenu = m; + //input()->SetMouseFocus( m_ContextMenu->GetVPanel() ); + + Menu::PlaceContextMenu( pMenuParent, m_ContextMenu ); +} +void CNodeView::AddNodesToContextMenu( Menu *pNodeMenu ) +{ + FlowGraphType_t type = GetFlowgraphType(); + + Menu *padd_misc = new Menu( pNodeMenu, "addmenu_misc" ); + + if ( type == FLOWGRAPH_HLSL || type == FLOWGRAPH_HLSL_TEMPLATE ) + { + Menu *padd_math = new Menu( pNodeMenu, "addmenu_math" ); + Menu *padd_math_round = new Menu( pNodeMenu, "addmenu_math_round" ); + Menu *padd_math_trigo = new Menu( pNodeMenu, "addmenu_math_trigo" ); + Menu *padd_math_vec = new Menu( pNodeMenu, "addmenu_math_vec" ); + Menu *padd_const = new Menu( pNodeMenu, "addmenu_constants" ); + Menu *padd_matrix = new Menu( pNodeMenu, "addmenu_matrix" ); + Menu *padd_tex = new Menu( pNodeMenu, "addmenu_textures" ); + Menu *padd_controlflow = new Menu( pNodeMenu, "addmenu_controlflow" ); + Menu *padd_utility = new Menu( pNodeMenu, "addmenu_utility" ); + Menu *padd_utility_studio = new Menu( pNodeMenu, "addmenu_utility_studio" ); + + padd_math->AddMenuItem( "Add", new KeyValues("spawnNode","type",HLSLNODE_MATH_ADD), this ); + padd_math->AddMenuItem( "Subtract", new KeyValues("spawnNode","type",HLSLNODE_MATH_SUBTRACT), this ); + padd_math->AddMenuItem( "Multiply", new KeyValues("spawnNode","type",HLSLNODE_MATH_MULTIPLY), this ); + padd_math->AddMenuItem( "Divide", new KeyValues("spawnNode","type",HLSLNODE_MATH_DIVIDE), this ); + padd_math->AddMenuItem( "Root", new KeyValues("spawnNode","type",HLSLNODE_MATH_SQRT), this ); + padd_math->AddMenuItem( "Invert", new KeyValues("spawnNode","type",HLSLNODE_MATH_INVERT), this ); + padd_math->AddMenuItem( "Power", new KeyValues("spawnNode","type",HLSLNODE_MATH_POW), this ); + padd_math->AddMenuItem( "Lerp", new KeyValues("spawnNode","type",HLSLNODE_MATH_LERP), this ); + padd_math->AddMenuItem( "FMod", new KeyValues("spawnNode","type",HLSLNODE_MATH_FMOD), this ); + padd_math->AddMenuItem( "Degrees", new KeyValues("spawnNode","type",HLSLNODE_MATH_DEGREES), this ); + padd_math->AddMenuItem( "Radians", new KeyValues("spawnNode","type",HLSLNODE_MATH_RADIANS), this ); + padd_math->AddMenuItem( "Log", new KeyValues("spawnNode","type",HLSLNODE_MATH_LOG), this ); + padd_math->AddMenuItem( "Log2", new KeyValues("spawnNode","type",HLSLNODE_MATH_LOG2), this ); + padd_math->AddMenuItem( "Log10", new KeyValues("spawnNode","type",HLSLNODE_MATH_LOG10), this ); + padd_math->AddMenuItem( "Exp", new KeyValues("spawnNode","type",HLSLNODE_MATH_EXP), this ); + padd_math->AddMenuItem( "Exp2", new KeyValues("spawnNode","type",HLSLNODE_MATH_EXP2), this ); + padd_math->AddMenuItem( "ddx", new KeyValues("spawnNode","type",HLSLNODE_MATH_DDX), this ); + padd_math->AddMenuItem( "ddy", new KeyValues("spawnNode","type",HLSLNODE_MATH_DDY), this ); + pNodeMenu->AddCascadingMenuItem( "Math", this, padd_math ); + + padd_math_round->AddMenuItem( "Abs", new KeyValues("spawnNode","type",HLSLNODE_MATH_ABS), this ); + padd_math_round->AddMenuItem( "Min", new KeyValues("spawnNode","type",HLSLNODE_MATH_MIN), this ); + padd_math_round->AddMenuItem( "Max", new KeyValues("spawnNode","type",HLSLNODE_MATH_MAX), this ); + padd_math_round->AddMenuItem( "Smooth step", new KeyValues("spawnNode","type",HLSLNODE_MATH_SMOOTHSTEP), this ); + padd_math_round->AddMenuItem( "Step", new KeyValues("spawnNode","type",HLSLNODE_MATH_STEP), this ); + padd_math_round->AddMenuItem( "Sign", new KeyValues("spawnNode","type",HLSLNODE_MATH_SIGN), this ); + padd_math_round->AddMenuItem( "Clamp", new KeyValues("spawnNode","type",HLSLNODE_MATH_CLAMP), this ); + padd_math_round->AddMenuItem( "Saturate", new KeyValues("spawnNode","type",HLSLNODE_MATH_SATURATE), this ); + padd_math_round->AddMenuItem( "Round", new KeyValues("spawnNode","type",HLSLNODE_MATH_ROUND), this ); + padd_math_round->AddMenuItem( "Fraction", new KeyValues("spawnNode","type",HLSLNODE_MATH_FRAC), this ); + padd_math_round->AddMenuItem( "Floor", new KeyValues("spawnNode","type",HLSLNODE_MATH_FLOOR), this ); + padd_math_round->AddMenuItem( "Ceil", new KeyValues("spawnNode","type",HLSLNODE_MATH_CEIL), this ); + pNodeMenu->AddCascadingMenuItem( "Math (Rounding)", this, padd_math_round ); + + padd_math_vec->AddMenuItem( "Dot", new KeyValues("spawnNode","type",HLSLNODE_MATH_DOT), this ); + padd_math_vec->AddMenuItem( "Length", new KeyValues("spawnNode","type",HLSLNODE_MATH_LENGTH), this ); + padd_math_vec->AddMenuItem( "Normalize", new KeyValues("spawnNode","type",HLSLNODE_MATH_NORMALIZE), this ); + padd_math_vec->AddMenuItem( "Append", new KeyValues("spawnNode","type",HLSLNODE_MATH_APPEND), this ); + padd_math_vec->AddMenuItem( "Swizzle", new KeyValues("spawnNode","type",HLSLNODE_MATH_SWIZZLE), this ); + padd_math_vec->AddMenuItem( "Reflect", new KeyValues("spawnNode","type",HLSLNODE_VECTOR_REFLECT), this ); + padd_math_vec->AddMenuItem( "Refract", new KeyValues("spawnNode","type",HLSLNODE_VECTOR_REFRACT), this ); + padd_math_vec->AddMenuItem( "Crossproduct", new KeyValues("spawnNode","type",HLSLNODE_VECTOR_CROSS), this ); + padd_math_vec->AddMenuItem( "Distance", new KeyValues("spawnNode","type",HLSLNODE_VECTOR_DISTANCE), this ); + pNodeMenu->AddCascadingMenuItem( "Math (Vectors)", this, padd_math_vec ); + + padd_math_trigo->AddMenuItem( "Sin", new KeyValues("spawnNode","type",HLSLNODE_MATH_SIN), this ); + padd_math_trigo->AddMenuItem( "ASin", new KeyValues("spawnNode","type",HLSLNODE_MATH_ASIN), this ); + padd_math_trigo->AddMenuItem( "SinH", new KeyValues("spawnNode","type",HLSLNODE_MATH_SINH), this ); + padd_math_trigo->AddMenuItem( "Cos", new KeyValues("spawnNode","type",HLSLNODE_MATH_COS), this ); + padd_math_trigo->AddMenuItem( "ACos", new KeyValues("spawnNode","type",HLSLNODE_MATH_ACOS), this ); + padd_math_trigo->AddMenuItem( "CosH", new KeyValues("spawnNode","type",HLSLNODE_MATH_COSH), this ); + padd_math_trigo->AddMenuItem( "Tan", new KeyValues("spawnNode","type",HLSLNODE_MATH_TAN), this ); + padd_math_trigo->AddMenuItem( "ATan", new KeyValues("spawnNode","type",HLSLNODE_MATH_ATAN), this ); + padd_math_trigo->AddMenuItem( "TanH", new KeyValues("spawnNode","type",HLSLNODE_MATH_TANH), this ); + padd_math_trigo->AddMenuItem( "ATan2", new KeyValues("spawnNode","type",HLSLNODE_MATH_ATAN2), this ); + pNodeMenu->AddCascadingMenuItem( "Math (Trig)", this, padd_math_trigo ); + + padd_const->AddMenuItem( "Local constant", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_LOCAL), this ); + padd_const->AddMenuItem( "Callback constant", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_CALLBACK), this ); + padd_const->AddMenuItem( "VParam static", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_VP_STATIC), this ); + padd_const->AddMenuItem( "VParam mutable", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_VP_MUTABLE), this ); + padd_const->AddMenuItem( "Random float", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_RANDOM), this ); + padd_const->AddMenuItem( "Array", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_ARRAY), this ); + padd_const->AddMenuItem( "View origin", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_VIEW_ORIGIN), this ); + padd_const->AddMenuItem( "View forward", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_VIEW_FORWARD), this ); + padd_const->AddMenuItem( "View up", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_VIEW_UP), this ); + padd_const->AddMenuItem( "View right", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_VIEW_RIGHT), this ); + padd_const->AddMenuItem( "View world distance", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_VIEW_WORLDSPACE_DEPTH), this ); + padd_const->AddMenuItem( "Time", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_TIME), this ); + padd_const->AddMenuItem( "FB texelsize", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_FB_PIXELSIZE), this ); + padd_const->AddMenuItem( "Fog params", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_FOGPARAMS), this ); + padd_const->AddMenuItem( "Lightscale", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_LIGHTSCALE), this ); + padd_const->AddMenuItem( "Bump basis", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_BUMPBASIS), this ); + padd_const->AddMenuItem( "Flashlight pos", new KeyValues("spawnNode","type",HLSLNODE_CONSTANT_FLASHLIGHTPOS), this ); + pNodeMenu->AddCascadingMenuItem( "Constants", this, padd_const ); + + padd_matrix->AddMenuItem( "Matrix - ModelViewProj", new KeyValues("spawnNode","type",HLSLNODE_MATRIX_MODELVIEWPROJ), this ); + padd_matrix->AddMenuItem( "Matrix - ViewProj", new KeyValues("spawnNode","type",HLSLNODE_MATRIX_VIEWPROJ), this ); + padd_matrix->AddMenuItem( "Matrix - Model", new KeyValues("spawnNode","type",HLSLNODE_MATRIX_MODEL), this ); + padd_matrix->AddMenuItem( "Matrix - ViewModel", new KeyValues("spawnNode","type",HLSLNODE_MATRIX_VIEWMODEL), this ); + padd_matrix->AddMenuItem( "Matrix - Flashlight VP", new KeyValues("spawnNode","type",HLSLNODE_MATRIX_FLASHLIGHT), this ); + padd_matrix->AddMenuItem( "Matrix compose", new KeyValues("spawnNode","type",HLSLNODE_MATRIX_COMPOSE), this ); + padd_matrix->AddMenuItem( "User matrix", new KeyValues("spawnNode","type",HLSLNODE_MATRIX_CUSTOM), this ); + pNodeMenu->AddCascadingMenuItem( "Matrices", this, padd_matrix ); + + padd_tex->AddMenuItem( "Texture sample", new KeyValues("spawnNode","type",HLSLNODE_TEXTURE_SAMPLER), this ); + padd_tex->AddMenuItem( "Texture transform", new KeyValues("spawnNode","type",HLSLNODE_TEXTURE_TRANSFORM), this ); + padd_tex->AddMenuItem( "Sampler object", new KeyValues("spawnNode","type",HLSLNODE_TEXTURE_SAMPLEROBJECT), this ); + padd_tex->AddMenuItem( "Parallax UV", new KeyValues("spawnNode","type",HLSLNODE_TEXTURE_PARALLAX), this ); + padd_tex->AddMenuItem( "Parallax shadow", new KeyValues("spawnNode","type",HLSLNODE_TEXTURE_PARALLAX_SHADOW), this ); + pNodeMenu->AddCascadingMenuItem( "Textures", this, padd_tex ); + + padd_controlflow->AddMenuItem( "Loop", new KeyValues("spawnNode","type",HLSLNODE_CONTROLFLOW_LOOP), this ); + //padd_controlflow->AddMenuItem( "Break", new KeyValues("spawnNode","type",HLSLNODE_CONTROLFLOW_BREAK), this ); + padd_controlflow->AddMenuItem( "Condition", new KeyValues("spawnNode","type",HLSLNODE_CONTROLFLOW_CONDITION), this ); + padd_controlflow->AddMenuItem( "Shader combo", new KeyValues("spawnNode","type",HLSLNODE_CONTROLFLOW_COMBO), this ); + padd_controlflow->AddMenuItem( "Clip", new KeyValues("spawnNode","type",HLSLNODE_CONTROLFLOW_CLIP), this ); + pNodeMenu->AddCascadingMenuItem( "Control flow", this, padd_controlflow ); + + padd_utility->AddMenuItem( "Declare", new KeyValues("spawnNode","type",HLSLNODE_UTILITY_DECLARE), this ); + padd_utility->AddMenuItem( "Assign", new KeyValues("spawnNode","type",HLSLNODE_UTILITY_ASSIGN), this ); + padd_utility->AddMenuItem( "Custom code", new KeyValues("spawnNode","type",HLSLNODE_UTILITY_CUSTOMCODE), this ); + padd_utility->AddMenuItem( "Pixel fog", new KeyValues("spawnNode","type",HLSLNODE_UTILITY_FOG), this ); + padd_utility->AddMenuItem( "Final output", new KeyValues("spawnNode","type",HLSLNODE_UTILITY_FINAL), this ); + padd_utility->AddMenuItem( "Flashlight", new KeyValues("spawnNode","type",HLSLNODE_UTILITY_FLASHLIGHT), this ); + + padd_utility_studio->AddMenuItem( "Vertex lighting", new KeyValues("spawnNode","type",HLSLNODE_STUDIO_VERTEXLIGHTING), this ); + padd_utility_studio->AddMenuItem( "Pixelshader lighting", new KeyValues("spawnNode","type",HLSLNODE_STUDIO_PIXELSHADER_LIGHTING), this ); + padd_utility_studio->AddMenuItem( "Pixelshader specular", new KeyValues("spawnNode","type",HLSLNODE_STUDIO_PIXELSHADER_SPECLIGHTING), this ); + padd_utility_studio->AddMenuItem( "Skinning", new KeyValues("spawnNode","type",HLSLNODE_STUDIO_SKINNING), this ); + padd_utility_studio->AddMenuItem( "Morph", new KeyValues("spawnNode","type",HLSLNODE_STUDIO_MORPH), this ); + padd_utility_studio->AddMenuItem( "Vertex decompress", new KeyValues("spawnNode","type",HLSLNODE_STUDIO_VCOMPRESSION), this ); + padd_utility->AddCascadingMenuItem( "Studio model", this, padd_utility_studio ); + pNodeMenu->AddCascadingMenuItem( "Utility", this, padd_utility ); + } + else if ( type == FLOWGRAPH_POSTPROC ) + { + Menu *padd_render = new Menu( pNodeMenu, "addmenu_render" ); + Menu *padd_stack = new Menu( pNodeMenu, "addmenu_stack" ); + Menu *padd_resource = new Menu( pNodeMenu, "addmenu_resource" ); + + padd_render->AddMenuItem( "Draw material", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_DRAW_MATERIAL), this ); + padd_render->AddMenuItem( "Clear buffers", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_CLEAR_BUFFERS), this ); + padd_render->AddMenuItem( "Update framebuffer texture", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_UPDATE_FB), this ); + padd_render->AddMenuItem( "Render view", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_RENDER_VIEW), this ); + pNodeMenu->AddCascadingMenuItem( "Render", this, padd_render ); + + padd_stack->AddMenuItem( "Push viewport", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_PUSH_VP), this ); + padd_stack->AddMenuItem( "Pop viewport", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_POP_VP), this ); + padd_stack->AddMenuItem( "Set rendertarget", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_SET_RT), this ); + pNodeMenu->AddCascadingMenuItem( "Viewport stack", this, padd_stack ); + + padd_resource->AddMenuItem( "Rendertarget", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_CREATE_RT), this ); + padd_resource->AddMenuItem( "Material", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_CREATE_MAT), this ); + padd_resource->AddMenuItem( "Copy rendertarget", new KeyValues("spawnNode","type",HLSLNODE_POSTPROCESSING_COPY_RT), this ); + pNodeMenu->AddCascadingMenuItem( "Resource", this, padd_resource ); + } + + padd_misc->AddMenuItem( "Group", new KeyValues("spawnNode","type",HLSLNODE_OTHER_COMMENT), this ); + pNodeMenu->AddCascadingMenuItem( "Misc", this, padd_misc ); +} +void CNodeView::OnOpenProperties( KeyValues *data ) +{ + CBaseNode *n = static_cast< CBaseNode* >( data->GetPtr( "pNode" ) ); + if ( !n ) + return; + CreatePropertyDialog( n ); +} +void CNodeView::CreatePropertyDialog( CBaseNode *pNode ) +{ + m_Properties = new CNodePropertySheet( pNode, this, "" ); + m_Properties->MakeReadyForUse(); + PropertySheet *pSheet = m_Properties->GetPropertySheet(); + pSheet->MakeReadyForUse(); + pSheet->InvalidateLayout( true, false ); + KeyValues *pKV = m_Properties->GetPropertyContainer(); + + int type = pNode->GetNodeType(); + CUtlVector< CSheet_Base* > hSheets; + + switch ( type ) + { +// SEMANTICS + case HLSLNODE_VS_IN: + hSheets.AddToTail( new CSheet_VSInput( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_VS_OUT: + case HLSLNODE_PS_IN: + hSheets.AddToTail( new CSheet_PSInVSOut( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_PS_OUT: + hSheets.AddToTail( new CSheet_PSOutput( pNode, this, pKV, pSheet ) ); + break; + +// MATH + case HLSLNODE_MATH_MULTIPLY: + hSheets.AddToTail( new CSheet_Multiply( pNode, this, pKV, pSheet ) ); + break; + +// VECTORS + case HLSLNODE_MATH_SWIZZLE: + hSheets.AddToTail( new CSheet_Swizzle( pNode, this, pKV, pSheet ) ); + break; + +// CONSTANTS + case HLSLNODE_CONSTANT_LOCAL: + hSheets.AddToTail( new CSheet_Constant( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONSTANT_CALLBACK: + hSheets.AddToTail( new CSheet_Callback( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONSTANT_VP_MUTABLE: + hSheets.AddToTail( new CSheet_VParam_Mutable( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONSTANT_VP_STATIC: + hSheets.AddToTail( new CSheet_VParam_Static( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONSTANT_LIGHTSCALE: + hSheets.AddToTail( new CSheet_Lightscale( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONSTANT_RANDOM: + hSheets.AddToTail( new CSheet_Random( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONSTANT_ARRAY: + hSheets.AddToTail( new CSheet_Array( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONSTANT_FB_PIXELSIZE: + hSheets.AddToTail( new CSheet_EnvCTexelsize( pNode, this, pKV, pSheet ) ); + break; + +// TEXTURES + case HLSLNODE_TEXTURE_SAMPLER: + hSheets.AddToTail( new CSheet_TextureSample( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_TEXTURE_TRANSFORM: + hSheets.AddToTail( new CSheet_TexTransform( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_TEXTURE_SAMPLEROBJECT: + { + CSheet_TextureSample *pAddSheet = new CSheet_TextureSample( pNode, this, pKV, pSheet ); + pAddSheet->MakeSamplerOnly(); + hSheets.AddToTail( pAddSheet ); + } + break; + case HLSLNODE_TEXTURE_PARALLAX: + hSheets.AddToTail( new CSheet_Parallax( pNode, this, pKV, pSheet ) ); + break; + +// FLOW CONTROL + case HLSLNODE_CONTROLFLOW_LOOP: + hSheets.AddToTail( new CSheet_Loop( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONTROLFLOW_CONDITION: + hSheets.AddToTail( new CSheet_Condition( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_CONTROLFLOW_COMBO: + hSheets.AddToTail( new CSheet_Combo( pNode, this, pKV, pSheet ) ); + break; + +// UTILITY + case HLSLNODE_STUDIO_VERTEXLIGHTING: + hSheets.AddToTail( new CSheet_Std_VLight( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_STUDIO_PIXELSHADER_LIGHTING: + hSheets.AddToTail( new CSheet_Std_PLight( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_STUDIO_PIXELSHADER_SPECLIGHTING: + hSheets.AddToTail( new CSheet_Std_PSpecLight( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_STUDIO_SKINNING: + hSheets.AddToTail( new CSheet_Std_Skinning( pNode, this, pKV, pSheet ) ); + hSheets.Tail()->SetDynamicTitle( "Skinning" ); + break; + case HLSLNODE_STUDIO_MORPH: + hSheets.AddToTail( new CSheet_Std_Skinning( pNode, this, pKV, pSheet ) ); + hSheets.Tail()->SetDynamicTitle( "Morphing" ); + break; + case HLSLNODE_STUDIO_VCOMPRESSION: + hSheets.AddToTail( new CSheet_VCompression( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_UTILITY_FINAL: + hSheets.AddToTail( new CSheet_Final( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_UTILITY_FLASHLIGHT: + hSheets.AddToTail( new CSheet_Flashlight( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_UTILITY_CUSTOMCODE: + { + CSheet_Custom_IO *pIO = new CSheet_Custom_IO( pNode, this, pKV, pSheet ); + CSheet_Custom *pCode = new CSheet_Custom( pNode, this, pKV, pSheet ); + pCode->SetIOPage( pIO ); + hSheets.AddToTail( pCode ); + hSheets.AddToTail( pIO ); + } + break; + +// MATRICES + case HLSLNODE_MATRIX_COMPOSE: + hSheets.AddToTail( new CSheet_MComp( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_MATRIX_CUSTOM: + hSheets.AddToTail( new CSheet_CMatrix( pNode, this, pKV, pSheet ) ); + break; + +// POST PROCESS + case HLSLNODE_POSTPROCESSING_CREATE_RT: + hSheets.AddToTail( new CSheet_PP_RT( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_POSTPROCESSING_CREATE_MAT: + hSheets.AddToTail( new CSheet_PP_Mat( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_POSTPROCESSING_CLEAR_BUFFERS: + hSheets.AddToTail( new CSheet_PP_ClearBuff( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_POSTPROCESSING_DRAW_MATERIAL: + hSheets.AddToTail( new CSheet_PP_DrawMat( pNode, this, pKV, pSheet ) ); + break; + case HLSLNODE_POSTPROCESSING_RENDER_VIEW: + hSheets.AddToTail( new CSheet_PP_RenderView( pNode, this, pKV, pSheet ) ); + break; + +// MISC + case HLSLNODE_OTHER_COMMENT: + hSheets.AddToTail( new CSheet_Comment( pNode, this, pKV, pSheet ) ); + break; + } + + if ( !pNode->IsNodeCrucial() ) + { + hSheets.AddToTail( new CSheet_General( pNode, this, pKV, pSheet ) ); + } + + for ( int i = 0; i < hSheets.Count(); i++ ) + { + m_Properties->AddPage( hSheets[i], hSheets[i]->GetSheetTitle() ); + } + + hSheets.Purge(); + m_Properties->DoModal(); + m_Properties->SetDeleteSelfOnClose( true ); +} +void CNodeView::MakeHistoryDirty() +{ + m_bHistoryDirty = true; +} +void CNodeView::Think_UpdateHistory() +{ + if ( !m_bHistoryDirty ) + return; + + m_bHistoryDirty = false; + if ( IsInDrag() ) + return; + + HistoryAction( HACT_PUSH ); +} +void CNodeView::HistoryAction( HistoryActions_t action ) +{ +#if ( ENABLE_HISTORY == 0 ) + return; +#endif + + switch ( action ) + { + case HACT_UNDO: + { + if ( m_hNodeViewHistory.Count() < 2 ) + break; + + m_HistoryIndex++; + + ApplyHistoryEntry( m_hNodeViewHistory[ 1 ] ); + m_hNodeViewHistory_Redo.AddToHead( m_hNodeViewHistory[ 0 ] ); + m_hNodeViewHistory.Remove( 0 ); + + Think_UpdateSolvers(); + } + break; + case HACT_REDO: + { + if ( m_hNodeViewHistory_Redo.Count() < 1 ) + break; + + m_HistoryIndex++; + + ApplyHistoryEntry( m_hNodeViewHistory_Redo[ 0 ] ); + m_hNodeViewHistory.AddToHead( m_hNodeViewHistory_Redo[ 0 ] ); + m_hNodeViewHistory_Redo.Remove( 0 ); + + Think_UpdateSolvers(); + } + break; + case HACT_PUSH: + { + NHistoryEntry_t *pE = AllocHistoryEntry(); + if ( !pE ) + break; + + m_HistoryIndex++; + + m_hNodeViewHistory.AddToHead( pE ); + FlushHistory( false, true ); + + while ( m_hNodeViewHistory.Count() > NODEVIEWHISTORY_MAXUNDO ) + { + delete m_hNodeViewHistory[ NODEVIEWHISTORY_MAXUNDO ]; + m_hNodeViewHistory.Remove( NODEVIEWHISTORY_MAXUNDO ); + } + } + break; + } + + m_bHistoryDirty = false; +} +void CNodeView::ApplyHistoryEntry( NHistoryEntry_t *pEntry ) +{ + RestoreFullCanvas( pEntry->pKV ); + pEditorRoot->SetCurrentShaderName( pEntry->szShaderName ); +} +NHistoryEntry_t *CNodeView::AllocHistoryEntry() +{ + KeyValues *pCanvas = BuildFullCanvas(); + if ( !pCanvas ) + return NULL; + + const char *pszSName = pEditorRoot->GetCurrentShaderName(); + NHistoryEntry_t *pE = new NHistoryEntry_t( pCanvas, pszSName ); + return pE; +} +void CNodeView::FlushHistory( bool bPast, bool bFuture ) +{ + if ( bPast ) + m_hNodeViewHistory.PurgeAndDeleteElements(); + + if ( bFuture ) + m_hNodeViewHistory_Redo.PurgeAndDeleteElements(); +} +int CNodeView::GetNumHistoryEntires_Undo() +{ + return m_hNodeViewHistory.Count(); +} +int CNodeView::GetNumHistoryEntires_Redo() +{ + return m_hNodeViewHistory_Redo.Count(); +} \ No newline at end of file diff --git a/sp/src/shadereditor/vnodeview.h b/sp/src/shadereditor/vnodeview.h new file mode 100644 index 00000000..de2bd756 --- /dev/null +++ b/sp/src/shadereditor/vnodeview.h @@ -0,0 +1,456 @@ +#ifndef CNODEVIEW_H +#define CNODEVIEW_H + +#include "cbase.h" +using namespace vgui; + +#include +#include +#include +#include "cSolverCallback.h" + +class CEditorRoot; +class CBaseContainerNode; +class CNodePropertySheet; +class CSmartTooltip; + +struct NHistoryEntry_t +{ +public: + NHistoryEntry_t( KeyValues *k, const char *n ) + { + pKV = k; + Q_memset( szShaderName, 0, sizeof( szShaderName ) ); + if ( n ) + Q_snprintf( szShaderName, sizeof( szShaderName ), "%s", n ); + }; + NHistoryEntry_t() + { + pKV = NULL; + Q_memset( szShaderName, 0, sizeof( szShaderName ) ); + }; + ~NHistoryEntry_t() + { + if ( pKV ) + pKV->deleteThis(); + pKV = NULL; + }; + KeyValues *pKV; + char szShaderName[MAX_PATH]; + +private: + NHistoryEntry_t( const NHistoryEntry_t &o ); +}; + +class CNodeView : public vgui::Panel, public CAutoSolverCallback +{ + DECLARE_CLASS_SIMPLE( CNodeView, vgui::Panel ); + +public: + + enum FlowGraphType_t + { + FLOWGRAPH_HLSL = ( 1 << 0 ), + FLOWGRAPH_HLSL_TEMPLATE = ( 1 << 1 ), + FLOWGRAPH_POSTPROC = ( 1 << 2 ), + }; + + CNodeView( Panel *parent, CEditorRoot *root, /*FlowGraphType_t type,*/ const char *pElementName ); + ~CNodeView(); + + FlowGraphType_t GetFlowgraphType(); + void SetFlowgraphType( FlowGraphType_t type, bool bValidateGraphData = true ); + bool ShouldCallCompiler(); + + virtual void OnThink(); + void Init( void ); + + static bool bRenderingScreenShot; + static Vector4D vecScreenshotBounds; + + void PurgeCanvas( bool OnShutdown = false ); + void InitCanvas( FlowGraphType_t type = FLOWGRAPH_HLSL, GenericShaderData *newData = NULL ); + + void OnBridgeRemoved( CBridge *b ); + void OnJackRemoved( const CJack *j ); + + void OnContainerRemoved( CBaseContainerNode *container ); + void OnContainerAdded( CBaseContainerNode *container ); + void ListContainerAtPos( Vector2D &pos, CUtlVector< CBaseContainerNode* > &hList ); // in node space + +private: + CUtlVector< CBaseContainerNode* > m_hContainerNodes; + int m_iCursorLast; + + FlowGraphType_t m_FlowGraphType; + +public: + bool IsMouseOver(); + + virtual void OnKeyCodeTyped(KeyCode code); + virtual void OnKeyCodePressed ( vgui::KeyCode code ); + virtual void OnKeyCodeReleased( vgui::KeyCode code ); + virtual void OnParentKeyCodeTyped(KeyCode code); + virtual void OnParentKeyCodePressed ( vgui::KeyCode code ); + virtual void OnParentKeyCodeReleased( vgui::KeyCode code ); + + virtual void OnMousePressed ( vgui::MouseCode code ); + virtual void OnMouseDoublePressed(MouseCode code); + virtual void OnMouseReleased( vgui::MouseCode code ); + virtual void OnCursorMoved( int x, int y ); + virtual void OnMouseWheeled( int delta ); + + virtual void OnCursorEntered(); + virtual void OnCursorExited(); + + void BeginDrag( bool bNodes ); + bool IsInDrag(); + void StopDrag( bool bNodes ); + + void HandleSelectionInputPressed( CBaseNode *pNode ); + void HandleSelectionInputReleased( CBaseNode *pNode ); + void HandleSelectionInputReleasedBox(); + + CBaseNode *GetNodeUnderCursor(); + CBaseNode *GetNodeUnderPos(Vector2D pos); + CJack *GetJackUnderCursor( float *tolerance = NULL, bool bInputs = true, bool bOutputs = true ); + CJack *GetJackUnderPos(Vector2D pos, float *tolerance = NULL, bool bInputs = true, bool bOutputs = true ); + + int GetNodeIndex( CBaseNode *n ); + CBaseNode *GetNodeFromIndex( int idx ); + CBaseNode *GetNodeFromType( int type ); + + float GetZoomScalar(); + void SetZoomScalar( float zoom ); + void ToNodeSpace( Vector2D &pos ); + void ToPanelSpace( Vector2D &pos ); + void GetGraphBoundaries( Vector4D &out ); + + void ResetView(); + void ResetView_User( bool bInitial = false ); + + Vector2D GetMousePosInNodeSpace(); + + HFont GetFontScaled( float Scale, bool &bVis, float *zoom = NULL ); + HFont GetFontScaledNoOutline( float Scale, bool &bVis, float *zoom = NULL ); + + const bool ShouldDraw_Datatypes(); + const bool ShouldDraw_Shadows(); + const bool ShouldDraw_Nodes(); + const bool ShouldDraw_Jacks(); + const bool ShouldDraw_Bridges(); + + MESSAGE_FUNC_PARAMS( OnMenuClosed, "MenuClose", pData ); + + virtual void Paint(); + +protected: + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void PerformLayout(); + +private: + + void InitColors(); + + float m_flErrorTime; + Color _col_Grid; + Color _col_Vignette; + Color _col_OutOfDate; + Color _col_Error; + +public: + Vector2D &AccessViewPos(){ return m_vecPosition; }; + float &AccessViewZoom(){ return m_flZoom; }; + +private: + + void UpdateMousePos(); + void AccumulateMouseMove(); + void SaveMousePos(); + int Mx, My; + int MxOld, MyOld; + int MxDelta, MyDelta; + + long m_lTime_MouseLastMoved; + + Vector2D m_vecPosition; + Vector2D m_vecPositionGoal; + float m_flZoom; + float m_flZoomGoal; + enum + { + DRAG_NONE = 0, + DRAG_VIEW, + DRAG_NODES, + DRAG_SBOX, + DRAG_BRDIGE, + }; + int iArmDrag; + bool bInDrag; + + void CreateTooltip( int iNodeIndex ); + void DestroyTooltip(); + CSmartTooltip *m_pTooltip; + + Vector2D m_vecSelectionBoxStart; + +public: + const int GetNumUserErrorLabels(); + CNodeViewError *GetUserErrorLabel( int index ); + + MESSAGE_FUNC_PARAMS( OnDestroyUserError, "DestroyUserError", pKV ); + +private: + CUtlVector< CNodeViewError* > m_hUserErrorLabels; + void UpdateUserErrors(); + void UpdateUserErrorLayouts(); + + int m_iTex_Darken; + void Paint_Grid(); + void Paint_Nodes( bool bShadow ); + void Paint_Bridges( bool bShadow ); + void Paint_SelectionBox(); + void Paint_CompilerIcon(); + void Paint_PreCompilerErrors(); + void Paint_StatusBar(); + + void Think_SmoothView(); + void Think_Drag(); + Vector2D Think_PullView(); + void Think_HighlightJacks(); + void Think_UpdateCursorIcon(); + void Think_CreateTooltip(); + void Think_UpdateSolvers(); +public: + bool UpdateSolvers(); +private: + + bool IsCursorOutOfBounds( Vector2D *delta = NULL ); + void ForceFocus(); + + MESSAGE_FUNC_CHARPTR( OnCommand, "Command", command ); + MESSAGE_FUNC_INT( OnSpawnNode, "spawnNode", type ); + MESSAGE_FUNC_PARAMS( OnOpenProperties, "OpenProperties", data ); + + Vector2D m_vecMenuCreationPosition; + void CreateContextMenu( CBaseNode *pMouseOverNode ); + void AddNodesToContextMenu( Menu *pNodeMenu ); + void CreatePropertyDialog( CBaseNode *pNode ); + + DHANDLE< Menu > m_ContextMenu; + DHANDLE< CNodePropertySheet > m_Properties; + + bool AllowKeyInput(); + + CUtlVector< CBaseNode* > m_hNodeList; + CUtlVector< CBaseNode* > m_hNodesInMove; + CUtlVector< CBridge* > m_hBridgeList; + CBaseNode *SpawnNode( int type ); + + void DoEnvmapOverride(); + +public: + int GetNumNodes(){ return m_hNodeList.Count(); }; + CBaseNode *GetNode( int i ){ Assert(m_hNodeList.IsValidIndex(i)); return m_hNodeList[i]; }; + + void MakeSolversDirty(); + void OnHierachyChanged(); + void DoFullHierachyUpdate(); + void DestroyAllSolvers(); + + CUtlVector< CHLSL_SolverBase* > &AccessSolverStack_VS(); + CUtlVector< CHLSL_SolverBase* > &AccessSolverStack_PS(); + CUtlVector< CHLSL_SolverBase* > &AccessSolverStack_UNDEFINED(); + CUtlVector< CHLSL_SolverBase* > &AccessSolverStack_POSTPROC(); + + void ResetTempHierachy(); + + static int CreatePPSolversFromFile( const char *fileName, CUtlVector &hOutput, GenericPPEData &config ); + GenericPPEData *AccessPPEConfig(); + +private: + bool m_bDirtySolvers; + void InvokeCreateSolvers( CUtlVector< CBaseNode* > &m_hNodeBottomList, + CUtlVector< CBaseNode* > &m_hNodeOutList, + CUtlVector< CBaseContainerNode* > &m_hContainerStack, + GenericShaderData *ShaderData ); + + CUtlVector< CHLSL_SolverBase* >m_hSolverStack_VertexShader; + CUtlVector< CHLSL_SolverBase* >m_hSolverStack_PixelShader; + CUtlVector< CHLSL_SolverBase* >m_hSolverStack_NoHierachy; + + CUtlVector< CHLSL_SolverBase* >m_hSolverStack_PostProcessing; + + bool IsSelectionBiggerThanOne(); + CBaseNode *GetFirstSelectedNode(); + void DeselectAllNodes( CBaseNode *pIgnore = NULL ); + void SelectNodes( CUtlVector< CBaseNode* > &m_hNodes, bool bAdd = true ); + void DragSelection( Vector2D delta ); + void MoveNodeToFront( CBaseNode *p ); + void CopySelection(); + void PasteSelection(); + void DeleteSelection(); + void DisconnectSelection(); + + int m_iTex_BusyIco; + + void StartOverrideIndices( CUtlVector< CBaseNode* > &m_hNodes ); + void FinishOverrideIndices(); + KeyValues *CopyNodes( CUtlVector< CBaseNode* > &m_hNodesToCopy, bool bCenterNodes = true ); + void PasteNodes( KeyValues *pKV, bool bAutoSelect, Vector2D *origin = NULL, CUtlVector< CBaseNode* > *m_hNewNodes = NULL ); + CBaseNode *AllocateSingleNode( KeyValues *pKV ); + void ConnectBridges( CUtlVector< CBaseNode* > &m_hInstantiatedNodes, KeyValues *pKV ); + + void MoveNodes( Vector2D offset, KeyValues *pKV ); + void MoveNodes( Vector2D offset, CBaseNode *n ); + void MoveNodes( Vector2D offset, CUtlVector< CBaseNode* > &m_hList ); + + CJack *pJackLast; + CBridge *m_pCurBridge; + bool bOverrideNodeIndices; + CUtlVector< CBaseNode* > m_hTmpNodeIndex; + +public: + void PurgeSolverClients(); + void AddSolverClient( ISolverRequester *client ); + void RemoveSolverClient( ISolverRequester *client ); + + void SaveToFile( const char *fullpath = NULL ); + bool LoadFromFile( const char *fullpath, bool bSuppressError = false ); + + + KeyValues *BuildFullCanvas(); + void RestoreFullCanvas( KeyValues *pCanvas ); + + GenericShaderData &GetDataForModify(); + + void UpdatePPECache(); + +private: + void OnSolvingFinsihed(); + void UpdateSolverClients(); + void CleanupNodes(); + + CUtlVector< ISolverRequester* > m_hSolverClients; + + GenericShaderData *m_ShaderData; + void ClearShaderData(); + void GenerateShaderData(); + void PrepShaderData(); + void CleanupShaderData(); + + GenericPPEData *m_PPEData; + void ClearPPEData(); + void GeneratePPEData(); + +public: + void CreateDragBridge( CJack *j ); + void UpdateDragBridge( CJack *j, CBaseNode *n ); + void FinishDragBridge( CJack *j ); + void AddBridgeToList( CBridge *b ); + + const HCURSTACKIDX &GetStackIndex(){ return m_StackIndex; }; + const HCURSTACKIDX &GetCompiledStackIndex(){ return m_StackIndex_LastCompiled; }; + const bool IsSaveDirty(){ return m_HistoryIndex != m_HistoryIndex_LastSaved; }; + void UnDirtySave(){ m_HistoryIndex_LastSaved = m_HistoryIndex; }; + const bool IsLastCompileSuccessful(){ return m_bLastCompileSuccessFull; }; + + virtual void OnCompilationEnd( int flags, int exitcode, GenericShaderData *data ); + void UploadPreviewData(); + +private: + void KillDragBridge(); + CJack *GetBridgeSnapJack(); + + CEditorRoot *pEditorRoot; + + HCURSTACKIDX m_StackIndex; + HCURSTACKIDX m_StackIndex_LastCompiled; + HCURSTACKIDX m_HistoryIndex; + HCURSTACKIDX m_HistoryIndex_LastSaved; + bool m_bLastCompileSuccessFull; + + KeyValues *pKV_Mat_PsIn; + IMaterial *m_pMat_PsIn; + void UpdatePsinMaterial( const char *vsName, GenericShaderData *data = NULL ); + IMaterialVar *m_pMatVar_PsIn_Operation; + + IMaterial *m_pPreview_Material; + KeyValues *m_pPreview_KV; + IMaterial *m_pPrevBackground_Material; + KeyValues *m_pPrevBackground_KV; + + GenericShaderData *m_pLastPreviewData; + int m_iLastPreviewFlags; + + char m_szEnvmap[MAX_PATH]; + char m_szShaderName[MAX_PATH]; + //ITexture *m_pTexCubemap; + bool m_bRenderBackground; + + void InitPreviewMaterials(); + void DestroyPreviewMaterials(); + +public: + void SetEnvmap( const char *pszPath ); + const char *GetEnvmap(); + void SetShadername( const char *pszPath ); + const char *GetShadername(); + void SetUsingBackgroundMaterial( bool bUse ); + const bool IsUsingBackgroundMaterial(); + //ITexture *GetEnvmapTexture(); + + IMaterial *GetPreviewMeshMaterial(); + IMaterial *GetPreviewBackgroundMaterial(); + KeyValues *GetKVMeshMaterial(); + KeyValues *GetKVBackgroundMaterial(); + + GenericShaderData *GetPreviewData(); + +private: + + void UpdateRTs(); + void RenderSolvers( CUtlVector< CHLSL_SolverBase* > &hSolvers ); + + bool m_bPreviewMode; + CUtlVector< LimitReport_t* > hErrorList; + +public: + void SetPreviewMode( bool bEnabled ); + bool IsPreviewModeEnabled(); + void UpdatePsinMaterialVar(); + + static void RenderSingleSolver( Preview2DContext &c, IMaterial *pMat ); + + + enum HistoryActions_t + { + HACT_UNDO = 0, + HACT_REDO, + + HACT_PUSH, + }; + void MakeHistoryDirty(); + void HistoryAction( HistoryActions_t action ); + void FlushHistory( bool bPast = true, bool bFuture = true); + int GetNumHistoryEntires_Undo(); + int GetNumHistoryEntires_Redo(); + +private: + + bool m_bHistoryDirty; + + void Think_UpdateHistory(); + + CUtlVector< NHistoryEntry_t* >m_hNodeViewHistory; + CUtlVector< NHistoryEntry_t* >m_hNodeViewHistory_Redo; + + void ApplyHistoryEntry( NHistoryEntry_t *pEntry ); + NHistoryEntry_t *AllocHistoryEntry(); +}; + + + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vnodeviewerror.cpp b/sp/src/shadereditor/vnodeviewerror.cpp new file mode 100644 index 00000000..ec442b1d --- /dev/null +++ b/sp/src/shadereditor/vnodeviewerror.cpp @@ -0,0 +1,166 @@ + +#include "cbase.h" +#include "editorCommon.h" + +static const char *szErrorNames[] = { + "YOU ARE USING MULTIPLE TEXTURE NODES WITH THE SAME VMT PARAMETER (%s) BUT DIFFERENT TEXTURE REFERENCES!", + "A RENDER VIEW NODE WITH 'DURING SCENE' CHECKED SHOULD BE AT THE VERY BEGINNING OF THE GRAPH!", +#ifdef SHADER_EDITOR_DLL_2006 + "USING UNSUPPORTED NODE IN SOURCE 2006 (%s)!", +#endif +}; + +#define ERROR_COLOR Color( 170, 64, 32, 255 ) //Color( 160, 24, 0, 255 ) +#define ERROR_OUTLINE_SIZE 2 +#define ERROR_DISTANCE 10 + +CNodeViewError::CNodeViewError( Panel *parent, int errorType ) : BaseClass( parent ) +{ + AddActionSignalTarget( parent ); + + Assert( ARRAYSIZE( szErrorNames ) == NVERROR_COUNT ); + + m_iErrorType = errorType; + m_bClosing = false; + + m_iTallCur = 1; + m_iWide = 200; + SetSize( m_iWide, m_iTallCur ); + + pL = new Label( this, "", "" ); + + SetMouseInputEnabled( false ); + SetKeyBoardInputEnabled( false ); + + m_iTallGoal = 10; +} + +CNodeViewError::~CNodeViewError() +{ +} + +void CNodeViewError::SetText( const char *szParam ) +{ + const char *szErrorText = szErrorNames[m_iErrorType]; + char tmp[MAX_PATH]; + if ( szParam != NULL ) + Q_snprintf( tmp, sizeof(tmp), szErrorText, szParam ); + else + Q_snprintf( tmp, sizeof(tmp), szErrorText ); + + pL->SetText( tmp ); + + pL->SetWrap( true ); + pL->SetTextInset( 5, 5 ); + pL->SetContentAlignment( Label::a_northwest ); + pL->SetSize( m_iWide, m_iTallCur ); + pL->InvalidateLayout( true, true ); + pL->SetFgColor( ERROR_COLOR ); + pL->SizeToContents(); + + int w; + pL->GetContentSize( w, m_iTallMax ); + m_iTallMax += 5; + + InvalidateLayout( true ); + DoOpen(); +} + +const int CNodeViewError::GetErrorType() +{ + return m_iErrorType; +} + +const bool CNodeViewError::IsAnimating() +{ + return m_iTallCur != m_iTallGoal; +} + +const bool CNodeViewError::IsClosing() +{ + return m_bClosing; +} + +void CNodeViewError::DoOpen() +{ + m_bClosing = false; + m_iTallGoal = m_iTallMax; +} + +void CNodeViewError::DoClose() +{ + m_bClosing = true; + m_iTallGoal = 0; +} + +void CNodeViewError::PerformLayout() +{ + BaseClass::PerformLayout(); + + if ( IsAnimating() ) + { + float move = (m_iTallGoal - m_iTallCur) * gpGlobals->frametime * 10.0f; + int dir = (move>0)?1:-1; + move = max( 1, min( abs(m_iTallGoal-m_iTallCur), abs(move) ) ) * dir; + m_iTallCur += move; + } + else if ( IsClosing() ) + PostActionSignal( new KeyValues( "DestroyUserError" ) ); + + SetSize( m_iWide, m_iTallCur ); + + if ( !GetParent() ) + return; + + int px, py; + CNodeView *p = assert_cast< CNodeView* >( GetParent() ); + p->GetSize( px, py ); + + int posx = px - m_iWide - ERROR_DISTANCE; + int posy = py; + + for ( int i = p->GetNumUserErrorLabels() - 1; i >= 0; i-- ) + { + CNodeViewError *pL = p->GetUserErrorLabel( i ); + if ( pL == this ) + break; + + int lx, ly; + pL->GetSize( lx, ly ); + + posy -= ly; + posy -= ERROR_DISTANCE; + } + + posy -= ERROR_DISTANCE + m_iTallCur; + + SetPos( posx, posy ); +} + +void CNodeViewError::ApplySchemeSettings( vgui::IScheme *pScheme ) +{ + BaseClass::ApplySchemeSettings( pScheme ); + + pL->SetFgColor( ERROR_COLOR ); + SetBgColor( Color( 0, 0, 0, 128 ) ); + + SetMouseInputEnabled( false ); + SetKeyBoardInputEnabled( false ); +} + +void CNodeViewError::Paint() +{ + BaseClass::Paint(); + + int sx, sy; + GetSize( sx, sy ); + + Color c = ERROR_COLOR; + c[3] = 128 + 127 * abs(sin(gpGlobals->curtime * 3)); + + surface()->DrawSetColor( c ); + surface()->DrawFilledRect( 0, 0, sx, ERROR_OUTLINE_SIZE ); + surface()->DrawFilledRect( 0, sy - ERROR_OUTLINE_SIZE, sx, sy ); + surface()->DrawFilledRect( 0, ERROR_OUTLINE_SIZE, ERROR_OUTLINE_SIZE, sy - ERROR_OUTLINE_SIZE ); + surface()->DrawFilledRect( sx - ERROR_OUTLINE_SIZE, ERROR_OUTLINE_SIZE, sx, sy - ERROR_OUTLINE_SIZE ); +} \ No newline at end of file diff --git a/sp/src/shadereditor/vnodeviewerror.h b/sp/src/shadereditor/vnodeviewerror.h new file mode 100644 index 00000000..f83e95a4 --- /dev/null +++ b/sp/src/shadereditor/vnodeviewerror.h @@ -0,0 +1,62 @@ +#ifndef C_NODE_VIEW_ERROR_H +#define C_NODE_VIEW_ERROR_H + + +#include "cbase.h" +#include + +using namespace vgui; + + +class CNodeViewError : public vgui::Panel +{ + DECLARE_CLASS_SIMPLE( CNodeViewError, vgui::Panel ); + +public: + + enum + { + NVERROR_TEXTURE_SAMPLER_PARAM_MISMATCH = 0, + NVERROR_RENDER_VIEW_SCENE_NOT_AT_START, +#ifdef SHADER_EDITOR_DLL_2006 + NVERROR_UNSUPPORTED_BY_2006, +#endif + NVERROR_COUNT, + }; + + CNodeViewError( Panel *parent, int errorType ); + ~CNodeViewError(); + + const int GetErrorType(); + + const bool IsAnimating(); + const bool IsClosing(); + + void DoOpen(); + void DoClose(); + + void SetText( const char *szParam ); + +protected: + + void PerformLayout(); + void ApplySchemeSettings(vgui::IScheme *pScheme); + + void Paint(); + + +private: + + Label *pL; + + bool m_bClosing; + int m_iErrorType; + + int m_iTallCur; + int m_iTallGoal; + int m_iTallMax; + int m_iWide; + +}; + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vpreview.cpp b/sp/src/shadereditor/vpreview.cpp new file mode 100644 index 00000000..4cb96f3f --- /dev/null +++ b/sp/src/shadereditor/vpreview.cpp @@ -0,0 +1,431 @@ + +#include "cbase.h" +#include "editorCommon.h" +//#include "vgui_int.h" + +#include "vgui_controls/colorpicker.h" + +#define PREVBROWSER_CONTEXT_MODEL "context_model" +#define PREVBROWSER_CONTEXT_BG "context_background" + +CPreview::CPreview( vgui::Panel *parent, CNodeView *nodeview ) : BaseClass( parent, nodeview, "preview", true ) +{ + //m_szEnvmap[0] = '\0'; + InitColors(); + + pRenderPanel = new CRenderPanel( this, "renderpanel" ); + + m_pCBox_RenderMode = new ComboBox( this, "cbox_rendermode", 10, false ); + m_pCBox_RenderMode->AddItem( "Sphere", NULL ); + m_pCBox_RenderMode->AddItem( "Cube", NULL ); + m_pCBox_RenderMode->AddItem( "Cylinder", NULL ); + m_pCBox_RenderMode->AddItem( "Plane", NULL ); + m_pCBox_RenderMode->AddItem( "Model", NULL ); + m_pCBox_RenderMode->AddItem( "Post process", NULL ); + m_pCBox_RenderMode->AddItem( "Pingpong RT 0", NULL ); + + m_pCBox_Model_Sequence = new ComboBox( this, "cbox_modelseq", 20, false ); + m_pCheck_MatOverride = new CheckButton( this, "check_moverride", "" ); + m_pCheck_DoPPE = new CheckButton( this, "check_ppe", "" ); + + LoadControlSettings("shadereditorui/vgui/shadereditor_preview.res"); + + m_pCheck_MatOverride->SetSelected( true ); + m_pCheck_DoPPE->SetSelected( true ); + + SetTitle("Preview",true); + SetMinimumSize( 440, 320 ); + + SetAutoDelete( true ); + SetDeleteSelfOnClose( false ); + + m_pCBox_RenderMode->ActivateItem( 0 ); + DoLayout_Empty(); + + psz_SequenceList = NULL; + m_iNumSequences = 0; +} +CPreview::~CPreview() +{ + KillBrowser(); + + if ( psz_SequenceList && sEditMRender ) + { + sEditMRender->DestroyModel(); + sEditMRender->DestroyCharPtrList( &psz_SequenceList ); + psz_SequenceList = NULL; + m_iNumSequences = 0; + } +} + +void CPreview::OnTextChanged( KeyValues *pKV ) +{ + Panel *pCaller = ((Panel*)pKV->GetPtr( "panel" )); + if ( pCaller == m_pCBox_RenderMode ) + { + UpdateLayout(); + } + else if ( pCaller == m_pCBox_Model_Sequence ) + { + if ( sEditMRender ) + { + char tmp[ MAX_PATH ]; + m_pCBox_Model_Sequence->GetItemText( m_pCBox_Model_Sequence->GetActiveItem(), tmp, MAX_PATH ); + sEditMRender->SetSequence( tmp ); + } + } + else + Assert( 0 ); + + return; +} +void CPreview::OnCheckButtonChecked( KeyValues *pKV ) +{ + Panel *pCaller = ((Panel*)pKV->GetPtr( "panel" )); + const bool bState = !!pKV->GetInt( "state" ); + + if ( pCaller == m_pCheck_MatOverride ) + { + pRenderPanel->SetMatOverrideEnabled( bState ); + } + else if ( pCaller == m_pCheck_DoPPE ) + { + pRenderPanel->SetPPEPreviewEnabled( bState ); + } +} +void CPreview::DoLayout_Empty() +{ + m_pCBox_RenderMode->SetVisible( true ); + Panel *p = FindChildByName( "button_modelload" ); if ( p ) p->SetVisible( false ); + p = FindChildByName( "label_sequence" ); if ( p ) p->SetVisible( false ); + for ( int i = 1; i < 4; i++ ){ + p = FindChildByName( VarArgs("Button%i",i) ); if ( p ) p->SetVisible( true );} + + m_pCBox_Model_Sequence->SetVisible( false ); + m_pCheck_MatOverride->SetVisible( false ); + m_pCheck_DoPPE->SetVisible( false ); +} +void CPreview::DoLayout_Model() +{ + m_pCBox_RenderMode->SetVisible( true ); + Panel *p = FindChildByName( "button_modelload" ); if ( p ) p->SetVisible( true ); + p = FindChildByName( "label_sequence" ); if ( p ) p->SetVisible( true ); + for ( int i = 1; i < 4; i++ ){ + p = FindChildByName( VarArgs("Button%i",i) ); if ( p ) p->SetVisible( true );} + + m_pCBox_Model_Sequence->SetVisible( true ); + m_pCheck_MatOverride->SetVisible( true ); + m_pCheck_DoPPE->SetVisible( false ); +} +void CPreview::DoLayout_PPE() +{ + m_pCBox_RenderMode->SetVisible( false ); + Panel *p = FindChildByName( "button_modelload" ); if ( p ) p->SetVisible( false ); + p = FindChildByName( "label_sequence" ); if ( p ) p->SetVisible( false ); + for ( int i = 1; i < 4; i++ ){ + p = FindChildByName( VarArgs("Button%i",i) ); if ( p ) p->SetVisible( false );} + + m_pCBox_Model_Sequence->SetVisible( false ); + m_pCheck_MatOverride->SetVisible( false ); + m_pCheck_DoPPE->SetVisible( true ); +} + +void CPreview::UpdateLayout() +{ + int var = m_pCBox_RenderMode->GetActiveItem(); + if ( var == PRENDER_MODEL && !sEditMRender ) + var = PRENDER_SPHERE; + + if ( pEditorRoot->GetSafeFlowgraph()->GetFlowgraphType() == CNodeView::FLOWGRAPH_POSTPROC ) + var = PRENDER_PPECHAIN; + + switch ( var ) + { + case PRENDER_SPHERE: + case PRENDER_CUBE: + case PRENDER_CYLINDER: + case PRENDER_PLANE: + pRenderPanel->CreateMesh( var ); + default: + DoLayout_Empty(); + break; + case PRENDER_MODEL: + DoLayout_Model(); + break; + case PRENDER_PPECHAIN: + DoLayout_PPE(); + break; + } + + pRenderPanel->SetRenderMode( var ); +} + +void CPreview::OnSceneRender() +{ + pRenderPanel->DrawScene(); +} + +void CPreview::OnPostRender() +{ + pRenderPanel->DrawPostProc(); +} + +void CPreview::Activate() +{ + BaseClass::Activate(); +} +void CPreview::OnFinishedClose() +{ + if ( GetParent() ) + GetParent()->OnCommand( "pv_closed" ); + + BaseClass::OnFinishedClose(); +} + +void CPreview::InitColors() +{ + _col_BorderBright = Color( 255,255,255,255 ); + _col_BorderDark = Color( 0,0,0,255 ); +} + +void CPreview::Paint() +{ + BaseClass::Paint(); + + if ( pRenderPanel ) + { + int x,y,sx,sy; + pRenderPanel->GetBounds( x, y, sx, sy ); + x -= 1; + y -= 1; + sx += 1; + sy += 1; + + surface()->DrawSetColor( _col_BorderBright ); + surface()->DrawLine( x, y+sy, x+sx, y+sy ); + surface()->DrawLine( x+sx, y, x+sx, y+sy ); + surface()->DrawSetColor( _col_BorderDark ); + surface()->DrawLine( x, y, x+sx, y ); + surface()->DrawLine( x, y, x, y+sy ); + } +} + +void CPreview::OnCommand(const char* pcCommand) +{ + if( !Q_stricmp(pcCommand, "loadmodel") ) + { + OpenBrowser( false ); + return; + } + if( !Q_stricmp(pcCommand, "loadbg") ) + { + OpenBrowser( true ); + return; + } + if( !Q_stricmp(pcCommand, "reset_view") ) + { + pRenderPanel->ResetView(); + return; + } + if( !Q_stricmp(pcCommand, "bgcolor") ) + { + ColorPicker *pPicker = new ColorPicker( pEditorRoot, "cpicker", this ); + Color bgRR = pRenderPanel->GetBgColor(); + pPicker->SetPickerColor( Vector( bgRR.r() / 255.0f, bgRR.g() / 255.0f, bgRR.b() / 255.0f ) ); + return; + } + + BaseClass::OnCommand( pcCommand ); +} + +void CPreview::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + InitColors(); + _col_BorderBright = pScheme->GetColor( "Border.Bright", _col_BorderBright ); + _col_BorderDark = pScheme->GetColor( "Border.Dark", _col_BorderDark ); +} + +void CPreview::PerformLayout() +{ + BaseClass::PerformLayout(); +} + +void CPreview::RememberPosition() +{ + GetBounds( _px, _py, _sx, _sy ); +} +void CPreview::RestorePosition() +{ + SetBounds( _px, _py, _sx, _sy ); +} + +void CPreview::KillBrowser() +{ + if ( m_hBrowser.Get() ) + m_hBrowser->MarkForDeletion(); +} +void CPreview::OpenBrowser( bool bPreviewMaterial ) +{ + KillBrowser(); + + const char *context = PREVBROWSER_CONTEXT_MODEL; + const char *dirFormat = "%s/models"; + const char *pExt = "*.mdl"; + const char *pDescription = "Models"; + const char *pFODPCContext = GetFODPathContext( FODPC_MDL ); + + if ( bPreviewMaterial ) + { + context = PREVBROWSER_CONTEXT_BG; + dirFormat = "%s/materials"; + pExt = "*.vtf"; + pDescription = "Materials"; + pFODPCContext = GetFODPathContext( FODPC_VTF ); + } + + m_hBrowser = new FileOpenDialog( this, "Load .mdl", FOD_OPEN, new KeyValues("FileOpenContext", "context", context) ); + + if ( m_hBrowser.Get() ) + { + char finalPath[MAX_PATH]; + Q_snprintf( finalPath, sizeof( finalPath ), dirFormat, GetGamePath() ); + + m_hBrowser->SetStartDirectoryContext( pFODPCContext, finalPath ); + m_hBrowser->AddFilter( pExt, pDescription, true ); + m_hBrowser->DoModal( true ); + } +} +void CPreview::OnFileSelected( KeyValues *pKV ) +{ + KeyValues *pContext = pKV->FindKey( "FileOpenContext" ); + if ( pContext ) + { + const char *context = pContext->GetString("context"); + const char *pathIn = pKV->GetString( "fullpath" ); + + const bool bLoadBG = !Q_stricmp( context, PREVBROWSER_CONTEXT_BG ); + if ( bLoadBG ) + pEditorRoot->GetSafeFlowgraph()->SetUsingBackgroundMaterial( false ); + // pRenderPanel->bRenderBackground = false; + + if ( Q_strlen( pathIn ) <= 1 ) + return; + + char tmp[MAX_PATH]; + if ( !g_pFullFileSystem->FullPathToRelativePath( pathIn, tmp, MAX_PATH ) ) + Q_snprintf( tmp, sizeof(tmp), "%s", pathIn ); + + if ( !bLoadBG ) + LoadModel( tmp ); + else + { + CHLSL_Image img; + bool bSuccess = img.LoadFromVTF( tmp ); + Assert( bSuccess ); + if ( !bSuccess ) + return; + + const char *matPath = Q_StripFirstDir( tmp ); + const bool bCubemap = img.IsEnvmap(); + + IMaterial *pMat = pEditorRoot->GetBGPreviewMat(); + KeyValues *pKV = pEditorRoot->GetBGPreviewKV(); + if ( !pMat || !pKV ) + return; + + char szNoExtension[MAX_PATH]; + Q_StripExtension( matPath, szNoExtension, MAX_PATH ); + + if ( bCubemap ) + SetEnvmap( szNoExtension ); + //Q_strcpy( m_szEnvmap, szNoExtension ); + else + SetEnvmap( NULL ); + //m_szEnvmap[0] = '\0'; + + //SetMaterialVar_Int( pMat, "$ISCUBEMAP", bCubemap ? 1 : 0 ); + //SetMaterialVar_String( pMat, "$BASETEXTURE", szNoExtension ); + //pMat->RecomputeStateSnapshots(); + + pKV->SetInt( "$ISCUBEMAP", bCubemap ? 1 : 0 ); + pKV->SetString( "$BASETEXTURE", szNoExtension ); + pMat->Refresh(); + + CNodeView *pView = pEditorRoot->GetSafeFlowgraph(); + pView->SetUsingBackgroundMaterial( true ); + pView->MakeSolversDirty(); + //pNodeView->MakeSolversDirty(); + } + } +} + +const char *CPreview::GetEnvmap() +{ + CNodeView *pView = pEditorRoot->GetActiveFlowGraph(); + Assert( pView ); + return pView->GetEnvmap(); +} + +void CPreview::SetEnvmap( const char *pszPath ) +{ + CNodeView *pView = pEditorRoot->GetActiveFlowGraph(); + Assert( pView ); + pView->SetEnvmap( pszPath ); +} + +void CPreview::OnColorSelected( KeyValues *pKV ) +{ + pEditorRoot->GetSafeFlowgraph()->SetUsingBackgroundMaterial( false ); + pRenderPanel->SetBgColor( pKV->GetColor( "color" ) ); +} + +int CPreview::FindSequenceByName( const char *name, SeqFindMode_t mode ) +{ + for ( int i = 0; i < m_iNumSequences; i++ ) + { + switch ( mode ) + { + case SEQFIND_EXACT: + if ( !Q_stricmp( psz_SequenceList[i], name ) ) + return i; + break; + case SEQFIND_STARTSWITH: + if ( Q_stristr( psz_SequenceList[i], name ) == psz_SequenceList[i] ) + return i; + break; + case SEQFIND_CONTAINS: + if ( Q_stristr( psz_SequenceList[i], name ) ) + return i; + break; + } + } + return -1; +} +void CPreview::LoadModel( const char *localPath ) +{ + if ( !sEditMRender ) + return; + + sEditMRender->LoadModel( localPath ); + + sEditMRender->DestroyCharPtrList( &psz_SequenceList ); + m_iNumSequences = sEditMRender->QuerySequences( &psz_SequenceList ); + sEditMRender->GetModelCenter( pRenderPanel->render_offset_modelBase.Base() ); + + m_pCBox_Model_Sequence->RemoveAll(); + + for ( int i = 0; i < m_iNumSequences; i++ ) + m_pCBox_Model_Sequence->AddItem( psz_SequenceList[i], NULL ); + + int iIdealSequence = FindSequenceByName( "idle_unarmed", SEQFIND_STARTSWITH ); + if ( iIdealSequence < 0 ) + iIdealSequence = FindSequenceByName( "idle_subtle", SEQFIND_STARTSWITH ); + if ( iIdealSequence < 0 ) + iIdealSequence = FindSequenceByName( "idle", SEQFIND_STARTSWITH ); + if ( iIdealSequence < 0 ) + iIdealSequence = FindSequenceByName( "idle" ); + + m_pCBox_Model_Sequence->ActivateItem( max( 0, iIdealSequence ) ); +} diff --git a/sp/src/shadereditor/vpreview.h b/sp/src/shadereditor/vpreview.h new file mode 100644 index 00000000..d05c8583 --- /dev/null +++ b/sp/src/shadereditor/vpreview.h @@ -0,0 +1,83 @@ +#ifndef CHLSL_PREVIEW_H +#define CHLSL_PREVIEW_H + +#include "cbase.h" +#include "editorCommon.h" +#include "cSolverCallback.h" + +class CPreview : public CBaseDiag +{ + DECLARE_CLASS_SIMPLE( CPreview, CBaseDiag ); + +public: + CPreview( vgui::Panel *parent, CNodeView *nodeview ); + ~CPreview(); + + virtual void Activate(); + + void RememberPosition(); + void RestorePosition(); + + void OnSceneRender(); + void OnPostRender(); + + const char *GetEnvmap(); //{ return m_szEnvmap; }; + void SetEnvmap( const char *pszPath ); + + void UpdateLayout(); + +protected: + + virtual void Paint(); + + void OnCommand(const char* pcCommand); + + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + virtual void PerformLayout(); + + virtual void OnFinishedClose(); + + MESSAGE_FUNC_PARAMS( OnTextChanged, "TextChanged", pKV ); + + MESSAGE_FUNC_PARAMS( OnFileSelected, "FileSelected", pKV ); + MESSAGE_FUNC_PARAMS( OnCheckButtonChecked, "CheckButtonChecked", pKV ); + + MESSAGE_FUNC_PARAMS( OnColorSelected, "ColorSelected", pKV ); + +private: + CRenderPanel *pRenderPanel; + int _px, _py, _sx, _sy; + + void InitColors(); + Color _col_BorderBright; + Color _col_BorderDark; + + ComboBox *m_pCBox_RenderMode; + ComboBox *m_pCBox_Model_Sequence; + CheckButton *m_pCheck_MatOverride; + CheckButton *m_pCheck_DoPPE; + + DHANDLE< FileOpenDialog > m_hBrowser; + void KillBrowser(); + void OpenBrowser( bool bPreviewMaterial ); + + void LoadModel( const char *localPath ); + enum SeqFindMode_t + { + SEQFIND_EXACT = 0, + SEQFIND_STARTSWITH, + SEQFIND_CONTAINS, + }; + int FindSequenceByName( const char *name, SeqFindMode_t mode = SEQFIND_CONTAINS ); + char **psz_SequenceList; + int m_iNumSequences; + + void DoLayout_Empty(); + void DoLayout_Model(); + void DoLayout_PPE(); + + //char m_szEnvmap[MAX_PATH]; +}; + + +#endif \ No newline at end of file diff --git a/sp/src/shadereditor/vrenderpanel.cpp b/sp/src/shadereditor/vrenderpanel.cpp new file mode 100644 index 00000000..3a72bca5 --- /dev/null +++ b/sp/src/shadereditor/vrenderpanel.cpp @@ -0,0 +1,677 @@ + +#include "cbase.h" +#include "editorCommon.h" + +#include "view_shared.h" +#include "materialsystem/imesh.h" + + +CRenderPanel::CRenderPanel( Panel *parent, const char *pElementName ) : BaseClass( parent, pElementName ) +{ + render_ang.Init(); + render_pos.Init(); + render_offset.Init(); + render_offset_modelBase.Init(); + + m_bDoMatOverride = true; + m_bDoPPE = true; + ResetView(); + + m_iDragMode = RDRAG_NONE; + m_iCachedMpos_x = 0; + m_iCachedMpos_y = 0; + + CreateMesh( PRENDER_SPHERE ); + + __view.Identity(); + __proj.Identity(); + __ViewProj.Identity(); + __ViewProjNDC.Identity(); + + m_iRendermode = 0; + + SetupVguiTex( m_iVguitex_pp0, "shadereditor/_rtdebug_pp0" ); + SetupVguiTex( m_iVguitex_postprocPrev, "shadereditor/_rt_framebuffer_prev" ); +} +CRenderPanel::~CRenderPanel() +{ +} + +void CRenderPanel::CreateMesh( int mode ) +{ + switch ( mode ) + { + case PRENDER_SPHERE: + _mesh.CreateSphere( sedit_mesh_size.GetFloat(), sedit_mesh_subdiv.GetInt() ); + break; + case PRENDER_CUBE: + _mesh.CreateCube( sedit_mesh_size.GetFloat(), sedit_mesh_subdiv.GetInt() ); + break; + case PRENDER_PLANE: + _mesh.CreatePlane( sedit_mesh_size.GetFloat(), sedit_mesh_subdiv.GetInt() ); + break; + case PRENDER_CYLINDER: + _mesh.CreateCylinder( sedit_mesh_size.GetFloat(), sedit_mesh_subdiv.GetInt() ); + break; + } +} + +void CRenderPanel::SetRenderMode( int mode ) +{ + m_iRendermode = mode; + if ( m_iRendermode == PRENDER_MODEL && sEditMRender ) + sEditMRender->GetModelCenter( render_offset_modelBase.Base() ); + else + render_offset_modelBase.Init(); +} + +void CRenderPanel::UpdateRenderPosition() +{ + QAngle out( m_flPitch, m_flYaw, 0 ); + Vector fwd; + AngleVectors( out, &fwd ); + + render_pos = vec3_origin - fwd * m_flDist; + VectorAngles( fwd, render_ang ); + + render_pos += render_offset; + if ( m_iRendermode == PRENDER_MODEL ) + render_pos += render_offset_modelBase; +} + +void CRenderPanel::OnThink() +{ + const bool bIsRenderingModel = m_iRendermode == PRENDER_MODEL; + + int iInset_base = 15; + int iInset_Top = 70; + if ( bIsRenderingModel ) + iInset_Top = 110; + + int parentSx, parentSy; + if ( GetParent() ) + { + GetParent()->GetSize( parentSx, parentSy ); + parentSx -= iInset_base * 2; + parentSy -= iInset_base + iInset_Top; + + SetBounds( iInset_base, iInset_Top, parentSx, parentSy ); + } + + //if ( bIsRenderingModel && sEditMRender ) + // sEditMRender->GetModelCenter( render_offset.Base() ); + + if ( m_iDragMode ) + { + int mdelta_x, mdelta_y; + input()->GetCursorPosition( mdelta_x, mdelta_y ); + mdelta_x -= m_iCachedMpos_x; + mdelta_y -= m_iCachedMpos_y; + input()->SetCursorPos( m_iCachedMpos_x, m_iCachedMpos_y ); + switch ( m_iDragMode ) + { + case RDRAG_LIGHT: + { + VMatrix viewInv, viewInvT; + MatrixInverseGeneral( __view, viewInv ); + matrix3x4_t rot_x, rot_y, rot_comb; + Vector fwd, right, up; + + viewInv.GetBasisVectors( right, up, fwd ); + +#ifdef SHADER_EDITOR_DLL_2006 + VMatrix rot_tmp; + MatrixBuildRotationAboutAxis( rot_tmp, right, mdelta_y ); + rot_x = rot_tmp.As3x4(); + MatrixBuildRotationAboutAxis( rot_tmp, up, mdelta_x ); + rot_y = rot_tmp.As3x4(); +#else + MatrixBuildRotationAboutAxis( right, mdelta_y, rot_x ); + MatrixBuildRotationAboutAxis( up, mdelta_x, rot_y ); + ConcatTransforms( rot_x, rot_y, rot_comb ); +#endif + QAngle rot( -mdelta_y, mdelta_x,0 ); + Vector tmp,tmp2; + AngleVectors( lightAng, &tmp ); + //VectorRotate(tmp,rot,tmp2); + VectorRotate(tmp,rot_comb,tmp2); + VectorAngles(tmp2,lightAng); + } + break; + case RDRAG_ROTATE: + { + m_flPitch -= mdelta_y * 0.5f; + m_flYaw += mdelta_x * 0.5f; + + m_flPitch = clamp( m_flPitch, -89, 89 ); + if ( m_flYaw > 180.0f ) + m_flYaw -= 360.0f; + if ( m_flYaw < -180.0f ) + m_flYaw += 360.0f; + } + break; + case RDRAG_POS: + { +#define RENDER_DRAGPOS_MOVESCALE 0.2f + Vector viewRight, viewUp; + AngleVectors( render_ang, NULL, &viewRight, &viewUp ); + render_offset += mdelta_x * -viewRight * RENDER_DRAGPOS_MOVESCALE + + mdelta_y * viewUp * RENDER_DRAGPOS_MOVESCALE; + +#ifdef SHADER_EDITOR_DLL_SWARM + if ( !input()->IsMouseDown( MOUSE_MIDDLE ) ) + OnMouseReleased( MOUSE_MIDDLE ); +#endif + } + break; + } + } +} +void CRenderPanel::ResetView() +{ + const bool bIsRenderingModel = m_iRendermode == PRENDER_MODEL; + + m_flDist = 128; + m_flPitch = 45; + m_flYaw = 180; + lightAng.Init( 45, -135, 0 ); + + if ( bIsRenderingModel && sEditMRender ) + sEditMRender->GetModelCenter( render_offset_modelBase.Base() ); + else + render_offset_modelBase.Init(); + render_offset.Init(); + + UpdateRenderPosition(); +} + +void CRenderPanel::OnMouseWheeled( int delta ) +{ + BaseClass::OnMouseWheeled( delta ); + + float amt = RemapVal( m_flDist, 0, 100, 2, 25 ); + m_flDist -= delta * amt; + m_flDist = clamp( m_flDist, 5, 16000 ); +} + +void CRenderPanel::OnMousePressed( MouseCode code ) +{ + BaseClass::OnMousePressed( code ); + if ( m_iDragMode ) + return; + + if ( code == MOUSE_LEFT ) + m_iDragMode = RDRAG_ROTATE; + else if ( code == MOUSE_RIGHT ) + m_iDragMode = RDRAG_LIGHT; + else + m_iDragMode = RDRAG_POS; + + input()->GetCursorPosition( m_iCachedMpos_x, m_iCachedMpos_y ); + input()->SetCursorOveride( dc_none ); + input()->SetMouseCapture( GetVPanel() ); +} +void CRenderPanel::OnMouseReleased( MouseCode code ) +{ + BaseClass::OnMouseReleased( code ); + if ( !m_iDragMode ) + return; + + input()->SetCursorOveride( NULL ); + input()->SetMouseCapture( NULL ); + m_iDragMode = RDRAG_NONE; +} +void CRenderPanel::OnCursorMoved( int x, int y ) +{ +} + +void CRenderPanel::SetupView( CViewSetup &setup ) +{ + UpdateRenderPosition(); + + int x,y,w,t; + GetSize( w, t ); + x = y = 0; + LocalToScreen( x, y ); + if ( x < 0 ) + w += x; + if ( y < 0 ) + t += y; + x = max( 0, x ); + y = max( 0, y ); + + setup.angles = render_ang; + setup.origin = render_pos; + + setup.fov = 70; + setup.m_bOrtho = false; + + setup.x = x; + setup.y = y; + + setup.width = max(1, w); + setup.height = max(1, t); + + setup.zNear = 1; + setup.zFar = 10000; +} + +void CRenderPanel::DrawBackground() +{ + VMatrix viewProjInv; + MatrixInverseGeneral( __ViewProj, viewProjInv ); + + const Vector vec_pos_start[4] = { + Vector(-1.01f, 1.01f, 1 ), // 00 + Vector( 1, 1.01f, 1 ), // 10 + Vector( 1,-1, 1 ), // 11 + Vector(-1.01f,-1, 1 ) // 01 + }; + Vector vec_pos[4]; + + float _UVs[4][2] = { + 0, 0, + 1, 0, + 1, 1, + 0, 1 + }; + + for ( int i = 0; i < 4; i++ ) + { + Vector3DMultiplyPositionProjective( viewProjInv, vec_pos_start[i], vec_pos[i] ); + vec_pos[i] -= render_pos; + //vec_pos[i] *= 0.1f; + //vec_pos[i] += render_pos; + } + + if ( !pEditorRoot->GetBGPreviewMat() ) + return; + + IMaterial *pMat = pEditorRoot->GetBGPreviewMat(); + CMatRenderContextPtr pRenderContext( materials ); + CMeshBuilder pMeshBuilder; + + IMesh *pMesh = pRenderContext->GetDynamicMesh( true, 0, 0, pMat ); + pMeshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); +#ifndef SHADER_EDITOR_DLL_2006 + pMeshBuilder.SetCompressionType( VERTEX_COMPRESSION_NONE ); +#endif + + for ( int i = 0; i < 4; i++ ) + { + //Vector _normal = render_pos - vec_pos[i]; + Vector _normal = -vec_pos[i]; + _normal.NormalizeInPlace(); + + pMeshBuilder.Position3fv( vec_pos_start[i].Base() ); + pMeshBuilder.Normal3fv( _normal.Base() ); + pMeshBuilder.TexCoord2fv( 0, _UVs[i] ); + pMeshBuilder.AdvanceVertex(); + } + + pMeshBuilder.End(); + pMesh->Draw(); +} + +void CRenderPanel::SetupVert( CMeshBuilder &builder, CHLSL_Vertex &vert, float alpha ) +{ + builder.Position3fv( vert.pos ); + builder.Normal3fv( vert.normal ); + builder.TangentS3fv( vert.tangent_s ); + builder.TangentT3f( -vert.tangent_t[0], -vert.tangent_t[1], -vert.tangent_t[2] ); + Vector4D tang_s( vert.tangent_s[0], vert.tangent_s[1], vert.tangent_s[2], vert.tangent_s[3] ); + builder.UserData( tang_s.Base() ); + + GenericShaderData *data = pEditorRoot->GetSafeFlowgraph()->GetPreviewData(); + + if ( !data ) + { + builder.TexCoord2f( 0, vert.uv[0][0], vert.uv[0][1] ); + } + else + { + for ( int i = 0; i < data->shader->iVFMT_numTexcoords && i < 3; i++ ) + { + switch ( data->shader->iVFMT_texDim[i] ) + { + default: + Assert(0); + case 1: + builder.TexCoord1f( i, vert.uv[0][0] ); + break; + case 2: + builder.TexCoord2f( i, vert.uv[0][0], vert.uv[0][1] ); + break; + case 3: + builder.TexCoord3f( i, vert.uv[0][0], vert.uv[0][1], 0 ); + break; +#ifndef SHADER_EDITOR_DLL_2006 + case 4: + builder.TexCoord4f( i, vert.uv[0][0], vert.uv[0][1], 0, 0 ); + break; +#endif + } + } + } + + builder.Color4f( 1, 1, 1, alpha ); + builder.Specular4f( 0.3f, 0.3f, 0.3f, 1 ); + +#ifndef SHADER_EDITOR_DLL_2006 + builder.m_NumBoneWeights = 0; +#endif + + builder.AdvanceVertex(); +} + + + +void CRenderPanel::Paint() +{ + BaseClass::Paint(); + +#ifndef SHADER_EDITOR_DLL_2006 + modelrender->SuppressEngineLighting( true ); +#endif + + CViewSetup setup; + SetupView( setup ); + + gShaderEditorSystem->UpdateConstants( &setup ); + +#ifdef SHADER_EDITOR_DLL_2006 + render->Push3DView( setup, 0, false, NULL, frustum ); + GetMatricesForView( setup, __view, __proj, __ViewProj ); +#else + render->Push3DView( setup, 0, NULL, frustum ); + render->GetMatricesForView( setup, &__view, &__proj, &__ViewProj, &__ViewProjNDC ); +#endif + CMatRenderContextPtr pRenderContext( materials ); + + //ITexture *pCubemap = pEditorRoot->GetSafeFlowgraph()->GetEnvmapTexture(); + //if ( pCubemap ) + // pRenderContext->BindLocalCubemap( pCubemap ); + pRenderContext->ClearColor4ub( 0, 0, 0, 0 ); + pRenderContext->ClearBuffers( false, true ); + +#ifndef SHADER_EDITOR_DLL_2006 + pRenderContext->SetLightingOrigin( vec3_origin ); +#endif + g_pStudioRender->SetLocalLights( 0, NULL ); + LightDesc_t inf; + Vector lightDir; + AngleVectors( lightAng, &lightDir ); +#ifdef SHADER_EDITOR_DLL_2006 + InitLightDirectional( inf, lightDir, Vector( 1, 1, 1 ) ); +#else + inf.InitDirectional( lightDir, Vector( 1, 1, 1 ) ); +#endif + g_pStudioRender->SetLocalLights( 1, &inf ); +#define AMBIENT_ 0.05f + static Vector white[6] = + { + Vector( AMBIENT_, AMBIENT_, AMBIENT_ ), + Vector( AMBIENT_, AMBIENT_, AMBIENT_ ), + Vector( AMBIENT_, AMBIENT_, AMBIENT_ ), + Vector( AMBIENT_, AMBIENT_, AMBIENT_ ), + Vector( AMBIENT_, AMBIENT_, AMBIENT_ ), + Vector( AMBIENT_, AMBIENT_, AMBIENT_ ), + }; + g_pStudioRender->SetAmbientLightColors( white ); +#ifndef SHADER_EDITOR_DLL_SWARM + pRenderContext->SetAmbientLight( AMBIENT_, AMBIENT_, AMBIENT_ ); + pRenderContext->SetLight( 0, inf ); +#else + pRenderContext->SetLights( 1, &inf ); +#endif + + float color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + render->SetColorModulation( color ); + render->SetBlend( 1.0f ); + + ITexture *oldCopyTex = pRenderContext->GetFrameBufferCopyTexture( 0 ); + + const bool bShouldDrawBG = m_iRendermode == PRENDER_SPHERE || + m_iRendermode == PRENDER_CUBE || + m_iRendermode == PRENDER_CYLINDER || + m_iRendermode == PRENDER_PLANE || + m_iRendermode == PRENDER_MODEL; + + Rect_t rSrc; + rSrc.x = setup.x; + rSrc.y = setup.y; + rSrc.width = setup.width; + rSrc.height = setup.height; + + if ( bShouldDrawBG ) + { + shaderEdit->SetFramebufferCopyTexOverride( GetFBCopyTex() ); + + if ( pEditorRoot && + pEditorRoot->GetSafeFlowgraph()->IsUsingBackgroundMaterial() ) + DrawBackground(); + + if ( sedit_prev_HOMFun.GetInt() == 0 ) + pRenderContext->CopyRenderTargetToTextureEx( GetFBCopyTex(), 0, &rSrc ); + } + + MaterialFogMode_t oldFog = pRenderContext->GetFogMode(); + pRenderContext->FogMode( MATERIAL_FOG_NONE ); + + switch ( m_iRendermode ) + { + case PRENDER_SPHERE: + case PRENDER_CUBE: + case PRENDER_CYLINDER: + case PRENDER_PLANE: + DrawHardware(); + break; + case PRENDER_MODEL: + DrawModel(); + break; + } + + pRenderContext->FogMode( oldFog ); + + if ( bShouldDrawBG ) + pRenderContext->CopyRenderTargetToTextureEx( GetFBCopyTex(), 0, &rSrc ); + + //if ( sEditMRender ) + // sEditMRender->DoPostProc( setup.x, setup.y, setup.width, setup.height ); + + if ( bShouldDrawBG ) + pRenderContext->SetFrameBufferCopyTexture( oldCopyTex, 0 ); + + render->PopView( frustum ); +#ifndef SHADER_EDITOR_DLL_2006 + modelrender->SuppressEngineLighting( false ); +#endif + + switch ( m_iRendermode ) + { + case PRENDER_PINGPONG_0: + DrawPingpongRTs(); + break; + case PRENDER_POSTPROC: + case PRENDER_PPECHAIN: + DrawPostProcPreview(); + break; + } + + gShaderEditorSystem->UpdateConstants(); +} +void CRenderPanel::DrawPostProcPreview() +{ + surface()->DrawSetTexture( m_iVguitex_postprocPrev ); + surface()->DrawSetColor( Color(255,255,255,255) ); + + int w,t; + GetSize(w,t); + surface()->DrawTexturedRect( 0, 0, w, t ); +} + +void CRenderPanel::DrawScene() +{ + Assert( pEditorRoot ); + const bool bShaderAsPP = m_iRendermode == PRENDER_POSTPROC; + const bool bDoPPE = m_iRendermode == PRENDER_PPECHAIN; + + if ( !bShaderAsPP && bDoPPE && m_bDoPPE && pEditorRoot->GetSafeFlowgraph()->GetFlowgraphType() == CNodeView::FLOWGRAPH_POSTPROC ) + { + CUtlVector< CHLSL_SolverBase* > &hSolverStack = pEditorRoot->GetSafeFlowgraph()->AccessSolverStack_POSTPROC(); + GenericPPEData *pPPECfg = pEditorRoot->GetSafeFlowgraph()->AccessPPEConfig(); + + if ( hSolverStack.Count() && pPPECfg ) + { + EditorPostProcessingEffect effect( hSolverStack, *pPPECfg, false ); + GetPPCache()->RenderSinglePPE( &effect, true, true ); + } + } +} +void CRenderPanel::DrawPostProc() +{ + Assert( pEditorRoot ); + const bool bShaderAsPP = m_iRendermode == PRENDER_POSTPROC; + const bool bDoPPE = m_iRendermode == PRENDER_PPECHAIN; + + if ( !bShaderAsPP && !bDoPPE ) + return; + + if ( bShaderAsPP ) + { + CMatRenderContextPtr pRenderContext( materials ); + pRenderContext->PushRenderTargetAndViewport(); + + GeneralFramebufferUpdate( pRenderContext ); + + //shaderEdit->SetFramebufferCopyTexOverride( NULL ); + + int w,t; + engine->GetScreenSize( w, t ); + pRenderContext->DrawScreenSpaceRectangle( + pEditorRoot->GetMainPreviewMat(), + 0, 0, w, t, + 0, 0, w-1, t-1, + w, t ); + + pRenderContext->PopRenderTargetAndViewport(); + } + else + { + if ( m_bDoPPE && pEditorRoot->GetSafeFlowgraph()->GetFlowgraphType() == CNodeView::FLOWGRAPH_POSTPROC ) + { + CUtlVector< CHLSL_SolverBase* > &hSolverStack = pEditorRoot->GetSafeFlowgraph()->AccessSolverStack_POSTPROC(); + GenericPPEData *pPPECfg = pEditorRoot->GetSafeFlowgraph()->AccessPPEConfig(); + + if ( hSolverStack.Count() && pPPECfg ) + { + EditorPostProcessingEffect effect( hSolverStack, *pPPECfg, false ); + GetPPCache()->RenderSinglePPE( &effect, true ); + } + } + } + + shaderEdit->UpdateFramebufferTexture( true, true ); +} +void CRenderPanel::DrawModel() +{ + if ( !sEditMRender ) + return; + if ( !pEditorRoot || !pEditorRoot->GetMainPreviewMat() ) + return; + IMaterial *pMat = pEditorRoot->GetMainPreviewMat(); + + if ( m_bDoMatOverride ) + modelrender->ForcedMaterialOverride( pMat ); + sEditMRender->ExecRender(); + modelrender->ForcedMaterialOverride( NULL ); +} +void CRenderPanel::DrawPingpongRTs() +{ + surface()->DrawSetTexture( m_iVguitex_pp0 ); + surface()->DrawSetColor( Color(255,255,255,255) ); + + int w,t; + GetSize(w,t); + surface()->DrawTexturedRect( 0, 0, w, t ); +} + +//static ConVar sedit_debug_tangentspace( "sedit_debug_tangentspace", "1" ); +void CRenderPanel::DrawHardware() +{ + if ( !pEditorRoot || !pEditorRoot->GetMainPreviewMat() ) + return; + + IMaterial *pMat = pEditorRoot->GetMainPreviewMat(); + //pMat = materials->FindMaterial( "shadereditor/tex", TEXTURE_GROUP_OTHER ); + + float alpha = surface()->DrawGetAlphaMultiplier(); + + CMatRenderContextPtr pRenderContext( materials ); + int numtris = _mesh.GetNumTriangles(); + CMeshBuilder pMeshBuilder; + IMesh *pMesh = pRenderContext->GetDynamicMesh( true, 0, 0, pMat ); +#ifndef SHADER_EDITOR_DLL_2006 + pMeshBuilder.SetCompressionType( VERTEX_COMPRESSION_NONE ); +#endif + pMeshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, numtris ); + for ( int i = 0; i < numtris; i++ ) + { + CHLSL_Triangle &tri = _mesh.GetTriangles()[i]; + + for ( int t = 0; t < 3; t++ ) + SetupVert( pMeshBuilder, *tri.vertices[t], alpha ); + } + pMeshBuilder.End(); + pMesh->Draw(); + +#if 0 + if ( true ) + { + pMat = materials->FindMaterial( "shadereditor/blank", TEXTURE_GROUP_OTHER ); + pMesh = pRenderContext->GetDynamicMesh( true, 0, 0, pMat ); + pMeshBuilder.Begin( pMesh, MATERIAL_LINES, _mesh.GetNumVertices() * 3 ); + pMeshBuilder.SetCompressionType( VERTEX_COMPRESSION_NONE ); + for ( int i = 0; i < _mesh.GetNumVertices(); i++ ) + { + CHLSL_Vertex &vert = _mesh.GetVertices()[i]; + Vector pos; + VectorCopy( vert.pos, pos.Base() ); + Vector normal; + VectorCopy( vert.normal, normal.Base() ); + Vector tangent_s; + VectorCopy( vert.tangent_s, tangent_s.Base() ); + Vector tangent_t; + VectorCopy( vert.tangent_t, tangent_t.Base() ); + + pos += normal * 2; + normal = normal * 3 + pos; + tangent_s = tangent_s * 3 + pos; + tangent_t = tangent_t * 3 + pos; + + pMeshBuilder.Position3fv( pos.Base() ); + pMeshBuilder.Color3f( 0, 0, 1 ); + pMeshBuilder.AdvanceVertex(); + pMeshBuilder.Position3fv( normal.Base() ); + pMeshBuilder.Color3f( 0, 0, 1 ); + pMeshBuilder.AdvanceVertex(); + + pMeshBuilder.Position3fv( pos.Base() ); + pMeshBuilder.Color3f( 1, 0, 0 ); + pMeshBuilder.AdvanceVertex(); + pMeshBuilder.Position3fv( tangent_s.Base() ); + pMeshBuilder.Color3f( 1, 0, 0 ); + pMeshBuilder.AdvanceVertex(); + + pMeshBuilder.Position3fv( pos.Base() ); + pMeshBuilder.Color3f( 0, 1, 0 ); + pMeshBuilder.AdvanceVertex(); + pMeshBuilder.Position3fv( tangent_t.Base() ); + pMeshBuilder.Color3f( 0, 1, 0 ); + pMeshBuilder.AdvanceVertex(); + } + pMeshBuilder.End(); + pMesh->Draw(); + } +#endif +} diff --git a/sp/src/shadereditor/vrenderpanel.h b/sp/src/shadereditor/vrenderpanel.h new file mode 100644 index 00000000..01a81d2b --- /dev/null +++ b/sp/src/shadereditor/vrenderpanel.h @@ -0,0 +1,114 @@ +#ifndef CRENDERPANEL_H +#define CRENDERPANEL_H + +#include "cbase.h" +using namespace vgui; + +#include +#include +#include +#include "editorCommon.h" +#include + +#include "ivrenderview.h" + +enum +{ + PRENDER_SPHERE = 0, + PRENDER_CUBE, + PRENDER_CYLINDER, + PRENDER_PLANE, + PRENDER_MODEL, + PRENDER_POSTPROC, + PRENDER_PINGPONG_0, + PRENDER_PPECHAIN, +}; + +class CMeshBuilder; + +enum +{ + RDRAG_NONE = 0, + RDRAG_ROTATE, + RDRAG_LIGHT, + RDRAG_POS, +}; + +class CRenderPanel : public vgui::Panel +{ + DECLARE_CLASS_SIMPLE( CRenderPanel, vgui::Panel ); + +public: + CRenderPanel( Panel *parent, const char *pElementName ); + ~CRenderPanel(); + + virtual void OnThink(); + + virtual void Paint(); + + void SetupView( CViewSetup &setup ); + + void OnMousePressed( MouseCode code ); + void OnMouseReleased( MouseCode code ); + void OnCursorMoved( int x, int y ); + void OnMouseWheeled( int delta ); + + //void ReceiveRGBA( CHLSL_Image *img ); + + QAngle render_ang; + Vector render_pos; + Vector render_offset; + Vector render_offset_modelBase; + QAngle lightAng; + + void UpdateRenderPosition(); + void CreateMesh( int mode ); + + float m_flDist; + float m_flPitch; + float m_flYaw; + + Frustum frustum; + int m_iDragMode; + int m_iCachedMpos_x; + int m_iCachedMpos_y; + + void SetupVert( CMeshBuilder &builder, CHLSL_Vertex &vert, float alpha ); + + VMatrix __view; + VMatrix __proj; + VMatrix __ViewProj; + VMatrix __ViewProjNDC; + + void SetRenderMode( int mode ); + void SetMatOverrideEnabled( bool b ){ + m_bDoMatOverride = b; + }; + + void DrawScene(); + void DrawPostProc(); + void SetPPEPreviewEnabled( bool bEnabled ){ + m_bDoPPE = bEnabled; + }; + + void ResetView(); + +private: + CHLSL_Mesh _mesh; + + int m_iRendermode; + bool m_bDoMatOverride; + bool m_bDoPPE; + + void DrawBackground(); + void DrawHardware(); + void DrawPingpongRTs(); + void DrawModel(); + void DrawPostProcPreview(); + + int m_iVguitex_pp0; + int m_iVguitex_postprocPrev; +}; + + +#endif \ No newline at end of file