Jump to content

Paul Thomas

Members
  • Posts

    339
  • Joined

  • Last visited

Everything posted by Paul Thomas

  1. Paul Thomas

    Even Faster

    http://attractivechaos.github.com/plb/
  2. All loads good here, NA. My only suggestion is the twitter background color (sticks out like a sore thumb compared to the overal color scheme) and the type of blue font you use in the body I would just make it white. Basically what gamecreator said. The colors clash with the overall theme and art. Art looks great, great job on that.
  3. Paul Thomas

    Even Deeper

    Almost finished my own text editor
  4. How it seems you're doing it now, with your desired results, you should just keep going with it
  5. I was wondering who stole my keyboard. Kidding aside, congrats Josh, a huge step forward for Leadwerks.
  6. C++ version to send a message to BMax window (yes, it's specific, any other way doesn't work correctly that I've noticed): HWND pHandle = FindWindow(NULL, _T("WINDOW TITLE")); if(pHandle != NULL && GetLastError() != ERROR_SUCCESS) { std::string msgString = "THIS IS A TEST"; COPYDATASTRUCT dataStruct; dataStruct.dwData = 3; // this just tells my app that this is coming from C++ DLL - use any number dataStruct.cpData = (msgString.length() + 1); dataStruct.lpData = (PVOID)msgString.c_str(); LRESULT msgSent = SendMessage(pHandle, WM_COPYDATA, (WPARAM)pHandle, (LPARAM)(LPVOID)&dataStruct); } I still cannot figure out why BMax cannot read from the named pipe (different subject, just using this spot for quick thoughts). Using pure C++ I have no problems, BMax can only send, but not receive. I'm guessing it's something wrong I'm doing in BMax but it's hard to tell.
  7. I just now got this working and I haven't made it all organized yet, I'm going to do that when I add it to my actual application, instead of using this testing application. One portion turned out to be a problem. When trying to get the window handle from the process ID it actually is a list of the window and basically any/all gadgets that can receive messages (active panels for example). I don't know for fact that this is true but that's what it seems like to me, otherwise I don't see how all of these returned results from "GetWindowThreadProcessId" are all from the same process ID. Here is the function get the results from a process ID, one of which will be the window, and this has to be filtered in some way (send a message, check the title, something along those lines; I haven't done this filter yet): ' get the list of threads/windows matching the passed in process id ' Function GetProcessWindow:int[](id:int) Local hWnd:int = GetTopWindow(0) Local hWnds:int[] While(hWnd) Local pId:int Local dThreadId:int = GetWindowThreadProcessId(hWnd, Varptr pId) If pId = id hWnds = hWnds[..hWnds.Length+1] hWnds[hWnds.Length-1] = hWnd EndIf hWnd = _GetNextWindow(hWnd, GW_HWNDNEXT) Wend Return hWnds EndFunction Now, you can use this list and send the message to all of them, which I did to be quick about it, and it seems safe because the message will just fail to send if it's not a correct window. That seems odd, so a filtering process should be done, but I haven't done that yet. Either way you will still be sending a message of some kind to all of the returned results before having the actual window handle. Anyway, the following is how to send the message (which would be a separate application at the time) and receive it (which would be the already running instance of the application). Sending: Global ChangeWindowMessageFilter:Int(message:Int, dwFlag:Int) = GetProcAddress(LoadLibraryA("user32.dll"), "ChangeWindowMessageFilter") Local MsgStr:String = "THIS IS A TEST" Local MsgData:int[3] MsgData[0] = 1 MsgData[1] = Len(MsgStr) + 1 MsgData[2] = Int(MsgStr.ToCString()) ChangeWindowMessageFilter(WM_COPYDATA, 1) SendMessageW(pHandle, WM_COPYDATA, 0, Int Byte Ptr MsgData) Receiving: Local MsgData:int[3] MemCopy(MsgData, Byte Ptr lp, 12) ' MsgData[0] - 1 ' ' MsgData[1] - Size ' ' MsgData[2] - String ' Notify(String.FromCString(Byte Ptr MsgData[2])) And there you have it. It will notify "THIS IS A TEST" correctly. You can use "MsgData[0]" as a form of message identification so you can decide what to do with the string you've received. For receiving, it's best to edit "win32maxguiex.bmx" and explains the "lp" variable. Line 372, you would do something like: ' Select msg ' Case WM_COPYDATA local msgData:int[3] MemCopy(msgData, Byte Ptr lp, 12) PostGuiEvent(EVENT_DATARECEIVED, Null, 0, 0, 0, 0, String.FromCString(Byte Ptr msgData[2])) Add the "EVENT_DATARECEIVED" to "brl.mod/event.bmx", around line 193: Const EVENT_DATARECEIVED=$50000 And around line 234: TEvent.RegisterId EVENT_DATARECEIVED,"DataReceived" Rebuild the two modules, and now you can use it like: repeat waitevent() select eventid() case EVENT_DATARECEIVED notify(eventextra().tostring()) That should be it. Thanks goes out to "col" from the BlitzMax forums for his help in figuring out the sending/receiving of the message.
  8. Very nice work, Ken. You display some awesome skills.
  9. Had this working but never tested actually getting the message, I only confirmed it worked with a notification, and so I spent all day trying to actually get the message. Going to give this more of a shot but if I still can't get it working strictly in BMax I'm probably going to take a shortcut and provide a helper function in C.
  10. Got this working but now I need to clean everything up.
  11. I would imagine anyone who uses LE editor for a long period of time would have seen this happen and probably would have reported it. I also never had seen Flexman mention this before either. So, either no one has used the editor for a long period of time, or Flexman/NA never played their own games for a long period of time, or it's something you're doing. I will come back and post here if I see it happen.
  12. lol, technically yeah, I could make my own task manager. However, my purpose is to deny multiple instances of my application, and eventually send messages (SendMessageW) to the application - which I'm working on now. My attempt is to deny a second application execution and send the application arguments to the application already running (this way double clicking a file that my application is registered to will open up in the application already running). Forgot about the tags. And fixed.
  13. xwinuser.c #include "xwinuser.h" HWND _GetNextWindow(HWND hWnd, UINT wCmd) { return GetNextWindow(hWnd, wCmd); } xwinuser.h #include <Windows.h> #include <Winuser.h> #ifdef __cplusplus extern "C"{ #endif extern HWND _GetNextWindow(HWND hWnd, UINT wCmd); #ifdef __cplusplus } #endif BMAX Import "xwinuser.c" Const GW_HWNDNEXT:int = 2 Const GW_HWNDPREV:int = 3 Extern "Win32" Function _GetNextWindow:Int(hWnd:Int, wCmd:Int) = "_GetNextWindow" EndExtern Not sure if this would be called "proper" but it works.
  14. Wow, "GetTopWindow" is in User32.dll but "GetNextWindow" is only available in Winuser.h? That is so lame.
  15. I started working on this today, got it working, and figured I'd share. I still have more work to do but this is a good start. Could use cleaning up but that's for later. SuperStrict Import "-lpsapi" Const PROCESS_QUERY_INFORMATION:Int = $0400 Const PROCESS_VM_READ:Int = $0010 Const PROCESS_VM_WRITE:Int = $0020 Extern "Win32" Function GetLastError:Int() Function OpenProcess:Int(dwDesiredAccess:Int, bInheritHandle:Int, dwProcessId:Int) Function EnumProcesses(pProcessIds:Byte Ptr, cb:Int, pBytesReturned:Int Ptr)="EnumProcesses@12" Function EnumProcessModules(hProcess:Int, lphModule:Byte Ptr, cb:Int, lpcbNeeded:Int Ptr) Function GetModuleBaseName(hProcess:Int, hModule:Int, lpBaseName:Byte Ptr, nSize:Int) = "GetModuleBaseNameA@16" Function TerminateProcess(hProcess:Int, uExitCode:Int) Function CloseHandle(hObject:Int) Function GetModuleFileName(hModule:Int, lpFileName:Byte Ptr, nSize:Int) Function GetModuleFileNameExA(hProcess:Int, hModule:Int, lpFilename:Byte Ptr, nSize:Int) Function GetProcessImageFileNameA(hProcess:Int, lpImageFileName:Byte Ptr, nSize:Int) EndExtern ' enumerate all processes ' Function EnumerateProcesses:Int[]() Local pProcessIds:Byte Ptr Local cb:Int = 1024 Local bBytesReturned:Int Local processes:Int[] pProcessIds = MemAlloc(cb) If Not EnumProcesses(pProcessIds , cb, Varptr bBytesReturned) MemFree(pProcessIds ) Return Null EndIf processes = New Int[bBytesReturned / 4] MemCopy(Varptr processes[0], pProcessIds, bBytesReturned) MemFree(pProcessIds) Return processes EndFunction ' get process name from process id ' Function GetProcessName:String(id:Int) Local hProcess:Int Local hModule:Int = 0 Local lpBaseName:Byte Ptr[1024] Local nSize:Int = 1024 Local processName:String = "" hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, 0, id) If hProcess = 0 Return "" GetModuleBaseName(hProcess, hModule, Varptr lpBaseName[0], nSize) processName = String.FromCString(lpBaseName) If processName = "?" Or processName = Null GetProcessImageFileNameA(hProcess, Varptr lpBaseName[0], nSize) processName = StripDir(String.FromCString(lpBaseName)) EndIf CloseHandle(hProcess) Return processName EndFunction ' EXAMPLE USEAGE ' Local pList:Int[] = EnumerateProcesses() If pList.length > 0 For Local i:Int = 0 To pList.length - 1 If pList[i] <> 0 Local pname:String = GetProcessName(pList[i]) If pname <> "" Notify(pname) EndIf Next EndIf
  16. You're using static camera positions, you could take advantage of that and alter the level design. For example, at around 0:37, you could be using a billboard in the distance instead of sculpting hills. Would most likely have a better visual result as well, depending on how well the art could be done for it, but overall it would let you decrease the size of the terrain. I'm not sure how much performance you'd gain from doing that but it's better than nothing. How are you handling the animals once they are out of view? You can again take advantage of static camera positions and never actually delete the animal, but instead hide and move them to another location just to run into view again. Animals that run out of view without dying can be recycled in the same way (be sure to reset their health points too on all of these animals being recycled). Other than sneaky art trickery on the level design you may need to investigate the animal meshes, see if they could be optimized, not sure if you purchased these animals or made them yourself. That's about all I can think of for the moment, maybe someone else will have more tips.
  17. Texture size would be the same, the only real difference using a mesh and painting the mesh would be less textures used, since it would all be painted on a single texture. I wouldn't go below 4096 unless you plan on a lot of vegetation because any lower resolution looks kind of bad. I would use 4096 on parts of the terrain that would have no, or very little, vegetation, and 2048 (maybe even 1024) on high vegetation density areas. The only downside to using mesh is ease of editing compared but I guess that really depends on your modeling/sculpting skills. You'd also have to make sure each section of mesh aligns with the next within your modeling program. Having your level already conceptualized before modeling would reduce the amount of edits you would have to do, because I can imagine a situation where you decided to make clearing for a building right at a location where four meshes combine to make the area. Not only would you be editing the four meshes but also repainting those meshes. You should also definitely have LOD's for your terrain meshes but you don't have to bother if you don't plan on open fields/areas. The overall level design concept should help define how the level should be designed. I predict multiple meshes instead of one large mesh so that the engine can cull sections correctly. Really all depends on the overall level design, what you need, and so on.
  18. The problem with the collision is what Marley's Ghost has been talking about: http://www.leadwerks.com/werkspace/topic/4482-linepicks-and-veg-layers/ Vegetation layers are blocking traces even though their collision is set to 0. Either Josh fixes it or you do away with using vegetation layers. Unless you meant the random animals running through some of the tree's. Everything looks good. Some of the animal running animations look too slow. The dust particles could be smaller for their running and add in particles when they are collapsing to the ground (about as large, or larger, than their current running particles). Need some bullet hit impacts with the environment and maybe the animals (you said arcade, so maybe no the animals/blood). That's all I got, good work.
  19. Also, I used something similar to what you did Josh for a slightly different purpose. I also used a thread so my UI doesn't freeze up during the process: field thread:tthread method beginprocess() thread = createthread(runprocess, null) endmethod function runprocess:object(data:object) local line:string = "" local lines:string = "" local process:tprocess = createprocess(PROCESSLOCATION, 1) while process.status() line = process.pipe.readline().trim() if line <> "" lines :+ line + "~n"; wend ' process lines ' process.terminate() endfunction Technically don't need to terminate the process at the end since it'll terminate once the thread is finished but it doesn't hurt. Every time I'm using processes I'm parsing it line by line so I edited the above to add all the lines. Meh, just felt like sharing code.
×
×
  • Create New...