1、通过本文你可以学到通过SDK暴露一个函数给Maxscript使用,你觉得脚本做不了的,就自己实现吧。
直接看主要代码,里面有我为初学者写的注释,c++语法不懂的就先别看了,工程是直接拷贝官方案例intervalarray修改的,下面是IntervalArray.cpp里的内容。
/**********************************************************************
*<
FILE: IntervalArray.cpp
DESCRIPTION: This plugin shows how to code a maxscript function
that adds one function to the maxsript language. This
function is called interval array, and returns an array
of numbers. The start of the array starts at one number
and proceeds by evenly spaced intervals to a high number.
3DSMAX USAGE: In 3DSMax, open up the maxscript listener
and type in (for example)
h = intervalarray 12.3 78.9 3
and it will return the array
#(12.3, 34.5, 56.7, 78.9)
CREATED BY: Chris Johnson
HISTORY: Started in March 2005
*> Copyright (c) 2005, All Rights Reserved.
**********************************************************************/
#include <maxscript/maxscript.h>
#include <maxscript/foundation/numbers.h>
#include <maxscript/foundation/arrays.h>
#include <conio.h>
void IntervalArrayInit()
{
// 创建一个新的控制台
AllocConsole();
//Todo: Place initialization code here. This gets called when Maxscript goes live
//during max startup.
}
// Declare C++ function and register it with MAXScript
#include <maxscript\macros\define_instantiation_functions.h>
def_visible_primitive(IntervalArray, "execute");//参数一是注册在c++里的函数名,和下面实现函数的名称有对应关系;第二个参数是暴露给Maxscript调用的函数名
/*
Value* IntervalArray_cf(Value **arg_list, int count)
{
//--------------------------------------------------------
//Maxscript usage:
//--------------------------------------------------------
// <array> IntervalArray <Start:Number> <End:Number> <steps:Integer>
check_arg_count(IntervalArray, 3, count);//确保是三个参数,否则抛出异常
Value* pBegin = arg_list[0];//获取输入的第一个参数,下面以此类推
Value* pEnd = arg_list[1];
Value* pStep = arg_list[2];
//First example of how to type check an argument
if ( ! (is_number(pBegin)))//确保参数是数字,如果不是那么抛异常
{
throw RuntimeError(_T("Expected a Number for the first argument, in function IntervalArray"));
}
if ( ! (is_number(pEnd)))//确保参数是数字,如果不是那么抛异常
{
throw RuntimeError(_T("Expected a Number for the second argument, in function IntervalArray"));
}
//Second example of how to type check an argument
type_check( pStep, Integer, _T("Expected an Integer for the step size" ));//确保pStep是Integer类型,否则抛异常
float begin = pBegin->to_float();//转换成对应类型的数据
float end = pEnd->to_float();
int steps = pStep->to_int();
if (steps <= 0) { throw RuntimeError(_T("Expected a positive Number for Steps, in function IntervalArray"));}
one_typed_value_local(Array* rArray);//在Maxscript变量容器里声明一个数组类型,直译为局部变量集合里申明数组类型
vl.rArray = new Array (steps);
float data = begin;
float increment = ((end-begin)/steps);
for (int i = 0 ; i <= steps ; i++)
{
Value* aTempNumber = Float::heap_intern(data);//float to value*
vl.rArray->append(aTempNumber);
data += increment;
}
return_value(vl.rArray);//返回数组内容
}
*/
// 因为3dsMaxSDK里统一使用的wchar,而打印输出的方法要求是char
char* WcharToChar(const wchar_t* wp)
{
char* m_char = NULL;
int len= WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),NULL,0,NULL,NULL);
m_char=new char[len+1];
WideCharToMultiByte(CP_ACP,0,wp,wcslen(wp),m_char,len,NULL,NULL);
m_char[len]='\0';
return m_char;
}
// 这里本方法名必须和前面注册的函数名对应:如果前面注册名是A,那么这里方法名就是A_cf,参数一是接受函数参数,参数二是参数个数,这个和命令行程序一样
Value* IntervalArray_cf(Value **arg_list, int count)
{
//--------------------------------------------------------
//Maxscript usage:
//--------------------------------------------------------
// <array> IntervalArray <Start:Number> <End:Number> <steps:Integer>
//check_arg_count(IntervalArray, 3, count);
Value* pBegin = arg_list[0];//获取第一个参数
const MCHAR* sadf = pBegin->to_string();
_cprintf(WcharToChar(sadf));//打印输出
bool res = false;
StringStream aa(sadf);
CharStream * saaa = &aa;
return ExecuteScript(saaa, &res);
// bool ddd = ExecuteMAXScriptScript(sadf);
// return ddd ? &true_value : &false_value;
}
def_visible_primitive(IntervalArray1, "filein");
Value* IntervalArray1_cf(Value **arg_list, int count)
{
//--------------------------------------------------------
//Maxscript usage:
//--------------------------------------------------------
// <array> IntervalArray <Start:Number> <End:Number> <steps:Integer>
//check_arg_count(IntervalArray, 3, count);
Value* pBegin = arg_list[0];
const MCHAR* sadf = pBegin->to_string();
/* std::cout<<sadf<<std::endl;*/
_cprintf(WcharToChar(sadf));
StringStream aa(sadf);
CharStream * saaa = &aa;
filein_script(sadf);
return &true_value;
}
2、利用同名函数可以直接覆盖原有脚本方法这点特性,达到混淆代码的还原。(3dsMaxSDK允许这点,我觉得设计的不合理,相当于允许破坏脚本原先的功能,我对比过MayaAPI,暴露一个同名的函数,插件是无法被加载的。)
这个是我的使用别人工具混淆后的代码,通过加载上面的插件,再次运行脚本时可以在控制台打印输出脚本源代码。
'try' (('DotNetClass' "System.Windows.Forms.Application").'CurrentCulture' = 'dotnetObject' "System.Globalization.CultureInfo" "zh-cn") 'catch'()
'fn' '庞銘怡螦鐋觙袶ㄞ脻藫论フ卖懇涋' str = 'execute' (('dotNetClass' "System.Text.Encoding").'UTF8'.GetString(('dotNetClass' "System.Convert").'FromBase64String'(str)))
'fn' '撥釼蟝栟吨厠蚕述擮阗漳旺翸渀Σ僿猰魺' =
(
::'頏※嚭黌魩瑠躒"蜚确嵁趐棠瞜'='庞銘怡螦鐋觙袶ㄞ脻藫论フ卖懇涋' "bWVzc2FnZWJveA=="
::'瘜督稊琪 畔盝惟 儳焔蚪坌胐 襚撯禒臟幣ㄈ鏖萅櫘儐覜搚俊嵀攡捸'='庞銘怡螦鐋觙袶ㄞ脻藫论フ卖懇涋' "InNhZGYi"
'ok' )
'撥釼蟝栟吨厠蚕述擮阗漳旺翸渀Σ僿猰魺'()
'頏※嚭黌魩瑠躒"蜚确嵁趐棠瞜' '瘜督稊琪 畔盝惟 儳焔蚪坌胐 襚撯禒臟幣ㄈ鏖萅櫘儐覜搚俊嵀攡捸'
3、演示的过程
3、因为好几个朋友联系我要工程文件,我决定上传共享给大家,下载链接:https://pan.baidu.com/s/167ZWPeQLdglJ8pTzmSYOLQ 密码:27v7。